Pipeline RAG
Por cada turno del paciente, Aura recupera contexto de dos bases vectoriales en
paralelo y lo inyecta en el prompt del LLM. El orquestador es
ProductionService.getRagContext() (src/memory/production/).
Los dos stores
| Store | Contenido | Se carga | Threshold (default) |
|---|---|---|---|
memory_embeddings | Correcciones y respuestas validadas por supervisores | Online, al dar feedback | SIMILARITY_THRESHOLD 0.78 / APPROVED_THRESHOLD 0.85 |
knowledge_base | Manuales técnicos de equipos | Offline, pnpm ingest:manuals | KNOWLEDGE_THRESHOLD 0.60 |
- El umbral de manuales es más bajo a propósito: el speech-to-text distorsiona nombres de equipos, pero los síntomas embeddean parecido.
- El de correcciones es más alto: un falso positivo haría repetir un patrón equivocado de un caso no relacionado.
Flujo por turno
El contexto se inyecta en el último mensaje del usuario, no en el system message.
Optimizaciones
- Normalización de STT:
equipment-normalizer.tsconvierte variantes fonéticas al nombre técnico antes de embeddear. - Context locking (canal Retell): al primer HIT de manual, el contexto se fija para toda la llamada; los turnos siguientes no re-embeddean ni re-buscan.
- Prompt caching: el system message es fijo por llamada (identidad + datos del paciente). Al mantener estable el prefijo, OpenAI cachea automáticamente los tokens repetidos entre turnos. Por eso el contexto RAG (dinámico) va en el último mensaje.
Recuperación de knowledge_base
knowledge.service.findRelevant():
- Query top-1 por coseno (
1 - (embedding <=> vector)),ORDER BY ... LIMIT 1. - Trae siempre el mejor match sin filtrar por threshold (para loguear el score real
incluso en un miss) y recién después descarta si
score < KNOWLEDGE_THRESHOLD. - No filtra por
category. La categoría es solo metadata; la única forma de que algo no compita por el único chunk es no ingestarlo. Por eso conviene curar qué entra (ver Ingesta).
El flywheel (memory_embeddings)
El feedback del supervisor entrena a Aura:
El id es sha256(customerComplaint) → dar feedback sobre el mismo reclamo actualiza
la lección en vez de duplicarla.
Observabilidad del RAG
Cada recuperación emite un evento knowledge_queried con la query, hit, scores,
embedMs y queryMs. Eso alimenta las métricas de cobertura y latencia por capa
del panel de Operación (ver Observabilidad). Si
las FAQ no matchean consultas habladas, el primer sospechoso es KNOWLEDGE_THRESHOLD.