Prompt — Fusión RAG multi-tenant para PyMEs (proyecto_1_dentistas + pyme-rag)
Fecha: 2026-09-27 Uso: este prompt se paga como primer mensaje de un agente de código (opencode / Claude Code) para implementar la fusión. Es autocontenido: no requiere leer la conversación original.
ENCARGO: Servicio RAG multi-tenant para PyMEs (fusión de dos repos)
0. Rol y modo de trabajo
Eres arquitecto e implementador. Fusiona dos proyectos existentes en un solo servicio RAG multi-tenant para PyMEs. Ejecuta por milestones, verificando cada uno antes de pasar al siguiente. Entrega evidencia (archivos creados, comandos ejecutados, tests). Prohibido afirmar éxito sin evidencia ejecutada. Si algo es ambiguo, elige la opción más pequeña que cumpla el DoD y documéntala. Responde en español; código y nombres de archivo en inglés.
1. Objetivo
Servicio RAG multi-tenant para PyMEs (clínicas dentales, despachos, tiendas) sobre OCI Always Free (Ampere A1, 2 OCPU / 12 GB RAM, $0/mes), con modelos open-weights y evaluación verificable para vender con números.
Cada cliente aporta sus documentos → se construye su índice → el asistente responde con citas → se mide y se reporta.
2. Los repos a fusionar
A. ~/nef/Proyectos/proyecto_1_dentistas/ — retrieval y evaluación (verificados 20/20).
Reutilizar de aquí:
src/dentistas/retrieve.py— FAISS + BM25 + RRF + reranker (Qwen3-Reranker-0.6B).src/dentistas/embeddings.py— Qwen3-Embedding-4B (2560d), con caché sqlite.src/dentistas/answer.py— prompt con citas [n], “no lo sé → canalizo”.src/dentistas/eval_runner.py+rg_eval.py— citation accuracy, escalate accuracy, RAGAS, coste por interacción.shared/corpus/(15 docs sintéticos) +shared/golden_set/v0.jsonl(20 preguntas).src/dentistas/config.py— abstracción de providers (hf/groq/space/ollama).
B. ~/nef/Proyectos/proyecto_1_dentistas/demo/pyme-rag/ — infra y multi-tenant.
Reutilizar de aquí:
infra/main.tf— VCN, security list, cloud-init (fix iptables Ubuntu), budget alert $0.01.infra/retry-capacity.sh— reintento por capacidad.infra/terraform.tfvars.example— tenancy_ocid, region, admin_cidr.app/store.py— SQLite por tenant (sqlite-vec + FTS5 + RRF), aislamiento real.app/config.py— variables de entorno.Caddyfile— TLS automático.docker-compose.yml— api + caddy, mem_limit 4g, restart unless-stopped.eval/harness.py— hit@k y MRR del retriever (sin llamadas al LLM).
3. Arquitectura objetivo
Caddy (TLS) → FastAPI (2 workers)
├─ embed → fastembed MiniLM (ONNX, CPU, 384d) [antes ZeroGPU]
├─ retrieve → FAISS + BM25 + RRF + reranker (CPU) [de proyecto_1]
├─ LLM → cadena: ZeroGPU Space → Groq → local pequeño
└─ store → SQLite por tenant (sqlite-vec + FTS5)
Cambio clave vs lo que había: embed y rerank pasan a CPU (fastembed) para que HF ZeroGPU quede solo para el chat, con cadena de respaldo. Esto reduce la dependencia de la cuota compartida de ZeroGPU (40 min/día PRO).
4. Decisiones
- Embed/rerank en CPU con
fastembed(ONNX, ~220 MB, multilingüe). El corpus de un cliente PyME es pequeño (decenas–centenas de documentos); CPU sobra. - Retrieval híbrido de proyecto_1 (FAISS + BM25 + RRF + reranker). Es superior al de pyme-rag (que no tiene reranker). Verificado 20/20.
- Multi-tenant de pyme-rag: un SQLite por cliente, aislamiento real, backup = 1 archivo.
- LLM con cadena de respaldo: ZeroGPU Space → Groq (gpt-oss-20b,
reasoning_effort: low) → modelo local pequeño (Qwen3-1.7B) si ambos fallan. La abstracción de providers de proyecto_1 ya permite esto. - Evaluación combinada: citation accuracy + escalate accuracy (de proyecto_1) + hit@k/MRR del retriever (de pyme-rag) + RAGAS + coste por interacción.
- Datos de salud (LFPDPPP): el texto recuperado viaja al LLM (ZeroGPU/Groq, US). Requisitos antes del piloto: aviso de privacidad que mencione la transferencia, logs sin texto de conversaciones (o anonimizados), corpus solo operativo (nunca expedientes).
5. Milestones
- M1 — Esqueleto fusionado: estructura de dirs, docker-compose (api + caddy),
FastAPI con rutas /health, /ingest, /ask, /documents, /delete. Auth por API key → tenant.
Verificación:
docker compose uplocal + curl /health. - M2 — Retrieval + embed CPU: portar retrieve.py (FAISS+BM25+RRF+reranker) y embeddings (fastembed). Índice por tenant. Verificación: smoke test de retrieval (SKUs, cifras, nombres) + hit@k ≥ 85%.
- M3 — LLM con cadena de respaldo: ZeroGPU → Groq → local. Verificación: ask responde con citas; forzar fallo de ZeroGPU y que Groq tome el relevo.
- M4 — Evaluación combinada: citation accuracy + escalate accuracy + RAGAS + coste. Verificación: golden set 20/20 con métricas completas.
- M5 — Infra OCI: Terraform (VCN, security list, cloud-init iptables fix, budget alert), desplegar en Ampere A1, rsync, compose up. Verificación: curl público con TLS.
6. Definition of Done
Un solo comando (docker compose up) levanta el servicio; /health responde;
/ask responde con citas; /ingest indexa un PDF; el harness reporta hit@k y citation
accuracy; todo en OCI Always Free ($0/mes) + HF ZeroGPU (solo chat).
7. Prohibido
- No subir a OCI/DO/GCP sin verificación previa de cada milestone.
- No dejar el LLM hardcodeado a un solo proveedor (siempre la cadena de respaldo).
- No logs con texto de conversaciones de pacientes.
- No sobre-ingeniar: lo que no esté en el DoD, no se construye.