Endpoint POST /api/oraculo/ask
Endpoint POST /api/oraculo/ask
Módulo: Oráculo de EL · Archivo:
functions/api/oraculo/ask.ts· Añadido en: s72 (2026-05-19)
Endpoint CF Pages Functions que expone el asistente conversacional Oráculo de EL para el Workspace. Realiza retrieval híbrido (significado por Vectorize ∪ término exacto por FTS5, fundidos por RRF — functions/_lib/retrieval-hybrid.ts, entrega 2 del 11-09-2026) sobre todo el grafo de la Biblioteca y sintetiza con modo oracle.
Request
POST /api/oraculo/ask
Content-Type: application/json
{
"question": "¿Cómo funciona el Auto-Plan en CreaRack Pro?"
}
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
question | string | ✅ | Pregunta en lenguaje natural. Máx 500 chars almacenados en telemetría. |
Response (200 OK)
{
"answer": "<markdown>",
"sources": [
{
"title": "...",
"sourcePath": "...",
"score": 0.87
}
],
"model": "gemini-...",
"chunks_used": 8,
"duration_ms": 1240
}
Respuesta sin matches (200 con chunks_used: 0)
Cuando searchChunks devuelve 0 resultados, el endpoint retorna inmediatamente (sin llamar a Gemma) con mensaje predefinido en español y sources: [].
Errores
| Status | Condición |
|---|---|
| 400 | JSON inválido o question ausente/vacía |
| 503 | Binding AI o GOOGLE_AI_API_KEY no configurados |
| 500 | Error no controlado en retrieval o síntesis |
Flujo interno
1. Parse JSON → validar question
2. embedTexts(env.AI, [question]) ← Workers AI · BGE-M3
3. searchHybrid(env, {question, queryVec, TOP_K=5}) ← entrega 2 (11-09-2026)
├── searchChunks: Vectorize primario / D1 fallback (significado), SIN filtros app/source_type
├── searchFts(order 'relevance'): bib_search_fts (FTS5), OR entre términos, solo activas
├── ftsHitsToChunks: cada página encontrada → su trozo de bib_chunks con el término
│ (o un fragmento fabricado si es diario/briefing/página fija)
└── rrfFuse: fusión por posición (k=60); metadata.retrieval = semantic | fts | both
RETRIEVAL_HYBRID="0" en wrangler.toml → vuelve a searchChunks a secas
4. synthesizeAnswer(apiKey, question, matches, 'oracle')
└── buildOraclePrompts() → system+user prompts scope amplio
└── Google AI Studio REST (fetch directo — SDK incompatible con Workerd)
5. logQuery() best-effort → oraculo_queries D1
6. Return JSON
Bindings requeridos (Cloudflare)
| Binding | Tipo | Uso |
|---|---|---|
env.AI | Workers AI | Embeddings BGE-M3 |
env.GOOGLE_AI_API_KEY | Secret | Síntesis Gemma 4 vía AI Studio |
env.VECTORIZE | Vectorize index | Búsqueda semántica primaria |
env.DB | D1 database | Fallback + telemetría oraculo_queries |
Diferencias vs /api/biblioteca/ask
| Aspecto | /api/biblioteca/ask | /api/oraculo/ask |
|---|---|---|
| Filtros retrieval | Por app/source_type | Ninguno — todo el grafo |
| Modo síntesis | help | oracle |
| Scope del sistema prompt | CreaRack Pro in-app | Universo EsfericLabs completo |
| Audiencia | Usuarios finales | Equipo interno (Edu/Dani/Txell) |
| Telemetría | biblioteca_queries | oraculo_queries |
Telemetría
Cada llamada registra en oraculo_queries:
question(truncado a 500 chars)sources_count— número de chunks usadostop_relevance— score del mejor chunk (0..1) o NULL si 0 matchesduration_ms— latencia total del handlermode— siempre'oracle'en esta versión
El INSERT es best-effort: si falla (D1 no disponible, constraint, etc.) la respuesta al cliente no se ve afectada.
Véase también
- [[feature—oraculo—backend-fase-1]]
- [[entity—oraculo—model—oraculo-queries]]
- [[feature—biblioteca—ask-endpoint]]
- [[concept—workspace—oraculo-el]]