Spaces:
Running
Running
Download script.js from SupaC/qwen-2.5-coder-assistant: direct link, hf CLI and curl.
- Browser
- Download file 6.04 kB
-
https://huggingface.co/spaces/SupaC/qwen-2.5-coder-assistant/resolve/main/script.js
- Command line
-
hf download hf://spaces/SupaC/qwen-2.5-coder-assistant/script.js
-
curl -L -o script.js https://huggingface.co/spaces/SupaC/qwen-2.5-coder-assistant/resolve/main/script.js
6.04 kB
| document.addEventListener("DOMContentLoaded", () => { | |
| const chatForm = document.getElementById("chat-form"); | |
| const userInput = document.getElementById("user-input"); | |
| const messagesContainer = document.getElementById("messages-container"); | |
| const tokenInput = document.getElementById("hf-token"); | |
| // Load saved HF Token from localStorage if present | |
| if (localStorage.getItem("hf_token")) { | |
| tokenInput.value = localStorage.getItem("hf_token"); | |
| } | |
| // Auto-resize textarea | |
| userInput.addEventListener("input", () => { | |
| userInput.style.height = "auto"; | |
| userInput.style.height = userInput.scrollHeight + "px"; | |
| }); | |
| // Handle shift+enter to submit | |
| userInput.addEventListener("keydown", (e) => { | |
| if (e.key === "Enter" && !e.shiftKey) { | |
| e.preventDefault(); | |
| chatForm.dispatchEvent(new Event("submit")); | |
| } | |
| }); | |
| // Save token changes | |
| tokenInput.addEventListener("change", () => { | |
| localStorage.setItem("hf_token", tokenInput.value.trim()); | |
| }); | |
| // Chat history state | |
| let chatHistory = []; | |
| // Parse streaming response | |
| async function handleStreamingResponse(response, messageEl, contentEl) { | |
| const reader = response.body.getReader(); | |
| const decoder = new TextDecoder("utf-8"); | |
| let buffer = ""; | |
| let fullText = ""; | |
| while (true) { | |
| const { done, value } = await reader.read(); | |
| if (done) break; | |
| buffer += decoder.decode(value, { stream: true }); | |
| const lines = buffer.split("\n"); | |
| buffer = lines.pop(); | |
| for (const line of lines) { | |
| const cleanLine = line.trim(); | |
| if (!cleanLine) continue; | |
| if (cleanLine.startsWith("data:")) { | |
| const dataStr = cleanLine.substring(5).trim(); | |
| if (dataStr === "[DONE]") break; | |
| try { | |
| const dataObj = JSON.parse(dataStr); | |
| const token = dataObj.choices[0].delta.content; | |
| if (token) { | |
| fullText += token; | |
| // Render Markdown | |
| contentEl.innerHTML = marked.parse(fullText); | |
| // Run Prism syntax highlighting | |
| Prism.highlightAllUnder(contentEl); | |
| // Auto scroll | |
| messagesContainer.scrollTop = messagesContainer.scrollHeight; | |
| } | |
| } catch (err) { | |
| // Suppress JSON parse errors on partial streams | |
| } | |
| } | |
| } | |
| } | |
| return fullText; | |
| } | |
| // Submit form handler | |
| chatForm.submit = async (e) => { | |
| // Fallback for form submit | |
| }; | |
| chatForm.addEventListener("submit", async (e) => { | |
| e.preventDefault(); | |
| const text = userInput.value.trim(); | |
| if (!text) return; | |
| // Reset input area | |
| userInput.value = ""; | |
| userInput.style.height = "auto"; | |
| // Append user message | |
| const userMsgEl = document.createElement("div"); | |
| userMsgEl.className = "message user-message"; | |
| userMsgEl.innerHTML = ` | |
| <div class="avatar">👤</div> | |
| <div class="message-content">${marked.parse(text)}</div> | |
| `; | |
| messagesContainer.appendChild(userMsgEl); | |
| messagesContainer.scrollTop = messagesContainer.scrollHeight; | |
| // Prepare assistant placeholder | |
| const assistantMsgEl = document.createElement("div"); | |
| assistantMsgEl.className = "message assistant-message"; | |
| assistantMsgEl.innerHTML = ` | |
| <div class="avatar">🧠</div> | |
| <div class="message-content typing-indicator">Thinking...</div> | |
| `; | |
| messagesContainer.appendChild(assistantMsgEl); | |
| messagesContainer.scrollTop = messagesContainer.scrollHeight; | |
| const contentEl = assistantMsgEl.querySelector(".message-content"); | |
| // Format system + history + new prompt | |
| const messages = [ | |
| { role: "system", content: "You are a helpful coding assistant. Provide clean, correct, and well-structured code when asked." }, | |
| ...chatHistory, | |
| { role: "user", content: text } | |
| ]; | |
| const token = tokenInput.value.trim(); | |
| const headers = { | |
| "Content-Type": "application/json" | |
| }; | |
| if (token) { | |
| headers["Authorization"] = `Bearer ${token}`; | |
| } | |
| try { | |
| const response = await fetch("https://api-inference.huggingface.co/models/Qwen/Qwen2.5-Coder-7B-Instruct/v1/chat/completions", { | |
| method: "POST", | |
| headers: headers, | |
| body: JSON.stringify({ | |
| model: "Qwen/Qwen2.5-Coder-7B-Instruct", | |
| messages: messages, | |
| max_tokens: 2048, | |
| temperature: 0.7, | |
| top_p: 0.9, | |
| stream: true | |
| }) | |
| }); | |
| if (!response.ok) { | |
| const errorData = await response.json().catch(() => ({})); | |
| const errMsg = errorData.error?.message || response.statusText; | |
| contentEl.innerHTML = `<span style="color: #ef4444;">API Error: ${errMsg}</span>`; | |
| return; | |
| } | |
| contentEl.innerHTML = ""; | |
| contentEl.classList.remove("typing-indicator"); | |
| const fullText = await handleStreamingResponse(response, assistantMsgEl, contentEl); | |
| // Save to history | |
| chatHistory.push({ role: "user", content: text }); | |
| chatHistory.push({ role: "assistant", content: fullText }); | |
| } catch (err) { | |
| contentEl.innerHTML = `<span style="color: #ef4444;">Connection Error: ${err.message}</span>`; | |
| } | |
| }); | |
| }); | |