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 |
+
}
|