File size: 2,665 Bytes
411fba2
af93b45
4b8b411
80b13a0
 
 
60216ec
 
3138e12
711cbbd
 
86574c0
a8ce6ad
 
bd6645c
 
 
 
 
 
 
 
 
 
 
 
fc99266
60216ec
a8ce6ad
 
 
 
80b13a0
 
 
74d5501
 
8b52b18
 
 
74d5501
80b13a0
a8ce6ad
 
60216ec
411fba2
 
a8ce6ad
15bd628
a8ce6ad
003aab5
60216ec
 
a8ce6ad
 
 
f459835
60216ec
711cbbd
411fba2
f459835
 
eeca96c
a8ce6ad
411fba2
f459835
 
bd6645c
60216ec
bd6645c
711cbbd
f459835
711cbbd
f459835
dee0245
f459835
c077f8a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
<script lang="ts">
	import type { Conversation, ModelEntryWithTokenizer } from "./types";

	import { goto } from "$app/navigation";
	import { page } from "$app/stores";

	import IconCaret from "../Icons/IconCaret.svelte";
	import ModelSelectorModal from "./InferencePlaygroundModelSelectorModal.svelte";

	export let models: ModelEntryWithTokenizer[] = [];
	export let conversation: Conversation;

	let showModelPickerModal = false;

	async function getAvatarUrl(orgName: string) {
		const url = `https://huggingface.co/api/organizations/${orgName}/avatar`;
		const res = await fetch(url);
		if (!res.ok) {
			console.error(`Error getting avatar url for org: ${orgName}`, res.status, res.statusText);
			return;
		}
		const json = await res.json();
		const { avatarUrl } = json;
		return avatarUrl;
	}

	function changeModel(modelId: ModelEntryWithTokenizer["id"]) {
		const model = models.find(m => m.id === modelId);
		if (!model) {
			return;
		}
		conversation.model = model;

		const url = new URL($page.url);
		url.searchParams.set("modelId", model.id);

		const parentOrigin = "https://huggingface.co";
		const searchParamsWithoutTheme = new URLSearchParams(url.searchParams.toString());
		searchParamsWithoutTheme.delete("__theme");
		window.parent.postMessage({ queryString: searchParamsWithoutTheme.toString() }, parentOrigin);

		goto(url.toString(), { replaceState: true });
	}

	$: [nameSpace, modelName] = conversation.model.id.split("/");
</script>

{#if showModelPickerModal}
	<ModelSelectorModal
		{models}
		{conversation}
		on:modelSelected={e => changeModel(e.detail)}
		on:close={e => (showModelPickerModal = false)}
	/>
{/if}

<div class="flex flex-col gap-2">
	<label for="countries" class="flex items-baseline text-sm font-medium text-gray-900 dark:text-white"
		>Models<span class="ml-4 font-normal text-gray-400">{models.length}</span>
	</label>

	<button
		class="relative flex items-center justify-between gap-6 overflow-hidden whitespace-nowrap rounded-lg border bg-gray-100/80 px-3 py-1.5 leading-tight shadow hover:brightness-95 dark:border-gray-700 dark:bg-gray-800 dark:hover:brightness-110"
		on:click={() => (showModelPickerModal = true)}
	>
		<div class="flex flex-col items-start">
			<div class="flex items-center gap-1 text-sm text-gray-500 dark:text-gray-300">
				{#await getAvatarUrl(nameSpace) then avatarUrl}
					<img class="size-3 flex-none rounded bg-gray-200 object-cover" src={avatarUrl} alt="{nameSpace} avatar" />
				{/await}
				{nameSpace}
			</div>
			<div>{modelName}</div>
		</div>
		<IconCaret classNames="text-xl bg-gray-100 dark:bg-gray-600 rounded size-4 flex-none absolute right-2" />
	</button>
</div>