Tabla D1: oraculo_queries (telemetría Oráculo de EL)
Tabla D1: oraculo_queries
Migración:
0031_create_oraculo_queries.sql· Añadida en: s72 (2026-05-19)
Tabla de telemetría para el Oráculo de EL. Registra metadatos de cada llamada a POST /api/oraculo/ask para iterar el prompt, detectar gaps en el corpus y medir latencia. No almacena respuestas (privacidad + tamaño de BD).
Schema
CREATE TABLE IF NOT EXISTS oraculo_queries (
id INTEGER PRIMARY KEY AUTOINCREMENT,
question TEXT NOT NULL,
sources_count INTEGER NOT NULL DEFAULT 0, -- chunks usados (0 = sin matches)
top_relevance REAL, -- score mejor chunk (0..1) o NULL
duration_ms INTEGER NOT NULL DEFAULT 0,
mode TEXT NOT NULL DEFAULT 'oracle', -- por si se añaden variantes
created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE INDEX IF NOT EXISTS idx_oraculo_queries_created_at
ON oraculo_queries(created_at DESC);
Campos
| Campo | Tipo | Descripción |
|---|---|---|
id | INTEGER PK | Autoincremento |
question | TEXT | Pregunta del usuario (truncada a 500 chars en el handler) |
sources_count | INTEGER | Número de chunks usados en la respuesta. 0 = sin matches en Vectorize/D1 |
top_relevance | REAL | Score coseno del chunk más relevante (rango 0..1). NULL si sources_count=0 |
duration_ms | INTEGER | Latencia total del handler desde recepción hasta respuesta |
mode | TEXT | Siempre 'oracle' en esta versión. Campo reservado para variantes futuras |
created_at | TEXT | ISO 8601 UTC. Índice DESC para consultas recientes primero |
Uso para análisis
-- Preguntas frecuentes (sin matches → gap en corpus)
SELECT question, COUNT(*) as n
FROM oraculo_queries
WHERE sources_count = 0
GROUP BY question
ORDER BY n DESC
LIMIT 20;
-- Latencia promedio por día
SELECT DATE(created_at) as dia, AVG(duration_ms) as avg_ms, COUNT(*) as calls
FROM oraculo_queries
GROUP BY dia
ORDER BY dia DESC;
-- Calidad de retrieval (relevancia promedio)
SELECT DATE(created_at) as dia, AVG(top_relevance) as avg_rel
FROM oraculo_queries
WHERE top_relevance IS NOT NULL
GROUP BY dia;
Inserción best-effort
El handler logQuery() en functions/api/oraculo/ask.ts envuelve el INSERT en try/catch silencioso. Si D1 no está disponible o el INSERT falla por cualquier razón, la respuesta al cliente no se ve afectada. Este patrón está documentado explícitamente en el commit como “best-effort para no bloquear respuesta”.
Contexto de diseño
La decisión de no almacenar respuestas responde a:
- Tamaño: las respuestas pueden ser largas (hasta 350 palabras en markdown); acumularlas inflaría la BD D1 con bajo valor.
- Contenido sensible: las respuestas pueden incluir fragmentos de ADRs, decisiones de equipo, datos internos.
- Propósito de la telemetría: basta con saber qué se pregunta y cómo va el retrieval, no qué se responde.
Véase también
- [[entity—oraculo—endpoint—ask]]
- [[feature—oraculo—backend-fase-1]]
- [[feature—biblioteca—ask-endpoint]]
- [[concept—workspace—oraculo-el]]