Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

tramites-rag

tests python licencia

Asistente que responde preguntas sobre trámites del Estado peruano citando la ficha oficial exacta. Corpus real de 116 trámites de gob.pe.

Lo que casi ningún RAG de portafolio trae: una evaluación que mide si el sistema realmente encuentra la respuesta, en vez de una demo que responde bonito.

tramites-rag preguntar "me robaron el brevete como obtengo otro"

La evaluación

50 preguntas escritas en el lenguaje que usaría un ciudadano, cada una con la ficha que debería responderla. Las preguntas no repiten el título de la ficha — hay un test que lo verifica — porque si lo repitieran, recuperar sería trivial y la métrica no mediría nada.

Recuperador recall@1 recall@3 recall@5 MRR
BM25 0,340 0,540 0,620 0,449
TF-IDF 0,320 0,520 0,580 0,427
híbrido (BM25 + TF-IDF) 0,360 0,500 0,600 0,449
expandido con sinónimos 0,260 0,520 0,680 0,408

recall@5 es la métrica que manda: si la ficha correcta no está entre las 5 recuperadas, el generador no tiene con qué responder y va a inventar.

Cómo se llegó a la expansión de sinónimos

BM25 arrancó en 0,620. Al mirar las preguntas que fallaban — que el proyecto publica, no esconde — el patrón era claro: el ciudadano escribe "me robaron el brevete" y la ficha dice "licencia de conducir"; escribe "mi documento" y la ficha dice "DNI". Desajuste de vocabulario, no falla del algoritmo.

La expansión con un diccionario de sinónimos del dominio sube recall@5 a 0,680. Pero hay un costo honesto: recall@1 baja de 0,340 a 0,260. Traer más candidatos correctos al top 5 también ensucia el primer puesto. Si el sistema mostrara una sola respuesta convendría BM25; como muestra cinco fragmentos al generador, conviene la expansión.

Esa es toda la idea del proyecto: medir, diagnosticar con los fallos, corregir, volver a medir — y reportar también lo que empeoró.

Un límite de la métrica

Varios "fallos" son aciertos disfrazados. A "quiero poner un negocio por dónde empiezo" el sistema responde con la ficha "Abrir o hacer negocio" cuando el ground truth dice "Abrir un negocio en Perú". Son fichas hermanas casi idénticas del propio gob.pe. El recall real es mejor que el reportado, y aun así la cifra se publica sin ajustar: inflar una métrica corrigiendo a mano los casos que no gustan es la forma más rápida de que deje de significar algo.


Cómo está construido

gob.pe ──barrido de ids──▶ corpus.json (116 fichas, versionado)
                                │
                            troceado (700 chars, 150 de solapamiento)
                                │
                           720 fragmentos
                                │
              ┌─────────────────┼─────────────────┐
            BM25             TF-IDF          expansión
              └─────────────────┼─────────────────┘
                          evaluación (50 preguntas)
                                │
                    respuesta con cita de la fuente

Sin embeddings neuronales, a propósito. sentence-transformers arrastra torch (más de 500 MB): volvería el CI lento y el repositorio imposible de correr en una máquina modesta. BM25 bien implementado sobre español, con tokenización que quita tildes y palabras vacías, es un punto de partida fuerte y —lo que importa aquí— completamente auditable: la fórmula está a la vista en indice.py, en treinta líneas.

La respuesta no puede alucinar por defecto. Sin GROQ_API_KEY el modo es extractivo: devuelve las oraciones del corpus tal cual, y un test verifica que cada oración devuelta exista textualmente en las fichas. Con la clave, redacta con Groq bajo la instrucción explícita de usar solo los fragmentos y de admitir cuando no sabe. El modo sin clave hace que el repositorio funcione para cualquiera y que el CI no necesite secretos.


Conseguir el corpus fue parte del problema

gob.pe no publica sitemap y su buscador se arma por JavaScript, así que no hay una lista de fichas para pedir. Lo que sí funciona: cada ficha vive en gob.pe/<id> y responde 200 solo si existe. El corpus se construye barriendo un rango de ids y quedándose con lo que responde.

Dos detalles que costaron encontrar:

  • gob.pe sirve UTF-8 pero el autodetector de requests se equivoca y deja todo el texto con mojibake (Dónde en vez de Dónde). Hay que forzar el encoding. Un test verifica que el corpus publicado esté limpio.
  • Varios ids distintos llevan al mismo trámite — "obtener licencia de conducir" aparecía seis veces. Dejarlos rompe la evaluación: si el mismo contenido está en seis documentos, no existe una respuesta correcta única contra la cual medir. Se deduplica por título conservando la versión más completa.

Cómo correrlo

pip install -e ".[dev]"

El corpus va versionado, así que se puede preguntar de inmediato:

tramites-rag preguntar "acabo de tener un bebe donde lo inscribo"
tramites-rag evaluar --fallos

Para redactar con IA en vez de extraer (opcional):

export GROQ_API_KEY=tu_clave

Para reconstruir el corpus desde cero:

tramites-rag corpus

Límites

  • 116 trámites, no todo gob.pe. El barrido cubrió un rango de ids acotado.
  • El corpus es una foto: si gob.pe actualiza requisitos o costos, hay que volver a correr tramites-rag corpus.
  • No sustituye a la fuente oficial. El asistente orienta y cita el enlace para que la persona verifique en gob.pe.

Stack

Python 3.11+ · scikit-learn (TF-IDF) · BM25 propio · Groq (opcional) · pytest (23 tests) · ruff · GitHub Actions

Licencia

MIT — ver LICENSE.

About

Asistente de tramites del Estado peruano con recuperacion evaluada: BM25, TF-IDF y expansion de sinonimos medidos contra 50 preguntas reales

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages