97 lines
3.5 KiB
JavaScript
97 lines
3.5 KiB
JavaScript
const messages = [];
|
|
const statusEl = document.getElementById("statusbox" );
|
|
const chatContainer = document.getElementById("chatbox" );
|
|
|
|
function setStatus(msg, stts) {
|
|
if (stts == "idle" ) statusEl.className = "status-idle";
|
|
if (stts == "responding" ) statusEl.className = "status-responding";
|
|
if (stts == "completed" ) statusEl.className = "status-completed";
|
|
if (stts == "failed" ) statusEl.className = "status-failed";
|
|
statusEl.textContent = msg;
|
|
}
|
|
|
|
async function sendPrompt() {
|
|
const role = document.getElementById("role" ).value;
|
|
const model = document.getElementById("model" ).value;
|
|
const response = document.getElementById("response" ).checked;
|
|
const promptBox = document.getElementById("prompt" );
|
|
const prompt = promptBox.value.trim();
|
|
|
|
if (!prompt) return;
|
|
|
|
const bubUser = document.createElement("div" );
|
|
const tagRole = document.createElement("span" );
|
|
const msgUser = document.createElement("div" );
|
|
|
|
const bubBot = document.createElement("div" );
|
|
const tagModel = document.createElement("span" );
|
|
const msgBot = document.createElement("div" );
|
|
|
|
bubUser .className = "bub bub-r bub-primary";
|
|
tagRole .className = "tag";
|
|
msgUser .className = "message";
|
|
|
|
bubBot .className = "bub bub-l bub-secondary";
|
|
tagModel .className = "tag";
|
|
msgBot .className = "message";
|
|
|
|
tagRole .textContent = `Role: ${role}`;
|
|
tagModel .textContent = `Model: ${model}`;
|
|
|
|
msgUser.innerHTML = marked.parse(prompt, { sanitize: true });
|
|
|
|
bubUser.appendChild(tagRole);
|
|
bubUser.appendChild(msgUser);
|
|
chatContainer.appendChild(bubUser);
|
|
|
|
bubBot.appendChild(tagModel);
|
|
bubBot.appendChild(msgBot);
|
|
if (response) chatContainer.appendChild(bubBot);
|
|
|
|
chatContainer.scrollTop = chatContainer.scrollHeight;
|
|
messages.push({ role: role, content: prompt }); // Add prompt to history
|
|
if (response) setStatus(`⏳ ${model} Loading…`, "responding");
|
|
|
|
if (response) try {
|
|
const res = await fetch("http://localhost:11434/api/chat", {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify({ model, messages, stream: true })
|
|
});
|
|
|
|
const reader = res.body.getReader();
|
|
const decoder = new TextDecoder("utf-8");
|
|
let botReply = "";
|
|
|
|
setStatus(`✏️ ${model} Typing…`, "responding");
|
|
while (true) {
|
|
const { done, value } = await reader.read();
|
|
if (done) break;
|
|
const chunk = decoder.decode(value, { stream: true }).trim();
|
|
for (const line of chunk.split("\n")) {
|
|
if (!line) continue;
|
|
try {
|
|
const j = JSON.parse(line);
|
|
if (j.message?.content) {
|
|
botReply += j.message.content;
|
|
msgBot.innerHTML = marked.parse(botReply, { sanitize: true });
|
|
msgBot.prepend(tagModel);
|
|
chatContainer.scrollTop = chatContainer.scrollHeight;
|
|
}
|
|
} catch {}
|
|
}
|
|
}
|
|
|
|
messages.push({ role: "assistant", content: botReply });
|
|
setStatus(`✅ Response completed by ${model}`, "completed");
|
|
|
|
} catch (e) {
|
|
msgBot.innerHTML = "<em>[Failed to load answer]</em>";
|
|
msgBot.prepend(tagModel);
|
|
setStatus(`❌ Failed to get a response from ${model}`, "failed");
|
|
}
|
|
|
|
promptBox.value = "";
|
|
}
|
|
|