Arsala Grey
commited on
Commit
•
c2d5ffe
1
Parent(s):
247453d
added temp param and restructured ui
Browse files- index.html +42 -22
- index.js +22 -20
- utils.css → main.css +32 -27
index.html
CHANGED
@@ -4,43 +4,63 @@
|
|
4 |
<meta charset="utf-8" />
|
5 |
<meta name="viewport" content="width=device-width" />
|
6 |
<title>Generate Text Stream - HuggingFace.js Live Examples</title>
|
7 |
-
<link rel="stylesheet" href="/
|
8 |
<link rel="stylesheet" href="/pico.classless.min.css" />
|
9 |
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
|
10 |
</head>
|
11 |
<body>
|
12 |
<div id="app" class="container">
|
13 |
<h1>Generate Text Stream with Vue</h1>
|
14 |
-
<
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
31 |
<label for="user-prompt">Prompt</label>
|
32 |
<textarea
|
33 |
id="user-prompt"
|
34 |
v-model="userPrompt"
|
35 |
-
style="width: 100%; height: 100px"
|
36 |
></textarea>
|
37 |
<div class="grid grid-cols-2 gap-2">
|
38 |
<button class="btn-error" @click="stop">STOP</button>
|
39 |
<button class="btn-success" @click="run">GENERATE</button>
|
40 |
</div>
|
41 |
-
<
|
42 |
-
<div v-
|
43 |
-
<div style="white-space: pre-wrap;" v-html="currentGeneratedText"></div>
|
44 |
</div>
|
45 |
<script type="module" src="./index.js"></script>
|
46 |
</body>
|
|
|
4 |
<meta charset="utf-8" />
|
5 |
<meta name="viewport" content="width=device-width" />
|
6 |
<title>Generate Text Stream - HuggingFace.js Live Examples</title>
|
7 |
+
<link rel="stylesheet" href="/main.css" />
|
8 |
<link rel="stylesheet" href="/pico.classless.min.css" />
|
9 |
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
|
10 |
</head>
|
11 |
<body>
|
12 |
<div id="app" class="container">
|
13 |
<h1>Generate Text Stream with Vue</h1>
|
14 |
+
<div class="grid grid-cols-2 gap-2">
|
15 |
+
<div>
|
16 |
+
<label for="hf-token"
|
17 |
+
>Hugging Face Token (optional but limited if absent)</label
|
18 |
+
>
|
19 |
+
<input
|
20 |
+
id="hf-token"
|
21 |
+
v-model="token"
|
22 |
+
placeholder="HF-TOKEN"
|
23 |
+
type="password"
|
24 |
+
/>
|
25 |
+
</div>
|
26 |
+
<div>
|
27 |
+
<label for="model-select">Select a model</label>
|
28 |
+
<select id="model-select" v-model="selectedModel">
|
29 |
+
<option v-for="model in models" :value="model">{{ model }}</option>
|
30 |
+
</select>
|
31 |
+
</div>
|
32 |
+
</div>
|
33 |
+
<div class="grid grid-cols-2 gap-2">
|
34 |
+
<div>
|
35 |
+
<label for="response-length">Response Length</label>
|
36 |
+
<select id="response-length" v-model="responseLength">
|
37 |
+
<option value="50">Short</option>
|
38 |
+
<option value="150">Medium</option>
|
39 |
+
<option value="250">Long</option>
|
40 |
+
</select>
|
41 |
+
</div>
|
42 |
+
<div>
|
43 |
+
<label for="temp">Temperature (Controls Randomness)</label>
|
44 |
+
<select id="temp" v-model="temperature">
|
45 |
+
<option value="1.0">1.0</option>
|
46 |
+
<option value="0.7">0.7</option>
|
47 |
+
<option value="0.5">0.5</option>
|
48 |
+
<option value="0.3">0.3</option>
|
49 |
+
<option value="0.1">0.1</option>
|
50 |
+
</select>
|
51 |
+
</div>
|
52 |
+
</div>
|
53 |
<label for="user-prompt">Prompt</label>
|
54 |
<textarea
|
55 |
id="user-prompt"
|
56 |
v-model="userPrompt"
|
|
|
57 |
></textarea>
|
58 |
<div class="grid grid-cols-2 gap-2">
|
59 |
<button class="btn-error" @click="stop">STOP</button>
|
60 |
<button class="btn-success" @click="run">GENERATE</button>
|
61 |
</div>
|
62 |
+
<h3>{{statusMessage}}</h3>
|
63 |
+
<div style="white-space: pre-wrap" v-html="currentGeneratedText"></div>
|
|
|
64 |
</div>
|
65 |
<script type="module" src="./index.js"></script>
|
66 |
</body>
|
index.js
CHANGED
@@ -1,34 +1,34 @@
|
|
1 |
-
const { createApp, ref, onMounted } = Vue;
|
2 |
import { HfInference } from "https://cdn.skypack.dev/@huggingface/inference@latest";
|
3 |
|
4 |
-
const textGenerationModels = [
|
5 |
-
"mistralai/Mistral-7B-v0.1",
|
6 |
-
"bigscience/bloom"
|
7 |
-
]
|
8 |
-
|
9 |
-
const responseLengthToTokenCount = {
|
10 |
-
"short": 100,
|
11 |
-
"medium": 250,
|
12 |
-
"long": 500,
|
13 |
-
}
|
14 |
-
|
15 |
const app = createApp({
|
16 |
setup() {
|
17 |
const token = ref(localStorage.getItem("token") || "");
|
18 |
-
const userPrompt = ref("Write about the difference between
|
19 |
const currentGeneratedText = ref("");
|
20 |
-
const models = ref([
|
21 |
-
|
|
|
22 |
const isRunning = ref(false);
|
23 |
-
const responseLength = ref("
|
|
|
|
|
24 |
let controller;
|
25 |
|
|
|
|
|
|
|
|
|
|
|
26 |
const createTextGenerationStream = (hfInstance, prompt, abortControllerSignal) => {
|
27 |
return hfInstance.textGenerationStream(
|
28 |
{
|
29 |
model: selectedModel.value,
|
30 |
inputs: prompt,
|
31 |
-
parameters: {
|
|
|
|
|
|
|
32 |
},
|
33 |
{
|
34 |
use_cache: false,
|
@@ -39,10 +39,12 @@ const app = createApp({
|
|
39 |
|
40 |
const generateTextStream = async function* (hfInstance, abortSignal, prompt) {
|
41 |
let generatedText = ""
|
|
|
42 |
for await (const output of createTextGenerationStream(hfInstance, prompt, abortSignal)) {
|
43 |
generatedText += output.token.text;
|
44 |
yield generatedText;
|
45 |
}
|
|
|
46 |
};
|
47 |
|
48 |
const run = async () => {
|
@@ -77,8 +79,6 @@ const app = createApp({
|
|
77 |
if (localStorageToken) {
|
78 |
token.value = localStorageToken;
|
79 |
}
|
80 |
-
models.value = textGenerationModels
|
81 |
-
selectedModel.value = textGenerationModels[0]
|
82 |
});
|
83 |
|
84 |
return {
|
@@ -90,7 +90,9 @@ const app = createApp({
|
|
90 |
models,
|
91 |
selectedModel,
|
92 |
isRunning,
|
93 |
-
responseLength,
|
|
|
|
|
94 |
};
|
95 |
},
|
96 |
});
|
|
|
1 |
+
const { createApp, ref, onMounted, computed } = Vue;
|
2 |
import { HfInference } from "https://cdn.skypack.dev/@huggingface/inference@latest";
|
3 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
const app = createApp({
|
5 |
setup() {
|
6 |
const token = ref(localStorage.getItem("token") || "");
|
7 |
+
const userPrompt = ref("Write about the difference between AI Engineering");
|
8 |
const currentGeneratedText = ref("");
|
9 |
+
const models = ref(["mistralai/Mistral-7B-v0.1",
|
10 |
+
"google/flan-t5-xxl"]);
|
11 |
+
const selectedModel = ref("mistralai/Mistral-7B-v0.1");
|
12 |
const isRunning = ref(false);
|
13 |
+
const responseLength = ref("150");
|
14 |
+
const temperature = ref("1.0");
|
15 |
+
const generating = ref(false);
|
16 |
let controller;
|
17 |
|
18 |
+
const statusMessage = computed(() => {
|
19 |
+
if (generating.value) return "Generating..."
|
20 |
+
return "Ready"
|
21 |
+
})
|
22 |
+
|
23 |
const createTextGenerationStream = (hfInstance, prompt, abortControllerSignal) => {
|
24 |
return hfInstance.textGenerationStream(
|
25 |
{
|
26 |
model: selectedModel.value,
|
27 |
inputs: prompt,
|
28 |
+
parameters: {
|
29 |
+
max_new_tokens: parseInt(responseLength.value),
|
30 |
+
temperature: parseFloat(temperature.value),
|
31 |
+
},
|
32 |
},
|
33 |
{
|
34 |
use_cache: false,
|
|
|
39 |
|
40 |
const generateTextStream = async function* (hfInstance, abortSignal, prompt) {
|
41 |
let generatedText = ""
|
42 |
+
generating.value = true
|
43 |
for await (const output of createTextGenerationStream(hfInstance, prompt, abortSignal)) {
|
44 |
generatedText += output.token.text;
|
45 |
yield generatedText;
|
46 |
}
|
47 |
+
generating.value = false
|
48 |
};
|
49 |
|
50 |
const run = async () => {
|
|
|
79 |
if (localStorageToken) {
|
80 |
token.value = localStorageToken;
|
81 |
}
|
|
|
|
|
82 |
});
|
83 |
|
84 |
return {
|
|
|
90 |
models,
|
91 |
selectedModel,
|
92 |
isRunning,
|
93 |
+
responseLength,
|
94 |
+
temperature,
|
95 |
+
statusMessage
|
96 |
};
|
97 |
},
|
98 |
});
|
utils.css → main.css
RENAMED
@@ -1,89 +1,89 @@
|
|
1 |
/* Flexbox utilities */
|
2 |
.flex {
|
3 |
-
|
4 |
}
|
5 |
|
6 |
.flex-row {
|
7 |
-
|
8 |
}
|
9 |
|
10 |
.flex-column {
|
11 |
-
|
12 |
}
|
13 |
|
14 |
.justify-center {
|
15 |
-
|
16 |
}
|
17 |
|
18 |
.align-center {
|
19 |
-
|
20 |
}
|
21 |
|
22 |
/* Grid utilities */
|
23 |
.grid {
|
24 |
-
|
25 |
}
|
26 |
|
27 |
.grid-cols {
|
28 |
-
|
29 |
}
|
30 |
|
31 |
@media (min-width: 640px) {
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
}
|
36 |
|
37 |
@media (min-width: 768px) {
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
}
|
42 |
|
43 |
.grid-cols-1 {
|
44 |
-
|
45 |
}
|
46 |
|
47 |
.grid-cols-2 {
|
48 |
-
|
49 |
}
|
50 |
|
51 |
.grid-cols-3 {
|
52 |
-
|
53 |
}
|
54 |
|
55 |
.grid-cols-4 {
|
56 |
-
|
57 |
}
|
58 |
|
59 |
/* Gap utilities */
|
60 |
.gap-0 {
|
61 |
-
|
62 |
}
|
63 |
|
64 |
.gap-1 {
|
65 |
-
|
66 |
}
|
67 |
|
68 |
.gap-2 {
|
69 |
-
|
70 |
}
|
71 |
|
72 |
.gap-3 {
|
73 |
-
|
74 |
}
|
75 |
|
76 |
.gap-4 {
|
77 |
-
|
78 |
}
|
79 |
|
80 |
/* Responsive container class */
|
81 |
|
82 |
.container {
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
}
|
88 |
|
89 |
.btn-error {
|
@@ -114,4 +114,9 @@
|
|
114 |
.btn-success:hover {
|
115 |
background-color: #0ca83d;
|
116 |
border-color: #0ca83d;
|
117 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
1 |
/* Flexbox utilities */
|
2 |
.flex {
|
3 |
+
display: flex;
|
4 |
}
|
5 |
|
6 |
.flex-row {
|
7 |
+
flex-direction: row;
|
8 |
}
|
9 |
|
10 |
.flex-column {
|
11 |
+
flex-direction: column;
|
12 |
}
|
13 |
|
14 |
.justify-center {
|
15 |
+
justify-content: center;
|
16 |
}
|
17 |
|
18 |
.align-center {
|
19 |
+
align-items: center;
|
20 |
}
|
21 |
|
22 |
/* Grid utilities */
|
23 |
.grid {
|
24 |
+
display: grid;
|
25 |
}
|
26 |
|
27 |
.grid-cols {
|
28 |
+
grid-template-columns: repeat(1, minmax(0, 1fr));
|
29 |
}
|
30 |
|
31 |
@media (min-width: 640px) {
|
32 |
+
.grid-cols {
|
33 |
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
34 |
+
}
|
35 |
}
|
36 |
|
37 |
@media (min-width: 768px) {
|
38 |
+
.grid-cols {
|
39 |
+
grid-template-columns: repeat(3, minmax(0, 1fr));
|
40 |
+
}
|
41 |
}
|
42 |
|
43 |
.grid-cols-1 {
|
44 |
+
grid-template-columns: repeat(1, minmax(0, 1fr));
|
45 |
}
|
46 |
|
47 |
.grid-cols-2 {
|
48 |
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
49 |
}
|
50 |
|
51 |
.grid-cols-3 {
|
52 |
+
grid-template-columns: repeat(3, minmax(0, 1fr));
|
53 |
}
|
54 |
|
55 |
.grid-cols-4 {
|
56 |
+
grid-template-columns: repeat(4, minmax(0, 1fr));
|
57 |
}
|
58 |
|
59 |
/* Gap utilities */
|
60 |
.gap-0 {
|
61 |
+
gap: 0;
|
62 |
}
|
63 |
|
64 |
.gap-1 {
|
65 |
+
gap: 0.25rem;
|
66 |
}
|
67 |
|
68 |
.gap-2 {
|
69 |
+
gap: 0.5rem;
|
70 |
}
|
71 |
|
72 |
.gap-3 {
|
73 |
+
gap: 0.75rem;
|
74 |
}
|
75 |
|
76 |
.gap-4 {
|
77 |
+
gap: 1rem;
|
78 |
}
|
79 |
|
80 |
/* Responsive container class */
|
81 |
|
82 |
.container {
|
83 |
+
width: 100%;
|
84 |
+
max-width: 1280px;
|
85 |
+
margin: 0 auto;
|
86 |
+
padding: 2rem;
|
87 |
}
|
88 |
|
89 |
.btn-error {
|
|
|
114 |
.btn-success:hover {
|
115 |
background-color: #0ca83d;
|
116 |
border-color: #0ca83d;
|
117 |
+
}
|
118 |
+
|
119 |
+
#user-prompt {
|
120 |
+
width: 100%;
|
121 |
+
height: 100px;
|
122 |
+
}
|