Initial local LLM web app

This commit is contained in:
seo-amugae committed 2026-08-09 18:18:59 +09:00
commit afa8f3780f
7 files changed
+395

No files matched your search

+84
View File
@@ -0,0 +1,84 @@
const form = document.querySelector("#chatForm");
const promptInput = document.querySelector("#prompt");
const messagesEl = document.querySelector("#messages");
const sendButton = document.querySelector("#sendButton");
const newChatButton = document.querySelector("#newChat");
let messages = [];
function addMessage(role, content) {
const article = document.createElement("article");
article.className = `message ${role}`;
const avatar = document.createElement("div");
avatar.className = "avatar";
avatar.textContent = role === "user" ? "U" : "L";
const bubble = document.createElement("div");
bubble.className = "bubble";
bubble.textContent = content;
article.append(avatar, bubble);
messagesEl.append(article);
messagesEl.scrollTop = messagesEl.scrollHeight;
return bubble;
}
function resetChat() {
messages = [];
messagesEl.innerHTML = "";
addMessage("assistant", "새 대화를 시작합니다.");
promptInput.focus();
}
promptInput.addEventListener("input", () => {
promptInput.style.height = "auto";
promptInput.style.height = `${promptInput.scrollHeight}px`;
});
promptInput.addEventListener("keydown", (event) => {
if (event.key === "Enter" && !event.shiftKey) {
event.preventDefault();
form.requestSubmit();
}
});
newChatButton.addEventListener("click", resetChat);
form.addEventListener("submit", async (event) => {
event.preventDefault();
const content = promptInput.value.trim();
if (!content || sendButton.disabled) {
return;
}
promptInput.value = "";
promptInput.style.height = "auto";
addMessage("user", content);
messages.push({ role: "user", content });
sendButton.disabled = true;
const pending = addMessage("assistant", "생각 중...");
try {
const response = await fetch("/api/chat", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ messages }),
});
const data = await response.json();
if (!response.ok) {
throw new Error(data.error || "응답 생성 실패");
}
pending.textContent = data.reply;
messages.push({ role: "assistant", content: data.reply });
} catch (error) {
pending.textContent = `오류: ${error.message}`;
} finally {
sendButton.disabled = false;
promptInput.focus();
}
});