Buckets:
| const $ = (id) => document.getElementById(id); | |
| const state = { | |
| streamingBuffer: "", | |
| }; | |
| function renderResponse(text) { | |
| $("responseBox").textContent = text || "(empty response)"; | |
| } | |
| function renderSources(sources = []) { | |
| const tbody = $("sourcesBody"); | |
| if (!sources.length) { | |
| tbody.innerHTML = '<tr><td colspan="4">No sources.</td></tr>'; | |
| return; | |
| } | |
| tbody.innerHTML = sources | |
| .map( | |
| (s) => | |
| `<tr> | |
| <td>${s.file || "-"}</td> | |
| <td>${s.section || "-"}</td> | |
| <td>${s.score ?? "-"}</td> | |
| <td>${s.rerank_score ?? "-"}</td> | |
| </tr>` | |
| ) | |
| .join(""); | |
| } | |
| function appendChat(role, text) { | |
| const row = document.createElement("div"); | |
| row.className = `chat-row ${role}`; | |
| row.textContent = `${role === "user" ? "Broker" : "Assistant"}: ${text}`; | |
| const log = $("chatLog"); | |
| log.appendChild(row); | |
| log.scrollTop = log.scrollHeight; | |
| } | |
| async function postJson(path, payload) { | |
| const res = await fetch(path, { | |
| method: "POST", | |
| headers: { "Content-Type": "application/json" }, | |
| body: JSON.stringify(payload), | |
| }); | |
| if (!res.ok) { | |
| const err = await res.text(); | |
| throw new Error(err || `HTTP ${res.status}`); | |
| } | |
| return res.json(); | |
| } | |
| async function checkHealth() { | |
| try { | |
| const res = await fetch("/health"); | |
| const data = await res.json(); | |
| if (data.index_ready && data.llm_configured) { | |
| $("health-pill").textContent = "API OK • Index Ready • LLM Ready"; | |
| $("health-pill").style.borderColor = "#1f7d4c"; | |
| $("health-pill").style.color = "#1f7d4c"; | |
| } else if (data.index_ready && !data.llm_configured) { | |
| $("health-pill").textContent = "API OK • Index Ready • Add API Key"; | |
| $("health-pill").style.borderColor = "#b14f16"; | |
| $("health-pill").style.color = "#b14f16"; | |
| } else { | |
| $("health-pill").textContent = "API OK • Build Index Needed"; | |
| $("health-pill").style.borderColor = "#b14f16"; | |
| $("health-pill").style.color = "#b14f16"; | |
| } | |
| } catch { | |
| $("health-pill").textContent = "API unreachable"; | |
| $("health-pill").style.color = "#a22020"; | |
| } | |
| } | |
| function getInputs() { | |
| return { | |
| question: $("question").value.trim(), | |
| message: $("question").value.trim(), | |
| session_id: $("sessionId").value.trim() || "default", | |
| use_reranker: $("useReranker").checked, | |
| use_rag_context: $("useRagContext").checked, | |
| }; | |
| } | |
| $("btnRag").addEventListener("click", async () => { | |
| const { question, session_id, use_reranker } = getInputs(); | |
| if (!question) return; | |
| renderResponse("Running RAG query..."); | |
| try { | |
| const data = await postJson("/rag/query", { question, session_id, use_reranker }); | |
| renderResponse(`${data.answer}\n\nLatency: ${data.latency_ms} ms`); | |
| renderSources(data.sources || []); | |
| } catch (err) { | |
| renderResponse(`Error: ${err.message}`); | |
| } | |
| }); | |
| $("btnChat").addEventListener("click", async () => { | |
| const { message, session_id } = getInputs(); | |
| if (!message) return; | |
| appendChat("user", message); | |
| renderResponse("Running one-turn chat..."); | |
| try { | |
| const data = await postJson("/chat", { message, session_id }); | |
| appendChat("assistant", data.response); | |
| renderResponse(`${data.response}\n\nLatency: ${data.latency_ms} ms`); | |
| renderSources([]); | |
| } catch (err) { | |
| renderResponse(`Error: ${err.message}`); | |
| } | |
| }); | |
| $("btnCont").addEventListener("click", async () => { | |
| const { message, session_id, use_rag_context, use_reranker } = getInputs(); | |
| if (!message) return; | |
| appendChat("user", message); | |
| renderResponse("Running continuous chat..."); | |
| try { | |
| const data = await postJson("/chat/continuous", { | |
| message, | |
| session_id, | |
| use_rag_context, | |
| use_reranker, | |
| }); | |
| appendChat("assistant", data.response); | |
| renderResponse(`${data.response}\n\nLatency: ${data.latency_ms} ms`); | |
| renderSources(data.sources || []); | |
| } catch (err) { | |
| renderResponse(`Error: ${err.message}`); | |
| } | |
| }); | |
| $("btnAgent").addEventListener("click", async () => { | |
| const { message, session_id, use_reranker } = getInputs(); | |
| if (!message) return; | |
| appendChat("user", message); | |
| renderResponse("Running agent tool loop..."); | |
| try { | |
| const data = await postJson("/agent/chat", { | |
| message, | |
| session_id, | |
| use_reranker, | |
| max_turns: 6, | |
| }); | |
| appendChat("assistant", data.response); | |
| renderResponse( | |
| `${data.response}\n\nLatency: ${data.latency_ms} ms\nTool Calls: ${data.tool_calls_made}\nTurns Used: ${data.turns_used}` | |
| ); | |
| const toolSources = (data.tool_trace || []) | |
| .filter((call) => call.tool_name === "search_policy") | |
| .flatMap((call) => | |
| ((call.result && call.result.results) || []).map((r) => ({ | |
| file: r.source, | |
| section: r.section, | |
| score: r.score, | |
| rerank_score: r.rerank_score, | |
| })) | |
| ); | |
| renderSources(toolSources); | |
| } catch (err) { | |
| renderResponse(`Error: ${err.message}`); | |
| } | |
| }); | |
| $("btnStream").addEventListener("click", async () => { | |
| const { message, session_id, use_rag_context, use_reranker } = getInputs(); | |
| if (!message) return; | |
| appendChat("user", message); | |
| renderResponse("Streaming response...\n"); | |
| state.streamingBuffer = ""; | |
| const res = await fetch("/chat/continuous/stream", { | |
| method: "POST", | |
| headers: { "Content-Type": "application/json" }, | |
| body: JSON.stringify({ message, session_id, use_rag_context, use_reranker }), | |
| }); | |
| if (!res.ok || !res.body) { | |
| renderResponse(`Error: ${await res.text()}`); | |
| return; | |
| } | |
| const reader = res.body.getReader(); | |
| const decoder = new TextDecoder(); | |
| let done = false; | |
| let finalMeta = null; | |
| while (!done) { | |
| const result = await reader.read(); | |
| done = result.done; | |
| if (done) break; | |
| const chunk = decoder.decode(result.value, { stream: true }); | |
| const lines = chunk.split("\n").filter((line) => line.startsWith("data:")); | |
| for (const line of lines) { | |
| const payload = line.replace(/^data:\s*/, "").trim(); | |
| if (payload === "[DONE]") continue; | |
| try { | |
| const parsed = JSON.parse(payload); | |
| if (parsed.token) { | |
| state.streamingBuffer += parsed.token; | |
| renderResponse(state.streamingBuffer); | |
| } | |
| if (parsed.meta) { | |
| finalMeta = parsed.meta; | |
| } | |
| } catch { | |
| // no-op | |
| } | |
| } | |
| } | |
| appendChat("assistant", state.streamingBuffer || "(empty)"); | |
| if (finalMeta) { | |
| renderResponse(`${state.streamingBuffer}\n\nLatency: ${finalMeta.latency_ms} ms`); | |
| renderSources(finalMeta.sources || []); | |
| } | |
| }); | |
| $("btnClearSession").addEventListener("click", async () => { | |
| const sessionId = $("sessionId").value.trim() || "default"; | |
| const [chatRes, agentRes] = await Promise.all([ | |
| fetch(`/chat/session/${encodeURIComponent(sessionId)}`, { method: "DELETE" }), | |
| fetch(`/agent/session/${encodeURIComponent(sessionId)}`, { method: "DELETE" }), | |
| ]); | |
| if (chatRes.ok || agentRes.ok) { | |
| $("chatLog").innerHTML = ""; | |
| renderResponse(`Session ${sessionId} cleared (chat + agent).`); | |
| } | |
| }); | |
| $("btnBenchmark").addEventListener("click", async () => { | |
| const { question, use_reranker } = getInputs(); | |
| const runs = Number($("benchRuns").value || 5); | |
| if (!question) return; | |
| $("benchmarkBox").textContent = `Running benchmark for ${runs} runs...`; | |
| try { | |
| const data = await postJson("/rag/benchmark", { question, runs, use_reranker }); | |
| $("benchmarkBox").textContent = JSON.stringify(data, null, 2); | |
| } catch (err) { | |
| $("benchmarkBox").textContent = `Error: ${err.message}`; | |
| } | |
| }); | |
| $("btnJsonEval").addEventListener("click", async () => { | |
| const max_questions = Number($("jsonMaxQuestions").value || 8); | |
| const dataset_path = $("jsonPath").value.trim() || "../rag.json"; | |
| const use_reranker = $("useReranker").checked; | |
| $("benchmarkBox").textContent = `Running JSON evaluation (${max_questions} questions)...`; | |
| try { | |
| const data = await postJson("/rag/evaluate/json", { | |
| dataset_path, | |
| max_questions, | |
| use_reranker, | |
| }); | |
| $("benchmarkBox").textContent = JSON.stringify(data, null, 2); | |
| } catch (err) { | |
| $("benchmarkBox").textContent = `Error: ${err.message}`; | |
| } | |
| }); | |
| $("btnMetrics").addEventListener("click", async () => { | |
| try { | |
| const res = await fetch("/metrics"); | |
| const data = await res.json(); | |
| $("metricsBox").textContent = JSON.stringify(data, null, 2); | |
| } catch (err) { | |
| $("metricsBox").textContent = `Error: ${err.message}`; | |
| } | |
| }); | |
| checkHealth(); | |
| setInterval(checkHealth, 12000); | |
Xet Storage Details
- Size:
- 8.54 kB
- Xet hash:
- 9b0b319eee21074d783273e98b5f81b5ed8fe775fd97a582f180e474730dc93d
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.