Comparamos el rendimiento de cinco marcos RAG: LangChain, LangGraph, LlamaIndex, Haystack y DSPy, mediante la creación del mismo flujo de trabajo RAG con componentes estandarizados: modelos idénticos (GPT-4.1-mini), incrustaciones (BGE-small), recuperador (Qdrant) y herramientas (búsqueda web Tavily). Esto permite aislar la sobrecarga real y la eficiencia de tokens de cada marco.
Resultados comparativos de los marcos RAG
La prueba de rendimiento consistió en 100 consultas, y cada plataforma ejecutó el conjunto completo 100 veces para proporcionar promedios estables.
- Tokens promedio : Total de tokens consumidos en todas las llamadas LLM (enrutador, evaluador de documentos, evaluador de respuestas y generador), incluyendo tanto las solicitudes (con el contexto recuperado) como las respuestas completadas. Un valor menor implica un menor costo de la API.
- Sobrecarga del marco : Tiempo de orquestación puro (ms), procesamiento interno del marco (lógica de enrutamiento, gestión de estado, etc.), excluyendo la API de LLM y las llamadas a herramientas. Un valor menor indica un marco más eficiente.
Todas las implementaciones lograron una precisión del 100 % en el conjunto de prueba. Se utilizaron los mismos modelos, temperaturas, proveedor de recuperación, herramienta de búsqueda web y un límite de tokens de contexto compartido.
Principales conclusiones
- Nos centramos en controlar lo que es controlable : misma familia de modelos y temperaturas, max_tokens a nivel de nodo, recuperador (Qdrant + BGE-small, k=5, normalización activada), proveedor web (solo Tavily), política de enrutamiento (heurística + modelo), retorno anticipado de la calculadora, límite de tokens de contexto compartido, rúbrica de calificación idéntica, instrumentación unificada. Esto reduce sustancialmente los principales factores de confusión en nuestras mediciones.
- La sobrecarga del framework es medible pero pequeña : observamos entre 3 y 14 ms por consulta debido a la lógica de orquestación. Estas diferencias son reales, pero no son la principal causa de las brechas de latencia superiores a 1 s; la mayor parte del tiempo se dedica a operaciones de entrada/salida con modelos/herramientas externas.
- El rendimiento de los tokens (bajo estas restricciones) es menor : DSPy muestra la menor sobrecarga del framework (~3,53 ms). Le siguen Haystack (~5,9 ms) y LlamaIndex (~6 ms), mientras que LangChain (~10 ms) y LangGraph (~14 ms) son más altos. El uso de tokens es menor para Haystack (~1,57k), seguido de LlamaIndex (~1,60k); DSPy y LangGraph son ~2,03k, y LangChain ~2,40k.
- Importancia del enrutamiento/ruta de la herramienta : Los ligeros cambios en el enrutamiento inicial (recuperador frente a web frente a calculadora) y el comportamiento de reserva afectan tanto a los tokens como al tiempo, incluso cuando las indicaciones y los presupuestos están alineados.
¿Por qué persisten las diferencias? El “ADN del marco”
A pesar de la estandarización, persisten pequeñas variaciones en el número de tokens y la latencia. Estas variaciones se deben a las características inherentes de bajo nivel de cada framework, su "ADN".
- Serialización de mensajes y solicitudes: Cada marco de trabajo envuelve el mismo contenido lógico con un formato ligeramente diferente antes de enviarlo al LLM, creando pequeñas pero consistentes diferencias de tokens.
- Ensamblaje de contexto: El orden preciso y la inclusión de metadatos dentro del contexto concatenado pueden variar ligeramente según el marco de trabajo, lo que afecta al recuento final de tokens.
- Desempates en el enrutamiento: En casos límite, las sutiles diferencias en la forma en que un marco de trabajo analiza la salida JSON del enrutador pueden llevar a una elección inicial de herramienta diferente.
En esta configuración, el tamaño del token parece ser el factor principal, más que el tiempo de ejecución del framework.
La arquitectura RAG de agentes compartidos
Para lograr una comparación justa, las cinco implementaciones se basaron en el mismo flujo de control:
- Enrutador: Un nodo híbrido de modelo y heurística que elige entre recuperador, búsqueda web o calculadora.
- Recuperar documentos: Obtiene los 5 documentos principales de Qdrant utilizando incrustaciones BGE-small normalizadas.
- Evaluación de documentos: Un juez del programa LLM evalúa la relevancia del documento. Si no es relevante, se activa una búsqueda web alternativa.
- Generar respuesta: Utiliza un LLM de temperatura=0.0 con un límite de token de contexto compartido para generar un borrador de respuesta.
- Respuesta de evaluación: Un segundo juez del programa LLM evalúa el borrador en cuanto a su fundamento, contradicciones (alucinaciones) y exhaustividad.
- Recuperación anticipada: Si la calificación de la respuesta es insuficiente, se realiza una búsqueda en la web. Sin embargo, los resultados de la calculadora se devuelven directamente, omitiendo los pasos de generación y calificación.
Ejemplos de flujo de trabajo
Escenario A: Acceso directo desde la base de datos:
Escenario B: Un evento reciente activa una herramienta web:
Escenario C: La calculadora proporciona un retorno anticipado:
Escenario D: La base de datos Vector es insuficiente, por lo que se recurre a la búsqueda web.
Metodología de los marcos RAG
Las cinco implementaciones lograron una precisión del 100 % en nuestro conjunto de prueba de 100 consultas, coincidiendo con las respuestas reales. Este era el requisito fundamental: garantizar que cada marco pudiera ejecutar con éxito el mismo flujo de trabajo RAG con agentes antes de medir las diferencias de rendimiento.
1. Componentes principales y configuración
Las herramientas fundamentales se estandarizaron para eliminar las variables de rendimiento en su origen.
- Másteres en Derecho:
- Modelo: Todos los nodos (enrutador, generador, calificador) utilizaron el modelo openai/gpt-4.1-mini a través de la API OpenRouter.
- Determinismo: la temperatura se estableció en 0,0 para todas las llamadas LLM con el fin de garantizar la máxima coherencia en el enrutamiento, la generación y la clasificación.
- Límites de tokens: Se aplicaron límites estrictos de max_tokens: 256 para el enrutador y los evaluadores, y 512 para el generador. Esto evita diferencias de latencia causadas por la generación de respuestas excesivamente largas por parte de un framework.
- Modelo de incrustación y recuperación:
- Modelo: Todos los frameworks utilizados BAAI/bge-small-en-v1.5 de HuggingFace.
- Normalización: Un paso fundamental para el rendimiento, normalize_embeddings se estableció en True en los cinco frameworks. (LangChain/LangGraph mediante encode_kwargs; LlamaIndex mediante normalize=True; Haystack mediante normalize_embeddings; DSPy retriever normalizado).
- Recuperación: Se consultó el almacén de vectores Qdrant para ak=5 (los 5 documentos principales) en todas las implementaciones.
- Herramientas:
- Búsqueda web: La prueba de rendimiento se limitó a Tavily únicamente (máximo de resultados = 3).
- Calculadora: Las cinco implementaciones utilizaron la biblioteca sympy para el análisis y la evaluación de expresiones matemáticas, lo que garantizó capacidades idénticas.
2. Flujo de control RAG y política
El proceso de “toma de decisiones” del agente se reflejó explícitamente en todos los ámbitos.
- Lógica de enrutamiento: Se implementó una estrategia de enrutamiento híbrida en los cinco scripts para equilibrar la inteligencia del modelo con reglas deterministas:
- Una ruta heurística basada en expresiones regulares primero busca patrones obvios de calculadora o búsqueda web (por ejemplo, símbolos matemáticos, años como "2024").
- Un nodo enrutador LLM toma entonces su propia decisión.
- La decisión final prioriza la heurística para las calculadoras, respetando en lo demás la elección del LLM.
- Presupuesto de contexto: Esta es una de las estandarizaciones más importantes. Antes de que se llame al nodo generate_answer, todo el contexto del documento recuperado y los resultados de la búsqueda web se concatenan y luego se truncan a un límite compartido de 2000 tokens mediante una utilidad común llamada truncate_to_token_budget. Esto garantiza que el generador LLM en cada marco reciba una entrada del mismo tamaño, evitando que un marco en particular se vea beneficiado o perjudicado por la verbosidad de su contexto recuperado.
- Política de calificación de respuestas:
- Criterios de evaluación flexibles: El nodo grade_answer utiliza una instrucción idéntica y flexible en todos los marcos de trabajo, lo que indica al evaluador de LLM que acepte respuestas semánticamente similares y razonablemente completas.
- Manejo de errores: Se estandarizó la lógica para manejar un análisis JSON fallido del evaluador. Si la salida del evaluador no es JSON válido, el sistema asigna por defecto una calificación permisiva (grounded=True, complete=True), imitando un escenario real donde no se desearía que un analizador inestable fallara una respuesta que, de otro modo, sería correcta. Los campos estructurados de DSPy devuelven (sin análisis JSON); esto se registra como una diferencia de robustez, no como una ventaja de rendimiento.
- Retorno anticipado de la calculadora: Como se observa en el código, una llamada exitosa al nodo calculator_node establece directamente la respuesta final y finaliza el flujo de trabajo de forma anticipada. Esta es una optimización significativa que se aplica de forma consistente, evitando que la ruta de la calculadora invoque innecesariamente los LLM generate y grade_answer.
- Alineación con DSPy. Para mantener la equidad con las líneas base que no son CoT, DSPy usa dspy.Predict (sin CoT) para Router y AnswerGenerator. Las firmas reflejan los contratos de nodo de otros frameworks; cuando está disponible, el recuento de tokens utiliza el uso reportado por el modelo; de lo contrario, se utiliza el método de reserva de tiktoken.
3. Instrumentación y métricas
El proceso de medición fue idéntico, utilizando los mismos principios y recursos.
- Latencia: Se utilizó time.perf_counter() de alta precisión para todas las mediciones de tiempo. La sobrecarga del marco de trabajo se calcula consistentemente como la latencia total menos la latencia de las llamadas externas.
- Tokenización: Todos los recuentos de tokens para las solicitudes y las finalizaciones se calcularon utilizando tiktoken, la codificación cl100k_base, lo que garantiza una única fuente de verdad para las métricas de tokens. La métrica "Tokens promedio" que se muestra en los resultados representa la suma acumulativa de todos los tokens de entrada (solicitud) y salida (finalización) para cada llamada LLM (por ejemplo, enrutador, evaluadores, generador) dentro de un único flujo de trabajo de consulta.
- Gestión de estado: Si bien la sintaxis de implementación varía (TypedDict de LangGraph, clase de LlamaIndex, diccionario de LangChain), la estructura de estado es funcionalmente idéntica. Cada framework pasa el mismo conjunto de claves (pregunta, documentos, resultados web, etc.) entre nodos, lo que garantiza que la lógica del flujo de control opere sobre la misma información.
Al imponer estas estrictas estandarizaciones a nivel de código, esta evaluación comparativa pretende ir más allá de las comparaciones superficiales y ofrecer un análisis replicable del rendimiento del marco bajo una política RAG fija.
Interpretación de los resultados:
- Se puede concluir que, en esta configuración específica y altamente controlada, la sobrecarga de orquestación tiende a ser mínima; las diferencias se deben principalmente al número de tokens y a las rutas de las herramientas.
- En esta configuración específica y altamente controlada, la sobrecarga del framework es insignificante.
- Las diferencias de rendimiento se debieron a la cantidad de tokens y a las variaciones en la trayectoria de la herramienta.
- No se puede generalizar: los resultados son específicos de esta arquitectura, modelos, indicaciones, recuperador y proveedor web; cambiarlos puede alterar las clasificaciones.
Experiencia del desarrollador: una comparación cualitativa
El rendimiento no es el único factor; la sensación que transmite un framework al trabajar con él es igualmente importante.
- LangGraph: El grafo declarativo
Utiliza un paradigma basado en grafos. Se definen los nodos y se conectan con aristas (incluyendo add_conditional_edges), por lo que el flujo de control forma parte de la arquitectura. El estado se tipifica mediante un TypedDict con actualizaciones al estilo de un reductor (Annotated[…, add]).- Elija LangGraph para: flujos de trabajo complejos con múltiples ramificaciones, reintentos y ciclos; su estructura aumenta en robustez y mantenibilidad a medida que crecen los agentes.
- LlamaIndex: Orquestación imperativa
Un script procedimental donde el flujo de control es el estándar if/else de Python; el "grafo" reside en tu código. El estado es una clase PipelineState dedicada, y el marco proporciona primitivas de recuperación limpias (VectorStoreIndex → .as_retriever(k=5)).- Elija LlamaIndex para: flujos de trabajo legibles en un solo archivo donde valore la lógica procedimental clara y la facilidad de depuración.
- LangChain: Imperativo con componentes declarativos
La orquestación sigue siendo un script de Python, pero las tareas individuales son pequeñas cadenas componibles que utilizan el operador | (por ejemplo, prompt | llm | parser). El estado es un diccionario de Python flexible y sin tipado.- Elija LangChain para: Prototipado rápido o equipos que ya forman parte del ecosistema de LangChain y que prefieren componer pequeñas unidades declarativas dentro de un controlador imperativo más amplio.
- Haystack: Orquestación manual basada en componentes. Componentes tipados y reutilizables (@component) con E/S explícita, mientras que el flujo de control se mantiene en Python puro (if/else). Fácil intercambio de backends LLM/retriever/web, además de instrumentación paso a paso de primera clase (tiempo externo frente a tiempo del framework).
- Elija Haystack para obtener: pipelines listos para producción y comprobables, con contratos claros y un control preciso.
- DSPy: Programas basados en firmas (menos líneas de código)
Define una tarea mediante una firma (entradas/salidas + intención) y luego impleméntala con módulos que encapsulan las llamadas a la solicitud y a LLM. Centraliza el manejo de la solicitud/uso y elimina el código de conexión; intercambiar elementos internos (por ejemplo, Predict ↔ CoT ) no cambia el contrato.- Elija DSPy para: mínimo código repetitivo, flujos de trabajo legibles en un solo archivo, desarrollo basado en contratos (con optimizadores opcionales).
Intercambio de rendimiento óptimo por comparabilidad
- LangGraph podría destacar gracias a sus optimizaciones de grafos nativas cuando se le permite usar la ejecución paralela, el almacenamiento en caché de estado y su sistema de aristas condicionales para lógica de ramificación compleja.
- DSPy podría mostrar resultados radicalmente diferentes al utilizar sus optimizadores característicos (como MIPROv2) y la función de sugerencias de cadena de pensamiento, lo que puede mejorar significativamente la calidad de las respuestas.
- Haystack podría aprovechar sus funciones de almacenamiento en caché y procesamiento por lotes, así como las optimizaciones a nivel de componentes, que hemos desactivado por motivos de equidad.
- LlamaIndex podría beneficiarse de sus estrategias de indexación avanzadas, motores de consulta y capacidades multimodales que no se pusieron a prueba en esta evaluación comparativa.
- LangChain podría destacar por su extenso ecosistema de herramientas y las optimizaciones de LCEL (LangChain Expression Language) cuando no esté limitado a nuestro conjunto de herramientas estandarizado.
El marco de trabajo "óptimo" depende de si se optimiza para: velocidad de desarrollo, mantenibilidad, rendimiento o patrones arquitectónicos específicos.
Conclusión
En una canalización RAG de agentes estrechamente emparejada, la sobrecarga de orquestación suele ser mínima. Lo que realmente marca la diferencia es la cantidad de tokens que se procesan y las herramientas que se invocan, factores que dependen de las indicaciones, la recuperación y el enrutamiento. El marco de trabajo "correcto" depende, en última instancia, del estilo de orquestación preferido por el equipo: grafos declarativos (LangGraph), scripts imperativos (LlamaIndex), cadenas componibles (LangChain), componentes modulares (Haystack) o programas basados en firmas (DSPy) que minimizan el código repetitivo.
Lecturas adicionales
Explore otros puntos de referencia RAG, como:
- Modelos de incrustación: OpenAI vs Gemini vs Cohere
- Base de datos de vectores principal para RAG: Qdrant vs Weaviate vs Pinecone
- Prueba de rendimiento Agentic RAG: enrutamiento y generación de consultas en múltiples bases de datos.
- RAG híbrido: Mejorando la precisión del RAG
Sé el primero en comentar
Tu dirección de correo electrónico no será publicada. Todos los campos son obligatorios.