Support OAI clients in code snippets
Browse files
src/lib/components/InferencePlayground/InferencePlaygroundCodeSnippets.svelte
CHANGED
@@ -32,6 +32,11 @@
|
|
32 |
needsToken?: boolean;
|
33 |
}
|
34 |
|
|
|
|
|
|
|
|
|
|
|
35 |
interface MessagesJoiner {
|
36 |
sep: string;
|
37 |
start: string;
|
@@ -44,12 +49,19 @@
|
|
44 |
|
45 |
$: tokenStr = getTokenStr(showToken);
|
46 |
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
53 |
|
54 |
function getTokenStr(showToken: boolean) {
|
55 |
if (hfToken && showToken) {
|
@@ -83,7 +95,7 @@
|
|
83 |
return hljs.highlight(code, { language }).value;
|
84 |
}
|
85 |
|
86 |
-
function
|
87 |
const formattedMessages = ({ sep, start, end }: MessagesJoiner) =>
|
88 |
start +
|
89 |
getMessages()
|
@@ -148,7 +160,79 @@ console.log(out.choices[0].message);`,
|
|
148 |
return snippets;
|
149 |
}
|
150 |
|
151 |
-
function
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
152 |
const formattedMessages = ({ sep, start, end }: MessagesJoiner) =>
|
153 |
start +
|
154 |
getMessages()
|
@@ -196,7 +280,6 @@ for chunk in output:
|
|
196 |
needsToken: true,
|
197 |
code: `from huggingface_hub import InferenceClient
|
198 |
|
199 |
-
model_id="${conversation.model.id}"
|
200 |
client = InferenceClient(api_key="${tokenStr}")
|
201 |
|
202 |
messages = ${formattedMessages({ sep: ",\n\t", start: `[\n\t`, end: `\n]` })}
|
@@ -207,6 +290,77 @@ output = client.chat.completions.create(
|
|
207 |
${formattedConfig({ sep: ",\n\t", start: "", end: "", connector: "=" })}
|
208 |
)
|
209 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
210 |
print(output.choices[0].message)`,
|
211 |
});
|
212 |
}
|
@@ -297,38 +451,55 @@ print(output.choices[0].message)`,
|
|
297 |
</ul>
|
298 |
</div>
|
299 |
|
300 |
-
{#
|
301 |
-
<div class="flex
|
302 |
-
|
303 |
-
<div class="flex items-center gap-x-4">
|
304 |
-
{#if needsToken && hfToken}
|
305 |
-
<label class="flex select-none items-center gap-x-1.5 text-sm">
|
306 |
-
<input type="checkbox" bind:checked={showToken} />
|
307 |
-
<p class="leading-none">With token</p>
|
308 |
-
</label>
|
309 |
-
{/if}
|
310 |
<button
|
311 |
-
class="
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
navigator.clipboard.writeText(code);
|
316 |
-
if (timeout) {
|
317 |
-
clearTimeout(timeout);
|
318 |
-
}
|
319 |
-
timeout = setTimeout(() => {
|
320 |
-
el.classList.remove("text-green-500");
|
321 |
-
}, 400);
|
322 |
-
}}
|
323 |
>
|
324 |
-
|
325 |
-
</button>
|
326 |
-
</div>
|
327 |
</div>
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
333 |
{/each}
|
334 |
</div>
|
|
|
32 |
needsToken?: boolean;
|
33 |
}
|
34 |
|
35 |
+
interface ClientSnippet {
|
36 |
+
name: string;
|
37 |
+
snippets: Snippet[];
|
38 |
+
}
|
39 |
+
|
40 |
interface MessagesJoiner {
|
41 |
sep: string;
|
42 |
start: string;
|
|
|
49 |
|
50 |
$: tokenStr = getTokenStr(showToken);
|
51 |
|
52 |
+
$: clientSnippetsByLang = {
|
53 |
+
javascript: [
|
54 |
+
{ name: "@huggingface/inference", snippets: getJavascriptSnippetsHfClient(conversation, tokenStr) },
|
55 |
+
{ name: "openai", snippets: getJavascriptSnippetsOAIClient(conversation, tokenStr) },
|
56 |
+
],
|
57 |
+
python: [
|
58 |
+
{ name: "huggingface_hub", snippets: getPythonSnippetsHfClient(conversation, tokenStr) },
|
59 |
+
{ name: "openai", snippets: getPythonSnippetsOAIClient(conversation, tokenStr) },
|
60 |
+
],
|
61 |
+
http: [{ name: "curl", snippets: getHttpSnippets(conversation, tokenStr) }],
|
62 |
+
} as Record<Language, ClientSnippet[]>;
|
63 |
+
|
64 |
+
const selectedClientIdxByLang: Record<Language, number> = Object.fromEntries(lanuages.map(lang => [lang, 0]));
|
65 |
|
66 |
function getTokenStr(showToken: boolean) {
|
67 |
if (hfToken && showToken) {
|
|
|
95 |
return hljs.highlight(code, { language }).value;
|
96 |
}
|
97 |
|
98 |
+
function getJavascriptSnippetsHfClient(conversation: Conversation, tokenStr: string) {
|
99 |
const formattedMessages = ({ sep, start, end }: MessagesJoiner) =>
|
100 |
start +
|
101 |
getMessages()
|
|
|
160 |
return snippets;
|
161 |
}
|
162 |
|
163 |
+
function getJavascriptSnippetsOAIClient(conversation: Conversation, tokenStr: string) {
|
164 |
+
const formattedMessages = ({ sep, start, end }: MessagesJoiner) =>
|
165 |
+
start +
|
166 |
+
getMessages()
|
167 |
+
.map(({ role, content }) => `{ role: "${role}", content: "${content}" }`)
|
168 |
+
.join(sep) +
|
169 |
+
end;
|
170 |
+
|
171 |
+
const formattedConfig = ({ sep, start, end }: MessagesJoiner) =>
|
172 |
+
start +
|
173 |
+
Object.entries(conversation.config)
|
174 |
+
.map(([key, val]) => `${key}: ${val}`)
|
175 |
+
.join(sep) +
|
176 |
+
end;
|
177 |
+
|
178 |
+
const snippets: Snippet[] = [];
|
179 |
+
snippets.push({
|
180 |
+
label: "Install openai",
|
181 |
+
language: "http",
|
182 |
+
code: `npm install --save openai`,
|
183 |
+
});
|
184 |
+
if (conversation.streaming) {
|
185 |
+
snippets.push({
|
186 |
+
label: "Streaming API",
|
187 |
+
needsToken: true,
|
188 |
+
code: `import { OpenAI } from "openai"
|
189 |
+
|
190 |
+
const client = new OpenAI({
|
191 |
+
baseURL: "https://api-inference.huggingface.co/models/${conversation.model.id}/v1/",
|
192 |
+
apiKey: "${tokenStr}"
|
193 |
+
})
|
194 |
+
|
195 |
+
let out = "";
|
196 |
+
|
197 |
+
for await (const chunk of await client.chat.completions.create({
|
198 |
+
model: "${conversation.model.id}",
|
199 |
+
messages: ${formattedMessages({ sep: ",\n\t", start: "[\n\t", end: "\n ]" })},
|
200 |
+
${formattedConfig({ sep: ",\n ", start: "", end: "" })},
|
201 |
+
stream: true,
|
202 |
+
})) {
|
203 |
+
if (chunk.choices && chunk.choices.length > 0) {
|
204 |
+
const newContent = chunk.choices[0].delta.content;
|
205 |
+
out += newContent;
|
206 |
+
console.log(newContent);
|
207 |
+
}
|
208 |
+
}`,
|
209 |
+
});
|
210 |
+
} else {
|
211 |
+
// non-streaming
|
212 |
+
snippets.push({
|
213 |
+
label: "Non-Streaming API",
|
214 |
+
needsToken: true,
|
215 |
+
code: `import { OpenAI } from "openai"
|
216 |
+
|
217 |
+
const client = new OpenAI({
|
218 |
+
baseURL: "https://api-inference.huggingface.co/models/${conversation.model.id}/v1/",
|
219 |
+
apiKey: "${tokenStr}"
|
220 |
+
})
|
221 |
+
|
222 |
+
const out = await client.chat.completions.create({
|
223 |
+
model: "${conversation.model.id}",
|
224 |
+
messages: ${formattedMessages({ sep: ",\n\t\t", start: "[\n\t\t", end: "\n\t]" })},
|
225 |
+
${formattedConfig({ sep: ",\n\t", start: "", end: "" })}
|
226 |
+
});
|
227 |
+
|
228 |
+
console.log(out.choices[0].message);`,
|
229 |
+
});
|
230 |
+
}
|
231 |
+
|
232 |
+
return snippets;
|
233 |
+
}
|
234 |
+
|
235 |
+
function getPythonSnippetsHfClient(conversation: Conversation, tokenStr: string) {
|
236 |
const formattedMessages = ({ sep, start, end }: MessagesJoiner) =>
|
237 |
start +
|
238 |
getMessages()
|
|
|
280 |
needsToken: true,
|
281 |
code: `from huggingface_hub import InferenceClient
|
282 |
|
|
|
283 |
client = InferenceClient(api_key="${tokenStr}")
|
284 |
|
285 |
messages = ${formattedMessages({ sep: ",\n\t", start: `[\n\t`, end: `\n]` })}
|
|
|
290 |
${formattedConfig({ sep: ",\n\t", start: "", end: "", connector: "=" })}
|
291 |
)
|
292 |
|
293 |
+
print(output.choices[0].message)`,
|
294 |
+
});
|
295 |
+
}
|
296 |
+
|
297 |
+
return snippets;
|
298 |
+
}
|
299 |
+
|
300 |
+
function getPythonSnippetsOAIClient(conversation: Conversation, tokenStr: string) {
|
301 |
+
const formattedMessages = ({ sep, start, end }: MessagesJoiner) =>
|
302 |
+
start +
|
303 |
+
getMessages()
|
304 |
+
.map(({ role, content }) => `{ "role": "${role}", "content": "${content}" }`)
|
305 |
+
.join(sep) +
|
306 |
+
end;
|
307 |
+
|
308 |
+
const formattedConfig = ({ sep, start, end, connector }: MessagesJoiner & { connector: string }) =>
|
309 |
+
start +
|
310 |
+
Object.entries(conversation.config)
|
311 |
+
.map(([key, val]) => `${key}${connector}${val}`)
|
312 |
+
.join(sep) +
|
313 |
+
end;
|
314 |
+
|
315 |
+
const snippets: Snippet[] = [];
|
316 |
+
snippets.push({
|
317 |
+
label: "Install the latest openai",
|
318 |
+
language: "http",
|
319 |
+
code: `pip install openai --upgrade`,
|
320 |
+
});
|
321 |
+
if (conversation.streaming) {
|
322 |
+
snippets.push({
|
323 |
+
label: "Streaming API",
|
324 |
+
needsToken: true,
|
325 |
+
code: `from openai import OpenAI
|
326 |
+
|
327 |
+
client = OpenAI(
|
328 |
+
base_url="https://api-inference.huggingface.co/models/${conversation.model.id}/v1/",
|
329 |
+
api_key="${tokenStr}"
|
330 |
+
)
|
331 |
+
|
332 |
+
messages = ${formattedMessages({ sep: ",\n\t", start: `[\n\t`, end: `\n]` })}
|
333 |
+
|
334 |
+
output = client.chat.completions.create(
|
335 |
+
model="${conversation.model.id}",
|
336 |
+
messages=messages,
|
337 |
+
stream=True,
|
338 |
+
${formattedConfig({ sep: ",\n\t", start: "", end: "", connector: "=" })}
|
339 |
+
)
|
340 |
+
|
341 |
+
for chunk in output:
|
342 |
+
print(chunk.choices[0].delta.content)`,
|
343 |
+
});
|
344 |
+
} else {
|
345 |
+
// non-streaming
|
346 |
+
snippets.push({
|
347 |
+
label: "Non-Streaming API",
|
348 |
+
needsToken: true,
|
349 |
+
code: `from openai import OpenAI
|
350 |
+
|
351 |
+
client = OpenAI(
|
352 |
+
base_url="https://api-inference.huggingface.co/models/${conversation.model.id}/v1/",
|
353 |
+
api_key="${tokenStr}"
|
354 |
+
)
|
355 |
+
|
356 |
+
messages = ${formattedMessages({ sep: ",\n\t", start: `[\n\t`, end: `\n]` })}
|
357 |
+
|
358 |
+
output = client.chat.completions.create(
|
359 |
+
model="${conversation.model.id}",
|
360 |
+
messages=messages,
|
361 |
+
${formattedConfig({ sep: ",\n\t", start: "", end: "", connector: "=" })}
|
362 |
+
)
|
363 |
+
|
364 |
print(output.choices[0].message)`,
|
365 |
});
|
366 |
}
|
|
|
451 |
</ul>
|
452 |
</div>
|
453 |
|
454 |
+
{#if clientSnippetsByLang[selectedLanguage].length > 1}
|
455 |
+
<div class="flex gap-x-2 px-2 pt-6">
|
456 |
+
{#each clientSnippetsByLang[selectedLanguage] as { name }, idx}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
457 |
<button
|
458 |
+
class="rounded-md px-2 py-1 {idx === selectedClientIdxByLang[selectedLanguage]
|
459 |
+
? 'bg-black text-white dark:bg-white dark:text-black'
|
460 |
+
: ''}"
|
461 |
+
on:click={() => (selectedClientIdxByLang[selectedLanguage] = idx)}>{name}</button
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
462 |
>
|
463 |
+
{/each}
|
|
|
|
|
464 |
</div>
|
465 |
+
{/if}
|
466 |
+
|
467 |
+
{#each clientSnippetsByLang[selectedLanguage] as { snippets }, idx}
|
468 |
+
{#if idx === selectedClientIdxByLang[selectedLanguage]}
|
469 |
+
{#each snippets as { label, code, language, needsToken }}
|
470 |
+
<div class="flex items-center justify-between px-2 pb-4 pt-6">
|
471 |
+
<h2 class="font-semibold">{label}</h2>
|
472 |
+
<div class="flex items-center gap-x-4">
|
473 |
+
{#if needsToken && hfToken}
|
474 |
+
<label class="flex select-none items-center gap-x-1.5 text-sm">
|
475 |
+
<input type="checkbox" bind:checked={showToken} />
|
476 |
+
<p class="leading-none">With token</p>
|
477 |
+
</label>
|
478 |
+
{/if}
|
479 |
+
<button
|
480 |
+
class="flex items-center gap-x-2 rounded-md border bg-white px-1.5 py-0.5 text-sm shadow-sm transition dark:border-gray-800 dark:bg-gray-800"
|
481 |
+
on:click={e => {
|
482 |
+
const el = e.currentTarget;
|
483 |
+
el.classList.add("text-green-500");
|
484 |
+
navigator.clipboard.writeText(code);
|
485 |
+
if (timeout) {
|
486 |
+
clearTimeout(timeout);
|
487 |
+
}
|
488 |
+
timeout = setTimeout(() => {
|
489 |
+
el.classList.remove("text-green-500");
|
490 |
+
}, 400);
|
491 |
+
}}
|
492 |
+
>
|
493 |
+
<IconCopyCode classNames="text-xs" /> Copy code
|
494 |
+
</button>
|
495 |
+
</div>
|
496 |
+
</div>
|
497 |
+
<pre
|
498 |
+
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(
|
499 |
+
code,
|
500 |
+
language ?? selectedLanguage
|
501 |
+
)}</pre>
|
502 |
+
{/each}
|
503 |
+
{/if}
|
504 |
{/each}
|
505 |
</div>
|