<script lang="ts"> import hljs from 'highlight.js/lib/core'; import javascript from 'highlight.js/lib/languages/javascript'; import python from 'highlight.js/lib/languages/python'; import http from 'highlight.js/lib/languages/http'; import type { Conversation } from '$lib/types'; import IconCopyCode from '../Icons/IconCopyCode.svelte'; import { onDestroy } from 'svelte'; hljs.registerLanguage('javascript', javascript); hljs.registerLanguage('python', python); hljs.registerLanguage('http', http); export let conversation: Conversation; const lanuages = ['javascript', 'python', 'http']; type Language = (typeof lanuages)[number]; const labelsByLanguage: Record<Language, string> = { javascript: 'JavaScript', python: 'Python', http: 'Curl' }; interface Snippet { label: string; code: string; language?: Language; } $: snippetsByLanguage = { javascript: getJavascriptSnippets(conversation), python: getPythonSnippets(conversation), http: getHttpSnippets(conversation) }; let selectedLanguage: Language = 'javascript'; let timeout: ReturnType<typeof setTimeout>; function getMessages() { const placeholder = [{ role: 'user', content: 'Tell me a story' }]; let messages = conversation.messages; if (messages.length === 1 && messages[0].role === 'user' && !messages[0].content) { messages = placeholder; } return messages; } function highlight(code: string, language: Language) { return hljs.highlight(code, { language }).value; } function getJavascriptSnippets(conversation: Conversation) { const formattedMessages = ({ sep, start, end }) => start + getMessages() .map(({ role, content }) => `{ role: "${role}", content: "${content}" }`) .join(sep) + end; const formattedConfig = ({ sep, start, end }) => start + Object.entries(conversation.config) .map(([key, val]) => `${key}: ${val}`) .join(sep) + end; const snippets: Snippet[] = []; snippets.push({ label: 'Install @huggingface/inference', language: 'http', code: `npm install --save @huggingface/inference` }); if (conversation.streaming) { snippets.push({ label: 'Streaming API', code: `import { HfInference } from "@huggingface/inference" const inference = new HfInference("your HF token") let out = ""; for await (const chunk of inference.chatCompletionStream({ model: "${conversation.model.id}", messages: ${formattedMessages({ sep: ',\n ', start: '[\n ', end: '\n ]' })}, ${formattedConfig({ sep: ',\n ', start: '', end: '' })}, seed: 0, })) { if (chunk.choices && chunk.choices.length > 0) { const newContent = chunk.choices[0].delta.content; out += newContent; console.clear(); console.log(out); } }` }); } else { // non-streaming snippets.push({ label: 'Non-Streaming API', code: `import { HfInference } from '@huggingface/inference' const inference = new HfInference("your access token") const out = await inference.chatCompletion({ model: "${conversation.model.id}", messages: ${formattedMessages({ sep: ',\n ', start: '[\n ', end: '\n ]' })}, ${formattedConfig({ sep: ',\n ', start: '', end: '' })}, seed: 0, }); console.log(out.choices[0].message);` }); } return snippets; } function getPythonSnippets(conversation: Conversation) { const formattedMessages = ({ sep, start, end }) => start + getMessages() .map(({ role, content }) => `{ "role": "${role}", "content": "${content}" }`) .join(sep) + end; const formattedConfig = ({ sep, start, end }) => start + Object.entries(conversation.config) .map(([key, val]) => `${key}: ${val}`) .join(sep) + end; const snippets: Snippet[] = []; snippets.push({ label: 'Install huggingface_hub', language: 'http', code: `pip install huggingface_hub` }); if (conversation.streaming) { snippets.push({ label: 'Streaming API', code: `from huggingface_hub import InferenceClient model_id="${conversation.model.id}" hf_token = "your HF token" inference_client = InferenceClient(model_id, token=hf_token) output = "" messages = ${formattedMessages({ sep: ',\n ', start: `[\n `, end: `\n]` })} for token in client.chat_completion(messages, stream=True, ${formattedConfig({ sep: ', ', start: '', end: '' })}): new_content = token.choices[0].delta.content print(new_content, end="") output += new_content` }); } else { // non-streaming snippets.push({ label: 'Non-Streaming API', code: `from huggingface_hub import InferenceClient model_id="${conversation.model.id}" hf_token = "your HF token" inference_client = InferenceClient(model_id, token=hf_token) messages = ${formattedMessages({ sep: ',\n ', start: `[\n `, end: `\n]` })} output = inference_client.chat_completion(messages, ${formattedConfig({ sep: ', ', start: '', end: '' })}) print(output.choices[0].message)` }); } return snippets; } function getHttpSnippets(conversation: Conversation) { const formattedMessages = ({ sep, start, end }) => start + getMessages() .map(({ role, content }) => `{ "role": "${role}", "content": "${content}" }`) .join(sep) + end; const formattedConfig = ({ sep, start, end }) => start + Object.entries(conversation.config) .map(([key, val]) => `"${key}": ${val}`) .join(sep) + end; const snippets: Snippet[] = []; if (conversation.streaming) { snippets.push({ label: 'Streaming API', code: `curl 'https://api-inference.huggingface.co/models/${conversation.model.id}/v1/chat/completions' \\ --header "Authorization: Bearer {YOUR_HF_TOKEN}" \\ --header 'Content-Type: application/json' \\ --data '{ "model": "meta-llama/Meta-Llama-3-8B-Instruct", "messages": ${formattedMessages({ sep: ',\n ', start: `[\n `, end: `\n]` })}, ${formattedConfig({ sep: ',\n ', start: '', end: '' })}, "stream": true }'` }); } else { // non-streaming snippets.push({ label: 'Non-Streaming API', code: `curl 'https://api-inference.huggingface.co/models/${conversation.model.id}/v1/chat/completions' \\ --header "Authorization: Bearer {YOUR_HF_TOKEN}" \\ --header 'Content-Type: application/json' \\ --data '{ "model": "meta-llama/Meta-Llama-3-8B-Instruct", "messages": ${formattedMessages({ sep: ',\n ', start: `[\n `, end: `\n]` })}, ${formattedConfig({ sep: ',\n ', start: '', end: '' })} }'` }); } return snippets; } onDestroy(() => { if (timeout) { clearTimeout(timeout); } }); </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 Object.entries(labelsByLanguage) as [language, label]} <li> <button on:click={() => (selectedLanguage = language)} class="inline-block rounded-t-lg border-b-2 p-4 {language === selectedLanguage ? '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} </ul> </div> {#each snippetsByLanguage[selectedLanguage] as { label, code, language }} <div class="flex items-center justify-between px-4 pb-4 pt-6"> <h2 class="font-semibold">{label}</h2> <button class="flex items-center gap-x-1.5 rounded-md bg-gray-200 px-1.5 py-0.5 transition dark:bg-gray-950 text-sm" on:click={(e) => { const el = e.currentTarget; el.classList.add('text-green-500'); navigator.clipboard.writeText(code); if (timeout) { clearTimeout(timeout); } timeout = setTimeout(() => { el.classList.remove('text-green-500'); }, 1000); }} > <IconCopyCode /> Copy code </button> </div> <pre class="overflow-x-auto rounded-lg border border-gray-200/80 bg-white px-4 py-6 text-sm shadow-sm dark:border-gray-800 dark:bg-gray-800/50">{@html highlight( code, language ?? selectedLanguage )}</pre> {/each} </div>