Spaces:
Running
Running
add the missing modal so i can put the API key from huggingface and use models pls. it should be able to generate also from models on hugging face, video; sound & images, the MOST SOTA ever - Follow Up Deployment
Browse files- index.html +209 -4
index.html
CHANGED
@@ -241,6 +241,95 @@ Query: {query} Include: 1) Technical requirements 2) Implementation steps 3) Sam
|
|
241 |
</div>
|
242 |
</div>
|
243 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
244 |
<script>
|
245 |
// API Client
|
246 |
class HuggingFaceClient {
|
@@ -270,7 +359,18 @@ Query: {query} Include: 1) Technical requirements 2) Implementation steps 3) Sam
|
|
270 |
throw new Error(error.error || 'API request failed');
|
271 |
}
|
272 |
|
273 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
274 |
}
|
275 |
}
|
276 |
|
@@ -291,7 +391,23 @@ Query: {query} Include: 1) Technical requirements 2) Implementation steps 3) Sam
|
|
291 |
localStorage.setItem('terminalHistory', JSON.stringify(AppState.history));
|
292 |
}
|
293 |
|
294 |
-
static async streamResponse(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
295 |
const terminalOutput = document.querySelector('.terminal-scrollbar');
|
296 |
const responseDiv = document.createElement('div');
|
297 |
responseDiv.className = 'mb-4';
|
@@ -415,8 +531,97 @@ Query: {query} Include: 1) Technical requirements 2) Implementation steps 3) Sam
|
|
415 |
}
|
416 |
|
417 |
static showSettings() {
|
418 |
-
|
419 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
420 |
}
|
421 |
}
|
422 |
|
|
|
241 |
</div>
|
242 |
</div>
|
243 |
</div>
|
244 |
+
|
245 |
+
<!-- Settings Modal -->
|
246 |
+
<div id="settingsModal" class="fixed inset-0 bg-black/80 z-50 hidden flex items-center justify-center">
|
247 |
+
<div class="bg-gray-900 border-2 border-cyan-700 rounded-lg w-full max-w-2xl max-h-[90vh] overflow-y-auto">
|
248 |
+
<div class="sticky top-0 bg-gray-900 border-b border-cyan-700 p-4 flex justify-between items-center">
|
249 |
+
<h3 class="text-xl text-green-400 font-bold">NEUROCOGNITIVE TERMINAL SETTINGS</h3>
|
250 |
+
<button onclick="document.getElementById('settingsModal').classList.add('hidden')"
|
251 |
+
class="text-cyan-400 hover:text-red-500">
|
252 |
+
<i class="fas fa-times"></i>
|
253 |
+
</button>
|
254 |
+
</div>
|
255 |
+
|
256 |
+
<div class="p-6">
|
257 |
+
<div class="mb-6">
|
258 |
+
<label class="block text-cyan-300 mb-2">HuggingFace API Key</label>
|
259 |
+
<input type="password" id="hfApiKeyInput"
|
260 |
+
class="w-full bg-black/50 border border-cyan-700 rounded px-3 py-2 text-green-300 focus:outline-none focus:ring-1 focus:ring-cyan-500"
|
261 |
+
placeholder="hf_xxxxxxxxxxxxxxxxxxxx">
|
262 |
+
<p class="text-xs text-gray-500 mt-1">Get your API key from <a href="https://huggingface.co/settings/tokens" target="_blank" class="text-blue-400 hover:underline">HuggingFace settings</a></p>
|
263 |
+
</div>
|
264 |
+
|
265 |
+
<div class="mb-6">
|
266 |
+
<label class="block text-cyan-300 mb-2">Model Type</label>
|
267 |
+
<div class="grid grid-cols-2 gap-4">
|
268 |
+
<div>
|
269 |
+
<input type="radio" id="modelTypeText" name="modelType" value="text" checked
|
270 |
+
class="hidden peer">
|
271 |
+
<label for="modelTypeText" class="block p-3 border border-cyan-700 rounded cursor-pointer peer-checked:border-green-500 peer-checked:bg-green-900/20">
|
272 |
+
<div class="flex items-center">
|
273 |
+
<i class="fas fa-font text-green-400 mr-2"></i>
|
274 |
+
<span>Text Generation</span>
|
275 |
+
</div>
|
276 |
+
</label>
|
277 |
+
</div>
|
278 |
+
<div>
|
279 |
+
<input type="radio" id="modelTypeMultimodal" name="modelType" value="multimodal"
|
280 |
+
class="hidden peer">
|
281 |
+
<label for="modelTypeMultimodal" class="block p-3 border border-cyan-700 rounded cursor-pointer peer-checked:border-purple-500 peer-checked:bg-purple-900/20">
|
282 |
+
<div class="flex items-center">
|
283 |
+
<i class="fas fa-images text-purple-400 mr-2"></i>
|
284 |
+
<span>Multimodal</span>
|
285 |
+
</div>
|
286 |
+
</label>
|
287 |
+
</div>
|
288 |
+
</div>
|
289 |
+
</div>
|
290 |
+
|
291 |
+
<div id="textModelsSection">
|
292 |
+
<label class="block text-cyan-300 mb-2">Text Model</label>
|
293 |
+
<select id="textModelSelect" class="w-full bg-black/50 border border-cyan-700 rounded px-3 py-2 text-green-300 mb-4 focus:outline-none focus:ring-1 focus:ring-cyan-500">
|
294 |
+
<option value="mistralai/Mixtral-8x7B-Instruct-v0.1">Mixtral 8x7B</option>
|
295 |
+
<option value="meta-llama/Llama-2-70b-chat-hf">Llama 2 70B</option>
|
296 |
+
<option value="google/gemma-7b-it">Gemma 7B</option>
|
297 |
+
<option value="NousResearch/Nous-Hermes-2-Mixtral-8x7B-DPO">Hermes 2 Mixtral</option>
|
298 |
+
<option value="mistralai/Mistral-7B-Instruct-v0.2">Mistral 7B</option>
|
299 |
+
</select>
|
300 |
+
</div>
|
301 |
+
|
302 |
+
<div id="multimodalModelsSection" class="hidden">
|
303 |
+
<label class="block text-cyan-300 mb-2">Multimodal Model</label>
|
304 |
+
<select id="multimodalModelSelect" class="w-full bg-black/50 border border-cyan-700 rounded px-3 py-2 text-purple-300 mb-4 focus:outline-none focus:ring-1 focus:ring-purple-500">
|
305 |
+
<option value="llava-hf/llava-1.5-7b-hf">LLaVA 1.5 (7B)</option>
|
306 |
+
<option value="vikhyatk/moondream2">Moondream2 (Vision)</option>
|
307 |
+
<option value="openai/whisper-large-v3">Whisper (Speech)</option>
|
308 |
+
<option value="facebook/musicgen-small">MusicGen (Audio)</option>
|
309 |
+
<option value="stabilityai/stable-video-diffusion-img2vid-xt">Stable Video Diffusion</option>
|
310 |
+
</select>
|
311 |
+
|
312 |
+
<div id="fileInputSection" class="mt-4 hidden">
|
313 |
+
<label class="block text-cyan-300 mb-2">Input File</label>
|
314 |
+
<input type="file" id="multimodalFileInput"
|
315 |
+
class="w-full bg-black/50 border border-cyan-700 rounded px-3 py-2 text-green-300 focus:outline-none focus:ring-1 focus:ring-cyan-500">
|
316 |
+
</div>
|
317 |
+
</div>
|
318 |
+
|
319 |
+
<div class="mt-6 flex justify-end gap-3">
|
320 |
+
<button onclick="document.getElementById('settingsModal').classList.add('hidden')"
|
321 |
+
class="px-4 py-2 border border-cyan-700 rounded text-cyan-300 hover:bg-cyan-900/30">
|
322 |
+
Cancel
|
323 |
+
</button>
|
324 |
+
<button onclick="TerminalApp.saveSettings()"
|
325 |
+
class="px-4 py-2 bg-green-700 rounded text-white hover:bg-green-600">
|
326 |
+
Save Settings
|
327 |
+
</button>
|
328 |
+
</div>
|
329 |
+
</div>
|
330 |
+
</div>
|
331 |
+
</div>
|
332 |
+
|
333 |
<script>
|
334 |
// API Client
|
335 |
class HuggingFaceClient {
|
|
|
359 |
throw new Error(error.error || 'API request failed');
|
360 |
}
|
361 |
|
362 |
+
const contentType = response.headers.get('content-type');
|
363 |
+
if (contentType.includes('application/json')) {
|
364 |
+
return response.json();
|
365 |
+
} else if (contentType.includes('image')) {
|
366 |
+
const blob = await response.blob();
|
367 |
+
return URL.createObjectURL(blob);
|
368 |
+
} else if (contentType.includes('audio')) {
|
369 |
+
const blob = await response.blob();
|
370 |
+
return URL.createObjectURL(blob);
|
371 |
+
} else {
|
372 |
+
return response.text();
|
373 |
+
}
|
374 |
}
|
375 |
}
|
376 |
|
|
|
391 |
localStorage.setItem('terminalHistory', JSON.stringify(AppState.history));
|
392 |
}
|
393 |
|
394 |
+
static async streamResponse(response, prompt) {
|
395 |
+
// Handle different response types
|
396 |
+
let responseText;
|
397 |
+
if (typeof response === 'string') {
|
398 |
+
responseText = response;
|
399 |
+
} else if (response instanceof Blob || response.startsWith('blob:')) {
|
400 |
+
// Handle image/audio responses
|
401 |
+
if (response.type?.includes('image') || response.includes('image')) {
|
402 |
+
responseText = `[IMAGE RESPONSE] <img src="${response}" class="max-w-full mt-2 border border-cyan-700">`;
|
403 |
+
} else {
|
404 |
+
responseText = `[AUDIO RESPONSE] <audio controls src="${response}" class="w-full mt-2"></audio>`;
|
405 |
+
}
|
406 |
+
} else if (response.generated_text) {
|
407 |
+
responseText = response.generated_text;
|
408 |
+
} else {
|
409 |
+
responseText = JSON.stringify(response, null, 2);
|
410 |
+
}
|
411 |
const terminalOutput = document.querySelector('.terminal-scrollbar');
|
412 |
const responseDiv = document.createElement('div');
|
413 |
responseDiv.className = 'mb-4';
|
|
|
531 |
}
|
532 |
|
533 |
static showSettings() {
|
534 |
+
const modal = document.getElementById('settingsModal');
|
535 |
+
document.getElementById('hfApiKeyInput').value = AppState.apiKey;
|
536 |
+
modal.classList.remove('hidden');
|
537 |
+
|
538 |
+
// Set up model type toggle
|
539 |
+
document.querySelectorAll('input[name="modelType"]').forEach(radio => {
|
540 |
+
radio.addEventListener('change', (e) => {
|
541 |
+
if (e.target.value === 'text') {
|
542 |
+
document.getElementById('textModelsSection').classList.remove('hidden');
|
543 |
+
document.getElementById('multimodalModelsSection').classList.add('hidden');
|
544 |
+
} else {
|
545 |
+
document.getElementById('textModelsSection').classList.add('hidden');
|
546 |
+
document.getElementById('multimodalModelsSection').classList.remove('hidden');
|
547 |
+
}
|
548 |
+
});
|
549 |
+
});
|
550 |
+
|
551 |
+
// Set up file input toggle for multimodal
|
552 |
+
document.getElementById('multimodalModelSelect').addEventListener('change', (e) => {
|
553 |
+
const fileInput = document.getElementById('fileInputSection');
|
554 |
+
fileInput.classList.toggle('hidden', !e.target.value.includes('llava') && !e.target.value.includes('moondream'));
|
555 |
+
});
|
556 |
+
}
|
557 |
+
|
558 |
+
static saveSettings() {
|
559 |
+
AppState.apiKey = document.getElementById('hfApiKeyInput').value.trim();
|
560 |
+
localStorage.setItem('hfApiKey', AppState.apiKey);
|
561 |
+
|
562 |
+
const modelType = document.querySelector('input[name="modelType"]:checked').value;
|
563 |
+
if (modelType === 'text') {
|
564 |
+
AppState.currentModel = document.getElementById('textModelSelect').value;
|
565 |
+
} else {
|
566 |
+
AppState.currentModel = document.getElementById('multimodalModelSelect').value;
|
567 |
+
}
|
568 |
+
|
569 |
+
document.getElementById('settingsModal').classList.add('hidden');
|
570 |
+
document.getElementById('llmStatus').textContent = AppState.currentModel.split('/').pop();
|
571 |
+
}
|
572 |
+
|
573 |
+
static async executePrompt() {
|
574 |
+
const input = document.getElementById('promptInput');
|
575 |
+
const prompt = input.value.trim();
|
576 |
+
if (!prompt) return;
|
577 |
+
|
578 |
+
const mode = document.querySelector('select').value;
|
579 |
+
const fullPrompt = PROMPT_TEMPLATES[mode].replace('{query}', prompt);
|
580 |
+
|
581 |
+
TerminalUI.toggleLoading(true);
|
582 |
+
|
583 |
+
try {
|
584 |
+
let payload = {
|
585 |
+
inputs: fullPrompt,
|
586 |
+
parameters: {
|
587 |
+
max_new_tokens: 1024,
|
588 |
+
temperature: mode === 'technical' ? 0.3 : 0.7,
|
589 |
+
return_full_text: false
|
590 |
+
}
|
591 |
+
};
|
592 |
+
|
593 |
+
// Handle multimodal inputs
|
594 |
+
if (AppState.currentModel.includes('llava') || AppState.currentModel.includes('moondream')) {
|
595 |
+
const fileInput = document.getElementById('multimodalFileInput');
|
596 |
+
if (fileInput.files.length > 0) {
|
597 |
+
const file = fileInput.files[0];
|
598 |
+
const reader = new FileReader();
|
599 |
+
|
600 |
+
await new Promise((resolve) => {
|
601 |
+
reader.onload = (e) => {
|
602 |
+
payload.inputs = {
|
603 |
+
image: e.target.result.split(',')[1],
|
604 |
+
question: prompt
|
605 |
+
};
|
606 |
+
resolve();
|
607 |
+
};
|
608 |
+
reader.readAsDataURL(file);
|
609 |
+
});
|
610 |
+
}
|
611 |
+
}
|
612 |
+
|
613 |
+
const response = await HuggingFaceClient.query(payload, AppState.currentModel);
|
614 |
+
const result = Array.isArray(response) ? response[0].generated_text : response.generated_text;
|
615 |
+
const processedText = await TerminalUI.streamResponse(result, prompt);
|
616 |
+
|
617 |
+
document.getElementById('tokenCounter').textContent = processedText.length;
|
618 |
+
input.value = '';
|
619 |
+
} catch (error) {
|
620 |
+
TerminalUI.showError(error.message);
|
621 |
+
console.error('API Error:', error);
|
622 |
+
} finally {
|
623 |
+
TerminalUI.toggleLoading(false);
|
624 |
+
}
|
625 |
}
|
626 |
}
|
627 |
|