Improve scope handling in RAG playground
This commit is contained in:
parent
6557aea0bc
commit
02798085b1
2 changed files with 71 additions and 14 deletions
|
|
@ -21,6 +21,8 @@ const contextStatusText = document.getElementById("contextStatusText");
|
||||||
const contextScopeText = document.getElementById("contextScopeText");
|
const contextScopeText = document.getElementById("contextScopeText");
|
||||||
|
|
||||||
const ingestSourceType = document.getElementById("ingestSourceType");
|
const ingestSourceType = document.getElementById("ingestSourceType");
|
||||||
|
const ingestScopeMode = document.getElementById("ingestScopeMode");
|
||||||
|
const ingestSourceIdWrapper = document.getElementById("ingestSourceIdWrapper");
|
||||||
const ingestSourceId = document.getElementById("ingestSourceId");
|
const ingestSourceId = document.getElementById("ingestSourceId");
|
||||||
const ingestSourceRef = document.getElementById("ingestSourceRef");
|
const ingestSourceRef = document.getElementById("ingestSourceRef");
|
||||||
const ingestUploadFile = document.getElementById("ingestUploadFile");
|
const ingestUploadFile = document.getElementById("ingestUploadFile");
|
||||||
|
|
@ -35,14 +37,18 @@ const useModelInRetrieve = document.getElementById("useModelInRetrieve");
|
||||||
const reuseBootstrapContext = document.getElementById("reuseBootstrapContext");
|
const reuseBootstrapContext = document.getElementById("reuseBootstrapContext");
|
||||||
const allowAdditionalRetrieve = document.getElementById("allowAdditionalRetrieve");
|
const allowAdditionalRetrieve = document.getElementById("allowAdditionalRetrieve");
|
||||||
const scopePresetSelect = document.getElementById("scopePresetSelect");
|
const scopePresetSelect = document.getElementById("scopePresetSelect");
|
||||||
|
const selectedSourceId = document.getElementById("selectedSourceId");
|
||||||
const scopeSourceRef = document.getElementById("scopeSourceRef");
|
const scopeSourceRef = document.getElementById("scopeSourceRef");
|
||||||
const scopeTags = document.getElementById("scopeTags");
|
const scopeTags = document.getElementById("scopeTags");
|
||||||
|
const scopeEditMode = document.getElementById("scopeEditMode");
|
||||||
const compareWithoutRag = document.getElementById("compareWithoutRag");
|
const compareWithoutRag = document.getElementById("compareWithoutRag");
|
||||||
const chatMode = document.getElementById("chatMode");
|
const chatMode = document.getElementById("chatMode");
|
||||||
|
const chatScopeInfo = document.getElementById("chatScopeInfo");
|
||||||
const chatInput = document.getElementById("chatInput");
|
const chatInput = document.getElementById("chatInput");
|
||||||
|
|
||||||
let lastBootstrapContext = null;
|
let lastBootstrapContext = null;
|
||||||
let chatHistory = [];
|
let chatHistory = [];
|
||||||
|
let availableScopes = [];
|
||||||
|
|
||||||
function format(value) {
|
function format(value) {
|
||||||
return JSON.stringify(value, null, 2);
|
return JSON.stringify(value, null, 2);
|
||||||
|
|
@ -62,6 +68,7 @@ function updateIngestUiState() {
|
||||||
ingestSourceType.value = hasUpload ? "file" : ingestSourceType.value;
|
ingestSourceType.value = hasUpload ? "file" : ingestSourceType.value;
|
||||||
ingestSourceType.disabled = hasUpload;
|
ingestSourceType.disabled = hasUpload;
|
||||||
ingestSourceRef.disabled = hasUpload;
|
ingestSourceRef.disabled = hasUpload;
|
||||||
|
ingestSourceIdWrapper.style.display = ingestScopeMode.value === "custom" ? "block" : "none";
|
||||||
|
|
||||||
if (hasUpload) {
|
if (hasUpload) {
|
||||||
ingestModeHint.textContent = `Upload directo activo: se ingerira el archivo local "${ingestUploadFile.files[0].name}" y se ignorara la ruta manual.`;
|
ingestModeHint.textContent = `Upload directo activo: se ingerira el archivo local "${ingestUploadFile.files[0].name}" y se ignorara la ruta manual.`;
|
||||||
|
|
@ -72,6 +79,27 @@ function updateIngestUiState() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function applySelectedScope(scope) {
|
||||||
|
selectedSourceId.value = scope?.sourceId || "";
|
||||||
|
scopeSourceRef.value = scope?.sourceRef || "";
|
||||||
|
scopeTags.value = (scope?.tags || []).join(", ");
|
||||||
|
chatScopeInfo.value = [scope?.sourceId, scope?.sourceRef].filter(Boolean).join(" | ");
|
||||||
|
|
||||||
|
if (scope?.chunkModes?.includes("codigo")) {
|
||||||
|
bootstrapMode.value = "codigo";
|
||||||
|
chatMode.value = "codigo";
|
||||||
|
} else if (scope?.chunkModes?.includes("documental")) {
|
||||||
|
bootstrapMode.value = "documental";
|
||||||
|
chatMode.value = "documental";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateScopeEditState() {
|
||||||
|
const locked = scopeEditMode.value !== "manual";
|
||||||
|
scopeSourceRef.readOnly = locked;
|
||||||
|
scopeTags.readOnly = locked;
|
||||||
|
}
|
||||||
|
|
||||||
function request(url, payload, method = "POST") {
|
function request(url, payload, method = "POST") {
|
||||||
return fetch(url, {
|
return fetch(url, {
|
||||||
method,
|
method,
|
||||||
|
|
@ -94,6 +122,7 @@ function renderBootstrapContext() {
|
||||||
contextIndicator.className = "indicator indicator-off";
|
contextIndicator.className = "indicator indicator-off";
|
||||||
contextStatusText.textContent = "Sin contexto cargado";
|
contextStatusText.textContent = "Sin contexto cargado";
|
||||||
contextScopeText.textContent = "No hay bootstrap activo.";
|
contextScopeText.textContent = "No hay bootstrap activo.";
|
||||||
|
chatScopeInfo.value = [selectedSourceId.value, scopeSourceRef.value].filter(Boolean).join(" | ") || "Sin scope seleccionado";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -101,6 +130,7 @@ function renderBootstrapContext() {
|
||||||
contextIndicator.className = "indicator indicator-on";
|
contextIndicator.className = "indicator indicator-on";
|
||||||
contextStatusText.textContent = "Contexto bootstrap activo";
|
contextStatusText.textContent = "Contexto bootstrap activo";
|
||||||
contextScopeText.textContent = lastBootstrapContext.scope?.sourceRef || "Scope no especificado";
|
contextScopeText.textContent = lastBootstrapContext.scope?.sourceRef || "Scope no especificado";
|
||||||
|
chatScopeInfo.value = [lastBootstrapContext.scope?.sourceId, lastBootstrapContext.scope?.sourceRef].filter(Boolean).join(" | ");
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderChatHistory() {
|
function renderChatHistory() {
|
||||||
|
|
@ -120,7 +150,17 @@ function renderChatHistory() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildScopeFromInputs() {
|
function buildScopeFromInputs() {
|
||||||
|
if (scopeEditMode.value !== "manual" && scopePresetSelect.value) {
|
||||||
|
const scope = JSON.parse(scopePresetSelect.value);
|
||||||
|
return {
|
||||||
|
sourceId: scope.sourceId,
|
||||||
|
sourceRef: scope.sourceRef,
|
||||||
|
tags: scope.tags || []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
sourceId: selectedSourceId.value || undefined,
|
||||||
sourceRef: scopeSourceRef.value,
|
sourceRef: scopeSourceRef.value,
|
||||||
tags: splitTags(scopeTags.value)
|
tags: splitTags(scopeTags.value)
|
||||||
};
|
};
|
||||||
|
|
@ -137,6 +177,7 @@ function applyPreset(mode, query, sourceRef, useRetrieveModel = false) {
|
||||||
async function loadScopes() {
|
async function loadScopes() {
|
||||||
try {
|
try {
|
||||||
const scopes = await fetch("/sources").then((response) => response.json());
|
const scopes = await fetch("/sources").then((response) => response.json());
|
||||||
|
availableScopes = scopes;
|
||||||
scopePresetSelect.innerHTML = "";
|
scopePresetSelect.innerHTML = "";
|
||||||
|
|
||||||
const placeholder = document.createElement("option");
|
const placeholder = document.createElement("option");
|
||||||
|
|
@ -153,6 +194,9 @@ async function loadScopes() {
|
||||||
|
|
||||||
if (scopes.length === 0) {
|
if (scopes.length === 0) {
|
||||||
placeholder.textContent = "No hay scopes detectados";
|
placeholder.textContent = "No hay scopes detectados";
|
||||||
|
} else if (!scopePresetSelect.value) {
|
||||||
|
scopePresetSelect.value = JSON.stringify(scopes[0]);
|
||||||
|
applySelectedScope(scopes[0]);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
scopePresetSelect.innerHTML = `<option value="">Error cargando scopes: ${error}</option>`;
|
scopePresetSelect.innerHTML = `<option value="">Error cargando scopes: ${error}</option>`;
|
||||||
|
|
@ -192,19 +236,12 @@ scopePresetSelect.addEventListener("change", () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const scope = JSON.parse(scopePresetSelect.value);
|
const scope = JSON.parse(scopePresetSelect.value);
|
||||||
scopeSourceRef.value = scope.sourceRef || "";
|
applySelectedScope(scope);
|
||||||
scopeTags.value = (scope.tags || []).join(", ");
|
|
||||||
|
|
||||||
if (scope.chunkModes.includes("codigo")) {
|
|
||||||
bootstrapMode.value = "codigo";
|
|
||||||
chatMode.value = "codigo";
|
|
||||||
} else if (scope.chunkModes.includes("documental")) {
|
|
||||||
bootstrapMode.value = "documental";
|
|
||||||
chatMode.value = "documental";
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
ingestUploadFile.addEventListener("change", updateIngestUiState);
|
ingestUploadFile.addEventListener("change", updateIngestUiState);
|
||||||
|
ingestScopeMode.addEventListener("change", updateIngestUiState);
|
||||||
|
scopeEditMode.addEventListener("change", updateScopeEditState);
|
||||||
|
|
||||||
healthButton.addEventListener("click", async () => {
|
healthButton.addEventListener("click", async () => {
|
||||||
healthResult.textContent = "Comprobando...";
|
healthResult.textContent = "Comprobando...";
|
||||||
|
|
@ -226,7 +263,7 @@ ingestButton.addEventListener("click", async () => {
|
||||||
formData.append("file", ingestUploadFile.files[0]);
|
formData.append("file", ingestUploadFile.files[0]);
|
||||||
formData.append("mode", ingestMode.value);
|
formData.append("mode", ingestMode.value);
|
||||||
formData.append("tags", splitTags(ingestTags.value).join(","));
|
formData.append("tags", splitTags(ingestTags.value).join(","));
|
||||||
if (ingestSourceId.value.trim()) {
|
if (ingestScopeMode.value === "custom" && ingestSourceId.value.trim()) {
|
||||||
formData.append("sourceId", ingestSourceId.value.trim());
|
formData.append("sourceId", ingestSourceId.value.trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -240,7 +277,7 @@ ingestButton.addEventListener("click", async () => {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
data = await request("/ingest", {
|
data = await request("/ingest", {
|
||||||
sourceId: ingestSourceId.value.trim() || undefined,
|
sourceId: ingestScopeMode.value === "custom" ? (ingestSourceId.value.trim() || undefined) : undefined,
|
||||||
sourceType: ingestSourceType.value,
|
sourceType: ingestSourceType.value,
|
||||||
sourceRef: ingestSourceRef.value,
|
sourceRef: ingestSourceRef.value,
|
||||||
mode: ingestMode.value,
|
mode: ingestMode.value,
|
||||||
|
|
@ -369,3 +406,4 @@ loadAnswerModels();
|
||||||
renderBootstrapContext();
|
renderBootstrapContext();
|
||||||
renderChatHistory();
|
renderChatHistory();
|
||||||
updateIngestUiState();
|
updateIngestUiState();
|
||||||
|
updateScopeEditState();
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,13 @@
|
||||||
<article class="panel">
|
<article class="panel">
|
||||||
<h2>Ingesta</h2>
|
<h2>Ingesta</h2>
|
||||||
<div class="grid single-grid">
|
<div class="grid single-grid">
|
||||||
<label>Source ID / scope custom
|
<label>Crear scope aislado
|
||||||
|
<select id="ingestScopeMode">
|
||||||
|
<option value="existing">usar generacion automatica</option>
|
||||||
|
<option value="custom">definir sourceId propio</option>
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
<label id="ingestSourceIdWrapper">Source ID / scope custom
|
||||||
<input id="ingestSourceId" placeholder="ej: src:cliente-a:manual:pdf-tecnico" />
|
<input id="ingestSourceId" placeholder="ej: src:cliente-a:manual:pdf-tecnico" />
|
||||||
</label>
|
</label>
|
||||||
<label>Tipo de fuente
|
<label>Tipo de fuente
|
||||||
|
|
@ -69,6 +75,9 @@
|
||||||
<option value="">Cargando scopes...</option>
|
<option value="">Cargando scopes...</option>
|
||||||
</select>
|
</select>
|
||||||
</label>
|
</label>
|
||||||
|
<label>Source ID seleccionado
|
||||||
|
<input id="selectedSourceId" readonly />
|
||||||
|
</label>
|
||||||
<label>Scope por sourceRef
|
<label>Scope por sourceRef
|
||||||
<input id="scopeSourceRef" value="/home/pancho/Documentos/Empresa/Desarrollo/IA/docs" />
|
<input id="scopeSourceRef" value="/home/pancho/Documentos/Empresa/Desarrollo/IA/docs" />
|
||||||
</label>
|
</label>
|
||||||
|
|
@ -82,6 +91,12 @@
|
||||||
<option value="auto">auto</option>
|
<option value="auto">auto</option>
|
||||||
</select>
|
</select>
|
||||||
</label>
|
</label>
|
||||||
|
<label>Edicion manual del scope
|
||||||
|
<select id="scopeEditMode">
|
||||||
|
<option value="locked">bloqueado al scope seleccionado</option>
|
||||||
|
<option value="manual">editar manualmente</option>
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
<label>Modelo para sintetizar bootstrap
|
<label>Modelo para sintetizar bootstrap
|
||||||
<select id="answerModel">
|
<select id="answerModel">
|
||||||
<option value="openai/gpt-4.1-mini">openai/gpt-4.1-mini</option>
|
<option value="openai/gpt-4.1-mini">openai/gpt-4.1-mini</option>
|
||||||
|
|
@ -111,7 +126,7 @@
|
||||||
<div class="grid chat-grid">
|
<div class="grid chat-grid">
|
||||||
<article class="panel context-panel">
|
<article class="panel context-panel">
|
||||||
<h2>Estado del contexto</h2>
|
<h2>Estado del contexto</h2>
|
||||||
<div class="context-status" id="contextStatusCard">
|
<div class="context-status" id="contextStatusCard">
|
||||||
<span id="contextIndicator" class="indicator indicator-off"></span>
|
<span id="contextIndicator" class="indicator indicator-off"></span>
|
||||||
<div>
|
<div>
|
||||||
<strong id="contextStatusText">Sin contexto cargado</strong>
|
<strong id="contextStatusText">Sin contexto cargado</strong>
|
||||||
|
|
@ -119,6 +134,10 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<label>Scope activo para chat
|
||||||
|
<input id="chatScopeInfo" readonly />
|
||||||
|
</label>
|
||||||
|
|
||||||
<label class="checkbox">
|
<label class="checkbox">
|
||||||
<input type="checkbox" id="reuseBootstrapContext" checked />
|
<input type="checkbox" id="reuseBootstrapContext" checked />
|
||||||
Reutilizar bootstrap como contexto base
|
Reutilizar bootstrap como contexto base
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue