kit/src/lib/InferenceSnippet/InferenceSnippet.svelte (365 lines of code) (raw):
<script lang="ts">
import hljs from "highlight.js";
import type {
InferenceSnippetLanguage,
ModelDataMinimal,
PipelineType,
} from "@huggingface/tasks";
import { type InferenceProvider, snippets } from "@huggingface/inference";
import { onMount, SvelteComponent } from "svelte";
import CodeBlock from "$lib/CodeBlock.svelte";
import IconCurl from "$lib/IconCurl.svelte";
import IconJs from "$lib/IconJs.svelte";
import IconPython from "$lib/IconPython.svelte";
import IconInferenceBlackForest from "./IconInferenceBlackForest.svelte";
import IconInferenceCerebras from "./IconInferenceCerebras.svelte";
import IconInferenceCohere from "./IconInferenceCohere.svelte";
import IconInferenceFal from "./IconInferenceFal.svelte";
import IconInferenceFeatherless from "./IconInferenceFeatherless.svelte";
import IconInferenceFireworks from "./IconInferenceFireworks.svelte";
import IconInferenceGroq from "./IconInferenceGroq.svelte";
import IconInferenceHf from "./IconInferenceHf.svelte";
import IconInferenceHyperbolic from "./IconInferenceHyperbolic.svelte";
import IconInferenceNebius from "./IconInferenceNebius.svelte";
import IconInferenceNovita from "./IconInferenceNovita.svelte";
import IconInferenceNscale from "./IconInferenceNscale.svelte";
import IconInferenceOvh from "./IconInferenceOvh.svelte";
import IconInferenceReplicate from "./IconInferenceReplicate.svelte";
import IconInferenceSambaNova from "./IconInferenceSambaNova.svelte";
import IconInferenceTogetherAI from "./IconInferenceTogetherAI.svelte";
import Dropdown from "$lib/Dropdown.svelte";
import DropdownEntry from "$lib/DropdownEntry.svelte";
import IconSettings from "./IconSettings.svelte";
import IconLinkExternal from "./IconLinkExternal.svelte";
type InferenceProviderNotOpenAI = Exclude<InferenceProvider, "openai">;
export let pipeline: PipelineType;
export let conversational = false;
export let providersMapping: Partial<
Record<
InferenceProviderNotOpenAI,
{
modelId: string;
providerModelId: string;
}
>
> = {};
let providers = Object.keys(providersMapping) as InferenceProviderNotOpenAI[];
let selectedProvider = providers[0];
let streaming = false;
const model = {
id: providersMapping[selectedProvider]!.modelId,
pipeline_tag: pipeline,
tags: conversational ? ["conversational"] : [],
};
const availableSnippets = snippets.getInferenceSnippets(
model as ModelDataMinimal,
selectedProvider,
{
hfModelId: providersMapping[selectedProvider]!.modelId,
providerId: providersMapping[selectedProvider]!.providerModelId,
status: "live",
task: pipeline,
provider: selectedProvider,
}
);
const languages = [...new Set(availableSnippets.map((s) => s.language))];
let selectedLanguage = languages[0];
const clientsByLanguage = Object.fromEntries(
languages.map((lang) => [
lang,
[...new Set(availableSnippets.filter((s) => s.language === lang).map((s) => s.client))],
])
);
$: clients = clientsByLanguage[selectedLanguage];
$: selectedClient = clients?.[0];
$: code = snippets
.getInferenceSnippets(
model as ModelDataMinimal,
selectedProvider,
{
hfModelId: providersMapping[selectedProvider]!.modelId,
providerId: providersMapping[selectedProvider]!.providerModelId,
status: "live",
task: pipeline,
provider: selectedProvider,
},
{
streaming,
}
)
.find((s) => s.language === selectedLanguage && s.client === selectedClient)?.content;
const PRETTY_NAMES: Partial<
Record<InferenceProviderNotOpenAI | InferenceSnippetLanguage, string>
> = {
// inference providers
"black-forest-labs": "Black Forest Labs",
cerebras: "Cerebras",
cohere: "Cohere",
"fal-ai": "fal",
"featherless-ai": "Featherless",
"fireworks-ai": "Fireworks",
groq: "Groq",
hyperbolic: "Hyperbolic",
"hf-inference": "HF Inference API",
nebius: "Nebius AI Studio",
novita: "Novita",
nscale: "Nscale",
ovhcloud: "OVHcloud AI Endpoints",
replicate: "Replicate",
sambanova: "SambaNova",
together: "Together AI",
// languages
sh: "cURL",
python: "Python",
js: "JavaScript",
// clients
};
const ICONS: Partial<
Record<
InferenceProviderNotOpenAI | InferenceSnippetLanguage,
new (...args: any) => SvelteComponent
>
> = {
// inference providers
"black-forest-labs": IconInferenceBlackForest,
cerebras: IconInferenceCerebras,
cohere: IconInferenceCohere,
"fal-ai": IconInferenceFal,
"featherless-ai": IconInferenceFeatherless,
"fireworks-ai": IconInferenceFireworks,
groq: IconInferenceGroq,
hyperbolic: IconInferenceHyperbolic,
nebius: IconInferenceNebius,
novita: IconInferenceNovita,
nscale: IconInferenceNscale,
ovhcloud: IconInferenceOvh,
replicate: IconInferenceReplicate,
sambanova: IconInferenceSambaNova,
together: IconInferenceTogetherAI,
"hf-inference": IconInferenceHf,
// languages
sh: IconCurl,
python: IconPython,
js: IconJs,
// clients
};
const base64 = (val: string) => btoa(encodeURIComponent(val));
onMount(() => {
// shuffle providers
providers = providers.sort(() => Math.random() - 0.5);
selectedProvider = providers[0];
});
</script>
<div
class="md:items-top not-prose flex w-full flex-col justify-between gap-x-2 text-sm md:flex-row"
>
<!-- Language selection -->
{#if languages.length > 1}
<div>
<p class="hidden font-mono text-xs opacity-50 md:block">Language</p>
<div class="my-1.5 flex flex-wrap items-center gap-x-1 gap-y-0.5">
{#each languages as language}
<button
class="text-md flex select-none items-center rounded-lg border px-1.5 py-1 leading-none
{selectedLanguage === language
? 'border-gray-800 bg-black text-white dark:bg-gray-700'
: 'hover:shadow-xs cursor-pointer text-gray-500 opacity-90 hover:text-gray-700 dark:hover:text-gray-200'}"
type="button"
on:click={() => (selectedLanguage = language)}
>
{#if ICONS[language]}
<svelte:component this={ICONS[language]} classNames="mr-1.5 text-current" />
{/if}
{PRETTY_NAMES[language] ?? language}
</button>
{/each}
</div>
</div>
{/if}
<!-- Client selection -->
{#if clients.length > 1}
<div>
<p class="hidden font-mono text-xs opacity-50 md:block">Client</p>
<div class="my-1.5 flex flex-wrap items-center gap-x-1 gap-y-0.5">
{#each clients as client}
<button
class="text-md flex select-none items-center rounded-lg border px-1.5 py-1 leading-none
{selectedClient === client
? 'border-gray-800 bg-black text-white dark:bg-gray-700'
: 'hover:shadow-xs cursor-pointer text-gray-500 opacity-90 hover:text-gray-700 dark:hover:text-gray-200'}"
type="button"
on:click={() => (selectedClient = client)}
>
{client}
</button>
{/each}
</div>
</div>
{/if}
<!-- Provider selection -->
{#if providers.length > 0}
{@const nVisibleProviders = 2}
<div>
<p class="hidden font-mono text-xs opacity-50 md:block">Provider</p>
<div class="my-1.5 flex flex-wrap items-center gap-x-1 gap-y-0.5">
{#each providers.slice(0, nVisibleProviders) as provider}
<button
class="text-md flex select-none items-center rounded-lg border px-1.5 py-1 leading-none
{selectedProvider === provider
? 'border-gray-800 bg-black text-white dark:bg-gray-700'
: 'hover:shadow-xs cursor-pointer text-gray-500 opacity-90 hover:text-gray-700 dark:hover:text-gray-200'}"
type="button"
on:click={() => (selectedProvider = provider)}
>
{#if ICONS[provider]}
<svelte:component this={ICONS[provider]} classNames="mr-1.5 text-current" />
{/if}
{PRETTY_NAMES[provider] ?? provider}
</button>
{/each}
{#if providers.length > nVisibleProviders}
<Dropdown btnLabel="" classNames="colab-dropdown" noBtnClass useDeprecatedJS={false}>
<slot slot="button">
<p
class="text-md hover:shadow-xs flex cursor-pointer select-none items-center rounded-lg border px-1.5 py-1 leading-none text-gray-500 opacity-90 hover:text-gray-700 dark:hover:text-gray-200"
>
+{providers.length - nVisibleProviders}
</p>
</slot>
<slot slot="menu">
{#each providers.slice(nVisibleProviders) as provider, idx}
<DropdownEntry
classNames="text-sm !no-underline"
iconClassNames="mr-1.5 text-current"
icon={ICONS[provider]}
label={PRETTY_NAMES[provider] ?? provider}
useDeprecatedJS={false}
onClick={() => {
selectedProvider = provider;
providers = [
selectedProvider,
...providers.filter((p) => p !== selectedProvider),
];
}}
/>
{/each}
</slot>
</Dropdown>
{/if}
</div>
</div>
{/if}
<div>
<p class="invisible hidden font-mono text-xs md:block">Settings</p>
<div class="not-prose my-1.5 flex">
<Dropdown
btnLabel=""
classNames="hidden md:block"
noBtnClass
useDeprecatedJS={false}
forceMenuAlignement="right"
>
<slot slot="button">
<button
class="text-md hover:shadow-xs flex cursor-pointer select-none items-center rounded-lg border px-1.5 py-1 leading-none text-gray-500 opacity-90 hover:text-gray-700 dark:hover:text-gray-200"
type="button"
title="Settings dropdown"
>
<IconSettings classNames="mr-1" />
Settings
</button>
</slot>
<slot slot="menu">
<div class="flex flex-col gap-y-2 p-2">
{#if model.tags.includes("conversational")}
<button
class="text-md do-not-close-dropdown group relative flex w-full cursor-default items-center gap-x-2 self-start border-b pb-2 leading-tight"
on:click={() => (streaming = !streaming)}
type="button"
>
<input
class="form-input not-prose do-not-close-dropdown"
type="checkbox"
bind:checked={streaming}
id="stream-checkbox"
/>
<span class="do-not-close-dropdown">Stream</span>
</button>
{/if}
<a
href="https://huggingface.co/settings/tokens"
class="flex items-center gap-x-1 whitespace-nowrap"
target="_blank"
title="Tokens settings"
>
<IconLinkExternal /> Manage tokens
</a>
<a
href="https://huggingface.co/settings/inference-providers"
class="flex items-center gap-x-1 whitespace-nowrap"
title="Inference providers settings"
target="_blank"
>
<IconLinkExternal /> Manage providers
</a>
</div>
</slot>
</Dropdown>
<Dropdown
classNames="md:hidden"
noBtnClass
useDeprecatedJS={false}
forceMenuAlignement="left"
>
<slot slot="button">
<button
class="text-md hover:shadow-xs flex cursor-pointer select-none items-center rounded-lg border px-1.5 py-1 leading-none text-gray-500 opacity-90 hover:text-gray-700 dark:hover:text-gray-200"
type="button"
title="Settings dropdown"
>
<IconSettings classNames="mr-1" />
Settings
</button>
</slot>
<slot slot="menu">
<div class="flex flex-col gap-y-2 p-2">
{#if model.tags.includes("conversational")}
<button
class="text-md do-not-close-dropdown group relative flex w-full cursor-default items-center gap-x-2 self-start border-b pb-2 leading-tight"
on:click={() => (streaming = !streaming)}
type="button"
>
<input
class="form-input not-prose do-not-close-dropdown"
type="checkbox"
bind:checked={streaming}
/>
<span class="do-not-close-dropdown">Stream</span>
</button>
{/if}
<a
href="/settings/tokens"
class="flex items-center gap-x-1 whitespace-nowrap"
target="_blank"
title="Tokens settings"
>
<IconLinkExternal /> Manage tokens
</a>
<a
href="/settings/inference-providers"
class="flex items-center gap-x-1 whitespace-nowrap"
title="Inference providers settings"
target="_blank"
>
<IconLinkExternal /> Manage providers
</a>
</div>
</slot>
</Dropdown>
<div class="flex-grow md:hidden" />
</div>
</div>
</div>
{#if code}
<CodeBlock code={base64(code)} highlighted={hljs.highlight(selectedLanguage, code, true).value} />
{/if}