Spaces:
Running
Running
Download index.html from Yethikrishna/hypervision-chat: direct link, hf CLI and curl.
- Browser
- Download file 19.9 kB
-
https://huggingface.co/spaces/Yethikrishna/hypervision-chat/resolve/main/index.html
- Command line
-
hf download hf://spaces/Yethikrishna/hypervision-chat/index.html
-
curl -L -o index.html https://huggingface.co/spaces/Yethikrishna/hypervision-chat/resolve/main/index.html
19.9 kB
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8" /> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |
| <title>HyperVision Chat — Tool Calling</title> | |
| <style> | |
| :root { | |
| --bg: #0f1117; | |
| --surface: #1a1d27; | |
| --surface-2: #242836; | |
| --border: #2e3345; | |
| --text: #e4e6f0; | |
| --text-dim: #8b90a5; | |
| --accent: #6c5ce7; | |
| --accent-hover: #7c6ef7; | |
| --user-msg: #2d1b69; | |
| --assistant-msg: #1a1d27; | |
| --tool-msg: #1a2d1b; | |
| --success: #2ecc71; | |
| --warning: #f39c12; | |
| --radius: 12px; | |
| --font: 'Segoe UI', system-ui, -apple-system, sans-serif; | |
| } | |
| * { margin: 0; padding: 0; box-sizing: border-box; } | |
| body { | |
| font-family: var(--font); | |
| background: var(--bg); | |
| color: var(--text); | |
| height: 100vh; | |
| display: flex; | |
| flex-direction: column; | |
| } | |
| /* Header */ | |
| header { | |
| background: var(--surface); | |
| border-bottom: 1px solid var(--border); | |
| padding: 16px 24px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: space-between; | |
| flex-shrink: 0; | |
| } | |
| header h1 { | |
| font-size: 20px; | |
| font-weight: 600; | |
| display: flex; | |
| align-items: center; | |
| gap: 8px; | |
| } | |
| header h1 span { color: var(--accent); } | |
| header .subtitle { | |
| font-size: 13px; | |
| color: var(--text-dim); | |
| } | |
| header a { | |
| color: var(--accent); | |
| text-decoration: none; | |
| } | |
| header a:hover { text-decoration: underline; } | |
| /* Main Layout */ | |
| .container { | |
| display: flex; | |
| flex: 1; | |
| overflow: hidden; | |
| } | |
| /* Chat Area */ | |
| .chat-panel { | |
| flex: 1; | |
| display: flex; | |
| flex-direction: column; | |
| min-width: 0; | |
| } | |
| .messages { | |
| flex: 1; | |
| overflow-y: auto; | |
| padding: 20px 24px; | |
| display: flex; | |
| flex-direction: column; | |
| gap: 16px; | |
| } | |
| .message { | |
| max-width: 80%; | |
| padding: 12px 16px; | |
| border-radius: var(--radius); | |
| line-height: 1.5; | |
| font-size: 14px; | |
| animation: fadeIn 0.2s ease; | |
| } | |
| @keyframes fadeIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } } | |
| .message.user { | |
| align-self: flex-end; | |
| background: var(--user-msg); | |
| border: 1px solid #4a2d9e; | |
| border-bottom-right-radius: 4px; | |
| } | |
| .message.assistant { | |
| align-self: flex-start; | |
| background: var(--assistant-msg); | |
| border: 1px solid var(--border); | |
| border-bottom-left-radius: 4px; | |
| } | |
| .message.tool-call { | |
| align-self: flex-start; | |
| background: var(--tool-msg); | |
| border: 1px solid #1a4a2b; | |
| font-family: 'Cascadia Code', 'Fira Code', monospace; | |
| font-size: 12px; | |
| max-width: 90%; | |
| } | |
| .message .label { | |
| font-size: 11px; | |
| font-weight: 600; | |
| text-transform: uppercase; | |
| letter-spacing: 0.5px; | |
| margin-bottom: 4px; | |
| opacity: 0.7; | |
| } | |
| .message .tool-name { color: var(--success); } | |
| .message .tool-result { | |
| color: var(--text-dim); | |
| white-space: pre-wrap; | |
| word-break: break-all; | |
| margin-top: 4px; | |
| } | |
| .message .error { color: #e74c3c; } | |
| .typing-indicator { | |
| align-self: flex-start; | |
| display: none; | |
| padding: 12px 16px; | |
| background: var(--assistant-msg); | |
| border: 1px solid var(--border); | |
| border-radius: var(--radius); | |
| border-bottom-left-radius: 4px; | |
| } | |
| .typing-indicator.active { display: flex; gap: 4px; } | |
| .typing-indicator span { | |
| width: 8px; height: 8px; | |
| background: var(--text-dim); | |
| border-radius: 50%; | |
| animation: bounce 1.4s infinite ease-in-out; | |
| } | |
| .typing-indicator span:nth-child(2) { animation-delay: 0.2s; } | |
| .typing-indicator span:nth-child(3) { animation-delay: 0.4s; } | |
| @keyframes bounce { | |
| 0%, 80%, 100% { transform: scale(0.6); } | |
| 40% { transform: scale(1); } | |
| } | |
| /* Input Area */ | |
| .input-area { | |
| padding: 16px 24px; | |
| background: var(--surface); | |
| border-top: 1px solid var(--border); | |
| display: flex; | |
| gap: 12px; | |
| flex-shrink: 0; | |
| } | |
| .input-area textarea { | |
| flex: 1; | |
| background: var(--surface-2); | |
| border: 1px solid var(--border); | |
| border-radius: 8px; | |
| padding: 12px 16px; | |
| color: var(--text); | |
| font-family: var(--font); | |
| font-size: 14px; | |
| resize: none; | |
| outline: none; | |
| min-height: 48px; | |
| max-height: 120px; | |
| transition: border-color 0.2s; | |
| } | |
| .input-area textarea:focus { border-color: var(--accent); } | |
| .input-area textarea::placeholder { color: var(--text-dim); } | |
| .input-area button { | |
| background: var(--accent); | |
| color: white; | |
| border: none; | |
| border-radius: 8px; | |
| padding: 0 24px; | |
| font-size: 14px; | |
| font-weight: 600; | |
| cursor: pointer; | |
| transition: background 0.2s; | |
| white-space: nowrap; | |
| } | |
| .input-area button:hover { background: var(--accent-hover); } | |
| .input-area button:disabled { | |
| background: var(--surface-2); | |
| color: var(--text-dim); | |
| cursor: not-allowed; | |
| } | |
| /* Sidebar */ | |
| .sidebar { | |
| width: 280px; | |
| background: var(--surface); | |
| border-left: 1px solid var(--border); | |
| padding: 20px; | |
| overflow-y: auto; | |
| flex-shrink: 0; | |
| display: flex; | |
| flex-direction: column; | |
| gap: 16px; | |
| } | |
| .sidebar h3 { | |
| font-size: 13px; | |
| text-transform: uppercase; | |
| letter-spacing: 1px; | |
| color: var(--text-dim); | |
| } | |
| .tool-list { display: flex; flex-direction: column; gap: 8px; } | |
| .tool-item { | |
| background: var(--surface-2); | |
| border: 1px solid var(--border); | |
| border-radius: 8px; | |
| padding: 10px 12px; | |
| font-size: 13px; | |
| } | |
| .tool-item .tool-name { color: var(--accent); font-weight: 600; } | |
| .tool-item .tool-desc { color: var(--text-dim); font-size: 12px; margin-top: 2px; } | |
| .sidebar .info-box { | |
| background: var(--surface-2); | |
| border: 1px solid var(--border); | |
| border-radius: 8px; | |
| padding: 12px; | |
| font-size: 12px; | |
| color: var(--text-dim); | |
| line-height: 1.6; | |
| } | |
| .sidebar .info-box code { | |
| background: var(--bg); | |
| padding: 2px 6px; | |
| border-radius: 4px; | |
| font-size: 11px; | |
| } | |
| .examples { | |
| display: flex; | |
| flex-direction: column; | |
| gap: 6px; | |
| } | |
| .examples button { | |
| background: var(--surface-2); | |
| border: 1px solid var(--border); | |
| border-radius: 6px; | |
| padding: 8px 12px; | |
| color: var(--text-dim); | |
| font-size: 12px; | |
| cursor: pointer; | |
| text-align: left; | |
| transition: all 0.2s; | |
| } | |
| .examples button:hover { | |
| border-color: var(--accent); | |
| color: var(--text); | |
| } | |
| /* Footer */ | |
| footer { | |
| background: var(--surface); | |
| border-top: 1px solid var(--border); | |
| padding: 8px 24px; | |
| text-align: center; | |
| font-size: 12px; | |
| color: var(--text-dim); | |
| flex-shrink: 0; | |
| } | |
| footer a { color: var(--accent); text-decoration: none; } | |
| @media (max-width: 768px) { | |
| .sidebar { display: none; } | |
| .message { max-width: 95%; } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <header> | |
| <div> | |
| <h1>🤖 <span>HyperVision</span> Chat</h1> | |
| <div class="subtitle">Tool Calling · <a href="https://myndlabs.tech" target="_blank">Myndlabs.tech</a></div> | |
| </div> | |
| <div class="subtitle">llama3.1-8B · jimmy.aikit.club</div> | |
| </header> | |
| <div class="container"> | |
| <!-- Chat Panel --> | |
| <div class="chat-panel"> | |
| <div class="messages" id="messages"> | |
| <div class="message assistant"> | |
| Hello! I'm HyperVision AI. I can use tools to help you — try asking about weather, calculations, web searches, or time in any timezone. | |
| </div> | |
| </div> | |
| <div class="typing-indicator" id="typingIndicator"> | |
| <span></span><span></span><span></span> | |
| </div> | |
| <div class="input-area"> | |
| <textarea id="userInput" rows="1" placeholder="Ask me anything..." onkeydown="handleKeyDown(event)"></textarea> | |
| <button id="sendBtn" onclick="sendMessage()">Send</button> | |
| </div> | |
| </div> | |
| <!-- Sidebar --> | |
| <div class="sidebar"> | |
| <div> | |
| <h3>Available Tools</h3> | |
| <div class="tool-list"> | |
| <div class="tool-item"> | |
| <div class="tool-name">🌤️ get_weather</div> | |
| <div class="tool-desc">Get current weather for any city</div> | |
| </div> | |
| <div class="tool-item"> | |
| <div class="tool-name">🔍 search_web</div> | |
| <div class="tool-desc">Search the web for information</div> | |
| </div> | |
| <div class="tool-item"> | |
| <div class="tool-name">🧮 calculate</div> | |
| <div class="tool-desc">Perform mathematical calculations</div> | |
| </div> | |
| <div class="tool-item"> | |
| <div class="tool-name">⏰ get_time</div> | |
| <div class="tool-desc">Current time in any timezone</div> | |
| </div> | |
| </div> | |
| </div> | |
| <div> | |
| <h3>Try Examples</h3> | |
| <div class="examples"> | |
| <button onclick="setExample('What is the weather in Tokyo?')">🌤️ What is the weather in Tokyo?</button> | |
| <button onclick="setExample('Calculate 2 + 2')">🧮 Calculate 2 + 2</button> | |
| <button onclick="setExample('What time is it in India?')">⏰ What time is it in India?</button> | |
| <button onclick="setExample('Search the web for HyperVision AI')">🔍 Search the web for HyperVision AI</button> | |
| </div> | |
| </div> | |
| <div> | |
| <h3>How It Works</h3> | |
| <div class="info-box"> | |
| <ol style="padding-left: 16px;"> | |
| <li>You ask a question</li> | |
| <li>The model decides which tool to use</li> | |
| <li>The tool executes and returns results</li> | |
| <li>The model formulates a response</li> | |
| </ol> | |
| <br/> | |
| <strong>API:</strong> <code>https://jimmy.aikit.club/v1</code> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <footer> | |
| <a href="https://myndlabs.tech" target="_blank">Myndlabs.tech</a> — Enterprise-grade AI solutions | |
| </footer> | |
| <script> | |
| // ── Configuration ────────────────────────────────────────────────────── | |
| const API_BASE = 'https://jimmy.aikit.club/v1'; | |
| const API_KEY = 'tarun-mykey'; | |
| const MODEL = 'llama3.1-8B'; | |
| const MAX_TOKENS = 2048; | |
| const SYSTEM_PROMPT = 'You are HyperVision AI, an intelligent assistant by Myndlabs.tech. You have access to tools. Use them when the user asks for something the tool can do. Respond in a helpful, concise manner.'; | |
| const TOOLS = [ | |
| { | |
| type: 'function', | |
| function: { | |
| name: 'get_weather', | |
| description: 'Get current weather for a city', | |
| parameters: { | |
| type: 'object', | |
| properties: { | |
| city: { type: 'string', description: 'City name, e.g. Tokyo, London, New York' }, | |
| unit: { type: 'string', enum: ['celsius', 'fahrenheit'], description: 'Temperature unit' }, | |
| }, | |
| required: ['city'], | |
| }, | |
| }, | |
| }, | |
| { | |
| type: 'function', | |
| function: { | |
| name: 'search_web', | |
| description: 'Search the web for information', | |
| parameters: { | |
| type: 'object', | |
| properties: { | |
| query: { type: 'string', description: 'Search query' }, | |
| max_results: { type: 'integer', description: 'Number of results (max 10)' }, | |
| }, | |
| required: ['query'], | |
| }, | |
| }, | |
| }, | |
| { | |
| type: 'function', | |
| function: { | |
| name: 'calculate', | |
| description: 'Perform a mathematical calculation', | |
| parameters: { | |
| type: 'object', | |
| properties: { | |
| expression: { type: 'string', description: 'Math expression, e.g. 2 + 2' }, | |
| }, | |
| required: ['expression'], | |
| }, | |
| }, | |
| }, | |
| { | |
| type: 'function', | |
| function: { | |
| name: 'get_time', | |
| description: 'Get current time for a timezone', | |
| parameters: { | |
| type: 'object', | |
| properties: { | |
| timezone: { type: 'string', description: "Timezone, e.g. 'Asia/Kolkata', 'America/New_York'" }, | |
| }, | |
| required: ['timezone'], | |
| }, | |
| }, | |
| }, | |
| ]; | |
| // ── Tool Execution ───────────────────────────────────────────────────── | |
| function executeTool(name, args) { | |
| switch (name) { | |
| case 'get_weather': { | |
| const city = args.city || 'unknown'; | |
| const unit = args.unit || 'celsius'; | |
| const temp = unit === 'celsius' ? 28 : 82; | |
| return JSON.stringify({ | |
| city, | |
| temperature: temp, | |
| condition: 'partly cloudy', | |
| humidity: 65, | |
| unit, | |
| }); | |
| } | |
| case 'search_web': { | |
| const query = args.query || ''; | |
| const maxResults = Math.min(args.max_results || 5, 10); | |
| const results = []; | |
| for (let i = 0; i < maxResults; i++) { | |
| results.push({ title: `Result ${i + 1} for '${query}'`, url: `https://example.com/result-${i + 1}` }); | |
| } | |
| return JSON.stringify({ query, results, total_results: maxResults }); | |
| } | |
| case 'calculate': { | |
| try { | |
| const result = Function('"use strict"; return (' + args.expression + ')')(); | |
| return JSON.stringify({ expression: args.expression, result }); | |
| } catch (e) { | |
| return JSON.stringify({ expression: args.expression, error: e.message }); | |
| } | |
| } | |
| case 'get_time': { | |
| const tz = args.timezone || 'UTC'; | |
| try { | |
| const now = new Date(); | |
| const options = { timeZone: tz, weekday: 'long', year: 'numeric', month: 'long', day: 'numeric', hour: '2-digit', minute: '2-digit', second: '2-digit', timeZoneName: 'short' }; | |
| const timeStr = new Intl.DateTimeFormat('en-US', options).format(now); | |
| return JSON.stringify({ timezone: tz, time: timeStr }); | |
| } catch (e) { | |
| return JSON.stringify({ timezone: tz, error: 'Invalid timezone', time: new Date().toUTCString() }); | |
| } | |
| } | |
| default: | |
| return JSON.stringify({ error: `Unknown tool: ${name}` }); | |
| } | |
| } | |
| // ── Chat State ───────────────────────────────────────────────────────── | |
| let messages = [ | |
| { role: 'system', content: SYSTEM_PROMPT } | |
| ]; | |
| const messagesEl = document.getElementById('messages'); | |
| const userInput = document.getElementById('userInput'); | |
| const sendBtn = document.getElementById('sendBtn'); | |
| const typingIndicator = document.getElementById('typingIndicator'); | |
| // ── UI Functions ─────────────────────────────────────────────────────── | |
| function addMessage(role, content, extraClass = '') { | |
| const div = document.createElement('div'); | |
| div.className = `message ${role} ${extraClass}`.trim(); | |
| div.textContent = content; | |
| messagesEl.appendChild(div); | |
| messagesEl.scrollTop = messagesEl.scrollHeight; | |
| } | |
| function addToolCallMessage(toolName, args, result) { | |
| const div = document.createElement('div'); | |
| div.className = 'message tool-call'; | |
| div.innerHTML = ` | |
| <div class="label">🔧 Tool Call: <span class="tool-name">${toolName}</span></div> | |
| <div class="tool-result">Arguments: ${JSON.stringify(args, null, 2)}</div> | |
| <div class="tool-result">Result: ${result}</div> | |
| `; | |
| messagesEl.appendChild(div); | |
| messagesEl.scrollTop = messagesEl.scrollHeight; | |
| } | |
| function setLoading(loading) { | |
| typingIndicator.classList.toggle('active', loading); | |
| sendBtn.disabled = loading; | |
| userInput.disabled = loading; | |
| } | |
| function setExample(text) { | |
| userInput.value = text; | |
| userInput.focus(); | |
| } | |
| function handleKeyDown(e) { | |
| if (e.key === 'Enter' && !e.shiftKey) { | |
| e.preventDefault(); | |
| sendMessage(); | |
| } | |
| } | |
| // ── API Call ─────────────────────────────────────────────────────────── | |
| async function chatWithTools(currentMessages) { | |
| const res = await fetch(`${API_BASE}/chat/completions`, { | |
| method: 'POST', | |
| headers: { | |
| 'Authorization': `Bearer ${API_KEY}`, | |
| 'Content-Type': 'application/json', | |
| }, | |
| body: JSON.stringify({ | |
| model: MODEL, | |
| messages: currentMessages, | |
| tools: TOOLS, | |
| max_tokens: MAX_TOKENS, | |
| temperature: 0.7, | |
| }), | |
| }); | |
| if (!res.ok) { | |
| const err = await res.text(); | |
| throw new Error(`API Error (${res.status}): ${err}`); | |
| } | |
| return await res.json(); | |
| } | |
| // ── Send Message ─────────────────────────────────────────────────────── | |
| async function sendMessage() { | |
| const text = userInput.value.trim(); | |
| if (!text) return; | |
| // Add user message | |
| addMessage('user', text); | |
| messages.push({ role: 'user', content: text }); | |
| userInput.value = ''; | |
| setLoading(true); | |
| try { | |
| // Tool calling loop (max 5 iterations) | |
| let toolCallCount = 0; | |
| while (toolCallCount < 5) { | |
| const data = await chatWithTools(messages); | |
| const choice = data.choices?.[0]; | |
| const msg = choice?.message; | |
| if (!msg) { | |
| addMessage('assistant', 'No response from API.'); | |
| break; | |
| } | |
| const toolCalls = msg.tool_calls; | |
| if (toolCalls && toolCalls.length > 0) { | |
| // Add assistant message with tool calls | |
| messages.push(msg); | |
| toolCallCount++; | |
| // Execute each tool call | |
| for (const tc of toolCalls) { | |
| const toolName = tc.function.name; | |
| const toolArgs = JSON.parse(tc.function.arguments); | |
| const toolResult = executeTool(toolName, toolArgs); | |
| addToolCallMessage(toolName, toolArgs, toolResult); | |
| messages.push({ | |
| role: 'tool', | |
| tool_call_id: tc.id, | |
| content: toolResult, | |
| }); | |
| } | |
| // Continue the loop | |
| continue; | |
| } | |
| // No tool calls — show the text response | |
| const content = msg.content || 'No text response.'; | |
| addMessage('assistant', content); | |
| messages.push({ role: 'assistant', content }); | |
| break; | |
| } | |
| if (toolCallCount >= 5) { | |
| addMessage('assistant', 'Tool calling loop exceeded maximum iterations.'); | |
| } | |
| } catch (err) { | |
| addMessage('assistant', `Error: ${err.message}`); | |
| } finally { | |
| setLoading(false); | |
| } | |
| } | |
| // Auto-resize textarea | |
| userInput.addEventListener('input', function() { | |
| this.style.height = 'auto'; | |
| this.style.height = Math.min(this.scrollHeight, 120) + 'px'; | |
| }); | |
| </script> | |
| </body> | |
| </html> |