215 lines
7 KiB
JavaScript
215 lines
7 KiB
JavaScript
const healthButton = document.getElementById("healthButton");
|
|
const ingestButton = document.getElementById("ingestButton");
|
|
const queryButton = document.getElementById("queryButton");
|
|
const presetDocs = document.getElementById("presetDocs");
|
|
const presetRagDocs = document.getElementById("presetRagDocs");
|
|
const presetCode = document.getElementById("presetCode");
|
|
|
|
const healthResult = document.getElementById("healthResult");
|
|
const mainResult = document.getElementById("mainResult");
|
|
const compareResult = document.getElementById("compareResult");
|
|
|
|
const queryInput = document.getElementById("queryInput");
|
|
const queryMode = document.getElementById("queryMode");
|
|
const queryIntent = document.getElementById("queryIntent");
|
|
const queryOperation = document.getElementById("queryOperation");
|
|
const answerModel = document.getElementById("answerModel");
|
|
const useModelInRetrieve = document.getElementById("useModelInRetrieve");
|
|
const scopePresetSelect = document.getElementById("scopePresetSelect");
|
|
const scopeSourceRef = document.getElementById("scopeSourceRef");
|
|
const scopeTags = document.getElementById("scopeTags");
|
|
const compareWithoutRag = document.getElementById("compareWithoutRag");
|
|
|
|
const ingestSourceType = document.getElementById("ingestSourceType");
|
|
const ingestSourceRef = document.getElementById("ingestSourceRef");
|
|
const ingestMode = document.getElementById("ingestMode");
|
|
const ingestTags = document.getElementById("ingestTags");
|
|
|
|
function format(value) {
|
|
return JSON.stringify(value, null, 2);
|
|
}
|
|
|
|
function splitTags(value) {
|
|
return value.split(",").map((entry) => entry.trim()).filter(Boolean);
|
|
}
|
|
|
|
function buildScopeLabel(scope) {
|
|
const modes = scope.chunkModes.join(", ") || "sin modo";
|
|
return `${scope.sourceRef} [${modes}]`;
|
|
}
|
|
|
|
async function request(url, payload, method = "POST") {
|
|
const response = await fetch(url, {
|
|
method,
|
|
headers: {
|
|
"Content-Type": "application/json"
|
|
},
|
|
body: payload ? JSON.stringify(payload) : undefined
|
|
});
|
|
|
|
const data = await response.json();
|
|
if (!response.ok) {
|
|
throw new Error(data.error || `HTTP ${response.status}`);
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
async function loadScopes() {
|
|
try {
|
|
const scopes = await fetch("/sources").then((response) => response.json());
|
|
scopePresetSelect.innerHTML = "";
|
|
|
|
const placeholder = document.createElement("option");
|
|
placeholder.value = "";
|
|
placeholder.textContent = "Selecciona un scope disponible";
|
|
scopePresetSelect.appendChild(placeholder);
|
|
|
|
for (const scope of scopes) {
|
|
const option = document.createElement("option");
|
|
option.value = JSON.stringify(scope);
|
|
option.textContent = buildScopeLabel(scope);
|
|
scopePresetSelect.appendChild(option);
|
|
}
|
|
|
|
if (scopes.length === 0) {
|
|
placeholder.textContent = "No hay scopes detectados";
|
|
}
|
|
} catch (error) {
|
|
scopePresetSelect.innerHTML = "";
|
|
const option = document.createElement("option");
|
|
option.value = "";
|
|
option.textContent = `Error cargando scopes: ${error}`;
|
|
scopePresetSelect.appendChild(option);
|
|
}
|
|
}
|
|
|
|
async function loadAnswerModels() {
|
|
try {
|
|
const payload = await fetch("/models/answer").then((response) => response.json());
|
|
answerModel.innerHTML = "";
|
|
|
|
for (const model of payload.models || []) {
|
|
const option = document.createElement("option");
|
|
option.value = model;
|
|
option.textContent = model;
|
|
answerModel.appendChild(option);
|
|
}
|
|
|
|
if (payload.defaultModel) {
|
|
answerModel.value = payload.defaultModel;
|
|
}
|
|
} catch {
|
|
answerModel.innerHTML = "";
|
|
const option = document.createElement("option");
|
|
option.value = "openai/gpt-4.1-mini";
|
|
option.textContent = "openai/gpt-4.1-mini";
|
|
answerModel.appendChild(option);
|
|
}
|
|
}
|
|
|
|
scopePresetSelect.addEventListener("change", () => {
|
|
if (!scopePresetSelect.value) {
|
|
return;
|
|
}
|
|
|
|
const scope = JSON.parse(scopePresetSelect.value);
|
|
scopeSourceRef.value = scope.sourceRef || "";
|
|
scopeTags.value = (scope.tags || []).join(", ");
|
|
|
|
if (scope.chunkModes.includes("codigo")) {
|
|
queryMode.value = "codigo";
|
|
} else if (scope.chunkModes.includes("documental")) {
|
|
queryMode.value = "documental";
|
|
}
|
|
});
|
|
|
|
healthButton.addEventListener("click", async () => {
|
|
healthResult.textContent = "Comprobando...";
|
|
try {
|
|
const response = await fetch("/health");
|
|
const data = await response.json();
|
|
healthResult.textContent = format(data);
|
|
} catch (error) {
|
|
healthResult.textContent = String(error);
|
|
}
|
|
});
|
|
|
|
ingestButton.addEventListener("click", async () => {
|
|
mainResult.textContent = "Ejecutando ingesta...";
|
|
try {
|
|
const data = await request("/ingest", {
|
|
sourceType: ingestSourceType.value,
|
|
sourceRef: ingestSourceRef.value,
|
|
mode: ingestMode.value,
|
|
tags: splitTags(ingestTags.value)
|
|
});
|
|
mainResult.textContent = format(data);
|
|
} catch (error) {
|
|
mainResult.textContent = String(error);
|
|
}
|
|
});
|
|
|
|
queryButton.addEventListener("click", async () => {
|
|
mainResult.textContent = "Consultando...";
|
|
compareResult.textContent = compareWithoutRag.checked ? "Comparando..." : "Desactivada.";
|
|
|
|
const payload = {
|
|
mode: queryMode.value,
|
|
intent: queryIntent.value,
|
|
query: queryInput.value,
|
|
model: answerModel.value,
|
|
useModelInRetrieve: useModelInRetrieve.checked,
|
|
scope: {
|
|
sourceRef: scopeSourceRef.value,
|
|
tags: splitTags(scopeTags.value)
|
|
}
|
|
};
|
|
|
|
try {
|
|
const endpoint = queryOperation.value === "answer" ? "/answer" : "/retrieve";
|
|
const data = await request(endpoint, payload);
|
|
mainResult.textContent = format(data);
|
|
|
|
if (compareWithoutRag.checked && queryOperation.value === "answer") {
|
|
const comparison = await request("/answer/direct", {
|
|
query: queryInput.value,
|
|
model: answerModel.value
|
|
});
|
|
compareResult.textContent = format(comparison);
|
|
}
|
|
} catch (error) {
|
|
mainResult.textContent = String(error);
|
|
compareResult.textContent = compareWithoutRag.checked ? String(error) : "Desactivada.";
|
|
}
|
|
});
|
|
|
|
presetDocs.addEventListener("click", () => {
|
|
queryMode.value = "documental";
|
|
queryIntent.value = "specific";
|
|
queryOperation.value = "answer";
|
|
queryInput.value = "que tenemos pendiente por hacer en este workspace";
|
|
scopeSourceRef.value = "/home/pancho/Documentos/Empresa/Desarrollo/IA/docs";
|
|
answerModel.value = "openai/gpt-4.1-mini";
|
|
});
|
|
|
|
presetRagDocs.addEventListener("click", () => {
|
|
queryMode.value = "documental";
|
|
queryIntent.value = "bootstrap";
|
|
queryOperation.value = "retrieve";
|
|
queryInput.value = "dame un mapa inicial del modulo RAG, su arquitectura, decisiones, estado actual y documentos clave";
|
|
scopeSourceRef.value = "/home/pancho/Documentos/Empresa/Desarrollo/IA/RAG/docs";
|
|
answerModel.value = "openai/gpt-4.1-mini";
|
|
});
|
|
|
|
presetCode.addEventListener("click", () => {
|
|
queryMode.value = "codigo";
|
|
queryIntent.value = "specific";
|
|
queryOperation.value = "answer";
|
|
queryInput.value = "como se construye source_id en el rag";
|
|
scopeSourceRef.value = "/home/pancho/Documentos/Empresa/Desarrollo/IA/RAG/src";
|
|
answerModel.value = "openai/gpt-4.1-mini";
|
|
});
|
|
|
|
loadScopes();
|
|
loadAnswerModels();
|