Adrián López Rendón · proyectos

Asistente RAG de Calidad del Aire

557 words 3 min read #LLM#RAG#FastAPI#Dagster

Un asistente de generación aumentada por recuperación (RAG) que permite hacer preguntas en lenguaje natural sobre la calidad del aire en ciudades mexicanas, construido como proyecto capstone del DataTalks LLM Zoomcamp 2026. Este repositorio es únicamente la capa de servicio RAG/LLM — lee tablas mart de BigQuery ya construidas por un pipeline separado, air-quality-dlt-dbt-dagster, y las convierte en una interfaz de chat consultable.

Arquitectura y Stack

  • Resumen → Un asset de Dagster (generate_summaries, con programación mensual) lee air_quality_marts.fct_city_daily_aqi y dim_stations de BigQuery y genera 6,596 fragmentos de texto en lenguaje natural — 6,097 resúmenes diarios (ciudad × parámetro × fecha) y 499 resúmenes mensuales (ciudad × parámetro × mes)
  • Embeddings → Un asset de Dagster (embed_chunks) genera embeddings de cada fragmento con text-embedding-3-small de OpenAI (1536 dimensiones) hacia pgvector en PostgreSQL
  • Recuperación → modos semántico (solo vectores) e híbrido (vectores + BM25 vía Reciprocal Rank Fusion), seleccionables por consulta
  • Generacióngpt-4o-mini de OpenAI, con detección del idioma de la consulta para que la respuesta llegue en el mismo idioma (inglés o español) que la pregunta
  • Servicio → backend en FastAPI (routers chat y feedback) detrás de una interfaz de chat en Next.js + Tailwind CSS
  • Monitoreo → los registros de consultas y retroalimentación se guardan en PostgreSQL, visualizados en un dashboard de Grafana con 10 paneles (incluyendo paneles de costo de LLM)
  • Infraestructura → Docker Compose (pgvector, Grafana, API)

Logros Técnicos Clave

Recuperación híbrida que supera notablemente a la búsqueda solo-semánticaretrieval_eval.py mide Hit@1/3/5 en 50% para recuperación solo-semántica frente a 75% para la híbrida (vectores + BM25 RRF), a costa de latencia adicional (565ms → 776ms en promedio).

Corrección de un bug de coincidencia de palabras clave que desbloqueó la búsqueda híbridaextract_keywords() dejaba puntuación pegada a los tokens (p. ej. “PM2.5” se quedaba como pm2.5), lo cual nunca coincidía con el pm25 sin punto almacenado en el contenido de los fragmentos, privando a BM25 de coincidencias reales y dejando que tokens casi universales como el año dominaran el ranking. Quitar la puntuación común en inglés/español (incluyendo ¿/¡) antes de comparar tokens llevó el Hit@1/3/5 híbrido de 50% a 75%.

Evaluación con LLM como juezllm_eval.py califica las respuestas generadas usando gpt-4o-mini como juez, con un promedio de 4.0/5 general, 4.0/5 en relevancia y 4.8/5 en precisión sobre el conjunto de evaluación.

Manejo bilingüe de consultas — las preguntas entrantes se detectan por idioma y el system prompt obliga al LLM a responder en el mismo idioma, de modo que las preguntas en inglés y en español reciben respuestas redactadas de forma nativa en lugar de una traducción desajustada.

Separación limpia entre upstream y downstream — este repositorio nunca ejecuta dlt ni dbt por su cuenta; únicamente lee los marts de BigQuery que el pipeline de ETL ya pobló, manteniendo la ingesta/transformación y el servicio RAG como sistemas desplegables de forma independiente que solo comparten un dataset de BigQuery como contrato.

Repositorio

github.com/sargent-mg/air-quality-rag