Spaces:
Running
Running
File size: 6,035 Bytes
db5fc17 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 | 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>`;
}
});
});
|