Fix theme and fouc (#58)
Browse files- .env.example +1 -0
- .github/workflows/lint-and-test.yml +20 -8
- .prettierignore +14 -0
- Dockerfile +9 -6
- README.md +6 -4
- package-lock.json +0 -0
- package.json +4 -3
- pnpm-lock.yaml +0 -0
- src/app.html +32 -0
- src/lib/components/InferencePlayground/InferencePlayground.svelte +13 -14
- src/lib/components/InferencePlayground/InferencePlaygroundCodeSnippets.svelte +13 -12
- src/lib/components/InferencePlayground/InferencePlaygroundMessage.svelte +2 -2
- src/lib/components/InferencePlayground/inferencePlaygroundUtils.ts +8 -11
- src/lib/components/InferencePlayground/types.ts +4 -2
- src/routes/+layout.svelte +1 -39
- src/routes/+page.server.ts +2 -1
.env.example
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
HF_TOKEN=
|
.github/workflows/lint-and-test.yml
CHANGED
@@ -4,24 +4,36 @@ on:
|
|
4 |
push:
|
5 |
branches:
|
6 |
- main
|
7 |
-
|
8 |
jobs:
|
9 |
lint:
|
10 |
runs-on: ubuntu-latest
|
11 |
timeout-minutes: 10
|
12 |
-
|
13 |
steps:
|
14 |
- uses: actions/checkout@v3
|
15 |
-
|
16 |
- uses: actions/setup-node@v3
|
17 |
with:
|
18 |
node-version: "20"
|
19 |
-
|
20 |
-
|
21 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
- name: "Checking lint/format errors"
|
23 |
run: |
|
24 |
-
|
25 |
- name: "Checking type errors"
|
26 |
run: |
|
27 |
-
|
|
|
4 |
push:
|
5 |
branches:
|
6 |
- main
|
|
|
7 |
jobs:
|
8 |
lint:
|
9 |
runs-on: ubuntu-latest
|
10 |
timeout-minutes: 10
|
|
|
11 |
steps:
|
12 |
- uses: actions/checkout@v3
|
|
|
13 |
- uses: actions/setup-node@v3
|
14 |
with:
|
15 |
node-version: "20"
|
16 |
+
- name: Install pnpm
|
17 |
+
uses: pnpm/action-setup@v2
|
18 |
+
with:
|
19 |
+
version: latest
|
20 |
+
run_install: false
|
21 |
+
- name: Get pnpm store directory
|
22 |
+
id: pnpm-cache
|
23 |
+
shell: bash
|
24 |
+
run: |
|
25 |
+
echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
|
26 |
+
- uses: actions/cache@v3
|
27 |
+
with:
|
28 |
+
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
|
29 |
+
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
30 |
+
restore-keys: |
|
31 |
+
${{ runner.os }}-pnpm-store-
|
32 |
+
- name: Install dependencies
|
33 |
+
run: pnpm install --frozen-lockfile
|
34 |
- name: "Checking lint/format errors"
|
35 |
run: |
|
36 |
+
pnpm run lint
|
37 |
- name: "Checking type errors"
|
38 |
run: |
|
39 |
+
pnpm run check
|
.prettierignore
CHANGED
@@ -2,3 +2,17 @@
|
|
2 |
package-lock.json
|
3 |
pnpm-lock.yaml
|
4 |
yarn.lock
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
package-lock.json
|
3 |
pnpm-lock.yaml
|
4 |
yarn.lock
|
5 |
+
.pnpm-store
|
6 |
+
|
7 |
+
.DS_Store
|
8 |
+
node_modules
|
9 |
+
/build
|
10 |
+
/.svelte-kit
|
11 |
+
/package
|
12 |
+
.env
|
13 |
+
.env.*
|
14 |
+
!.env.example
|
15 |
+
|
16 |
+
# Ignore files for PNPM, NPM and YARN
|
17 |
+
pnpm-lock.yaml
|
18 |
+
yarn.lock
|
Dockerfile
CHANGED
@@ -1,22 +1,25 @@
|
|
1 |
FROM node:alpine
|
2 |
|
|
|
|
|
|
|
3 |
# Set the working directory
|
4 |
WORKDIR /app
|
5 |
|
6 |
-
# Copy package.json and pnpm-lock.yaml
|
7 |
-
COPY package.json
|
8 |
|
9 |
# Install all dependencies, including dev dependencies
|
10 |
-
RUN
|
11 |
|
12 |
# Copy the rest of the application code
|
13 |
COPY . .
|
14 |
|
15 |
# Build the application
|
16 |
-
RUN
|
17 |
|
18 |
# Prune dev dependencies
|
19 |
-
RUN
|
20 |
|
21 |
# Set correct permissions
|
22 |
RUN chown -R node:node /app
|
@@ -28,4 +31,4 @@ USER node
|
|
28 |
EXPOSE 3000
|
29 |
|
30 |
# Start the application
|
31 |
-
CMD ["node", "build"]
|
|
|
1 |
FROM node:alpine
|
2 |
|
3 |
+
# Install pnpm
|
4 |
+
RUN npm install -g pnpm
|
5 |
+
|
6 |
# Set the working directory
|
7 |
WORKDIR /app
|
8 |
|
9 |
+
# Copy package.json and pnpm-lock.yaml
|
10 |
+
COPY package.json pnpm-lock.yaml* ./
|
11 |
|
12 |
# Install all dependencies, including dev dependencies
|
13 |
+
RUN pnpm install --frozen-lockfile
|
14 |
|
15 |
# Copy the rest of the application code
|
16 |
COPY . .
|
17 |
|
18 |
# Build the application
|
19 |
+
RUN pnpm run build
|
20 |
|
21 |
# Prune dev dependencies
|
22 |
+
RUN pnpm prune --prod
|
23 |
|
24 |
# Set correct permissions
|
25 |
RUN chown -R node:node /app
|
|
|
31 |
EXPOSE 3000
|
32 |
|
33 |
# Start the application
|
34 |
+
CMD ["node", "build"]
|
README.md
CHANGED
@@ -12,11 +12,13 @@ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-
|
|
12 |
|
13 |
Demo: https://huggingface.co/spaces/huggingface-projects/inference-playground
|
14 |
|
15 |
-
|
16 |
|
17 |
-
```
|
18 |
-
|
19 |
-
HF_TOKEN=your_hf_token
|
20 |
```
|
21 |
|
22 |
get your READ token from http://hf.co/settings/token
|
|
|
|
|
|
12 |
|
13 |
Demo: https://huggingface.co/spaces/huggingface-projects/inference-playground
|
14 |
|
15 |
+
## Local development
|
16 |
|
17 |
+
```sh
|
18 |
+
pnpm i
|
19 |
+
HF_TOKEN=your_hf_token pnpm run dev
|
20 |
```
|
21 |
|
22 |
get your READ token from http://hf.co/settings/token
|
23 |
+
|
24 |
+
Hint: Use antfu's [ni](https://github.com/antfu-collective/ni) and never memorize a package manager again
|
package-lock.json
DELETED
The diff for this file is too large to render.
See raw diff
|
|
package.json
CHANGED
@@ -6,6 +6,7 @@
|
|
6 |
"dev": "vite dev",
|
7 |
"build": "vite build",
|
8 |
"preview": "vite preview",
|
|
|
9 |
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
10 |
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
11 |
"lint": "prettier . --check . && eslint --ext .js,.ts,.svelte src/",
|
@@ -36,9 +37,9 @@
|
|
36 |
},
|
37 |
"type": "module",
|
38 |
"dependencies": {
|
39 |
-
"@huggingface/hub": "^0.
|
40 |
-
"@huggingface/inference": "^
|
41 |
-
"@huggingface/tasks": "^0.
|
42 |
"@tailwindcss/container-queries": "^0.1.1"
|
43 |
}
|
44 |
}
|
|
|
6 |
"dev": "vite dev",
|
7 |
"build": "vite build",
|
8 |
"preview": "vite preview",
|
9 |
+
"prepare": "svelte-kit sync || echo ''",
|
10 |
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
11 |
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
12 |
"lint": "prettier . --check . && eslint --ext .js,.ts,.svelte src/",
|
|
|
37 |
},
|
38 |
"type": "module",
|
39 |
"dependencies": {
|
40 |
+
"@huggingface/hub": "^1.0.1",
|
41 |
+
"@huggingface/inference": "^3.5.1",
|
42 |
+
"@huggingface/tasks": "^0.17.1",
|
43 |
"@tailwindcss/container-queries": "^0.1.1"
|
44 |
}
|
45 |
}
|
pnpm-lock.yaml
ADDED
The diff for this file is too large to render.
See raw diff
|
|
src/app.html
CHANGED
@@ -6,7 +6,39 @@
|
|
6 |
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
7 |
%sveltekit.head%
|
8 |
</head>
|
|
|
9 |
<body data-sveltekit-preload-data="hover" class="dark:bg-gray-900">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10 |
<div style="display: contents">%sveltekit.body%</div>
|
11 |
</body>
|
12 |
</html>
|
|
|
6 |
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
7 |
%sveltekit.head%
|
8 |
</head>
|
9 |
+
|
10 |
<body data-sveltekit-preload-data="hover" class="dark:bg-gray-900">
|
11 |
+
<script>
|
12 |
+
(function () {
|
13 |
+
const urlParams = new URLSearchParams(window.location.search);
|
14 |
+
const theme = urlParams.get("__theme");
|
15 |
+
|
16 |
+
let systemPrefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
|
17 |
+
|
18 |
+
function updateTheme() {
|
19 |
+
if (theme === "dark") {
|
20 |
+
document.body.classList.add("dark");
|
21 |
+
} else if (theme === "light") {
|
22 |
+
document.body.classList.remove("dark");
|
23 |
+
} else if (theme === "system" || theme === null || theme === undefined) {
|
24 |
+
if (systemPrefersDark) {
|
25 |
+
document.body.classList.add("dark");
|
26 |
+
} else {
|
27 |
+
document.body.classList.remove("dark");
|
28 |
+
}
|
29 |
+
}
|
30 |
+
}
|
31 |
+
|
32 |
+
// Initial theme update
|
33 |
+
updateTheme();
|
34 |
+
|
35 |
+
// Listen for system preference changes
|
36 |
+
window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", event => {
|
37 |
+
systemPrefersDark = event.matches;
|
38 |
+
updateTheme();
|
39 |
+
});
|
40 |
+
})();
|
41 |
+
</script>
|
42 |
<div style="display: contents">%sveltekit.body%</div>
|
43 |
</body>
|
44 |
</html>
|
src/lib/components/InferencePlayground/InferencePlayground.svelte
CHANGED
@@ -1,37 +1,36 @@
|
|
1 |
<script lang="ts">
|
2 |
-
import type { Conversation, ModelEntryWithTokenizer, Session } from "./types";
|
3 |
-
import type { ChatCompletionInputMessage } from "@huggingface/tasks";
|
4 |
|
5 |
import { page } from "$app/stores";
|
6 |
import { defaultGenerationConfig } from "./generationConfigSettings";
|
7 |
import {
|
8 |
createHfInference,
|
9 |
-
|
10 |
handleNonStreamingResponse,
|
|
|
11 |
isSystemPromptSupported,
|
12 |
-
FEATURED_MODELS_IDS,
|
13 |
} from "./inferencePlaygroundUtils";
|
14 |
|
|
|
15 |
import { onDestroy, onMount } from "svelte";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
16 |
import GenerationConfig, { defaultSystemMessage } from "./InferencePlaygroundGenerationConfig.svelte";
|
17 |
import HFTokenModal from "./InferencePlaygroundHFTokenModal.svelte";
|
18 |
import ModelSelector from "./InferencePlaygroundModelSelector.svelte";
|
19 |
-
import PlaygroundConversation from "./InferencePlaygroundConversation.svelte";
|
20 |
-
import PlaygroundConversationHeader from "./InferencePlaygroundConversationHeader.svelte";
|
21 |
-
import IconDelete from "../Icons/IconDelete.svelte";
|
22 |
-
import IconCode from "../Icons/IconCode.svelte";
|
23 |
-
import IconInfo from "../Icons/IconInfo.svelte";
|
24 |
-
import IconCompare from "../Icons/IconCompare.svelte";
|
25 |
import ModelSelectorModal from "./InferencePlaygroundModelSelectorModal.svelte";
|
26 |
-
import IconThrashcan from "../Icons/IconThrashcan.svelte";
|
27 |
-
import { goto } from "$app/navigation";
|
28 |
|
29 |
export let models: ModelEntryWithTokenizer[];
|
30 |
|
31 |
-
const startMessageUser:
|
32 |
const modelIdsFromQueryParam = $page.url.searchParams.get("modelId")?.split(",");
|
33 |
const modelsFromQueryParam = modelIdsFromQueryParam?.map(id => models.find(model => model.id === id));
|
34 |
-
const systemMessage:
|
35 |
role: "system",
|
36 |
content: modelIdsFromQueryParam ? (defaultSystemMessage?.[modelIdsFromQueryParam[0]] ?? "") : "",
|
37 |
};
|
|
|
1 |
<script lang="ts">
|
2 |
+
import type { Conversation, ConversationMessage, ModelEntryWithTokenizer, Session } from "./types";
|
|
|
3 |
|
4 |
import { page } from "$app/stores";
|
5 |
import { defaultGenerationConfig } from "./generationConfigSettings";
|
6 |
import {
|
7 |
createHfInference,
|
8 |
+
FEATURED_MODELS_IDS,
|
9 |
handleNonStreamingResponse,
|
10 |
+
handleStreamingResponse,
|
11 |
isSystemPromptSupported,
|
|
|
12 |
} from "./inferencePlaygroundUtils";
|
13 |
|
14 |
+
import { goto } from "$app/navigation";
|
15 |
import { onDestroy, onMount } from "svelte";
|
16 |
+
import IconCode from "../Icons/IconCode.svelte";
|
17 |
+
import IconCompare from "../Icons/IconCompare.svelte";
|
18 |
+
import IconDelete from "../Icons/IconDelete.svelte";
|
19 |
+
import IconInfo from "../Icons/IconInfo.svelte";
|
20 |
+
import IconThrashcan from "../Icons/IconThrashcan.svelte";
|
21 |
+
import PlaygroundConversation from "./InferencePlaygroundConversation.svelte";
|
22 |
+
import PlaygroundConversationHeader from "./InferencePlaygroundConversationHeader.svelte";
|
23 |
import GenerationConfig, { defaultSystemMessage } from "./InferencePlaygroundGenerationConfig.svelte";
|
24 |
import HFTokenModal from "./InferencePlaygroundHFTokenModal.svelte";
|
25 |
import ModelSelector from "./InferencePlaygroundModelSelector.svelte";
|
|
|
|
|
|
|
|
|
|
|
|
|
26 |
import ModelSelectorModal from "./InferencePlaygroundModelSelectorModal.svelte";
|
|
|
|
|
27 |
|
28 |
export let models: ModelEntryWithTokenizer[];
|
29 |
|
30 |
+
const startMessageUser: ConversationMessage = { role: "user", content: "" };
|
31 |
const modelIdsFromQueryParam = $page.url.searchParams.get("modelId")?.split(",");
|
32 |
const modelsFromQueryParam = modelIdsFromQueryParam?.map(id => models.find(model => model.id === id));
|
33 |
+
const systemMessage: ConversationMessage = {
|
34 |
role: "system",
|
35 |
content: modelIdsFromQueryParam ? (defaultSystemMessage?.[modelIdsFromQueryParam[0]] ?? "") : "",
|
36 |
};
|
src/lib/components/InferencePlayground/InferencePlaygroundCodeSnippets.svelte
CHANGED
@@ -85,12 +85,13 @@
|
|
85 |
messages.unshift(systemMessage);
|
86 |
}
|
87 |
|
88 |
-
|
89 |
role,
|
90 |
content: JSON.stringify(content).slice(1, -1),
|
91 |
}));
|
|
|
92 |
|
93 |
-
return
|
94 |
}
|
95 |
|
96 |
function highlight(code: string, language: Language) {
|
@@ -139,7 +140,7 @@ for await (const chunk of stream) {
|
|
139 |
const newContent = chunk.choices[0].delta.content;
|
140 |
out += newContent;
|
141 |
console.log(newContent);
|
142 |
-
}
|
143 |
}`,
|
144 |
});
|
145 |
} else {
|
@@ -210,7 +211,7 @@ for await (const chunk of stream) {
|
|
210 |
const newContent = chunk.choices[0].delta.content;
|
211 |
out += newContent;
|
212 |
console.log(newContent);
|
213 |
-
}
|
214 |
}`,
|
215 |
});
|
216 |
} else {
|
@@ -270,8 +271,8 @@ client = InferenceClient(api_key="${tokenStr}")
|
|
270 |
messages = ${formattedMessages({ sep: ",\n\t", start: `[\n\t`, end: `\n]` })}
|
271 |
|
272 |
stream = client.chat.completions.create(
|
273 |
-
model="${conversation.model.id}",
|
274 |
-
messages=messages,
|
275 |
${formattedConfig({ sep: ",\n\t", start: "", end: "", connector: "=" })},
|
276 |
stream=True
|
277 |
)
|
@@ -291,8 +292,8 @@ client = InferenceClient(api_key="${tokenStr}")
|
|
291 |
messages = ${formattedMessages({ sep: ",\n\t", start: `[\n\t`, end: `\n]` })}
|
292 |
|
293 |
completion = client.chat.completions.create(
|
294 |
-
model="${conversation.model.id}",
|
295 |
-
messages=messages,
|
296 |
${formattedConfig({ sep: ",\n\t", start: "", end: "", connector: "=" })}
|
297 |
)
|
298 |
|
@@ -338,8 +339,8 @@ client = OpenAI(
|
|
338 |
messages = ${formattedMessages({ sep: ",\n\t", start: `[\n\t`, end: `\n]` })}
|
339 |
|
340 |
stream = client.chat.completions.create(
|
341 |
-
model="${conversation.model.id}",
|
342 |
-
messages=messages,
|
343 |
${formattedConfig({ sep: ",\n\t", start: "", end: "", connector: "=" })},
|
344 |
stream=True
|
345 |
)
|
@@ -362,8 +363,8 @@ client = OpenAI(
|
|
362 |
messages = ${formattedMessages({ sep: ",\n\t", start: `[\n\t`, end: `\n]` })}
|
363 |
|
364 |
completion = client.chat.completions.create(
|
365 |
-
model="${conversation.model.id}",
|
366 |
-
messages=messages,
|
367 |
${formattedConfig({ sep: ",\n\t", start: "", end: "", connector: "=" })}
|
368 |
)
|
369 |
|
|
|
85 |
messages.unshift(systemMessage);
|
86 |
}
|
87 |
|
88 |
+
const res = messages.map(({ role, content }) => ({
|
89 |
role,
|
90 |
content: JSON.stringify(content).slice(1, -1),
|
91 |
}));
|
92 |
+
messages = res;
|
93 |
|
94 |
+
return res;
|
95 |
}
|
96 |
|
97 |
function highlight(code: string, language: Language) {
|
|
|
140 |
const newContent = chunk.choices[0].delta.content;
|
141 |
out += newContent;
|
142 |
console.log(newContent);
|
143 |
+
}
|
144 |
}`,
|
145 |
});
|
146 |
} else {
|
|
|
211 |
const newContent = chunk.choices[0].delta.content;
|
212 |
out += newContent;
|
213 |
console.log(newContent);
|
214 |
+
}
|
215 |
}`,
|
216 |
});
|
217 |
} else {
|
|
|
271 |
messages = ${formattedMessages({ sep: ",\n\t", start: `[\n\t`, end: `\n]` })}
|
272 |
|
273 |
stream = client.chat.completions.create(
|
274 |
+
model="${conversation.model.id}",
|
275 |
+
messages=messages,
|
276 |
${formattedConfig({ sep: ",\n\t", start: "", end: "", connector: "=" })},
|
277 |
stream=True
|
278 |
)
|
|
|
292 |
messages = ${formattedMessages({ sep: ",\n\t", start: `[\n\t`, end: `\n]` })}
|
293 |
|
294 |
completion = client.chat.completions.create(
|
295 |
+
model="${conversation.model.id}",
|
296 |
+
messages=messages,
|
297 |
${formattedConfig({ sep: ",\n\t", start: "", end: "", connector: "=" })}
|
298 |
)
|
299 |
|
|
|
339 |
messages = ${formattedMessages({ sep: ",\n\t", start: `[\n\t`, end: `\n]` })}
|
340 |
|
341 |
stream = client.chat.completions.create(
|
342 |
+
model="${conversation.model.id}",
|
343 |
+
messages=messages,
|
344 |
${formattedConfig({ sep: ",\n\t", start: "", end: "", connector: "=" })},
|
345 |
stream=True
|
346 |
)
|
|
|
363 |
messages = ${formattedMessages({ sep: ",\n\t", start: `[\n\t`, end: `\n]` })}
|
364 |
|
365 |
completion = client.chat.completions.create(
|
366 |
+
model="${conversation.model.id}",
|
367 |
+
messages=messages,
|
368 |
${formattedConfig({ sep: ",\n\t", start: "", end: "", connector: "=" })}
|
369 |
)
|
370 |
|
src/lib/components/InferencePlayground/InferencePlaygroundMessage.svelte
CHANGED
@@ -1,8 +1,8 @@
|
|
1 |
<script lang="ts">
|
2 |
-
import { type ChatCompletionInputMessage } from "@huggingface/tasks";
|
3 |
import { createEventDispatcher } from "svelte";
|
|
|
4 |
|
5 |
-
export let message:
|
6 |
export let loading: boolean = false;
|
7 |
export let autofocus: boolean = false;
|
8 |
|
|
|
1 |
<script lang="ts">
|
|
|
2 |
import { createEventDispatcher } from "svelte";
|
3 |
+
import type { ConversationMessage } from "./types";
|
4 |
|
5 |
+
export let message: ConversationMessage;
|
6 |
export let loading: boolean = false;
|
7 |
export let autofocus: boolean = false;
|
8 |
|
src/lib/components/InferencePlayground/inferencePlaygroundUtils.ts
CHANGED
@@ -1,4 +1,4 @@
|
|
1 |
-
import { type
|
2 |
import type { Conversation, ModelEntryWithTokenizer } from "./types";
|
3 |
|
4 |
import { HfInference } from "@huggingface/inference";
|
@@ -25,7 +25,7 @@ export async function handleStreamingResponse(
|
|
25 |
messages,
|
26 |
...conversation.config,
|
27 |
},
|
28 |
-
{ signal: abortController.signal
|
29 |
)) {
|
30 |
if (chunk.choices && chunk.choices.length > 0 && chunk.choices[0]?.delta?.content) {
|
31 |
out += chunk.choices[0].delta.content;
|
@@ -37,21 +37,18 @@ export async function handleStreamingResponse(
|
|
37 |
export async function handleNonStreamingResponse(
|
38 |
hf: HfInference,
|
39 |
conversation: Conversation
|
40 |
-
): Promise<{ message:
|
41 |
const { model, systemMessage } = conversation;
|
42 |
const messages = [
|
43 |
...(isSystemPromptSupported(model) && systemMessage.content?.length ? [systemMessage] : []),
|
44 |
...conversation.messages,
|
45 |
];
|
46 |
|
47 |
-
const response = await hf.chatCompletion(
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
},
|
53 |
-
{ use_cache: false }
|
54 |
-
);
|
55 |
|
56 |
if (response.choices && response.choices.length > 0) {
|
57 |
const { message } = response.choices[0];
|
|
|
1 |
+
import { type ChatCompletionOutputMessage } from "@huggingface/tasks";
|
2 |
import type { Conversation, ModelEntryWithTokenizer } from "./types";
|
3 |
|
4 |
import { HfInference } from "@huggingface/inference";
|
|
|
25 |
messages,
|
26 |
...conversation.config,
|
27 |
},
|
28 |
+
{ signal: abortController.signal }
|
29 |
)) {
|
30 |
if (chunk.choices && chunk.choices.length > 0 && chunk.choices[0]?.delta?.content) {
|
31 |
out += chunk.choices[0].delta.content;
|
|
|
37 |
export async function handleNonStreamingResponse(
|
38 |
hf: HfInference,
|
39 |
conversation: Conversation
|
40 |
+
): Promise<{ message: ChatCompletionOutputMessage; completion_tokens: number }> {
|
41 |
const { model, systemMessage } = conversation;
|
42 |
const messages = [
|
43 |
...(isSystemPromptSupported(model) && systemMessage.content?.length ? [systemMessage] : []),
|
44 |
...conversation.messages,
|
45 |
];
|
46 |
|
47 |
+
const response = await hf.chatCompletion({
|
48 |
+
model: model.id,
|
49 |
+
messages,
|
50 |
+
...conversation.config,
|
51 |
+
});
|
|
|
|
|
|
|
52 |
|
53 |
if (response.choices && response.choices.length > 0) {
|
54 |
const { message } = response.choices[0];
|
src/lib/components/InferencePlayground/types.ts
CHANGED
@@ -2,11 +2,13 @@ import type { GenerationConfig } from "$lib/components/InferencePlayground/gener
|
|
2 |
import type { ModelEntry } from "@huggingface/hub";
|
3 |
import type { ChatCompletionInputMessage } from "@huggingface/tasks";
|
4 |
|
|
|
|
|
5 |
export type Conversation = {
|
6 |
model: ModelEntryWithTokenizer;
|
7 |
config: GenerationConfig;
|
8 |
-
messages:
|
9 |
-
systemMessage:
|
10 |
streaming: boolean;
|
11 |
};
|
12 |
|
|
|
2 |
import type { ModelEntry } from "@huggingface/hub";
|
3 |
import type { ChatCompletionInputMessage } from "@huggingface/tasks";
|
4 |
|
5 |
+
export type ConversationMessage = Omit<ChatCompletionInputMessage, "content"> & { content?: string };
|
6 |
+
|
7 |
export type Conversation = {
|
8 |
model: ModelEntryWithTokenizer;
|
9 |
config: GenerationConfig;
|
10 |
+
messages: ConversationMessage[];
|
11 |
+
systemMessage: ConversationMessage;
|
12 |
streaming: boolean;
|
13 |
};
|
14 |
|
src/routes/+layout.svelte
CHANGED
@@ -1,43 +1,5 @@
|
|
1 |
<script lang="ts">
|
2 |
import "../app.css";
|
3 |
-
import { onMount } from "svelte";
|
4 |
-
import { browser } from "$app/environment";
|
5 |
-
import { page } from "$app/stores";
|
6 |
-
|
7 |
-
type Theme = "light" | "dark" | "system" | null | undefined;
|
8 |
-
|
9 |
-
let systemPrefersDark = false;
|
10 |
-
|
11 |
-
function updateTheme(theme: Theme, systemPrefersDark: boolean) {
|
12 |
-
if (theme === "dark" || (theme === "system" && systemPrefersDark)) {
|
13 |
-
document.documentElement.classList.add("dark");
|
14 |
-
} else {
|
15 |
-
document.documentElement.classList.remove("dark");
|
16 |
-
}
|
17 |
-
}
|
18 |
-
|
19 |
-
$: if (browser) {
|
20 |
-
const theme = $page.url.searchParams.get("__theme") as Theme;
|
21 |
-
updateTheme(theme, systemPrefersDark);
|
22 |
-
}
|
23 |
-
|
24 |
-
onMount(() => {
|
25 |
-
if (browser) {
|
26 |
-
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
27 |
-
systemPrefersDark = mediaQuery.matches;
|
28 |
-
|
29 |
-
const handleChange = (event: MediaQueryListEvent) => {
|
30 |
-
systemPrefersDark = event.matches;
|
31 |
-
updateTheme($page.url.searchParams.get("__theme") as Theme, systemPrefersDark);
|
32 |
-
};
|
33 |
-
|
34 |
-
mediaQuery.addEventListener("change", handleChange);
|
35 |
-
|
36 |
-
return () => mediaQuery.removeEventListener("change", handleChange);
|
37 |
-
}
|
38 |
-
});
|
39 |
</script>
|
40 |
|
41 |
-
<slot
|
42 |
-
|
43 |
-
<style></style>
|
|
|
1 |
<script lang="ts">
|
2 |
import "../app.css";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3 |
</script>
|
4 |
|
5 |
+
<slot />
|
|
|
|
src/routes/+page.server.ts
CHANGED
@@ -4,7 +4,8 @@ import type { PageServerLoad } from "./$types";
|
|
4 |
import { env } from "$env/dynamic/private";
|
5 |
|
6 |
export const load: PageServerLoad = async ({ fetch }) => {
|
7 |
-
const apiUrl =
|
|
|
8 |
const HF_TOKEN = env.HF_TOKEN;
|
9 |
|
10 |
const res = await fetch(apiUrl, {
|
|
|
4 |
import { env } from "$env/dynamic/private";
|
5 |
|
6 |
export const load: PageServerLoad = async ({ fetch }) => {
|
7 |
+
const apiUrl =
|
8 |
+
"https://huggingface.co/api/models?pipeline_tag=text-generation&inference_provider=hf-inference&filter=conversational";
|
9 |
const HF_TOKEN = env.HF_TOKEN;
|
10 |
|
11 |
const res = await fetch(apiUrl, {
|