proyecto_1_dentistas — scaffold y primera evidencia E1 (2026-09-26)

Contexto: estado persistido tras construir, verificar y commitear el scaffold de RAG para el arquetipo ficticio “Sonrisa: tu clínica”, Centro CDMX.

## Repo y commit
 
- Repo: `~/nef/Proyectos/proyecto_1_dentistas/`
- Commit inicial: `6993f87 Build dental clinic RAG benchmark scaffold`
- Follow-up: `ea88a39 Harden RAG injection and citation parsing`
- Estado Git después del commit: limpio. `artifacts/` está ignorado; índice,
  caché de embeddings y corridas no se versionan.
- 41 archivos versionados: corpus sintético, golden set, pipeline, evaluador,
  marketing borrador y `uv.lock`.
 
## Artefactos
 
- 15 documentos ficticios de la clínica, 77 chunks resultantes.
- Golden set v0: 20 preguntas, 4 fuera de alcance que deben escalar.
- Marketing: prompt de investigación, guion de demo, one-pager y página de servicio.
- Prompt reusable también guardado en:
  `~/nef/decisions/[CREDENCIAL].md`
- El buyer persona 38-55 años está marcado como hipótesis a validar, no como hecho.
- Plantillas de venta no presentan como disponibles WhatsApp, agenda, CRM,
  campañas ni reportes; tampoco prometen piloto gratis o porcentajes no verificados.
 
## Verificación técnica
 
- Python 3.12.13 instalado con uv; dependencias resueltas sin torch.
- `uv run python tests/test_smoke.py`: pasa (15 docs, 77 chunks, 20 preguntas).
- `uv run python -m compileall -q src tests`: pasa.
- `git diff --check`: pasa antes del commit.
- Índice construido con Qwen3-Embedding-4B vía HF Inference Providers:
  2,560 dimensiones, 77 vectores.
- Consulta real de limpieza: respuesta con citas, 4.4 s, $0.0005 de generación.
 
## Eval E1
 
Primera corrida (`20260926-195626`): el límite de 400 tokens dejó cinco respuestas
vacías por consumo de razonamiento de V4.1-Flash. Citation accuracy 0.688.
Se corrigió a 1,200 tokens con un reintento de 2,500 cuando la respuesta queda vacía.
 
Segunda corrida (`20260926-200440`), tras la corrección:
 
- 20/20 respuestas: citation accuracy 1.0, retrieval hit rate 1.0,
  escalado correcto 1.0.
- Coste de generación: $0.0094 USD (no incluye juez RAGAS).
- RAGAS quedó **parcial** porque HF devolvió HTTP 402 al agotarse los créditos
  mensuales incluidos durante la evaluación. Cobertura real por métrica:
  - faithfulness: 0.853, 9/20 válidas.
  - answer relevancy: 0.798, 9/20 válidas.
  - context precision: 0.636, 8/20 válidas.
  - context recall: 1.000, 8/20 válidas.
- No usar estos promedios parciales como claims comerciales. El juez RAGAS no
  está incluido en el contador de costos y su costo real quedó sin medir.
- `artifacts/runs/20260926-200440/resumen.md` identifica cobertura, estado parcial
  y separa coste de generación del coste del juez.
 
## Pruebas posteriores con Groq (sin llamar a HF)
 
- Se usó `openai/gpt-oss-20b`; `HF_TOKEN` se quitó del proceso para impedir llamadas
  accidentales a HF. Retrieval usó vectores ya cacheados o un retriever sintético.
- FAQ normal: devuelve $850 y la cita del documento.
- Fuera de alcance: dice que no tiene el dato y canaliza a WhatsApp.
- Inyección directa del usuario: no acepta el precio falso de $1 ni divulga datos.
- Inyección indirecta en pasaje sintético: ignora la orden maliciosa, conserva el
  precio $850 del texto factual y cita la fuente.
- Groq puede emitir citas `【1】`; el parser ahora normaliza `[1]`, `[n1]` y `【1】`.
- Son pruebas puntuales, no un benchmark de robustez. Coste Groq no medido.
- Tras el ajuste: smoke test, `compileall` y `git diff --check` pasan.
 
## Corrida 20 muestras con Groq (2026-09-26-212019)
 
- Generación 20/20 completa: citation accuracy 1.0, retrieval hit rate 1.0,
  escalate accuracy 1.0. Tokens de generación agregados al resumen.
- RAGAS quedó **parcial (11/20)**: Groq free tiene límite de **200k tokens/día por
  modelo** y se agotó durante el juez (153 llamadas, 938.8s antes del corte).
- Hallazgo clave: la evaluación completa de 20 muestras con RAGAS necesita ~1.2M
  tokens de juez → **no cabe en un día de Groq free** (≈6 días). El camino viable
  es el **Space ZeroGPU** (40 min/día PRO) para el juez, o varios días en Groq.
- El juez Groq funciona (cobertura completa en 3 muestras: 33 llamadas, 307s),
  pero el TPD lo hace inviable para la corrida completa diaria.
- Mejoras aplicadas: backoff exponencial para 429 en `providers.chat`, retries por
  defecto 5, agregación de tokens/segundos de generación al resumen, overrides por
  entorno en config.
 
## Siguiente paso
 
**Bloqueador:** el token HF `opencode` es de solo lectura → no puede crear/pushear el
Space. Se necesita un token con permiso de escritura (o `hf auth login`).
 
Con el Space ZeroGPU activo:
1. Correr el golden set completo 20/20 con juez en el Space (cobertura íntegra).
2. Probar `rerank off` vs `rerank on` (Qwen3-Reranker en el Space) para atacar
   context precision (0.636 parcial era el cuello).
3. Registrar minutos de cuota GPU usados por corrida.
4. No publicar métricas hasta tener una corrida íntegra y reproducible.