Saltar al contenido
Ricardo RetamalSoftware y cosas que vale la pena construir
/
Conversemos
← Ver todos los escritos
AI14 min read

Lo que aprendí construyendo aplicaciones RAG en producción

Mi background es de desarrollador FullStack, más que todo orientado a hacer aplicaciones móviles con sus backends en .Net o python…

Publicado originalmente en Medium ↗

Lo que 2 años construyendo RAG empresariales me enseñaron que ningún tutorial te dirá jamás
Lo que 2 años construyendo RAG empresariales me enseñaron que ningún tutorial te dirá jamás

Mi background es de desarrollador FullStack, más que todo orientado a hacer aplicaciones móviles con sus backends en .Net o python, frontends con Vue, etc. Había hecho una especialización en Machine Learning y en un punto se abrió una oportunidad para hacer aplicaciones con IA.

Pasamos desde las pruebas de concepto, con el típico RAG en LangChain con un naive ingestion y su retrieval a ir apretando cada vez más e ir creciendo en requerimientos de los usuarios.

A lo largo de 2 años el crecimiento y aprendizaje han sido bastante. Cuando alguien inicia con IA y no estoy hablando de hacer vibe coding, ejecutar prompts con ChatGPT sino de realmente hacer knowledge augmentation de un modelo, te das cuenta de que internet está llena de tutoriales que se enfocan en el nivel inicial y que cuando vas a desarrollar plataformas a nivel empresarial, lo que te encuentras es totalmente distinto.

Pasamos de hacer RAG estándar donde con algunas consultas obteníamos datos de los documentos guardados en Sharepoint, a armar sistemas completos para recursos humanos, el área de la salud, armado de propuestas automáticas, scraping de información por internet, etc.

Mi aprendizaje mayor fue, las IA apps evolucionan constantemente, estamos acostumbrados en software development a las aplicaciones monolíticas que se desarrollan y no se tocan por años. Aquí los modelos cambian mes a mes, lo que antes te funcionaba ya no, las apps deben adaptarse todo el tiempo y sí, te comparan siempre con ChatGPT y Claude, por los que tus features se quedan atrás muy rápido y mantener un roadmap se hace crítico.

Eso me ha ido permitiendo armar mi propio checklist, mi lista de aprendizajes para que cada nuevo proyecto se beneficie de los anteriores.

Creo que un proyecto RAG debe pasar por las siguientes etapas:

1. Descubrimiento

Suena obvio pero no es tan obvio a veces. En esta etapa se deben revisar bien los requerimientos del cliente, se debe tener una exposición temprana a los datos para que puedas definir estrategias para su tratamiento, seguridad y obtención. Es súper importante aquí capturar las expectativas del cliente, que espera ver cuando se le entregue la plataforma. Aquí siempre dicen esperamos trabajar con archivos PDF o Word, pista, prepárate siempre para todo, word, pdf, xlsx, pptx, la realidad es que las empresas tienen de todo y no siempre tendrás texto plano como ves en los tutoriales.

Algo que también es crítico desde el inicio: seguridad y control de acceso. En entornos enterprise te vas a encontrar que no todos los usuarios deben ver todos los documentos. ¿Qué pasa si un usuario pregunta algo y el retrieval trae un documento al que no debería tener acceso? Nosotros lo manejábamos con una combinación según el proyecto: a veces metadata filtering en query time sobre el mismo índice (filtrando por permisos del usuario antes del similarity search), a veces índices completamente separados por rol o departamento cuando la separación era más estricta. Lo importante es pensarlo desde la fase de descubrimiento, no después.

Como comentario aquí, no siempre recibirás los datos a tiempo, cuando los vas recibiendo a lo largo del proyecto procura dejar espacio para afinar detalles como el chunking, documentos que no tenías considerados. Es invaluable tener test prompts con respuestas esperadas desde el inicio, ese es tu golden set (pista, muchas veces tampoco lo entregan).

Y hablando de los golden set, no basta con tener preguntas y respuestas esperadas. Necesitas definir desde aquí qué métricas vas a medir: faithfulness, answer relevancy, context precision, context recall. Nosotros usábamos RAGAS para esto, pero hay otras opciones como DeepEval o custom evals propias. Lo importante es que desde el inicio tengas algo medible, porque si no, “mejorar” se convierte en puro feeling.

Un disclaimer importante sobre RAGAS: las métricas automatizadas no son verdad absoluta. Nos pasó que RAGAS daba scores buenos, pero el usuario no estaba contento. Sobre todo en apps médicas, donde la semántica entre documentos era muy parecida y el contexto recuperado era técnicamente “relevante”, pero no era lo que el usuario necesitaba. Las métricas automatizadas usan un LLM como juez, lo que introduce su propio sesgo. Complementa siempre con feedback real de usuarios, eso te da la perspectiva que ningún eval sintético puede darte.

2. Arquitectura

Ya con las expectativas definidas y alineadas, con los datos en mano, puedes definir no solo la arquitectura del sistema (web, backend, si usarás LangChain, LangGraph) sino las estrategias que usarás para tratar cada formato de documento.

Document Processing Pipeline

Aquí me detengo porque esto es un tema que merece atención. En los tutoriales te muestran un PDF limpio con texto plano y parece trivial. En la realidad te encuentras con PDFs escaneados que necesitan OCR, tablas que se destrozan al extraerlas, layouts multi-columna, headers y footers que contaminan el texto, Excel con celdas mergeadas, PowerPoints donde la información está en imágenes.

Nosotros pasamos por varias herramientas antes de encontrar algo que funcionara consistentemente: PyMuPDF, pdfplumber, Unstructured, cada una con sus limitaciones dependiendo del formato. Docling fue lo que mejor nos funcionó para la variedad de documentos que encuentras en empresas. Siendo honestos, Azure Document Intelligence se veía superior en calidad de extracción, pero tiene su costo asociado. En proyectos donde el presupuesto lo permitía, lo usábamos. En otros, Docling cumplía y mantenía los costos bajos. No es que haya una herramienta perfecta, es encontrar el balance entre calidad de extracción y costo según el proyecto. La calidad de tu parsing define el techo de calidad de tu RAG, así que invierte tiempo aquí.

Chunking

El chunking no es universal y la estrategia se debe adaptar al tipo de documento con el que estás tratando. Documentos legales funcionan mejor por sección, un manual técnico podría funcionar mejor por semántica. Algo que casi siempre aplicábamos era overlap entre chunks, porque da continuidad y evita que pierdas contexto en los bordes.

Pero además de eso. ¿Qué pasa cuando un chunk corta una tabla por la mitad? ¿Cómo manejas headers que dan contexto a párrafos posteriores? Para estos casos usábamos parent-child chunking: cada chunk hijo tenía una referencia a su chunk padre, entonces cuando el retrieval traía un hijo podíamos ir al padre para obtener mayor contexto y evitar cortes. Así lográbamos precisión en el retrieval (buscando en chunks pequeños) sin perder el contexto amplio que el modelo necesitaba para dar buenas respuestas.

Embedding Models

Algo que no puedes ignorar: la selección del modelo de embeddings es una decisión de arquitectura, no un detalle. Nosotros comenzamos con Ada-002 de OpenAI y después migramos a text-embedding-3-small. Probamos también text-embedding-3-large y en nuestros casos de uso small ganó en el balance costo-latencia-calidad, la diferencia de calidad no justificaba el costo adicional para los tipos de documentos con los que trabajábamos. Pero eso es nuestro caso, evalúa con tus datos. Lo que sí es universal: cambiar modelo de embeddings implica reindexar todo, así que piénsalo bien desde el inicio. Si trabajas con documentos en español (o cualquier idioma que no sea inglés), asegúrate de que tu modelo de embeddings tenga buen soporte multilingüe.

Hybrid Search

Esto merece su propia mención. Keyword search (BM25) funciona mejor para códigos, nombres propios, IDs, términos técnicos específicos. Dense search (embeddings) funciona mejor para preguntas semánticas donde el usuario no usa las palabras exactas del documento. La combinación de ambos (hybrid search) te cubre escenarios que cualquiera de los dos solos no puede resolver.

Ejemplo real: en apps médicas nos pasó que la semántica era muy parecida entre documentos. Un documento sobre tratamiento de diabetes tipo 1 y otro sobre tipo 2 están semánticamente muy cerca, pero el usuario necesita uno específico. Ahí la búsqueda por términos exactos se hizo crítica. También necesitábamos distinguir entre tipos de documentos (guías clínicas vs protocolos vs formularios). Hybrid search fue lo que resolvió esos casos. Es una de las decisiones más impactantes que puedes tomar en tu pipeline.

Metadata Filtering

Pre-filtrar por metadata (fecha, departamento, tipo de documento, versión) antes de hacer similarity search es una de las optimizaciones más importantes en enterprise RAG. Si un usuario de recursos humanos pregunta algo, no necesitas buscar en los documentos de ingeniería. Esto reduce ruido, mejora precisión y baja costos.

Reranking

Después del retrieval inicial, un reranker puede reordenar los resultados por relevancia real. Nosotros empezamos con FlashRank que es ligero, rápido y corre local sin costo de API. Funcionaba bien para la mayoría de los casos. Pero cuando necesitábamos que fuera más sensible a términos específicos, especialmente en dominios como salud donde la terminología importa mucho, comenzamos a probar cross-encoders con Cohere. El salto en calidad se notó, pero también el costo y la latencia. El trade-off es real: FlashRank te da un 80% gratis y rápido, Cohere te da ese 20% extra pero pagas por ello. No siempre lo necesitas, evalúa si tu caso lo justifica.

¿RAG estándar, agentes o grafos?

Tendrás proyectos donde un RAG estándar es suficiente (muchas app de recursos humanos entran aquí, consultas sobre vacaciones, procedimientos, etc), tendrás otras donde quizás ya un agente comienza a tomar más sentido para responder las preguntas (tienes distintas fuentes, necesitas evaluar la respuesta, etc) o llega un punto donde además del agente quizás tenga sentido incluir grafos como con Neo4j donde el modelo pueda entender las relaciones (proyectos, CVs, clientes, procesos, etc).

En mi experiencia, el 80% de los casos enterprise se resuelven con buen metadata + hybrid search. Los knowledge graphs valen la pena cuando genuinamente tienes relaciones complejas entre entidades que no puedes capturar con metadata. No lo uses solo porque suena cool o avanzado.

Algo que me ayudó en su momento:

3. Ingestion

Crítico para una RAG app. Aquí pones en práctica tu arquitectura y comienzas de verdad a jugar con los datos. ¿Y te digo algo? Tu interfaz puede ser excelente, no tener bugs en la plataforma, pero si tu modelo no da buenas respuestas, el proyecto fracasa. En la fase anterior el cliente te mostró su Sharepoint, en la reunión todo lucía hermoso. Aquí te das cuenta de la verdad, documentos repetidos por doquier, formatos distintos por todos lados, algunos directorios te dan información, otros no, no hay nada normalizado, te dieron acceso a un data source que alimentaron por años y esperan que la IA o tú puedan sacar algo útil de ahí.

4. Desarrollo

En desarrollo es donde todo lo anterior se pone a prueba. Aquí descubres rápido si tu arquitectura realmente era buena o si solo se veía bien en diagramas.

Algo que aprendí es que una RAG app no es solo “hacer un chat”. Terminas construyendo: pipelines de ingestion, servicios de embeddings, orquestación de agentes, sistemas de evaluación, APIs de retrieval, caching de contexto, sistemas de feedback. Muchas veces terminas construyendo más infraestructura que features visibles.

Algo crítico aquí es separar responsabilidades: ingestion pipeline separado del runtime, indexación desacoplada del retrieval, agents desacoplados de tools, LLM provider abstraído. Porque los cambios vienen. Siempre. Hoy usas OpenAI, mañana Azure OpenAI, luego Claude, luego un modelo local. Si no abstraes eso, migrar duele.

No todo debe pasar por el LLM

Algo que también aparece rápido. Ejemplos reales: fechas van mejor con un parser determinístico, cálculos con código, queries estructuradas con un SQL agent o queries directas, metadata filtering con vector DB filters. Mientras más lógica saques del LLM, más estable se vuelve el sistema.

Los agentes no son magia

Muchas veces un buen pipeline RAG + reranking funciona mejor que un agente mal diseñado. Un agente empieza a tener sentido cuando hay múltiples fuentes, hay tools reales, hay decisiones que tomar, hay reasoning necesario. Si solo respondes preguntas sobre documentos, muchas veces un buen retrieval pipeline gana en simplicidad y costo.

Prompt Engineering para RAG

Algo que no se menciona suficiente: el prompt engineering para RAG es distinto al prompt engineering general. Necesitas instrucciones claras en tu system prompt sobre cómo usar el contexto recuperado, cuándo citar fuentes, cómo manejar el “no tengo información suficiente”, y cómo formatear las respuestas. Un buen prompt de RAG le dice al modelo explícitamente: responde solo basándote en el contexto proporcionado, si la información no está en el contexto dilo, cita el documento de donde sacaste la información.

El problema del “Lost in the Middle”

Cuando metes muchos chunks al contexto, los LLMs tienden a prestar más atención al inicio y al final, ignorando lo que está en el medio. Esto es especialmente relevante cuando subes el top_k. Si necesitas top_k=12 para que funcione, probablemente tu retrieval necesita mejorar. Más chunks no siempre es mejor: más tokens, más costo, más posibilidad de que el modelo se distraiga con información irrelevante.

Latencia acumulada

También aquí aparece un problema real. Ejemplo típico: user question → agent decide tool → retrieval → reranker → LLM answer. Y de repente tienes 8–15 segundos.

Ejemplo real nuestro: teníamos un proyecto donde las respuestas tomaban alrededor de 10 segundos. Después de optimizar logramos bajarlas a ~3 segundos. Lo que hicimos fue una combinación: reducir el top_k ayudó, cambiar a un modelo más rápido para el routing mejoró bastante, eliminamos pasos redundantes en el reranking, y dejamos de preguntar tanto al LLM para preclasificar intención (eso lo puedes hacer con lógica determinística en muchos casos). El streaming ayuda con la percepción del usuario, no con la latencia real, pero la percepción importa. Porque nadie espera 15 segundos feliz, ni siquiera 10.

Cost control

En producción empiezas a ver prompts gigantes, contextos mal optimizados, tokens innecesarios, agentes llamando modelos múltiples veces. Y eso escala rápido en costo. Algunas prácticas que ayudan: truncar contexto inteligentemente, usar summaries intermedios, modelos pequeños para clasificación, modelos grandes solo para respuesta final, limitar recursion depth en agentes. Porque sí, puedes tener una RAG técnicamente brillante… pero financieramente inviable.

5. Deployment

El deployment fue un paso súper curioso. Dado que las plataformas se deployaban en la infraestructura de los clientes, era importante hacerles llegar la versión inicial y luego pensar en las actualizaciones. Nosotros hacíamos deployments con Docker, dependiendo del cliente teníamos bicep templates para Azure o con Terraform, quizás no lo más fancy, pero funcionaba y nos permitía hacer despliegues con el menor dolor posible.

En la realidad, pasa que se define una arquitectura con un stack, usas modelos OpenAI, con una BD vectorial (p. ej.: Qdrant) y recién en esta etapa se involucra al equipo de TI del cliente y te dicen, no trabajamos con ese modelo, necesitamos todo en Azure/AWS, necesitamos que nos aprueben el costo, no permitimos acceso público (así que ellos son tus manos) y no puedes hacer ni mirar nada. Así que mi recomendación: súbelos desde el inicio, evita retrabajos y retrasos en el deployment.

6. Observabilidad

Necesitas poder ver las preguntas que hacen los usuarios, necesitas poder ver si un cambio afecta la calidad de las respuestas, necesitas poder monitorear el rendimiento del modelo. Cuando ya el agente tardó más de 10 segundos dando una respuesta y el usuario se pregunta si algo está mal.

Aquí es importante distinguir entre evaluación offline y online. Offline es tu golden set corriendo en batch, midiendo métricas como faithfulness y context recall con RAGAS o DeepEval. Online es lo que pasa en producción en tiempo real: latency, token usage, failures, y el feedback real del usuario.

Los sistemas de thumbs aquí te dan el feedback real del usuario, qué preguntó, qué se contestó, qué esperaba él. Puedes darlo como feedback al modelo y tú ir afinando también basado en eso. El logging no lo olvides, deberías poder ver qué documentos se obtuvieron y la lógica del agente.

Versionado de índices

Algo que aprendí con dolor: cuando reingestas o cambias estrategia de chunking, necesitas poder hacer rollback si la calidad baja. Versiona tus índices, no solo tus datos. Tener la capacidad de volver a un estado anterior te salva cuando un cambio que “debería mejorar” termina empeorando las respuestas.

7. Iterar, iterar, iterar

Si algo define las AI apps es que nunca están terminadas. Un RAG no se entrega y listo. Tu trabajo ahora es: mejorar retrieval, mejorar chunking, mejorar prompts, mejorar ranking, mejorar tools, mejorar contexto. Y muchas veces mejoras pequeñas cambian todo.

Ejemplo real: cambiar chunk size 800 → 400 puede mejorar precisión. Agregar hybrid search puede resolver queries que antes fallaban. Ajustar el overlap puede dar mejor continuidad. Pero ojo, cada cambio debería validarse contra tu golden dataset. No optimices a ciegas.

Otra realidad: los usuarios siempre encontrarán casos edge. Siempre. Van a preguntar cosas ambiguas, cosas incompletas, cosas que no están, cosas mal escritas, cosas fuera del dominio, a veces ni un prompt arman, solo colocan el término que quieren.

Y tu sistema debe fallar bien. Porque otra lección importante: una buena respuesta incorrecta es peor que decir que no sabes. Por eso los guardrails importan tanto como el retrieval.

Review periódico de preguntas reales

Nada reemplaza ver qué preguntan, qué falla, qué no encuentran, qué esperan. Porque muchas veces optimizamos para benchmarks y no para usuarios. Aquí te puede ayudar mucho el feedback: thumbs up/down, expected answer fields, user comments. Eso vale más que cualquier eval sintético. Porque ahí ves lo que el usuario realmente quería y entiendes el uso que le estan dando al sistema.

No todo se arregla con mejor prompting

A veces el problema es datos malos, chunking malo, metadata inexistente, duplicados, documentos obsoletos. Y ningún prompt arregla datos malos. Garbage in → garbage out sigue siendo verdad.

Mis reglas

De todo lo anterior tengo los siguientes “stakes/rules” que siempre tengo en mente:

Diseño

  • Usa el framework que mejor se adapte al problema (LangChain, LangGraph, LlamaIndex). El framework rara vez es el bottleneck real.
  • Diseña los tools de los agentes con intención. Un buen agent design impacta más que seguir iterando prompts.
  • Elige el modelo según estabilidad, costo y performance, no solo porque sea el más nuevo.
  • Prepárate para trabajar con cualquier formato empresarial real: PDFs, Excel, Word, PowerPoint, imágenes, tablas mal estructuradas. Invierte en tu document processing pipeline.
  • Selecciona tu modelo de embeddings pensando a largo plazo. Cambiar después implica reindexar todo.
  • Piensa en seguridad y control de acceso desde el día uno, no como un afterthought.

UX

  • Siempre que sea posible, implementa streaming de respuestas. La percepción de velocidad importa tanto como la velocidad real.
  • Incluye citas (sources). Los usuarios confían más cuando pueden ver de dónde viene la respuesta.
  • Permite follow-up questions y optimiza el contexto con resúmenes de conversación.
  • Mantén una UI clara y rápida. Una buena experiencia puede compensar pequeñas imperfecciones del modelo.
  • Implementa respuestas graceful tipo “no tengo suficiente información” en lugar de forzar respuestas.

Calidad y evaluación

  • Mantén siempre un golden dataset con preguntas reales.
  • Define métricas concretas: faithfulness, answer relevancy, context precision, context recall.
  • Usa frameworks de evaluación (RAGAS, DeepEval) pero no confíes ciegamente en ellos. Las métricas automatizadas usan LLMs como juez y tienen su propio sesgo.
  • Complementa siempre con feedback real de usuarios. Cuando RAGAS dice que todo está bien pero el usuario dice que no, el usuario tiene razón.
  • Cada cambio en retrieval, chunking o modelo debería validarse contra ese dataset.
  • Distingue entre evaluación offline (batch) y online (producción).
  • Mantén consistencia en el lenguaje y estilo de las respuestas.

Operación y producción

  • No pierdas de vista las métricas: latency, uso de tokens, failures.
  • Implementa observabilidad: logging de preguntas, documentos recuperados y respuestas generadas.
  • Implementa guardrails para reducir alucinaciones.
  • Versiona tus fuentes de datos, tus índices, y controla la frescura de la información.
  • Construye un feedback loop real de usuarios (thumbs up/down o similar).
  • Ten un plan de rollback para cuando los cambios empeoren la calidad.

Algunas ideas que siempre me repito

  • El modelo no sabe lo que no tiene.
  • Si las respuestas son malas, el proyecto es malo.
  • Si no puedes explicar qué documentos usa el RAG, no lo entiendes.
  • A veces la semántica no es suficiente, hybrid search existe por algo.
  • TI te puede frenar el proyecto si no los subes a tiempo o les das visibilidad.
  • A veces tendrás que hacer reingestión completa, versiona tus índices para poder volver atrás.
  • La calidad del parsing define el techo de calidad del RAG.
  • No todo se resuelve con un agente, a veces un buen pipeline es mejor.
  • Las métricas automatizadas mienten a veces, el feedback del usuario no.

Las RAG apps no son difíciles conceptualmente, pero no son tan simples como te las pintan los tutoriales, requieren diseñar un poco basado en los datos con los que trabajarás. Para aquellos que migramos a este mundo hay que cambiar el chip de las apps monolíticas, estas evolucionan mucho y muy rápido y tienes que mantenerte al día, estudiar, probar, fallar. Apóyate en tu equipo, a veces solo necesitas expresar una idea para que sola se aclare, la otra persona no necesariamente tiene la respuesta, pero te ayudará el discutirla desde otra perspectiva.