inference-playground
/
src
/lib
/components
/InferencePlayground
/InferencePlaygroundCodeSnippets.svelte
<script lang="ts"> | |
import type { Conversation } from "$lib/types"; | |
import hljs from "highlight.js/lib/core"; | |
import http from "highlight.js/lib/languages/http"; | |
import javascript from "highlight.js/lib/languages/javascript"; | |
import python from "highlight.js/lib/languages/python"; | |
import { createEventDispatcher } from "svelte"; | |
import { token } from "$lib/stores/token"; | |
import { entries, fromEntries, keys } from "$lib/utils/object"; | |
import type { InferenceProvider } from "@huggingface/inference"; | |
import IconCopyCode from "~icons/carbon/copy"; | |
import IconExternal from "~icons/carbon/arrow-up-right"; | |
import { | |
getInferenceSnippet, | |
type GetInferenceSnippetReturn, | |
type InferenceSnippetLanguage, | |
} from "./inferencePlaygroundUtils"; | |
hljs.registerLanguage("javascript", javascript); | |
hljs.registerLanguage("python", python); | |
hljs.registerLanguage("http", http); | |
export let conversation: Conversation; | |
const dispatch = createEventDispatcher<{ closeCode: void }>(); | |
const labelsByLanguage = { | |
javascript: "JavaScript", | |
python: "Python", | |
http: "cURL", | |
} as const satisfies Record<string, string>; | |
type Language = keyof typeof labelsByLanguage; | |
let lang: Language = "javascript"; | |
let showToken = false; | |
$: tokenStr = getTokenStr(showToken); | |
type GetSnippetArgs = { | |
tokenStr: string; | |
conversation: Conversation; | |
lang: InferenceSnippetLanguage; | |
}; | |
function getSnippet({ tokenStr, conversation, lang }: GetSnippetArgs) { | |
return getInferenceSnippet(conversation.model, conversation.provider as InferenceProvider, lang, tokenStr, { | |
messages: conversation.messages, | |
streaming: conversation.streaming, | |
max_tokens: conversation.config.max_tokens, | |
temperature: conversation.config.temperature, | |
top_p: conversation.config.top_p, | |
}); | |
} | |
$: snippetsByLang = { | |
javascript: getSnippet({ lang: "js", tokenStr, conversation }), | |
python: getSnippet({ lang: "python", tokenStr, conversation }), | |
http: getSnippet({ lang: "curl", tokenStr, conversation }), | |
} as Record<Language, GetInferenceSnippetReturn>; | |
// { javascript: 0, python: 0, http: 0 } at first | |
const selectedSnippetIdxByLang: Record<Language, number> = fromEntries( | |
keys(labelsByLanguage).map(lang => { | |
return [lang, 0]; | |
}) | |
); | |
$: selectedSnippet = snippetsByLang[lang][selectedSnippetIdxByLang[lang]]; | |
type InstallInstructions = { | |
title: string; | |
content: string; | |
docs: string; | |
}; | |
$: installInstructions = (function getInstallInstructions(): InstallInstructions | undefined { | |
if (lang === "javascript") { | |
const isHugging = selectedSnippet?.client.includes("hugging"); | |
const toInstall = isHugging ? "@huggingface/inference" : "openai"; | |
const docs = isHugging | |
? "https://huggingface.co/docs/huggingface.js/inference/README" | |
: "https://platform.openai.com/docs/libraries"; | |
return { | |
title: `Install ${toInstall}`, | |
content: `npm install --save ${toInstall}`, | |
docs, | |
}; | |
} else if (lang === "python") { | |
const isHugging = selectedSnippet?.client.includes("hugging"); | |
const toInstall = isHugging ? "huggingface_hub" : "openai"; | |
const docs = isHugging | |
? "https://huggingface.co/docs/huggingface_hub/guides/inference" | |
: "https://platform.openai.com/docs/libraries"; | |
return { | |
title: `Install the latest`, | |
content: `pip install --upgrade ${toInstall}`, | |
docs, | |
}; | |
} | |
})(); | |
function getTokenStr(showToken: boolean) { | |
if ($token.value && showToken) { | |
return $token.value; | |
} | |
return "YOUR_HF_TOKEN"; | |
} | |
function highlight(code?: string, language?: InferenceSnippetLanguage) { | |
if (!code || !language) return ""; | |
return hljs.highlight(code, { language: language === "curl" ? "http" : language }).value; | |
} | |
function copy(el: HTMLElement, _content?: string) { | |
let timeout: ReturnType<typeof setTimeout>; | |
let content = _content ?? ""; | |
function update(_content?: string) { | |
content = _content ?? ""; | |
} | |
function onClick() { | |
el.classList.add("text-green-500"); | |
navigator.clipboard.writeText(content); | |
clearTimeout(timeout); | |
timeout = setTimeout(() => { | |
el.classList.remove("text-green-500"); | |
}, 400); | |
} | |
el.addEventListener("click", onClick); | |
return { | |
update, | |
destroy() { | |
clearTimeout(timeout); | |
el.removeEventListener("click", onClick); | |
}, | |
}; | |
} | |
</script> | |
<div class="px-2 pt-2"> | |
<div | |
class="border-b border-gray-200 text-center text-sm font-medium text-gray-500 dark:border-gray-700 dark:text-gray-400" | |
> | |
<ul class="-mb-px flex flex-wrap"> | |
{#each entries(labelsByLanguage) as [language, label]} | |
<li> | |
<button | |
on:click={() => (lang = language)} | |
class="inline-block rounded-t-lg border-b-2 p-4 {lang === language | |
? 'border-black text-black dark:border-blue-500 dark:text-blue-500' | |
: 'border-transparent hover:border-gray-300 hover:text-gray-600 dark:hover:text-gray-300'}" | |
aria-current="page">{label}</button | |
> | |
</li> | |
{/each} | |
<li class="ml-auto self-center max-sm:hidden"> | |
<button | |
on:click={() => { | |
dispatch("closeCode"); | |
}} | |
class="flex size-7 items-center justify-center rounded-lg px-3 py-2.5 text-xs font-medium text-gray-900 focus:ring-4 focus:ring-gray-100 focus:outline-hidden dark:border-gray-600 dark:bg-gray-800 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white dark:focus:ring-gray-700" | |
> | |
✕ | |
</button> | |
</li> | |
</ul> | |
</div> | |
{#if (snippetsByLang[lang]?.length ?? 0) > 1} | |
<div class="flex gap-x-2 px-2 pt-6"> | |
{#each snippetsByLang[lang] ?? [] as { client }, idx} | |
{@const isActive = idx === selectedSnippetIdxByLang[lang]} | |
<button | |
class="rounded-lg border px-1.5 py-0.5 text-sm leading-tight | |
{isActive | |
? 'bg-black text-gray-100 dark:border-gray-500 dark:bg-gray-700 dark:text-white' | |
: 'text-gray-500 hover:text-gray-600 dark:border-gray-600 dark:hover:text-gray-400'}" | |
on:click={() => (selectedSnippetIdxByLang[lang] = idx)}>{client}</button | |
> | |
{/each} | |
</div> | |
{/if} | |
{#if installInstructions} | |
<div class="flex items-center justify-between px-2 pt-6 pb-4"> | |
<h2 class="flex items-baseline gap-2 font-semibold"> | |
{installInstructions.title} | |
<a | |
href={installInstructions.docs} | |
target="_blank" | |
class="relative -bottom-[1px] flex items-center gap-1 text-sm font-normal text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300" | |
> | |
<IconExternal class="text-xs" /> | |
Docs | |
</a> | |
</h2> | |
<div class="flex items-center gap-x-4"> | |
<button | |
class="flex items-center gap-x-2 rounded-md border bg-white px-1.5 py-0.5 text-sm shadow-xs transition dark:border-gray-800 dark:bg-gray-800" | |
use:copy={installInstructions.content} | |
> | |
<IconCopyCode class="text-2xs" /> Copy code | |
</button> | |
</div> | |
</div> | |
<pre | |
class="overflow-x-auto rounded-lg border border-gray-200/80 bg-white px-4 py-6 text-sm shadow-xs dark:border-gray-800 dark:bg-gray-800/50">{@html highlight( | |
installInstructions.content, | |
selectedSnippet?.language | |
)}</pre> | |
{/if} | |
<div class="flex items-center justify-between px-2 pt-6 pb-4"> | |
{#if conversation.streaming} | |
<h2 class="font-semibold">Streaming API</h2> | |
{:else} | |
<h2 class="font-semibold">Non-Streaming API</h2> | |
{/if} | |
<div class="flex items-center gap-x-4"> | |
<label class="flex items-center gap-x-1.5 text-sm select-none"> | |
<input type="checkbox" bind:checked={showToken} /> | |
<p class="leading-none">With token</p> | |
</label> | |
<button | |
class="flex items-center gap-x-2 rounded-md border bg-white px-1.5 py-0.5 text-sm shadow-xs transition dark:border-gray-800 dark:bg-gray-800" | |
use:copy={selectedSnippet?.content} | |
> | |
<IconCopyCode class="text-2xs" /> Copy code | |
</button> | |
</div> | |
</div> | |
<pre | |
class="overflow-x-auto rounded-lg border border-gray-200/80 bg-white px-4 py-6 text-sm shadow-xs dark:border-gray-800 dark:bg-gray-800/50">{@html highlight( | |
selectedSnippet?.content, | |
selectedSnippet?.language | |
)}</pre> | |
</div> | |