| | let MODEL_LIST = []; |
| |
|
| | async function fetchModelList() { |
| | try { |
| | const response = await fetch("/models"); |
| | if (response.ok) { |
| | MODEL_LIST = await response.json(); |
| | initializeDropdowns(); |
| | } else { |
| | console.error("Failed to fetch model list"); |
| | } |
| | } catch (error) { |
| | console.error("Error fetching models:", error); |
| | } |
| | } |
| |
|
| | function createDropdown(dropdownId) { |
| | const dropdown = document.getElementById(dropdownId); |
| | const selected = dropdown.querySelector(".selected"); |
| | const options = dropdown.querySelector(".options"); |
| | const modelZone = dropdown.closest(".model-zone"); |
| | const nameDisplay = modelZone.querySelector(".model-name"); |
| |
|
| | MODEL_LIST.forEach(model => { |
| | const option = document.createElement("div"); |
| | option.textContent = model.name; |
| | option.dataset.value = model.id; |
| | options.appendChild(option); |
| |
|
| | option.addEventListener("click", (e) => { |
| | e.stopPropagation(); |
| | selected.textContent = model.name; |
| | dropdown.dataset.value = model.id; |
| | if (nameDisplay) nameDisplay.textContent = model.name; |
| | options.classList.remove("show"); |
| | }); |
| | }); |
| |
|
| | selected.addEventListener("click", (e) => { |
| | e.stopPropagation(); |
| | options.classList.toggle("show"); |
| | }); |
| |
|
| | document.addEventListener("click", (e) => { |
| | if (!dropdown.contains(e.target)) { |
| | options.classList.remove("show"); |
| | } |
| | }); |
| | } |
| |
|
| | function initializeDropdowns() { |
| | createDropdown("modelA"); |
| | createDropdown("modelB"); |
| | createDropdown("modelC"); |
| | createDropdown("aggregator"); |
| | } |
| |
|
| | const themeToggle = document.getElementById("themeToggle"); |
| | const toggleConfig = document.getElementById("toggleConfig"); |
| | const docsButton = document.getElementById("docsButton"); |
| | const configPanel = document.getElementById("configPanel"); |
| | const html = document.documentElement; |
| |
|
| | function setInitialTheme() { |
| | const savedTheme = localStorage.getItem("theme"); |
| | if (savedTheme === "dark") { |
| | html.classList.add("dark"); |
| | themeToggle.textContent = "🌙"; |
| | } else if (savedTheme === "light") { |
| | html.classList.remove("dark"); |
| | themeToggle.textContent = "☀️"; |
| | } else { |
| | const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches; |
| | if (prefersDark) { |
| | html.classList.add("dark"); |
| | themeToggle.textContent = "🌙"; |
| | } else { |
| | html.classList.remove("dark"); |
| | themeToggle.textContent = "☀️"; |
| | } |
| | } |
| | } |
| |
|
| | setInitialTheme(); |
| |
|
| | themeToggle.addEventListener("click", () => { |
| | const isDark = html.classList.toggle("dark"); |
| | localStorage.setItem("theme", isDark ? "dark" : "light"); |
| | themeToggle.textContent = isDark ? "🌙" : "☀️"; |
| | }); |
| |
|
| | toggleConfig.addEventListener("click", () => { |
| | if (configPanel.classList.contains("minimal")) { |
| | configPanel.classList.remove("minimal"); |
| | configPanel.classList.add("expanded"); |
| | } else if (configPanel.classList.contains("expanded")) { |
| | configPanel.classList.remove("expanded"); |
| | configPanel.classList.add("minimal"); |
| |
|
| | |
| | document.querySelectorAll(".options").forEach(opt => opt.classList.remove("show")); |
| | } else { |
| | configPanel.classList.add("expanded"); |
| | configPanel.classList.remove("hidden"); |
| | } |
| | }); |
| |
|
| | docsButton.addEventListener("click", () => { |
| | window.location.href = "/docs"; |
| | }); |
| |
|
| | function showLoader(id) { |
| | const loader = document.getElementById(`loader${id}`); |
| | const modelZone = loader.closest(".model-zone"); |
| | loader.classList.remove("hidden"); |
| | modelZone.classList.add("loading"); |
| | loader.innerHTML = ` |
| | <div class="dot"></div> |
| | <div class="dot"></div> |
| | <div class="dot"></div> |
| | `; |
| | } |
| |
|
| | function hideLoader(id) { |
| | const loader = document.getElementById(`loader${id}`); |
| | const modelZone = loader.closest(".model-zone"); |
| | loader.classList.add("hidden"); |
| | modelZone.classList.remove("loading"); |
| | loader.innerHTML = ""; |
| | } |
| |
|
| | const chatForm = document.getElementById("chatForm"); |
| | const userInput = document.getElementById("userInput"); |
| | const chatContainer = document.getElementById("chatContainer"); |
| |
|
| | function appendMessage(role, text) { |
| | const wrapper = document.createElement("div"); |
| | wrapper.className = `flex ${role === "user" ? "justify-end" : "justify-start"}`; |
| |
|
| | const div = document.createElement("div"); |
| | div.className = `p-3 rounded shadow max-w-2xl whitespace-pre-wrap break-words ${ |
| | role === "user" ? "bg-blue text-fg0" : "bg-green text-fg0" |
| | }`; |
| |
|
| | div.textContent = text; |
| | wrapper.appendChild(div); |
| | chatContainer.appendChild(wrapper); |
| | chatContainer.scrollTop = chatContainer.scrollHeight; |
| | } |
| |
|
| | chatForm.addEventListener("submit", async (e) => { |
| | e.preventDefault(); |
| | const prompt = userInput.value.trim(); |
| | if (!prompt) return; |
| |
|
| | appendMessage("user", prompt); |
| | userInput.value = ""; |
| |
|
| | configPanel.classList.remove("expanded"); |
| | configPanel.classList.add("minimal"); |
| |
|
| | const selections = { |
| | "LLM-A": document.getElementById("modelA").dataset.value, |
| | "LLM-B": document.getElementById("modelB").dataset.value, |
| | "LLM-C": document.getElementById("modelC").dataset.value, |
| | "LLM-D": document.getElementById("aggregator").dataset.value |
| | }; |
| |
|
| | ["A", "B", "C"].forEach(id => showLoader(id)); |
| |
|
| | const settings = { |
| | models: { |
| | "LLM-A": selections["LLM-A"], |
| | "LLM-B": selections["LLM-B"], |
| | "LLM-C": selections["LLM-C"] |
| | }, |
| | aggregator: selections["LLM-D"] |
| | }; |
| |
|
| | try { |
| | const response = await fetch("/chat", { |
| | method: "POST", |
| | headers: { "Content-Type": "application/json" }, |
| | body: JSON.stringify({ prompt, settings }) |
| | }); |
| |
|
| | if (response.ok) { |
| | const data = await response.json(); |
| | appendMessage("bot", data.response); |
| | } else { |
| | appendMessage("bot", "An error occurred. Please check your model selections."); |
| | } |
| | } catch (error) { |
| | appendMessage("bot", "An unexpected error occurred."); |
| | } finally { |
| | ["A", "B", "C", "D"].forEach(id => hideLoader(id)); |
| | } |
| | }); |
| |
|
| | fetchModelList(); |
| |
|