enzostvs HF Staff commited on
Commit
de2d4cd
·
0 Parent(s):

migration in svelte

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .eslintignore +13 -0
  2. .eslintrc.cjs +31 -0
  3. .gitignore +12 -0
  4. .npmrc +1 -0
  5. .prettierignore +13 -0
  6. .prettierrc +8 -0
  7. .vscode/settings.json +3 -0
  8. Dockerfile +25 -0
  9. README.md +12 -0
  10. package-lock.json +0 -0
  11. package.json +42 -0
  12. postcss.config.js +6 -0
  13. src/app.d.ts +12 -0
  14. src/app.html +18 -0
  15. src/lib/components/CodePreview.svelte +33 -0
  16. src/lib/components/Input.svelte +59 -0
  17. src/lib/components/Loading.svelte +23 -0
  18. src/lib/components/ProTag.svelte +3 -0
  19. src/lib/components/Prompt.svelte +25 -0
  20. src/lib/components/SelectModel.svelte +73 -0
  21. src/lib/components/Toggle.svelte +41 -0
  22. src/lib/components/image-generation/Form.svelte +118 -0
  23. src/lib/components/image-generation/Response.svelte +55 -0
  24. src/lib/components/sidebar/Sidebar.svelte +93 -0
  25. src/lib/components/sidebar/links/Primary.svelte +13 -0
  26. src/lib/components/sidebar/links/Secondary.svelte +10 -0
  27. src/lib/components/snippets/Curl.svelte +52 -0
  28. src/lib/components/snippets/Javascript.svelte +56 -0
  29. src/lib/components/snippets/Python.svelte +70 -0
  30. src/lib/components/text-generation/Form.svelte +123 -0
  31. src/lib/components/text-generation/Preview.svelte +13 -0
  32. src/lib/components/text-generation/Response.svelte +66 -0
  33. src/lib/images/github.svg +16 -0
  34. src/lib/images/hf-logo.svg +24 -0
  35. src/lib/images/svelte-logo.svg +1 -0
  36. src/lib/images/svelte-welcome.png +0 -0
  37. src/lib/images/svelte-welcome.webp +0 -0
  38. src/lib/styles/tailwind.css +22 -0
  39. src/lib/utils/models.ts +23 -0
  40. src/lib/utils/type.ts +4 -0
  41. src/routes/+layout.svelte +12 -0
  42. src/routes/+page.svelte +59 -0
  43. src/routes/+page.ts +3 -0
  44. src/routes/Counter.svelte +102 -0
  45. src/routes/Header.svelte +129 -0
  46. src/routes/about/+page.svelte +26 -0
  47. src/routes/about/+page.ts +9 -0
  48. src/routes/api/image-generation/+server.ts +47 -0
  49. src/routes/api/text-generation/+server.ts +42 -0
  50. src/routes/image-generation/+page.svelte +63 -0
.eslintignore ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .DS_Store
2
+ node_modules
3
+ /build
4
+ /.svelte-kit
5
+ /package
6
+ .env
7
+ .env.*
8
+ !.env.example
9
+
10
+ # Ignore files for PNPM, NPM and YARN
11
+ pnpm-lock.yaml
12
+ package-lock.json
13
+ yarn.lock
.eslintrc.cjs ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /** @type { import("eslint").Linter.FlatConfig } */
2
+ module.exports = {
3
+ root: true,
4
+ extends: [
5
+ 'eslint:recommended',
6
+ 'plugin:@typescript-eslint/recommended',
7
+ 'plugin:svelte/recommended',
8
+ 'prettier'
9
+ ],
10
+ parser: '@typescript-eslint/parser',
11
+ plugins: ['@typescript-eslint'],
12
+ parserOptions: {
13
+ sourceType: 'module',
14
+ ecmaVersion: 2020,
15
+ extraFileExtensions: ['.svelte']
16
+ },
17
+ env: {
18
+ browser: true,
19
+ es2017: true,
20
+ node: true
21
+ },
22
+ overrides: [
23
+ {
24
+ files: ['*.svelte'],
25
+ parser: 'svelte-eslint-parser',
26
+ parserOptions: {
27
+ parser: '@typescript-eslint/parser'
28
+ }
29
+ }
30
+ ]
31
+ };
.gitignore ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .DS_Store
2
+ node_modules
3
+ /build
4
+ /.svelte-kit
5
+ /package
6
+ .env
7
+ .env.*
8
+ !.env.example
9
+ .vercel
10
+ .output
11
+ vite.config.js.timestamp-*
12
+ vite.config.ts.timestamp-*
.npmrc ADDED
@@ -0,0 +1 @@
 
 
1
+ engine-strict=true
.prettierignore ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .DS_Store
2
+ node_modules
3
+ /build
4
+ /.svelte-kit
5
+ /package
6
+ .env
7
+ .env.*
8
+ !.env.example
9
+
10
+ # Ignore files for PNPM, NPM and YARN
11
+ pnpm-lock.yaml
12
+ package-lock.json
13
+ yarn.lock
.prettierrc ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "useTabs": true,
3
+ "singleQuote": true,
4
+ "trailingComma": "none",
5
+ "printWidth": 100,
6
+ "plugins": ["prettier-plugin-svelte"],
7
+ "overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }]
8
+ }
.vscode/settings.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ {
2
+ "typescript.tsdk": "node_modules/typescript/lib"
3
+ }
Dockerfile ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Dockerfile
2
+
3
+ # Use an official Node.js runtime as the base image
4
+ FROM node:18
5
+
6
+ # Set the working directory in the container
7
+ WORKDIR /usr/src/app
8
+
9
+ # Copy package.json and package-lock.json to the container
10
+ COPY package.json package-lock.json ./
11
+
12
+ # Install dependencies
13
+ RUN npm install
14
+
15
+ # Copy the rest of the application files to the container
16
+ COPY . .
17
+
18
+ # Build the Next.js application for production
19
+ RUN npm run build
20
+
21
+ # Expose the application port (assuming your app runs on port 3000)
22
+ EXPOSE 3000
23
+
24
+ # Start the application
25
+ CMD ["npm", "preview"]
README.md ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: — Inference Api —
3
+ emoji: 📟
4
+ colorFrom: green
5
+ colorTo: yellow
6
+ sdk: docker
7
+ app_port: 3000
8
+ pinned: false
9
+ license: mit
10
+ ---
11
+
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
package-lock.json ADDED
The diff for this file is too large to render. See raw diff
 
package.json ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "inference-playground-svelte",
3
+ "version": "0.0.1",
4
+ "scripts": {
5
+ "dev": "vite dev",
6
+ "build": "vite build",
7
+ "preview": "vite preview",
8
+ "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
9
+ "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
10
+ "lint": "prettier --check . && eslint .",
11
+ "format": "prettier --write ."
12
+ },
13
+ "devDependencies": {
14
+ "@fontsource/fira-mono": "^4.5.10",
15
+ "@iconify/svelte": "^3.1.4",
16
+ "@neoconfetti/svelte": "^1.0.0",
17
+ "@sveltejs/adapter-auto": "^2.0.0",
18
+ "@sveltejs/kit": "^1.27.4",
19
+ "@types/cookie": "^0.5.1",
20
+ "@types/node": "^20.10.0",
21
+ "@typescript-eslint/eslint-plugin": "^6.0.0",
22
+ "@typescript-eslint/parser": "^6.0.0",
23
+ "autoprefixer": "^10.4.16",
24
+ "eslint": "^8.28.0",
25
+ "eslint-config-prettier": "^9.0.0",
26
+ "eslint-plugin-svelte": "^2.30.0",
27
+ "postcss": "^8.4.31",
28
+ "prettier": "^3.0.0",
29
+ "prettier-plugin-svelte": "^3.0.0",
30
+ "svelte": "^4.2.7",
31
+ "svelte-check": "^3.6.0",
32
+ "svelte-highlight": "^7.4.2",
33
+ "tailwindcss": "^3.3.5",
34
+ "tslib": "^2.4.1",
35
+ "typescript": "^5.0.0",
36
+ "vite": "^4.4.2"
37
+ },
38
+ "type": "module",
39
+ "dependencies": {
40
+ "iconify-icon": "^1.0.8"
41
+ }
42
+ }
postcss.config.js ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ export default {
2
+ plugins: {
3
+ tailwindcss: {},
4
+ autoprefixer: {},
5
+ },
6
+ }
src/app.d.ts ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // See https://kit.svelte.dev/docs/types#app
2
+ // for information about these interfaces
3
+ declare global {
4
+ namespace App {
5
+ // interface Error {}
6
+ // interface Locals {}
7
+ // interface PageData {}
8
+ // interface Platform {}
9
+ }
10
+ }
11
+
12
+ export {};
src/app.html ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <link rel="icon" href="%sveltekit.assets%/favicon.png" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
7
+ %sveltekit.head%
8
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
9
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
10
+ <link
11
+ href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@300;400;500&family=Source+Sans+3:wght@400;500;600;700;800;900&display=swap"
12
+ rel="stylesheet"
13
+ />
14
+ </head>
15
+ <body data-sveltekit-preload-data="hover">
16
+ <div style="display: contents">%sveltekit.body%</div>
17
+ </body>
18
+ </html>
src/lib/components/CodePreview.svelte ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <script lang="ts">
2
+ import Curl from "./snippets/Curl.svelte";
3
+ import Javascript from "./snippets/Javascript.svelte";
4
+ import Python from "./snippets/Python.svelte";
5
+
6
+ export let body: Record<string, any>;
7
+ export let endpoint: string;
8
+
9
+ let headers = {}
10
+
11
+ const handleCopyToClipboard = (e: string) => {}
12
+ </script>
13
+
14
+ <div class="p-6 font-code text-sm text-white flex flex-col gap-6 snippet">
15
+ <Curl
16
+ body={body}
17
+ headers={headers}
18
+ endpoint={endpoint}
19
+ onCopyToClipboard={handleCopyToClipboard}
20
+ />
21
+ <Javascript
22
+ body={body}
23
+ headers={headers}
24
+ endpoint={endpoint}
25
+ onCopyToClipboard={handleCopyToClipboard}
26
+ />
27
+ <Python
28
+ body={body}
29
+ headers={headers}
30
+ endpoint={endpoint}
31
+ onCopyToClipboard={handleCopyToClipboard}
32
+ />
33
+ </div>
src/lib/components/Input.svelte ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <script lang="ts">
2
+ import Icon from '@iconify/svelte';
3
+
4
+ export let tooltip: string | undefined = undefined;
5
+ export let label: string;
6
+ export let subLabel: string | undefined = undefined;
7
+
8
+ export let type: "text" | "number" = "text"
9
+ export let value: string | number;
10
+ export let min: number | undefined = undefined;
11
+ export let max: number | undefined = undefined;
12
+ let clazz: string | undefined = undefined;
13
+ export { clazz as class };
14
+ export let placeholder: string | undefined = undefined;
15
+ export let sanitize: undefined | ((value: string | number) => string | number) = undefined;
16
+ export let onChange: (value: string | number) => void;
17
+
18
+ const handleInputChange = (event: any) => {
19
+ const newValue = event.target.value;
20
+ if (type === "number" && /^[0-9]*$/.test(newValue)) {
21
+ return onChange(newValue)
22
+ }
23
+
24
+ return onChange(newValue)
25
+ };
26
+
27
+ const handleBlur = (event: any) => {
28
+ const newValue = event.target.value;
29
+ if (sanitize) return onChange(sanitize(newValue))
30
+ }
31
+
32
+ </script>
33
+
34
+ <div class={`w-full relative ${clazz}`}>
35
+ <div class="flex items-center justify-start gap-2 relative mb-2.5">
36
+ {#if tooltip}
37
+ <div class="group cursor-pointer">
38
+ <Icon icon="lucide:info" class="text-slate-500 group-hover:text-slate-300 text-xl" />
39
+ <div class="bg-slate-950/90 z-10 rounded-xl p-3 text-white absolute text-xs left-0 bottom-0 translate-y-[calc(100%+8px)] opacity-0 transition-all duration-200 group-hover:opacity-100 pointer-events-none group-hover:pointer-events-auto">
40
+ {tooltip}
41
+ </div>
42
+ </div>
43
+ {/if}
44
+ <p class="font-sans text-slate-400 font-regular text-sm">
45
+ {label}:
46
+ </p>
47
+ </div>
48
+ {#if subLabel} <p class="text-slate-500 text-xs mb-2.5">{subLabel}</p>{/if}
49
+ <input
50
+ type={type}
51
+ value={value}
52
+ min={min}
53
+ max={max}
54
+ placeholder={placeholder}
55
+ class="shadow-inner font-code border border-slate-800 bg-slate-900/60 focus:bg-slate-900/90 focus:border-slate-700/80 text-white rounded-lg text-sm px-4 py-3.5 w-full transition-all duration-200 leading-relaxed outline-none"
56
+ on:input={handleInputChange}
57
+ on:blur={handleBlur}
58
+ />
59
+ </div>
src/lib/components/Loading.svelte ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="absolute left-0 top-0 w-full h-full flex items-center justify-center bg-slate-950 bg-opacity-50 flex-col backdrop-blur-sm z-10">
2
+ <svg
3
+ class="animate-spin -ml-1 mr-3 h-8 w-8 text-white"
4
+ xmlns="http://www.w3.org/2000/svg"
5
+ fill="none"
6
+ viewBox="0 0 24 24"
7
+ >
8
+ <circle
9
+ class="opacity-25"
10
+ cx="12"
11
+ cy="12"
12
+ r="10"
13
+ stroke="currentColor"
14
+ stroke-width="4"
15
+ ></circle>
16
+ <path
17
+ class="opacity-75"
18
+ fill="currentColor"
19
+ d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
20
+ ></path>
21
+ </svg>
22
+ <slot />
23
+ </div>
src/lib/components/ProTag.svelte ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ <div class="inline-block -skew-x-12 bg-gradient-to-br text-sm font-bold shadow-lg from-pink-500 via-green-500 to-yellow-500 text-black shadow-green-500/20 rounded-lg px-2.5 py-0.5">
2
+ PRO
3
+ </div>
src/lib/components/Prompt.svelte ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <script lang="ts">
2
+ export let value: string;
3
+ export let placeholder: string = "Ask me anything...";
4
+ export let onChange: (v: string) => void
5
+ </script>
6
+
7
+ <div class="flex flex-col gap-2.5">
8
+ <label
9
+ for="prompt"
10
+ class="font-sans text-slate-400 font-regular text-sm"
11
+ >
12
+ Prompt:
13
+ </label>
14
+ <textarea
15
+ id="prompt"
16
+ {value}
17
+ {placeholder}
18
+ class="shadow-inner font-code border border-slate-800 bg-slate-900/60 focus:bg-slate-900/90 focus:border-slate-700/80 text-white rounded-lg text-sm p-4 w-full transition-all duration-200 h-44 resize-none leading-relaxed outline-none"
19
+ on:input={(e) => {
20
+ const target = e.target
21
+ // @ts-ignore
22
+ onChange(target.value)
23
+ }}
24
+ />
25
+ </div>
src/lib/components/SelectModel.svelte ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <script lang="ts">
2
+ import Icon from '@iconify/svelte';
3
+ import type { Model } from "$lib/utils/type";
4
+
5
+ let open = false;
6
+
7
+ export let items: Model[];
8
+ export let value: string;
9
+ export let onChange: (value: string) => void;
10
+
11
+ $: selectedModel = items.find(({ id }) => id === value)
12
+
13
+ const handleSelect = (id: string) => {
14
+ onChange(id)
15
+ open = false;
16
+ }
17
+
18
+ const handleOpen = () => open = !open
19
+ </script>
20
+
21
+ <div class="w-full flex flex-col gap-2.5">
22
+ <label
23
+ for="model"
24
+ class="font-sans text-slate-400 font-regular text-sm"
25
+ >
26
+ Model:
27
+ </label>
28
+ <div
29
+ id="model"
30
+ class={`cursor-pointer shadow-inner font-code border hover:bg-slate-900/90 hover:border-slate-700/80 text-white rounded-lg text-sm w-full transition-all duration-200 leading-relaxed outline-none relative ${open ? 'bg-slate-900/90 border-slate-700/80' : 'border-slate-800 bg-slate-900/60'}`}
31
+ >
32
+ <button class="w-full flex justify-between items-center px-4 py-3" role="searchbox" on:click={handleOpen}>
33
+ {#if selectedModel}
34
+ <div class="flex items-center justify-start gap-3">
35
+ <img
36
+ src={selectedModel.logo}
37
+ alt={selectedModel.id}
38
+ width={22}
39
+ height={22}
40
+ class="rounded-full"
41
+ />
42
+ <p>{selectedModel.id}</p>
43
+ </div>
44
+ {:else}
45
+ <p class="opacity-70">Select a model</p>
46
+ {/if}
47
+ <Icon icon="iconamoon:arrow-right-2-light" class={`text-slate-400 w-5 h-5 transition-all duration-150 ${open && 'transform rotate-90'}`} />
48
+ </button>
49
+ <div
50
+ class="absolute bottom-0 left-0 w-full pt-4 translate-y-full transition-all duration-150"
51
+ class:pointer-events-none={!open}
52
+ class:opacity-0={!open}
53
+ >
54
+ <div class="bg-slate-900 border border-slate-700/80 text-white p-2 font-code rounded-lg">
55
+ {#each items as { id, logo}}
56
+ <button
57
+ class={`w-full flex items-center justify-start gap-3 p-2 cursor-pointer hover:bg-slate-800/60 rounded-lg ${selectedModel?.id === id && 'bg-slate-800/60'}`}
58
+ on:click={() => handleSelect(id)}
59
+ >
60
+ <img
61
+ src={logo}
62
+ alt={id}
63
+ width={22}
64
+ height={22}
65
+ class="rounded-full"
66
+ />
67
+ <p>{id}</p>
68
+ </button>
69
+ {/each}
70
+ </div>
71
+ </div>
72
+ </div>
73
+ </div>
src/lib/components/Toggle.svelte ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <script lang="ts">
2
+ import Icon from '@iconify/svelte';
3
+
4
+ export let label: string;
5
+ export let checked: boolean;
6
+ export let tooltip: string | undefined = undefined;
7
+ export let onChange: (c: boolean) => void;
8
+ </script>
9
+
10
+ <div class="w-full flex items-center justify-between gap-2.5 relative">
11
+ <div class="flex items-center justify-start gap-2">
12
+ {#if tooltip}
13
+ <div class="group cursor-pointer">
14
+ <Icon icon="lucide:info" class="text-slate-500 group-hover:text-slate-300 text-xl" />
15
+ <div class="bg-slate-950/90 z-10 min-w-[200px] rounded-xl p-3 text-white absolute text-xs left-0 bottom-0 translate-y-[calc(100%+8px)] opacity-0 transition-all duration-200 group-hover:opacity-100 pointer-events-none group-hover:pointer-events-auto leading-relaxed">
16
+ {tooltip}
17
+ </div>
18
+ </div>
19
+ {/if}
20
+ <p class="font-sans text-slate-400 font-regular text-sm">
21
+ {label}
22
+ </p>
23
+ </div>
24
+ <div class="w-[62px] h-[32px] rounded-md relative cursor-pointer grid grid-cols-2 border border-slate-800 bg-slate-900/60 focus:bg-slate-900/90 focus:border-slate-700/80 overflow-hidden z-[1]">
25
+ <div class={`bg-slate-800/70 h-full w-[31px] absolute top-0 left-0 transition-all duration-150 z-[-1] ${!checked && 'translate-x-[31px]'}`}/>
26
+ <button
27
+ class="flex items-center justify-center"
28
+ class:text-slate-600={!checked}
29
+ on:click={() => onChange(true)}
30
+ >
31
+ <Icon icon="ic:round-check" class={`w-4 h-4 ${checked && 'text-green-500'}`} />
32
+ </button>
33
+ <button
34
+ class="flex items-center justify-center"
35
+ class:text-slate-600={checked}
36
+ on:click={() => onChange(false)}
37
+ >
38
+ <Icon icon="ic:round-close" class={`w-4 h-4 ${!checked && 'text-red-500'}`} />
39
+ </button>
40
+ </div>
41
+ </div>
src/lib/components/image-generation/Form.svelte ADDED
@@ -0,0 +1,118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <script lang="ts">
2
+ import Prompt from "$lib/components/Prompt.svelte";
3
+ import SelectModel from "$lib/components/SelectModel.svelte";
4
+ import Input from "$lib/components/Input.svelte";
5
+ import Toggle from "$lib/components/Toggle.svelte";
6
+ import { IMAGE_GENERATIONS } from "$lib/utils/models";
7
+
8
+ export let form: Record<string, any>;
9
+ export let onForm: (form: Record<string, any>) => void;
10
+ </script>
11
+
12
+ <SelectModel value={form.model} items={IMAGE_GENERATIONS} onChange={(model) => onForm({ ...form, model })} />
13
+ <Prompt
14
+ value={form.inputs}
15
+ placeholder="A red apple on a table"
16
+ onChange={(inputs) => onForm({ ...form, inputs })}
17
+ />
18
+ <div class="flex items-center justify-start gap-4 mt-3">
19
+ <p class="text-slate-500 uppercase font-medium text-sm">
20
+ Optional parameters
21
+ </p>
22
+ <div class="w-full flex-1 h-[1px] bg-slate-600" />
23
+ </div>
24
+ <div class="grid grid-cols-2 gap-x-10 gap-y-6">
25
+ <Input
26
+ label="Negative prompt"
27
+ type="text"
28
+ class="col-span-2"
29
+ tooltip="A text describing content that you want the model to steer away from."
30
+ value={form?.parameters?.negative_prompt}
31
+ onChange={(negative_prompt) =>
32
+ onForm({
33
+ ...form,
34
+ parameters: { ...form.parameters, negative_prompt },
35
+ })
36
+ }
37
+ />
38
+ <div class="flex flex-col gap-3">
39
+ <Input
40
+ label="Guidance scale"
41
+ type="number"
42
+ tooltip="How closely you want the model to match the prompt. Lower numbers are less accurate, very high numbers might decrease image quality or generate artifacts."
43
+ min={1}
44
+ max={100}
45
+ sanitize={(value) => {
46
+ const valueAsNumber = Number(value);
47
+ if (valueAsNumber > 1) return 1;
48
+ if (valueAsNumber < 0) return 0;
49
+ return valueAsNumber;
50
+ }}
51
+ value={form?.parameters?.guidance_scale}
52
+ onChange={(guidance_scale) =>
53
+ onForm({
54
+ ...form,
55
+ parameters: { ...form.parameters, guidance_scale },
56
+ })
57
+ }
58
+ />
59
+ <Input
60
+ label="Inference steps"
61
+ type="number"
62
+ tooltip="The number of denoising steps to run. Larger numbers may produce better quality but will be slower. Typical values are between 20 and 50 steps."
63
+ min={20}
64
+ max={50}
65
+ sanitize={(value) => {
66
+ const valueAsNumber = Number(value);
67
+ if (valueAsNumber > 1) return 1;
68
+ if (valueAsNumber < 0) return 0;
69
+ return valueAsNumber;
70
+ }}
71
+ value={form?.parameters?.num_inference_steps}
72
+ onChange={(num_inference_steps) =>
73
+ onForm({
74
+ ...form,
75
+ parameters: { ...form.parameters, num_inference_steps },
76
+ })
77
+ }
78
+ />
79
+ </div>
80
+ <div class="flex flex-col gap-3">
81
+ <Input
82
+ label="Width"
83
+ type="number"
84
+ tooltip="The desired image dimensions. SDXL works best for sizes between 768 and 1024."
85
+ sanitize={(value) => {
86
+ const valueAsNumber = Number(value);
87
+ if (valueAsNumber > 1) return 1;
88
+ if (valueAsNumber < 0) return 0;
89
+ return valueAsNumber;
90
+ }}
91
+ value={form?.parameters?.width}
92
+ onChange={(width) =>
93
+ onForm({
94
+ ...form,
95
+ parameters: { ...form.parameters, width },
96
+ })
97
+ }
98
+ />
99
+ <Input
100
+ label="Height"
101
+ type="number"
102
+ tooltip="The desired image dimensions. SDXL works best for sizes between 768 and 1024."
103
+ sanitize={(value) => {
104
+ const valueAsNumber = Number(value);
105
+ if (valueAsNumber > 1) return 1;
106
+ if (valueAsNumber < 0) return 0;
107
+ return valueAsNumber;
108
+ }}
109
+ value={form?.parameters?.height}
110
+ onChange={(height) =>
111
+ onForm({
112
+ ...form,
113
+ parameters: { ...form.parameters, height },
114
+ })
115
+ }
116
+ />
117
+ </div>
118
+ </div>
src/lib/components/image-generation/Response.svelte ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <script lang="ts">
2
+ import Icon from '@iconify/svelte';
3
+
4
+ import Loading from "$lib/components/Loading.svelte"
5
+ import CodePreview from '$lib/components/CodePreview.svelte';
6
+ import Preview from '$lib/components/text-generation/Preview.svelte';
7
+
8
+ export let loading: boolean;
9
+ export let res: any;
10
+ export let form: Record<string, any>;
11
+ export let body: Record<string, any>;
12
+ export let endpoint: string;
13
+
14
+ let tab = 0
15
+
16
+ $: code = JSON.stringify(res ?? {}, null, 2)
17
+
18
+ let TABS = [
19
+ {
20
+ label: "Formatted preview",
21
+ icon: "material-symbols:preview",
22
+ },
23
+ {
24
+ label: "Code example",
25
+ icon: "carbon:code",
26
+ },
27
+ ];
28
+ </script>
29
+
30
+ <div class="h-screen flex flex-col relative">
31
+ <div class="bg-slate-950 overflow-auto flex-1">
32
+ <div class="w-full uppercase text-zinc-400 text-sm font-semibold border-t border-slate-900 flex items-start sticky top-0 bg-slate-950">
33
+ {#each TABS as { label, icon }, idx }
34
+ <button
35
+ class={`flex items-center justify-start gap-2 px-5 border-r py-4 border-slate-900 bg-slate-900/40 cursor-pointer hover:bg-slate-900/60 transition-all duration-200 ${tab === idx ? '!bg-slate-950 hover:bg-slate-900/40' : 'border-b'}`}
36
+ on:click={() => tab = idx}
37
+ >
38
+ <Icon icon={icon} class="w-5 h-5" />
39
+ {label}
40
+ </button>
41
+ {/each}
42
+ <div class="flex flex-1 w-full pointer-events-none text-slate-950 border-b border-slate-900 h-[53px] bg-slate-900/40"></div>
43
+ </div>
44
+ {#if tab === 0}
45
+ <Preview body={body} res={res} />
46
+ {:else if tab === 1}
47
+ <CodePreview body={form} endpoint={endpoint} />
48
+ {/if}
49
+ </div>
50
+ {#if loading}
51
+ <Loading>
52
+ <p class="text-slate-400 text-lg mt-4">Processing...</p>
53
+ </Loading>
54
+ {/if}
55
+ </div>
src/lib/components/sidebar/Sidebar.svelte ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <script>
2
+ import Icon from '@iconify/svelte';
3
+
4
+ import logo from '$lib/images/hf-logo.svg';
5
+ import ProTag from '$lib/components/ProTag.svelte';
6
+ import PrimaryLink from '$lib/components/sidebar/links/Primary.svelte';
7
+ import SecondaryLink from '$lib/components/sidebar/links/Secondary.svelte';
8
+
9
+ const LINKS = [
10
+ {
11
+ path: "/text-generation",
12
+ label: "Text Generation",
13
+ description: "Generate text from a prompt, using a model of your choice.",
14
+ icon: "heroicons:chat-bubble-left-right-20-solid",
15
+ type: "green",
16
+ },
17
+ {
18
+ path: "/image-generation",
19
+ label: "Image Generation",
20
+ description: "Generate images from a prompt, using a model of your choice.",
21
+ icon: "ph:images-square-fill",
22
+ type: "pink",
23
+ },
24
+ ];
25
+
26
+ const FEW_SHOTS = [
27
+ {
28
+ path: "/text-generation/translation",
29
+ label: "Translation",
30
+ icon: "bi:translate",
31
+ },
32
+ {
33
+ path: "/text-generation/chat",
34
+ label: "Chat",
35
+ icon: "ph:chat-dots-fill",
36
+ },
37
+ ];
38
+
39
+ </script>
40
+
41
+ <aside class="hidden xl:block bg-slate-900 w-full max-w-[360px] h-screen border-r border-slate-800 text-white">
42
+ <header class="flex items-center justify-start p-8 gap-4">
43
+ <img src={logo} alt="Logo" width={34} height={34} />
44
+ <div class="flex items-center justify-start gap-2">
45
+ <p class="text-white font-bold text-xl">Inference API for</p>
46
+ <ProTag />
47
+ </div>
48
+ </header>
49
+ <nav class="grid grid-cols-1 gap-8 px-4">
50
+ <a
51
+ href="https://huggingface.co/pricing#pro"
52
+ target="_blank"
53
+ class="px-4"
54
+ >
55
+ <button class="group text-base font-bold uppercase tracking-wide bg-white text-slate-950 transition-all duration-200 px-6 py-3 w-full rounded-full relative">
56
+ Subscribe to Pro
57
+ </button>
58
+ </a>
59
+ <ul class="grid grid-cols-1 gap-4">
60
+ {#each LINKS as { path, description, label, type, icon }, i}
61
+ <PrimaryLink href={path} type={type}>
62
+ <div class="flex items-center justify-start gap-4">
63
+ <Icon icon={icon} class="w-6 h-6" />
64
+ <p class="font-semibold text-sm uppercase font-code">
65
+ {label}
66
+ </p>
67
+ </div>
68
+ <p class="text-sm mt-2 text-white/90">
69
+ {description ||
70
+ "Generate text from a prompt, using a model of your choice."}
71
+ </p>
72
+ </PrimaryLink>
73
+ {/each}
74
+ </ul>
75
+ <div class="grid grid-cols-1 gap-4">
76
+ <div class="flex items-center justify-start gap-4 mb-2">
77
+ <p class="text-slate-600 uppercase font-medium text-sm font-sans">
78
+ FEW SHOTS
79
+ </p>
80
+ <div class="w-full flex-1 h-[1px] bg-slate-800" />
81
+ </div>
82
+ {#each FEW_SHOTS as { path, label, icon }, i}
83
+ <SecondaryLink href={path}>
84
+ <Icon icon={icon} class="w-5 h-5" />
85
+ <p class="font-semibold text-sm uppercase font-code">
86
+ {label}
87
+ </p>
88
+ </SecondaryLink>
89
+ {/each}
90
+ </div>
91
+ </nav>
92
+ </aside>
93
+
src/lib/components/sidebar/links/Primary.svelte ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <script lang="ts">
2
+ import { page } from '$app/stores';
3
+ export let href: string;
4
+ export let type: string = "green"
5
+
6
+ $: active_class = $page.url.pathname === href ? type === 'green' ? 'bg-green-600 !text-green-500' : 'bg-pink-500 !text-pink-500' : 'bg-slate-700';
7
+ </script>
8
+
9
+ <a href={href} data-sveltekit-preload-data class="p-5 transition-all duration-200 bg-opacity-20 border-transparent rounded-xl {active_class}">
10
+ <li>
11
+ <slot />
12
+ </li>
13
+ </a>
src/lib/components/sidebar/links/Secondary.svelte ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <script lang="ts">
2
+ import { page } from '$app/stores';
3
+ export let href: string;
4
+
5
+ $: active_class = $page.url.pathname === href ? '!text-slate-800 !bg-white/90 !from-transparent' : 'hover:text-slate-200 hover:border-slate-800';
6
+ </script>
7
+
8
+ <a href={href} data-sveltekit-preload-data class="px-5 py-3.5 rounded-xl bg-gradient-to-r border from-slate-800/70 to-slate-900 border-slate-800/50 text-slate-400 flex items-center justify-start gap-4 cursor-pointer {active_class}">
9
+ <slot />
10
+ </a>
src/lib/components/snippets/Curl.svelte ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <script lang="ts">
2
+ import Icon from '@iconify/svelte';
3
+ import Highlight from "svelte-highlight";
4
+ import powershell from "svelte-highlight/languages/powershell";
5
+ import { PUBLIC_INFERENCE_API_URL } from '$env/static/public'
6
+
7
+
8
+ export let body: Record<string, any>;
9
+ export let endpoint: string;
10
+ export let headers: Record<string, any>;
11
+ export let onCopyToClipboard: (e: string) => void;
12
+
13
+ let isCopied: boolean = false;
14
+
15
+ const generateCurlRequestFromEndpoint = (body: Record<string, any>) => {
16
+ const fullpath = `${PUBLIC_INFERENCE_API_URL}/models/${endpoint}`;
17
+ delete body.model
18
+ return `curl -X POST "${fullpath}" \\
19
+ -H ${JSON.stringify(headers)}
20
+ -d ${JSON.stringify(body)}
21
+ `;
22
+ };
23
+
24
+ const handleCopy = () => {
25
+ onCopyToClipboard(generateCurlRequestFromEndpoint(body));
26
+ isCopied = true
27
+ setTimeout(() => {
28
+ isCopied = false
29
+ }, 1000);
30
+ };
31
+
32
+ $: code = generateCurlRequestFromEndpoint(body)
33
+ </script>
34
+
35
+ <div class="bg-slate-900/50 rounded-xl overflow-hidden">
36
+ <header class="bg-slate-900 flex items-center justify-start px-5 py-4 uppercase gap-2 text-slate-300">
37
+ <Icon icon="icon-park-outline:code-brackets" class="text-xl" />
38
+ <p class="text-xs font-semibold">Curl</p>
39
+ </header>
40
+ <main class="px-6 py-6">
41
+ <Highlight language={powershell} {code} />
42
+ <button class="flex justify-end relative w-full" on:click={handleCopy}>
43
+ <Icon icon="solar:copy-bold-duotone" class="text-slate-500 cursor-pointer hover:text-slate-300 transition-all duration-75 w-5 h-5" />
44
+ <div
45
+ class="bg-indigo-500/60 text-slate-100 text-xs font-semibold absolute bottom-0 right-0 z-10 rounded-lg px-2 py-1 pointer-events-none -translate-y-full transition-all duration-200"
46
+ class:opacity-0={!isCopied}
47
+ >
48
+ Copied!
49
+ </div>
50
+ </button>
51
+ </main>
52
+ </div>
src/lib/components/snippets/Javascript.svelte ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <script lang="ts">
2
+ import Icon from '@iconify/svelte';
3
+ import Highlight from "svelte-highlight";
4
+ import javascript from "svelte-highlight/languages/javascript";
5
+ import { PUBLIC_INFERENCE_API_URL } from '$env/static/public'
6
+
7
+ export let body: Record<string, any>;
8
+ export let endpoint: string;
9
+ export let headers: Record<string, any>;
10
+ export let onCopyToClipboard: (e: string) => void;
11
+
12
+ let isCopied: boolean = false;
13
+
14
+ const generateCurlRequestFromEndpoint = (body: Record<string, any>) => {
15
+ const fullpath = `${PUBLIC_INFERENCE_API_URL}/models/${endpoint}`;
16
+ delete body.model
17
+
18
+ return `const response = await fetch(
19
+ "${fullpath}",
20
+ {
21
+ method: "POST",
22
+ headers: ${JSON.stringify(headers)},
23
+ body: ${JSON.stringify(body)}
24
+ }
25
+ )`;
26
+ };
27
+
28
+ const handleCopy = () => {
29
+ onCopyToClipboard(generateCurlRequestFromEndpoint(body));
30
+ isCopied = true
31
+ setTimeout(() => {
32
+ isCopied = false
33
+ }, 1000);
34
+ };
35
+
36
+ $: code = generateCurlRequestFromEndpoint(body)
37
+ </script>
38
+
39
+ <div class="bg-slate-900/50 rounded-xl overflow-hidden">
40
+ <header class="bg-slate-900 flex items-center justify-start px-5 py-4 uppercase gap-2 text-yellow-500">
41
+ <Icon icon="ri:javascript-fill" class="text-xl" />
42
+ <p class="text-xs font-semibold">Javascript</p>
43
+ </header>
44
+ <main class="px-6 py-6">
45
+ <Highlight language={javascript} {code} />
46
+ <button class="flex justify-end relative w-full" on:click={handleCopy}>
47
+ <Icon icon="solar:copy-bold-duotone" class="text-slate-500 cursor-pointer hover:text-slate-300 transition-all duration-75 w-5 h-5" />
48
+ <div
49
+ class="bg-indigo-500/60 text-slate-100 text-xs font-semibold absolute bottom-0 right-0 z-10 rounded-lg px-2 py-1 pointer-events-none -translate-y-full transition-all duration-200"
50
+ class:opacity-0={!isCopied}
51
+ >
52
+ Copied!
53
+ </div>
54
+ </button>
55
+ </main>
56
+ </div>
src/lib/components/snippets/Python.svelte ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <script lang="ts">
2
+ import Icon from '@iconify/svelte';
3
+ import Highlight from "svelte-highlight";
4
+ import javascript from "svelte-highlight/languages/javascript";
5
+ import { PUBLIC_INFERENCE_API_URL } from '$env/static/public'
6
+
7
+ export let body: Record<string, any>;
8
+ export let endpoint: string;
9
+ export let headers: Record<string, any>;
10
+ export let onCopyToClipboard: (e: string) => void;
11
+
12
+ let isCopied: boolean = false;
13
+
14
+ const generateCurlRequestFromEndpoint = (body: Record<string, any>) => {
15
+ const fullpath = `${PUBLIC_INFERENCE_API_URL}/models/${endpoint}`;
16
+ delete body.model
17
+
18
+ const removeEmptyValues = (data: Record<string, any>) => {
19
+ const formattedData = { ...data };
20
+ Object.entries(formattedData).forEach(([key, value]) => {
21
+ if (typeof value === "object") {
22
+ const new_value = removeEmptyValues(value);
23
+ formattedData[key] = new_value
24
+ } else {
25
+ if (typeof value === "boolean") {
26
+ formattedData[key] = value ? "True" : "False";
27
+ }
28
+ }
29
+ });
30
+ return formattedData;
31
+ };
32
+
33
+ const formattedBody = removeEmptyValues(body ?? {});
34
+ return `import requests
35
+ response = requests.post(
36
+ "${fullpath}",
37
+ json=${JSON.stringify(formattedBody)},
38
+ headers=${JSON.stringify(headers)}
39
+ )`;
40
+ };
41
+
42
+ const handleCopy = () => {
43
+ onCopyToClipboard(generateCurlRequestFromEndpoint(body));
44
+ isCopied = true
45
+ setTimeout(() => {
46
+ isCopied = false
47
+ }, 1000);
48
+ };
49
+
50
+ $: code = generateCurlRequestFromEndpoint(body)
51
+ </script>
52
+
53
+ <div class="bg-slate-900/50 rounded-xl overflow-hidden">
54
+ <header class="bg-slate-900 flex items-center justify-start px-5 py-4 uppercase gap-2 text-blue-500">
55
+ <Icon icon="logos:python" class="text-xl" />
56
+ <p class="text-xs font-semibold">Python</p>
57
+ </header>
58
+ <main class="px-6 py-6">
59
+ <Highlight language={javascript} {code} />
60
+ <button class="flex justify-end relative w-full" on:click={handleCopy}>
61
+ <Icon icon="solar:copy-bold-duotone" class="text-slate-500 cursor-pointer hover:text-slate-300 transition-all duration-75 w-5 h-5" />
62
+ <div
63
+ class="bg-indigo-500/60 text-slate-100 text-xs font-semibold absolute bottom-0 right-0 z-10 rounded-lg px-2 py-1 pointer-events-none -translate-y-full transition-all duration-200"
64
+ class:opacity-0={!isCopied}
65
+ >
66
+ Copied!
67
+ </div>
68
+ </button>
69
+ </main>
70
+ </div>
src/lib/components/text-generation/Form.svelte ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <script lang="ts">
2
+ import Prompt from "$lib/components/Prompt.svelte";
3
+ import SelectModel from "$lib/components/SelectModel.svelte";
4
+ import Input from "$lib/components/Input.svelte";
5
+ import Toggle from "$lib/components/Toggle.svelte";
6
+ import { TEXT_GENERATIONS } from "$lib/utils/models";
7
+
8
+ export let loading: boolean;
9
+ export let form: Record<string, any>;
10
+ export let onForm: (form: Record<string, any>) => void;
11
+ </script>
12
+
13
+ <SelectModel value={form.model} items={TEXT_GENERATIONS} onChange={(model) => onForm({ ...form, model })} />
14
+ <Prompt
15
+ value={form.inputs}
16
+ onChange={(inputs) => onForm({ ...form, inputs })}
17
+ />
18
+ <div class="flex items-center justify-start gap-4 mt-3">
19
+ <p class="text-slate-500 uppercase font-medium text-sm">
20
+ Optional parameters
21
+ </p>
22
+ <div class="w-full flex-1 h-[1px] bg-slate-600" />
23
+ </div>
24
+ <div class="grid grid-cols-2 gap-x-10 gap-y-6">
25
+ <div class="flex flex-col gap-3">
26
+ <Toggle
27
+ label="Do Sample"
28
+ tooltip="If set to False (the default), the generation method will be greedy search, which selects the most probable continuation sequence after the prompt you provide. Greedy search is deterministic, so the same results will always be returned from the same input. When do_sample is True, tokens will be sampled from a probability distribution and will therefore vary across invocations."
29
+ checked={form?.parameters?.do_sample}
30
+ onChange={(do_sample) =>
31
+ onForm({
32
+ ...form,
33
+ parameters: { ...form.parameters, do_sample },
34
+ })
35
+ }
36
+ />
37
+ <Input
38
+ label="Max new tokens"
39
+ type="number"
40
+ tooltip="Whether to include the input sequence in the output returned by the endpoint. The default used by InferenceClient is False, but the endpoint itself uses True by default."
41
+ min={1}
42
+ max={244}
43
+ sanitize={(value) => {
44
+ const valueAsNumber = Number(value);
45
+ if (valueAsNumber < 1) return 1;
46
+ if (valueAsNumber > 244) return 244;
47
+ return valueAsNumber;
48
+ }}
49
+ value={form?.parameters?.max_new_tokens}
50
+ onChange={(max_new_tokens) =>
51
+ onForm({
52
+ ...form,
53
+ parameters: { ...form.parameters, max_new_tokens },
54
+ })
55
+ }
56
+ />
57
+ <Input
58
+ label="Temperature"
59
+ type="number"
60
+ tooltip="Controls the amount of variation we desire from the generation. A temperature of 0 is equivalent to greedy search. If we set a value for temperature, then do_sample will automatically be enabled. The same thing happens for top_k and top_p. When doing code-related tasks, we want less variability and hence recommend a low temperature. For other tasks, such as open-ended text generation, we recommend a higher one."
61
+ min={0}
62
+ max={1}
63
+ sanitize={(value) => {
64
+ const valueAsNumber = Number(value);
65
+ if (valueAsNumber > 1) return 1;
66
+ if (valueAsNumber < 0) return 0;
67
+ return valueAsNumber;
68
+ }}
69
+ value={form?.parameters?.temperature}
70
+ onChange={(temperature) =>
71
+ onForm({
72
+ ...form,
73
+ parameters: { ...form.parameters, temperature },
74
+ })
75
+ }
76
+ />
77
+ </div>
78
+ <div class="flex flex-col gap-3">
79
+ <Toggle
80
+ label="Return full Text"
81
+ tooltip="Whether to include the input sequence in the output returned by the endpoint. The default used by InferenceClient is False, but the endpoint itself uses True by default."
82
+ checked={form?.parameters?.return_full_text}
83
+ onChange={(return_full_text) =>
84
+ onForm({
85
+ ...form,
86
+ parameters: { ...form.parameters, return_full_text },
87
+ })
88
+ }
89
+ />
90
+ <Input
91
+ label="Top K"
92
+ type="number"
93
+ tooltip={`Enables "Top-K" sampling: the model will choose from the K most probable tokens that may occur after the input sequence. Typical values are between 10 to 50.`}
94
+ min={10}
95
+ max={50}
96
+ sanitize={(value) => {
97
+ const valueAsNumber = Number(value);
98
+ if (valueAsNumber < 10) return 10;
99
+ if (valueAsNumber > 50) return 50;
100
+ return valueAsNumber;
101
+ }}
102
+ value={form?.parameters?.top_k}
103
+ onChange={(top_k) =>
104
+ onForm({
105
+ ...form,
106
+ parameters: { ...form.parameters, top_k },
107
+ })
108
+ }
109
+ />
110
+ <Input
111
+ label="Stop sequences"
112
+ tooltip="A list of sequences that will cause generation to stop when encountered in the output."
113
+ subLabel="Separate each sequence with a comma"
114
+ value={form?.parameters?.stop_sequences}
115
+ onChange={(stop_sequences) =>
116
+ onForm({
117
+ ...form,
118
+ parameters: { ...form.parameters, stop_sequences },
119
+ })
120
+ }
121
+ />
122
+ </div>
123
+ </div>
src/lib/components/text-generation/Preview.svelte ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <script lang="ts">
2
+ export let body: Record<string, any>;
3
+ export let res: Record<string, any>;
4
+
5
+ console.log(body)
6
+ </script>
7
+
8
+ <div class="text-white p-6 font-code text-xs !leading-loose">
9
+ {body.inputs ?? "No input provided"}
10
+ {#if res?.[0]?.generated_text}
11
+ <span>{res[0]?.generated_text?.replace(body?.inputs, "")}</span>
12
+ {/if}
13
+ </div>
src/lib/components/text-generation/Response.svelte ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <script lang="ts">
2
+ import Icon from '@iconify/svelte';
3
+ import Highlight, { LineNumbers } from "svelte-highlight";
4
+ import json from "svelte-highlight/languages/json";
5
+ import "svelte-highlight/styles/night-owl.css"
6
+
7
+ import Loading from "$lib/components/Loading.svelte"
8
+ import CodePreview from '$lib/components/CodePreview.svelte';
9
+ import Preview from '$lib/components/text-generation/Preview.svelte';
10
+
11
+ export let loading: boolean;
12
+ export let res: any;
13
+ export let form: Record<string, any>;
14
+ export let body: Record<string, any>;
15
+ export let endpoint: string;
16
+
17
+ let tab = 0
18
+
19
+ $: code = JSON.stringify(res ?? {}, null, 2)
20
+
21
+ let TABS = [
22
+ {
23
+ label: "Formatted preview",
24
+ icon: "material-symbols:preview",
25
+ },
26
+ {
27
+ label: "Code example",
28
+ icon: "carbon:code",
29
+ },
30
+ ];
31
+ </script>
32
+
33
+ <div class="h-screen flex flex-col relative">
34
+ <div class="w-full jsonResponse relative">
35
+ <div class="bg-slate-950 w-full uppercase px-5 py-4 text-zinc-400 text-sm font-semibold border-b border-slate-900 flex items-center justify-start gap-2">
36
+ <Icon icon="carbon:json" class="w-5 h-5" />
37
+ Response
38
+ </div>
39
+ <Highlight language={json} {code}>
40
+ </Highlight>
41
+ {#if loading}
42
+ <Loading>
43
+ <p class="text-slate-400 text-lg mt-4">Processing...</p>
44
+ </Loading>
45
+ {/if}
46
+ </div>
47
+ <div class="bg-slate-950 overflow-auto flex-1">
48
+ <div class="w-full uppercase text-zinc-400 text-sm font-semibold border-t border-slate-900 flex items-start sticky top-0 bg-slate-950">
49
+ {#each TABS as { label, icon }, idx }
50
+ <button
51
+ class={`flex items-center justify-start gap-2 px-5 border-r py-4 border-slate-900 bg-slate-900/40 cursor-pointer hover:bg-slate-900/60 transition-all duration-200 ${tab === idx ? '!bg-slate-950 hover:bg-slate-900/40' : 'border-b'}`}
52
+ on:click={() => tab = idx}
53
+ >
54
+ <Icon icon={icon} class="w-5 h-5" />
55
+ {label}
56
+ </button>
57
+ {/each}
58
+ <div class="flex flex-1 w-full pointer-events-none text-slate-950 border-b border-slate-900 h-[53px] bg-slate-900/40"></div>
59
+ </div>
60
+ {#if tab === 0}
61
+ <Preview body={body} res={res} />
62
+ {:else if tab === 1}
63
+ <CodePreview body={form} endpoint={endpoint} />
64
+ {/if}
65
+ </div>
66
+ </div>
src/lib/images/github.svg ADDED
src/lib/images/hf-logo.svg ADDED
src/lib/images/svelte-logo.svg ADDED
src/lib/images/svelte-welcome.png ADDED
src/lib/images/svelte-welcome.webp ADDED
src/lib/styles/tailwind.css ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @tailwind base;
2
+ @tailwind components;
3
+ @tailwind utilities;
4
+
5
+ body, html {
6
+ @apply bg-slate-950 overflow-hidden min-h-screen;
7
+ font-family: "Source Sans 3", "sans-serif";
8
+ }
9
+
10
+ .jsonResponse .hljs {
11
+ @apply !text-sm !bg-black !font-code !whitespace-pre-wrap !p-8 !leading-relaxed;
12
+ }
13
+ .jsonResponse tbody.hljs {
14
+ @apply !h-full !leading-loose
15
+ }
16
+ .jsonResponse tbody.hljs tr td:first-of-type code {
17
+ @apply opacity-60 pl-2
18
+ }
19
+
20
+ .snippet .hljs {
21
+ @apply text-xs font-code !bg-transparent !p-0 !whitespace-pre-wrap break-all !leading-relaxed
22
+ }
src/lib/utils/models.ts ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import type { Model } from "./type";
2
+
3
+ export const TEXT_GENERATIONS: Array<Model> = [
4
+ {
5
+ id: "meta-llama/Llama-2-7b-chat-hf",
6
+ logo: "https://aeiljuispo.cloudimg.io/v7/https://cdn-uploads.huggingface.co/production/uploads/646cf8084eefb026fb8fd8bc/oCTqufkdTkjyGodsx1vo1.png?w=200&h=200&f=face",
7
+ },
8
+ {
9
+ id: "HuggingFaceH4/zephyr-7b-beta",
10
+ logo: "https://aeiljuispo.cloudimg.io/v7/https://cdn-uploads.huggingface.co/production/uploads/5f0c746619cb630495b814fd/j26aNEdiOgptZxJ6akGCC.png?w=200&h=200&f=face",
11
+ },
12
+ {
13
+ id: "mistralai/Mistral-7B-v0.1",
14
+ logo: "https://aeiljuispo.cloudimg.io/v7/https://cdn-uploads.huggingface.co/production/uploads/62dac1c7a8ead43d20e3e17a/wrLf5yaGC6ng4XME70w6Z.png?w=200&h=200&f=face",
15
+ },
16
+ ];
17
+
18
+ export const IMAGE_GENERATIONS: Array<Model> = [
19
+ {
20
+ id: "stabilityai/stable-diffusion-xl-base-1.0",
21
+ logo: "https://aeiljuispo.cloudimg.io/v7/https://cdn-uploads.huggingface.co/production/uploads/643feeb67bc3fbde1385cc25/7vmYr2XwVcPtkLzac_jxQ.png?w=200&h=200&f=face"
22
+ },
23
+ ]
src/lib/utils/type.ts ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ export interface Model {
2
+ id: string;
3
+ logo: string;
4
+ }
src/routes/+layout.svelte ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <script>
2
+ import Sidebar from '$lib/components/sidebar/Sidebar.svelte';
3
+ import '$lib/styles/tailwind.css';
4
+ </script>
5
+
6
+ <div class="app flex items-start justify-start">
7
+ <Sidebar />
8
+
9
+ <slot />
10
+
11
+ </div>
12
+
src/routes/+page.svelte ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <script>
2
+ import Counter from './Counter.svelte';
3
+ import welcome from '$lib/images/svelte-welcome.webp';
4
+ import welcome_fallback from '$lib/images/svelte-welcome.png';
5
+ </script>
6
+
7
+ <svelte:head>
8
+ <title>Home</title>
9
+ <meta name="description" content="Svelte demo app" />
10
+ </svelte:head>
11
+
12
+ <section>
13
+ <h1>
14
+ <span class="welcome">
15
+ <picture>
16
+ <source srcset={welcome} type="image/webp" />
17
+ <img src={welcome_fallback} alt="Welcome" />
18
+ </picture>
19
+ </span>
20
+
21
+ to your new<br />SvelteKit app
22
+ </h1>
23
+
24
+ <h2>
25
+ try editing <strong>src/routes/+page.svelte</strong>
26
+ </h2>
27
+
28
+ <Counter />
29
+ </section>
30
+
31
+ <style>
32
+ section {
33
+ display: flex;
34
+ flex-direction: column;
35
+ justify-content: center;
36
+ align-items: center;
37
+ flex: 0.6;
38
+ }
39
+
40
+ h1 {
41
+ width: 100%;
42
+ }
43
+
44
+ .welcome {
45
+ display: block;
46
+ position: relative;
47
+ width: 100%;
48
+ height: 0;
49
+ padding: 0 0 calc(100% * 495 / 2048) 0;
50
+ }
51
+
52
+ .welcome img {
53
+ position: absolute;
54
+ width: 100%;
55
+ height: 100%;
56
+ top: 0;
57
+ display: block;
58
+ }
59
+ </style>
src/routes/+page.ts ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ // since there's no dynamic data here, we can prerender
2
+ // it so that it gets served as a static asset in production
3
+ export const prerender = true;
src/routes/Counter.svelte ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <script lang="ts">
2
+ import { spring } from 'svelte/motion';
3
+
4
+ let count = 0;
5
+
6
+ const displayed_count = spring();
7
+ $: displayed_count.set(count);
8
+ $: offset = modulo($displayed_count, 1);
9
+
10
+ function modulo(n: number, m: number) {
11
+ // handle negative numbers
12
+ return ((n % m) + m) % m;
13
+ }
14
+ </script>
15
+
16
+ <div class="counter">
17
+ <button on:click={() => (count -= 1)} aria-label="Decrease the counter by one">
18
+ <svg aria-hidden="true" viewBox="0 0 1 1">
19
+ <path d="M0,0.5 L1,0.5" />
20
+ </svg>
21
+ </button>
22
+
23
+ <div class="counter-viewport">
24
+ <div class="counter-digits" style="transform: translate(0, {100 * offset}%)">
25
+ <strong class="hidden" aria-hidden="true">{Math.floor($displayed_count + 1)}</strong>
26
+ <strong>{Math.floor($displayed_count)}</strong>
27
+ </div>
28
+ </div>
29
+
30
+ <button on:click={() => (count += 1)} aria-label="Increase the counter by one">
31
+ <svg aria-hidden="true" viewBox="0 0 1 1">
32
+ <path d="M0,0.5 L1,0.5 M0.5,0 L0.5,1" />
33
+ </svg>
34
+ </button>
35
+ </div>
36
+
37
+ <style>
38
+ .counter {
39
+ display: flex;
40
+ border-top: 1px solid rgba(0, 0, 0, 0.1);
41
+ border-bottom: 1px solid rgba(0, 0, 0, 0.1);
42
+ margin: 1rem 0;
43
+ }
44
+
45
+ .counter button {
46
+ width: 2em;
47
+ padding: 0;
48
+ display: flex;
49
+ align-items: center;
50
+ justify-content: center;
51
+ border: 0;
52
+ background-color: transparent;
53
+ touch-action: manipulation;
54
+ font-size: 2rem;
55
+ }
56
+
57
+ .counter button:hover {
58
+ background-color: var(--color-bg-1);
59
+ }
60
+
61
+ svg {
62
+ width: 25%;
63
+ height: 25%;
64
+ }
65
+
66
+ path {
67
+ vector-effect: non-scaling-stroke;
68
+ stroke-width: 2px;
69
+ stroke: #444;
70
+ }
71
+
72
+ .counter-viewport {
73
+ width: 8em;
74
+ height: 4em;
75
+ overflow: hidden;
76
+ text-align: center;
77
+ position: relative;
78
+ }
79
+
80
+ .counter-viewport strong {
81
+ position: absolute;
82
+ display: flex;
83
+ width: 100%;
84
+ height: 100%;
85
+ font-weight: 400;
86
+ color: var(--color-theme-1);
87
+ font-size: 4rem;
88
+ align-items: center;
89
+ justify-content: center;
90
+ }
91
+
92
+ .counter-digits {
93
+ position: absolute;
94
+ width: 100%;
95
+ height: 100%;
96
+ }
97
+
98
+ .hidden {
99
+ top: -100%;
100
+ user-select: none;
101
+ }
102
+ </style>
src/routes/Header.svelte ADDED
@@ -0,0 +1,129 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <script>
2
+ import { page } from '$app/stores';
3
+ import logo from '$lib/images/svelte-logo.svg';
4
+ import github from '$lib/images/github.svg';
5
+ </script>
6
+
7
+ <header>
8
+ <div class="corner">
9
+ <a href="https://kit.svelte.dev">
10
+ <img src={logo} alt="SvelteKit" />
11
+ </a>
12
+ </div>
13
+
14
+ <nav>
15
+ <svg viewBox="0 0 2 3" aria-hidden="true">
16
+ <path d="M0,0 L1,2 C1.5,3 1.5,3 2,3 L2,0 Z" />
17
+ </svg>
18
+ <ul>
19
+ <li aria-current={$page.url.pathname === '/' ? 'page' : undefined}>
20
+ <a href="/">Home</a>
21
+ </li>
22
+ <li aria-current={$page.url.pathname === '/about' ? 'page' : undefined}>
23
+ <a href="/about">About</a>
24
+ </li>
25
+ <li aria-current={$page.url.pathname.startsWith('/sverdle') ? 'page' : undefined}>
26
+ <a href="/sverdle">Sverdle</a>
27
+ </li>
28
+ </ul>
29
+ <svg viewBox="0 0 2 3" aria-hidden="true">
30
+ <path d="M0,0 L0,3 C0.5,3 0.5,3 1,2 L2,0 Z" />
31
+ </svg>
32
+ </nav>
33
+
34
+ <div class="corner">
35
+ <a href="https://github.com/sveltejs/kit">
36
+ <img src={github} alt="GitHub" />
37
+ </a>
38
+ </div>
39
+ </header>
40
+
41
+ <style>
42
+ header {
43
+ display: flex;
44
+ justify-content: space-between;
45
+ }
46
+
47
+ .corner {
48
+ width: 3em;
49
+ height: 3em;
50
+ }
51
+
52
+ .corner a {
53
+ display: flex;
54
+ align-items: center;
55
+ justify-content: center;
56
+ width: 100%;
57
+ height: 100%;
58
+ }
59
+
60
+ .corner img {
61
+ width: 2em;
62
+ height: 2em;
63
+ object-fit: contain;
64
+ }
65
+
66
+ nav {
67
+ display: flex;
68
+ justify-content: center;
69
+ --background: rgba(255, 255, 255, 0.7);
70
+ }
71
+
72
+ svg {
73
+ width: 2em;
74
+ height: 3em;
75
+ display: block;
76
+ }
77
+
78
+ path {
79
+ fill: var(--background);
80
+ }
81
+
82
+ ul {
83
+ position: relative;
84
+ padding: 0;
85
+ margin: 0;
86
+ height: 3em;
87
+ display: flex;
88
+ justify-content: center;
89
+ align-items: center;
90
+ list-style: none;
91
+ background: var(--background);
92
+ background-size: contain;
93
+ }
94
+
95
+ li {
96
+ position: relative;
97
+ height: 100%;
98
+ }
99
+
100
+ li[aria-current='page']::before {
101
+ --size: 6px;
102
+ content: '';
103
+ width: 0;
104
+ height: 0;
105
+ position: absolute;
106
+ top: 0;
107
+ left: calc(50% - var(--size));
108
+ border: var(--size) solid transparent;
109
+ border-top: var(--size) solid var(--color-theme-1);
110
+ }
111
+
112
+ nav a {
113
+ display: flex;
114
+ height: 100%;
115
+ align-items: center;
116
+ padding: 0 0.5rem;
117
+ color: var(--color-text);
118
+ font-weight: 700;
119
+ font-size: 0.8rem;
120
+ text-transform: uppercase;
121
+ letter-spacing: 0.1em;
122
+ text-decoration: none;
123
+ transition: color 0.2s linear;
124
+ }
125
+
126
+ a:hover {
127
+ color: var(--color-theme-1);
128
+ }
129
+ </style>
src/routes/about/+page.svelte ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <svelte:head>
2
+ <title>About</title>
3
+ <meta name="description" content="About this app" />
4
+ </svelte:head>
5
+
6
+ <div class="text-column">
7
+ <h1>About this app</h1>
8
+
9
+ <p>
10
+ This is a <a href="https://kit.svelte.dev">SvelteKit</a> app. You can make your own by typing the
11
+ following into your command line and following the prompts:
12
+ </p>
13
+
14
+ <pre>npm create svelte@latest</pre>
15
+
16
+ <p>
17
+ The page you're looking at is purely static HTML, with no client-side interactivity needed.
18
+ Because of that, we don't need to load any JavaScript. Try viewing the page's source, or opening
19
+ the devtools network panel and reloading.
20
+ </p>
21
+
22
+ <p>
23
+ The <a href="/sverdle">Sverdle</a> page illustrates SvelteKit's data loading and form handling. Try
24
+ using it with JavaScript disabled!
25
+ </p>
26
+ </div>
src/routes/about/+page.ts ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ import { dev } from '$app/environment';
2
+
3
+ // we don't need any JS on this page, though we'll load
4
+ // it in dev so that we get hot module replacement
5
+ export const csr = dev;
6
+
7
+ // since there's no dynamic data here, we can prerender
8
+ // it so that it gets served as a static asset in production
9
+ export const prerender = true;
src/routes/api/image-generation/+server.ts ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { error, type RequestEvent } from '@sveltejs/kit';
2
+ import { SECRET_HF_TOKEN } from '$env/static/private'
3
+ import { PUBLIC_INFERENCE_API_URL } from '$env/static/public'
4
+
5
+ /** @type {import('./$types').RequestHandler} */
6
+ export async function POST({ request }: RequestEvent) {
7
+ const body = await request?.json().catch(() => {});
8
+
9
+ if (!body?.model) {
10
+ throw error(400, 'missing model value')
11
+ }
12
+
13
+ if (!body?.inputs || body.inputs === null) {
14
+ throw error(400, 'missing inputs value')
15
+ }
16
+
17
+ const response = await fetch(PUBLIC_INFERENCE_API_URL + "/models/" + body.model, {
18
+ method: "POST",
19
+ headers: {
20
+ Authorization: `Bearer ${SECRET_HF_TOKEN}`,
21
+ 'Content-Type': 'application/json',
22
+ ['x-use-cache']: "0"
23
+ },
24
+ body: JSON.stringify({
25
+ ...body,
26
+ stop_sequences: body?.stop_sequences?.split(",") ?? undefined,
27
+ }),
28
+ })
29
+ .then((res) => res.blob())
30
+ .then((blob) => blob)
31
+ .catch((error) => {
32
+ return {
33
+ error: error.message,
34
+ }
35
+ })
36
+
37
+ if ("error" in response) {
38
+ error(400, response.error as string)
39
+ }
40
+
41
+ return {
42
+ headers: {
43
+ 'Content-Type': 'image/png',
44
+ },
45
+ body: response,
46
+ }
47
+ }
src/routes/api/text-generation/+server.ts ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { error, json, type RequestEvent } from '@sveltejs/kit';
2
+ import { SECRET_HF_TOKEN } from '$env/static/private'
3
+ import { PUBLIC_INFERENCE_API_URL } from '$env/static/public'
4
+
5
+ /** @type {import('./$types').RequestHandler} */
6
+ export async function POST({ request }: RequestEvent) {
7
+ const body = await request?.json().catch(() => {});
8
+
9
+ if (!body?.model) {
10
+ throw error(400, 'missing model value')
11
+ }
12
+
13
+ if (!body?.inputs || body.inputs === null) {
14
+ throw error(400, 'missing inputs value')
15
+ }
16
+
17
+ const response = await fetch(PUBLIC_INFERENCE_API_URL + "/models/" + body.model, {
18
+ method: "POST",
19
+ headers: {
20
+ Authorization: `Bearer ${SECRET_HF_TOKEN}`,
21
+ 'Content-Type': 'application/json',
22
+ ['x-use-cache']: "0"
23
+ },
24
+ body: JSON.stringify({
25
+ ...body,
26
+ stop_sequences: body?.stop_sequences?.split(",") ?? undefined,
27
+ }),
28
+ })
29
+ .then((res) => res.json())
30
+ .then((res) => res)
31
+ .catch((error) => {
32
+ return {
33
+ error: error.message,
34
+ }
35
+ })
36
+
37
+ if ("error" in response) {
38
+ error(400, response.error as string)
39
+ }
40
+
41
+ return json(response)
42
+ }
src/routes/image-generation/+page.svelte ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <script lang="ts">
2
+ import Form from "$lib/components/image-generation/Form.svelte";
3
+ import Response from "$lib/components/image-generation/Response.svelte";
4
+
5
+ let loading: boolean = false;
6
+ let data: string | ArrayBuffer | null = ''
7
+ let bodyRequest: Record<string, any> = {}
8
+
9
+ let form: Record<string, any> = {
10
+ model: "stabilityai/stable-diffusion-xl-base-1.0",
11
+ inputs: "A red apple on a table, high definition, realistic, 4k",
12
+ parameters: {
13
+ negative_prompt: "not blurry, not low resolution, not pixelated",
14
+ guidance_scale: 9,
15
+ width: 768,
16
+ height: 1024,
17
+ num_inference_steps: 20,
18
+ },
19
+ }
20
+
21
+ const onchange = (newForm: Record<string, any>) => form = newForm
22
+
23
+ const onsubmit = async () => {
24
+ loading = true
25
+ const request = await fetch('/api/image-generation', {
26
+ method: 'POST',
27
+ body: JSON.stringify(form),
28
+ headers: {
29
+ "Content-Type": "application/json"
30
+ }
31
+ })
32
+ const blob = await request?.clone()?.blob()
33
+
34
+ const reader = new FileReader()
35
+ reader.readAsDataURL(blob)
36
+ reader.onloadend = () => {
37
+ const base64data = reader.result
38
+ data = base64data
39
+ }
40
+
41
+ bodyRequest = form
42
+ loading = false
43
+ }
44
+ </script>
45
+
46
+ <main class="min-h-screen w-full grid grid-cols-2">
47
+ <div class="p-10 w-full flex flex-col gap-6">
48
+ <Form form={form} onForm={onchange} />
49
+ <div>
50
+ <button
51
+ class="bg-gradient-to-r from-slate-900/50 to-slate-900 border border-slate-800/40 text-white rounded-lg text-base transition-all duration-200 leading-relaxed outline-none relative py-3 px-6"
52
+ disabled={loading}
53
+ on:click={onsubmit}
54
+ >
55
+ Submit
56
+ </button>
57
+ </div>
58
+ </div>
59
+ <div class="border-l border-slate-900 bg-slate-950">
60
+ <Response loading={loading} res={data} body={bodyRequest} form={form} endpoint={form.model} />
61
+ response
62
+ </div>
63
+ </main>