Store bootstrap metadata in evaluation logs

This commit is contained in:
Paco POR-CORREO 2026-04-06 20:36:14 +02:00
parent 8ce0d7223b
commit c34bc3b5d7
4 changed files with 52 additions and 1 deletions

View file

@ -50,6 +50,7 @@ const chatInput = document.getElementById("chatInput");
const manualLogNote = document.getElementById("manualLogNote"); const manualLogNote = document.getElementById("manualLogNote");
let lastBootstrapContext = null; let lastBootstrapContext = null;
let lastBootstrapMeta = null;
let chatHistory = []; let chatHistory = [];
let availableScopes = []; let availableScopes = [];
let lastInteraction = null; let lastInteraction = null;
@ -320,6 +321,13 @@ async function executeBootstrap() {
}); });
lastBootstrapContext = data; lastBootstrapContext = data;
lastBootstrapMeta = {
query: bootstrapQuery.value,
mode: bootstrapMode.value,
scope: buildScopeFromInputs(),
model: answerModel.value,
usedModelSummary: useModelInRetrieve.checked
};
bootstrapResult.textContent = format(data); bootstrapResult.textContent = format(data);
renderBootstrapContext(); renderBootstrapContext();
lastInteraction = { lastInteraction = {
@ -330,6 +338,7 @@ async function executeBootstrap() {
model: answerModel.value, model: answerModel.value,
scope: buildScopeFromInputs(), scope: buildScopeFromInputs(),
usedBootstrapContext: false, usedBootstrapContext: false,
bootstrapMeta: lastBootstrapMeta,
usedAdditionalRetrieve: useModelInRetrieve.checked, usedAdditionalRetrieve: useModelInRetrieve.checked,
responseSummary: data.modelSummary || data.summary, responseSummary: data.modelSummary || data.summary,
retrievedItems: data.items || [] retrievedItems: data.items || []
@ -345,6 +354,7 @@ replaceBootstrapButton.addEventListener("click", executeBootstrap);
clearBootstrapButton.addEventListener("click", () => { clearBootstrapButton.addEventListener("click", () => {
lastBootstrapContext = null; lastBootstrapContext = null;
lastBootstrapMeta = null;
renderBootstrapContext(); renderBootstrapContext();
}); });
@ -368,6 +378,7 @@ sendChatButton.addEventListener("click", async () => {
preloadedContext: reuseBootstrapContext.checked && lastBootstrapContext preloadedContext: reuseBootstrapContext.checked && lastBootstrapContext
? (lastBootstrapContext.modelSummary || lastBootstrapContext.summary || "") ? (lastBootstrapContext.modelSummary || lastBootstrapContext.summary || "")
: undefined, : undefined,
bootstrapMeta: reuseBootstrapContext.checked ? lastBootstrapMeta : undefined,
allowAdditionalRetrieve: allowAdditionalRetrieve.checked, allowAdditionalRetrieve: allowAdditionalRetrieve.checked,
scope: buildScopeFromInputs() scope: buildScopeFromInputs()
}); });
@ -383,6 +394,7 @@ sendChatButton.addEventListener("click", async () => {
model: answerModel.value, model: answerModel.value,
scope: buildScopeFromInputs(), scope: buildScopeFromInputs(),
usedBootstrapContext: response.usedBootstrapContext, usedBootstrapContext: response.usedBootstrapContext,
bootstrapMeta: reuseBootstrapContext.checked ? lastBootstrapMeta : undefined,
usedAdditionalRetrieve: response.usedAdditionalRetrieve, usedAdditionalRetrieve: response.usedAdditionalRetrieve,
responseSummary: response.answer, responseSummary: response.answer,
retrievedItems: response.retrieved?.items || [] retrievedItems: response.retrieved?.items || []
@ -395,7 +407,8 @@ sendChatButton.addEventListener("click", async () => {
model: answerModel.value, model: answerModel.value,
preloadedContext: reuseBootstrapContext.checked && lastBootstrapContext preloadedContext: reuseBootstrapContext.checked && lastBootstrapContext
? (lastBootstrapContext.modelSummary || lastBootstrapContext.summary || "") ? (lastBootstrapContext.modelSummary || lastBootstrapContext.summary || "")
: undefined : undefined,
bootstrapMeta: reuseBootstrapContext.checked ? lastBootstrapMeta : undefined
}); });
compareResult.textContent = format(comparison); compareResult.textContent = format(comparison);
} }

View file

@ -42,6 +42,21 @@ export function createApp() {
return /no se recupero contexto|no hay informacion suficiente|no dispongo de mas detalles|contexto insuficiente/i.test(text); return /no se recupero contexto|no hay informacion suficiente|no dispongo de mas detalles|contexto insuficiente/i.test(text);
} }
function parseBootstrapMeta(input: unknown) {
if (!input || typeof input !== "object") {
return {};
}
const value = input as Record<string, unknown>;
return {
bootstrapQuery: value.query ? String(value.query) : undefined,
bootstrapMode: value.mode as ChunkMode | undefined,
bootstrapScope: value.scope as RetrieveScope | undefined,
bootstrapModel: value.model ? String(value.model) : undefined,
bootstrapUsedModelSummary: Boolean(value.usedModelSummary)
};
}
app.use(express.json({ limit: "5mb" })); app.use(express.json({ limit: "5mb" }));
app.use(express.static(publicDir)); app.use(express.static(publicDir));
@ -155,6 +170,7 @@ export function createApp() {
const query = String(req.body.query ?? ""); const query = String(req.body.query ?? "");
const model = req.body.model ? String(req.body.model) : undefined; const model = req.body.model ? String(req.body.model) : undefined;
const useModel = Boolean(req.body.useModelInRetrieve); const useModel = Boolean(req.body.useModelInRetrieve);
const bootstrapMeta = parseBootstrapMeta(req.body.bootstrapMeta);
const scope: RetrieveScope | undefined = req.body.scope const scope: RetrieveScope | undefined = req.body.scope
? { ? {
sourceId: req.body.scope.sourceId, sourceId: req.body.scope.sourceId,
@ -182,6 +198,7 @@ export function createApp() {
intent, intent,
scope, scope,
model: payload.model, model: payload.model,
...bootstrapMeta,
responseSummary: payload.modelSummary, responseSummary: payload.modelSummary,
retrievedItems: items retrievedItems: items
}); });
@ -200,6 +217,7 @@ export function createApp() {
mode, mode,
intent, intent,
scope, scope,
...bootstrapMeta,
responseSummary: result.summary, responseSummary: result.summary,
retrievedItems: items retrievedItems: items
}); });
@ -225,6 +243,7 @@ export function createApp() {
: undefined; : undefined;
const model = req.body.model ? String(req.body.model) : undefined; const model = req.body.model ? String(req.body.model) : undefined;
const preloadedContext = req.body.preloadedContext ? String(req.body.preloadedContext) : undefined; const preloadedContext = req.body.preloadedContext ? String(req.body.preloadedContext) : undefined;
const bootstrapMeta = parseBootstrapMeta(req.body.bootstrapMeta);
const result = await answerService.answer(mode, intent, query, scope, model, preloadedContext); const result = await answerService.answer(mode, intent, query, scope, model, preloadedContext);
if (needsContextLog(result.summary, result.citations.length, result.answer)) { if (needsContextLog(result.summary, result.citations.length, result.answer)) {
@ -239,6 +258,7 @@ export function createApp() {
model: result.model, model: result.model,
note: preloadedContext ? "bootstrap_context_present" : undefined, note: preloadedContext ? "bootstrap_context_present" : undefined,
usedBootstrapContext: Boolean(preloadedContext), usedBootstrapContext: Boolean(preloadedContext),
...bootstrapMeta,
responseSummary: result.answer, responseSummary: result.answer,
retrievedItems: result.citations.map((citation) => ({ retrievedItems: result.citations.map((citation) => ({
chunkId: citation.chunkId, chunkId: citation.chunkId,
@ -278,6 +298,7 @@ export function createApp() {
const mode = (req.body.mode ?? "documental") as ChunkMode; const mode = (req.body.mode ?? "documental") as ChunkMode;
const model = req.body.model ? String(req.body.model) : undefined; const model = req.body.model ? String(req.body.model) : undefined;
const preloadedContext = req.body.preloadedContext ? String(req.body.preloadedContext) : undefined; const preloadedContext = req.body.preloadedContext ? String(req.body.preloadedContext) : undefined;
const bootstrapMeta = parseBootstrapMeta(req.body.bootstrapMeta);
const allowAdditionalRetrieve = Boolean(req.body.allowAdditionalRetrieve); const allowAdditionalRetrieve = Boolean(req.body.allowAdditionalRetrieve);
const historyEntries = Array.isArray(req.body.history) ? req.body.history as Array<{ role?: string; content?: unknown }> : []; const historyEntries = Array.isArray(req.body.history) ? req.body.history as Array<{ role?: string; content?: unknown }> : [];
const history: ChatMessage[] = historyEntries.length > 0 const history: ChatMessage[] = historyEntries.length > 0
@ -317,6 +338,7 @@ export function createApp() {
scope, scope,
model: result.model, model: result.model,
usedBootstrapContext: result.usedBootstrapContext, usedBootstrapContext: result.usedBootstrapContext,
...bootstrapMeta,
usedAdditionalRetrieve: result.usedAdditionalRetrieve, usedAdditionalRetrieve: result.usedAdditionalRetrieve,
responseSummary: result.answer, responseSummary: result.answer,
retrievedItems: result.retrieved?.items ?? [] retrievedItems: result.retrieved?.items ?? []
@ -343,6 +365,7 @@ export function createApp() {
model: req.body.model, model: req.body.model,
note: req.body.note ? `Log solicitado por el usuario. Nota: ${String(req.body.note)}` : "Log solicitado por el usuario.", note: req.body.note ? `Log solicitado por el usuario. Nota: ${String(req.body.note)}` : "Log solicitado por el usuario.",
usedBootstrapContext: Boolean(req.body.usedBootstrapContext), usedBootstrapContext: Boolean(req.body.usedBootstrapContext),
...parseBootstrapMeta(req.body.bootstrapMeta),
usedAdditionalRetrieve: Boolean(req.body.usedAdditionalRetrieve), usedAdditionalRetrieve: Boolean(req.body.usedAdditionalRetrieve),
responseSummary: req.body.responseSummary ? String(req.body.responseSummary) : undefined, responseSummary: req.body.responseSummary ? String(req.body.responseSummary) : undefined,
retrievedItems: Array.isArray(req.body.retrievedItems) ? req.body.retrievedItems : [] retrievedItems: Array.isArray(req.body.retrievedItems) ? req.body.retrievedItems : []

View file

@ -36,6 +36,11 @@ export class EvaluationLogService {
createdAt: new Date().toISOString(), createdAt: new Date().toISOString(),
scope: input.scope, scope: input.scope,
usedBootstrapContext: input.usedBootstrapContext, usedBootstrapContext: input.usedBootstrapContext,
bootstrapQuery: input.bootstrapQuery,
bootstrapMode: input.bootstrapMode,
bootstrapScope: input.bootstrapScope,
bootstrapModel: input.bootstrapModel,
bootstrapUsedModelSummary: input.bootstrapUsedModelSummary,
usedAdditionalRetrieve: input.usedAdditionalRetrieve, usedAdditionalRetrieve: input.usedAdditionalRetrieve,
responseSummary: input.responseSummary, responseSummary: input.responseSummary,
retrievedItemsCount: input.retrievedItems?.length ?? 0, retrievedItemsCount: input.retrievedItems?.length ?? 0,

View file

@ -117,6 +117,11 @@ export interface EvaluationLogInput {
model?: string; model?: string;
note?: string; note?: string;
usedBootstrapContext?: boolean; usedBootstrapContext?: boolean;
bootstrapQuery?: string;
bootstrapMode?: ChunkMode;
bootstrapScope?: RetrieveScope;
bootstrapModel?: string;
bootstrapUsedModelSummary?: boolean;
usedAdditionalRetrieve?: boolean; usedAdditionalRetrieve?: boolean;
responseSummary?: string; responseSummary?: string;
retrievedItems?: RetrievedItem[]; retrievedItems?: RetrievedItem[];
@ -135,6 +140,11 @@ export interface EvaluationLogEntry {
createdAt: string; createdAt: string;
scope?: RetrieveScope; scope?: RetrieveScope;
usedBootstrapContext?: boolean; usedBootstrapContext?: boolean;
bootstrapQuery?: string;
bootstrapMode?: ChunkMode;
bootstrapScope?: RetrieveScope;
bootstrapModel?: string;
bootstrapUsedModelSummary?: boolean;
usedAdditionalRetrieve?: boolean; usedAdditionalRetrieve?: boolean;
responseSummary?: string; responseSummary?: string;
retrievedItemsCount: number; retrievedItemsCount: number;