(Un canal RAG de producción para archivos PDF: análisis relacional, recuperación de TOC, respuestas escritas) actualizamos cada uno de los cuatro bloques: análisis de documentos, análisis de preguntas, recuperación y generación, y los conectamos en un canal limpio y lineal. Se ingresa un PDF y sale una respuesta citada y escrita. Ese fue un artículo y una pregunta. La verdadera prueba es lo que sucede cuando ejecutas el mismo proceso, sin cambiar una línea, en documentos que no se parecen en nada. Así que eso es lo que hacemos aquí: apuntamos un canal a cuatro PDF muy diferentes: un artículo de investigación, un estándar del NIST, otro artículo y un informe cuyo índice está desglosado, y vemos cómo se comporta en cada uno de ellos.
Este artículo es la segunda de dos partes sobre el proceso actualizado en la Parte III de Enterprise Document Intelligence, una serie que construye un sistema RAG empresarial a partir de cuatro bloques: análisis de documentos, análisis de preguntas, recuperación y generación. La primera parte, Actualización de un RAG básico, ladrillo por ladrillo (enlace a continuación), mejoró cada ladrillo por sí solo. Esta parte conecta los cuatro bloques actualizados en una sola llamada y la ejecuta de extremo a extremo en documentos reales.
📓 El cuaderno ejecutable para este artículo está en GitHub: doc-intel/notebooks-vol1. Ejecuta la única llamada pdf_qa en los cuatro documentos, imprime la respuesta escrita y el registro de auditoría por bloque para cada uno, y le permite colocar su propio PDF y observar cómo el mismo canal lo maneja sin cambios.
La parte A mejoró cada bloque por sí solo: el análisis ahora devuelve un conjunto relacional con un TOC y un parsing_summary escrito; el análisis de preguntas convierte las ruidosas entradas del usuario en un resumen estructurado; la recuperación lee el TOC del documento a través de un pequeño LLM y combina esas páginas con las coincidencias de palabras clave; La generación devuelve una respuesta escrita con un intervalo citable por elemento más cuatro indicadores de calidad del contexto. Construidos de forma aislada, los cuatro todavía tienen que funcionar como uno solo.
Esta parte los conecta a una única función, pdf_qa, y lee el resultado. Una llamada toma un PDF y una pregunta y devuelve la respuesta escrita más el registro de auditoría completo desde la pregunta hasta la cita. Dos canales laterales aparecen solo una vez que los ladrillos se juntan: parsing_summary alimenta ambos ladrillos LLM y una señal de retroalimentación desde la generación hasta la recuperación.
El documento actual sigue siendo el mismo envío público de arXiv de 15 páginas, Todo lo que necesita atención, con la misma pregunta de dos errores tipográficos: "¿Cuáles son las opciones para la codificación posicional?". Luego, el proceso ensamblado se ejecuta en tres documentos más que enfatizan diferentes ladrillos: el NIST Cybersecurity Framework 2.0, el documento original de recuperación-generación aumentada y el informe Perspectivas de los mercados de productos básicos del Banco Mundial (abril de 2024), cuyo PDF incluye un índice roto. (Las fuentes y licencias se enumeran al final).
1. El oleoducto de principio a fin
El diagrama del artículo 1 (RAG mínimo) mostraba cuatro cuadros seguidos con una pastilla de entrada por espacio. Lo suficiente como para introducir los ladrillos, pero no lo suficiente como para captar lo que realmente transporta el oleoducto mejorado. La siguiente versión agrega los dos canales laterales que atraviesa el código de producción.
Lea el diagrama en tres pasadas.
Los cuatro ladrillos de la fila principal. Mismas denominaciones que el artículo 1 (GAR mínimas). Cada bloque consume el objeto escrito que emitió el anterior (line_df fuera de análisis, ParsedQuestion fuera de discusión, ancla + contexto fuera de recuperación) y el contrato es el esquema de Pydantic, no un simple dictado. Los cuatro ladrillos siguen siendo independientes: ninguno importa al otro.
El primer canal lateral: parsing_summary alimenta el análisis de preguntas. El análisis de preguntas en el Artículo 1 (GAR mínimo) vio solo el texto sin formato de la pregunta. En la canalización actualizada, también recibe una proyección compacta de la síntesis a nivel de documento calculada por el bloque de análisis (tipo_doc, n_páginas, campos_típicos, resumen). La misma pregunta "¿cómo se llama?" analiza de manera muy diferente un CV (tipo_doc=resume, campos_típicos=[nombre, correo electrónico, …]) y un informe anual de 200 páginas. El canal está discontinuo porque viaja a través de PromptContext en el contenido del usuario de la llamada LLM, no a través de un kwarg de la API física. La API de ladrillo permanece parse_question(question, *, context=PromptContext(…)) independientemente de cuál sea doc_type.
El segundo canal lateral: el circuito de retroalimentación. La generación no siempre tiene éxito de una sola vez. El LLM puede marcar "el contexto recuperado cubrió solo una parte de la respuesta" (complete_answer_found=False) o "el documento usa 'exceso' donde la pregunta decía 'deducible'" (llm_discovered_keywords). El orquestador lee esas señales y las devuelve, normalmente para recuperarlas con una lista ampliada de palabras clave y, a veces, para cuestionar el análisis y reescribir una consulta. El artículo 13 (el proceso de flujo de trabajo) recorre el circuito en detalle. Este artículo ejecuta la versión de una sola pasada, que es lo que necesita el típico documento breve o de cumplimiento.
Cada uno de los cuatro ladrillos compuestos aquí se desarrolla, con su código en detalle, en sus propios artículos (este artículo muestra solo el cableado, no nuevamente el código por ladrillo):
La parte A colocó los ladrillos uno a la vez. El código de producción los envuelve en una sola función. El nombre dice qué hace la función y en qué lo hace: pdf_qa responde preguntas en un PDF. Su hermano excel_qa haría lo mismo en un libro de Excel; pdf_translate traduciría un PDF; pdf_compare compararía dos. Las cuatro actualizaciones se conectan en los cuatro pasos nombrados; el resto es fontanería:
def pdf_qa(pdf_path, question, *, client=Ninguno, expert_dict=Ninguno, contexto: PromptContext | Ninguno = Ninguno): # Ladrillo 1: Análisis: line_df + page_df + toc_df + parsing_summary parsed_pdf = parse_pdf(pdf_path, método="fitz") line_df, page_df, toc_df = parsed_pdf["line_df"], parsed_pdf["page_df"], parsed_pdf["toc_df"] parsing_summary = parsed_pdf["parsing_summary"] # Proyecte parsing_summary en el DocContext que ambos bloques LLM leen pipeline_ctx = (context o PromptContext()).with_doc_context( DocContext.from_parsing_summary(parsing_summary) ) # Ladrillo 2: Análisis de preguntas: una llamada de LLM corrige + extrae, luego expande parsed = parse_question(question, client=client, context=pipeline_ctx) palabras clave = expand_with_expert(parsed.keywords, expert_dict o {}) shape = infer_answer_shape(question) # Ladrillo 3: Recuperación: palabras clave en page_df + enrutador LLM TOC kw_pages, _ = retrieve_pages(page_df, line_df, palabras clave, top_k=3) selección = Reason_on_toc(question, toc_df, cliente=cliente) toc_pages = expand_sections_to_pages(toc_df, selección.section_ids) páginas = sorted(set(kw_pages['page_num']) | toc_pages) filtered = line_df[line_df['page_num'].isin(pages)] # Ladrillo 4: Generación: esquema elegido de expect_answer_shape, # pipeline_ctx enhebrado para que el LLM vea doc_type/típico_fields esquema = ListAnswer if shape == 'listing' else AnswerWithEvidence respuesta = llm_answer_with_evidence(pregunta, filtrado, cliente=cliente, contexto=pipeline_ctx) devuelve respuesta, {'pages': páginas, 'keywords': palabras clave, 'toc_selection': selección.model_dump()}
Firma de producción. El pdf_qa de la biblioteca contiene algunos kwargs más que la forma simplificada de arriba oculta:
tienda: el caché por bloque. Método: el motor de análisis. top_k: amplitud de recuperación. use_toc: apaga el enrutador LLM TOC cuando el documento no tiene un esquema utilizable. include_bbox: para casos sensibles al diseño.
Todos tienen un comportamiento predeterminado compatible con la versión corta. El propio organismo de recuperación delega en despacho_page_retrieval desde docintel.retrieval, el mismo asistente compartido que el corpus_pdf_qa entre documentos llama por documento, por lo que el control de calidad de un solo documento y de todo el proyecto permanece en la misma lógica de enrutamiento TOC. La carrocería sigue siendo el mismo cableado de cuatro ladrillos.
Esto es lo que cada ladrillo absorbió y produjo en esta ejecución:
Ladrillo 1, análisis. En: la ruta PDF Atención. Salida: line_df, page_df, toc_df. El fragmento de arranque en la parte superior del artículo ya mostraba cada uno de ellos; No hay una figura separada aquí.
Ladrillo 2, análisis de preguntas. En: la pregunta ruidosa. Fuera: el informe analizado.
{ "in": { "raw_question": "¿Cuáles son las opciones para la codificación posicional?" }, "out": { "raw_keywords": ["codificación posicional"], "corrected_keywords": ["codificación posicional"], "expert_keywords_added": ["sinusoidal", "aprendido"], "final_keywords": ["codificación posicional", "sinusoidal", "aprendido"], "expected_answer_shape": "listado" } }
Ladrillo 3, recuperación. En: palabras_clave_finales + página_df + toc_df. Fuera: el estado de recuperación.
{ "in": { "final_keywords": ["codificación posicional", "sinusoidal", "aprendido"], "scope": "page_df + toc_df" }, "out": { "keyword_candidates": [ {"page": 6, "matched_keywords": ["codificación posicional", "sinusoidal", "aprendido"], "match_count": 3}, {"page": 9, "matched_keywords": ["positional encoding", "sinusoidal", "learned"], "match_count": 3}, {"page": 4, "matched_keywords": ["learned"], "match_count": 1} ], "toc_routing": { "section_ids": ["10"], "reasoning": "La Sección 10, 'Codificación posicional', se centra explícitamente en…", "secciones_seleccionadas": [ {"section_id": "10", "title": "Codificación posicional", "start_page": 6, "end_page": 6} ] }, "merged_pages": [4, 6, 9] } }
El bloque 3 fusiona las páginas de palabras clave y las páginas seleccionadas del TOC en un solo conjunto. La siguiente tabla muestra el razonamiento: el TOC completo del artículo como columna vertebral, con para cada sección las palabras clave detectadas en sus líneas y tres Y/. banderas que muestran si esa sección fue seleccionada mediante recuperación de palabras clave, mediante recuperación de TOC y si terminó en merged_pages. La fusión es una unión determinista; esta tabla hace que la decisión sea auditable sección por sección.
Ladrillo 4, generación. En: pregunta + las líneas en merged_pages. Salida: una ListAnswer con un elemento por opción, espacios de línea, citas textuales y los cuatro indicadores de calidad del contexto.
{ "in": { "question": "¿Cuáles son las opciones para la codificación posicional?", "merged_pages": [4, 6, 9], "filtered_line_df": "256 filas" }, "out": { "items": [ {"text": "Codificaciones posicionales sinusoidales", "start_page_num": 6, "start_line_num": 33, "end_page_num": 6, "end_line_num": 35, "quote": "PE(pos,2i) = sin(pos/100002i/dmodel)nPE(pos,2i+1) = cos(po…"}, {"text": "Incrustaciones posicionales aprendidas", "start_page_num": 6, "start_line_num": 41, "end_page_num": 6, "end_line_num": 41, "quote": "También experimentamos con el uso de incrustación posicional aprendida…"}, {"text": "incrustación posicional en lugar de sinusoides", "start_page_num": 9, "start_line_num": 111, "end_page_num": 9, "end_line_num": 111, "quote": "incrustación posicional en lugar de sinusoides"} ], "answer_found": true, "complete_answer_found": verdadero, "context_completeness": 1.0, "context_structured": verdadero, "confianza": 1.0, "advertencias":[]} }
Los espacios de línea en cada elemento no son números abstractos. Se asignan a una página real en el PDF de origen, y el siguiente asistente dibuja un rectángulo rojo alrededor del rango de líneas de cada elemento para que el lector pueda ver la respuesta en la propia página:
Veinte líneas de Python, cuatro llamadas a LLM (dos en análisis y generación en cuestión, más los ladrillos que no llaman a LLM). El dictado de procedencia hace que cada paso sea reproducible: registre la llamada, un auditor puede rastrear desde la pregunta hasta la cita sin volver a ejecutar el proceso.
El documento de atención anterior es un trabajo de investigación. El mismo proceso, sin cambios de código, se ejecuta en documentos con formas muy diferentes. Tres pruebas más: un PDF de cumplimiento, un trabajo de investigación y un caso de estrés en un documento con un TOC roto.
2. Cuando la respuesta queda enterrada entre muchas coincidencias
El NIST Cybersecurity Framework 2.0 tiene 32 páginas, TOC nativo y diseño de una sola columna. El tipo de documento que un equipo empresarial analiza para recuperarlo. Esta vez la pregunta apunta a un solo concepto, no a una lista de opciones. La inferencia de forma del analizador de preguntas la marca como única y la canalización se envía a AnswerWithEvidence en lugar de ListAnswer. Misma función de ajuste, diferente esquema de salida. Las cuestiones de inclusión en la lista son objeto del artículo 12 (lista); aquí ejercitamos la otra rama del envío de formas:
Los cuatro ladrillos recorrieron este recorrido:
Ladrillo 1, análisis. En: test2_pdf (el PDF NIST CSWP-29). Salida: line_df, page_df, toc_df.
Ladrillo 2, análisis de preguntas. En: la pregunta ruidosa. Fuera: el informe analizado.
{ "in": { "raw_question": "¿Cómo se define un perfil en CSF 2.0?" }, "out": { "raw_keywords": ["Perfil", "CSF 2.0"], "corrected_keywords": ["Perfil", "CSF 2.0"], "expert_keywords_added":[], "final_keywords": ["Perfil", "CSF 2.0"], "expected_answer_shape": "único" } }
Ladrillo 3, recuperación. En: palabras_clave_finales + página_df + toc_df. Fuera: el estado de recuperación.
{ "in": { "final_keywords": ["Perfil", "CSF 2.0"], "scope": "page_df + toc_df" }, "out": { "keyword_candidates": [ {"page": 2, "matched_keywords": ["Perfil", "CSF 2.0"], "match_count": 2}, {"page": 5, "matched_keywords": ["Perfil", "CSF 2.0"], "match_count": 2}, {"page": 4, "matched_keywords": ["Profile"], "match_count": 1} ], "toc_routing": { "section_ids": ["3", "2", "11"], "reasoning": "La Sección 3.1 (Perfiles CSF) aborda directamente la definición…", "selected_sections": [ {"section_id": "2", "title": "3. Introducción a los perfiles y niveles de CSF", "start_page": 11, "end_page": 14}, {"section_id": "3", "title": "3.1. Perfiles de CSF", "start_page": 11, "end_page": 12}, {"section_id": "11", "title": "Apéndice C. Glosario", "start_page": 31, "end_page": 32} ] }, "merged_pages": [2, 4, 5, 11, 12, 13, 14, 31, 32] } }
La auditoría TOC por sección en la misma ejecución:
Ladrillo 4, generación. En: pregunta + las líneas en merged_pages. Salida: una AnswerWithEvidence con una cadena de respuestas, un intervalo citable, citas textuales, además de los indicadores de calidad (respuesta_completa_encontrada, contexto_estructurado, confianza).
{ "in": { "question": "¿Cómo se define un perfil en CSF 2.0?", "merged_pages": [2, 4, 5, 11, 12, 13, 14, 31, 32], "filtered_line_df": "280 filas" }, "out": { "answer": "Un perfil en CSF 2.0, específicamente un CSF Organizational Pro…", "start_page_num": 11, "start_line_num": 8, "end_page_num": 12, "end_line_num": 20, "confidence": 1.0, "justification": "Las líneas 11:8-12:20 proporcionan una definición detallada de CSF P…", "quotes": [ "Un perfil organizacional CSF describe la cu…", "Cada perfil organizacional incluye uno o ambos de los fo…", "A El perfil de la comunidad es una base de referencia de los resultados del CSF que es c…" ], "advertencias":[], "complete_answer_found": true, "context_structured": true, "llm_discovered_keywords": ["Perfil organizacional", "Perfil actual", "Perfil objetivo", "Perfil comunitario"] } }
El mismo lapso se convirtió en un rectángulo en la página de origen:
Debido a que la redacción de la pregunta no activa LISTING_TRIGGERS (sin opciones, todas, cuáles, cuáles son), la inferencia de forma devuelve única y la canalización envía la llamada a AnswerWithEvidence en lugar de ListAnswer. Los mismos cuatro ladrillos, el mismo registro de auditoría, un esquema de salida diferente.
El tramo único llega a la página que define un perfil CSF, y la página comentada arriba muestra el rectángulo resaltado en contexto. Los indicadores de calidad (respuesta_completa_encontrada, contexto_estructurado, confianza) vuelven limpios, por lo que el enrutador descendente enviará esta respuesta tal como está.
Las preguntas sobre la inclusión en la lista reciben su propio tratamiento específico en el Artículo 12 (lista); Aquí la conclusión es que la función de ajuste lleva ambas formas sin una ruta de código separada en el lado de la persona que llama.
3. Cuando la respuesta abarca varias secciones
Generación aumentada de recuperación para tareas de PNL intensivas en conocimiento (Lewis et al. 2020) es el artículo que presentó la arquitectura RAG de la que trata esta serie. 18 páginas, TOC nativo, estilo de trabajo de investigación con una sección central llena de tablas de resultados. Otra pregunta de respuesta única, esta vez sobre el patrón arquitectónico central del artículo:
La misma caminata de cuatro ladrillos en esta carrera:
Ladrillo 1, análisis. En: test3_pdf (el artículo RAG original, 18 páginas). Salida: line_df, page_df, toc_df.
Ladrillo 2, análisis de preguntas. En: la pregunta ruidosa. Fuera: el informe analizado.
{ "in": { "raw_question": "¿Cómo combina RAG la recuperación y la generación?" }, "out": { "raw_keywords": ["RAG", "recuperación", "generación"], "corrected_keywords": ["RAG", "recuperación", "generación"], "expert_keywords_added":[], "final_keywords": ["RAG", "recuperación", "generación"], "expected_answer_shape": "único" } }
Ladrillo 3, recuperación. En: palabras_clave_finales + página_df + toc_df. Fuera: el estado de recuperación.
{ "in": { "final_keywords": ["RAG", "recuperación", "generación"], "scope": "page_df + toc_df" }, "out": { "keyword_candidates": [ {"page": 1, "matched_keywords": ["RAG", "recuperación", "generación"], "match_count": 3}, {"page": 2, "matched_keywords": ["RAG", "recuperación", "generación"], "match_count": 3}, {"page": 3, "matched_keywords": ["RAG", "retrieval", "generación"], "match_count": 3} ], "toc_routing": { "section_ids": ["2", "3", "4"], "reasoning": "La Sección 2.1 Modelos probablemente explica la arquitectura general…", "selected_sections": [ {"section_id": "2", "title": "2.1 Modelos", "start_page": 3, "end_page": 3}, {"section_id": "3", "title": "2.2 Retriever: DPR", "start_page": 3, "end_page": 3}, {"section_id": "4", "title": "2.3 Generador: BART", "start_page": 3, "end_page": 3} ] }, "páginas_fusionadas": [1, 2, 3] } }
La auditoría TOC por sección en la misma ejecución:
Ladrillo 4, generación. En: pregunta + las líneas en merged_pages. Fuera: una AnswerWithEvidence que describe cómo RAG acopla el recuperador al generador, con un tramo citado y los indicadores de calidad.
{ "in": { "question": "¿Cómo combina RAG la recuperación y la generación?", "merged_pages": [1, 2, 3], "filtered_line_df": "200 filas" }, "out": { "answer": "RAG combina la recuperación y la generación mediante el uso de un entrenamiento previo…", "start_page_num": 2, "start_line_num": 46, "end_page_num": 3, "end_line_num": 40, "confidence": 0.98, "justification": "Las líneas 2:46 a 3:40 describen el mecanismo: la recuperación…", "quotes": [ "Figura 1: Descripción general de nuestro enfoque. Combinamos un entrenamiento previo…", "El componente de recuperación pη(z|x) se basa en DPR… Calcula…", "El componente generador pθ(yi|x, z, y1:i-1) podría ser modell…", "Modelo de secuencia RAG… el modelo usa el mismo documento para…", "En el modelo RAG-Token podemos dibujar un documento latente diferente…" ], "caveats": [ "Los pasos algorítmicos detallados (p. ej., entrenamiento o más avanzados…" ], "complete_answer_found": true, "context_structured": true, "llm_discovered_keywords": ["retriever", "generador", "marginar", "documento latente", "seq2seq", "DPR", "BART", "Máxima búsqueda interna de productos", "RAG-Sequence", "RAG-Token"] } }
El mismo lapso citado dibujado en la página fuente:
La inferencia de forma vuelve a ser única y la canalización se envía a AnswerWithEvidence. La pregunta es más amplia que la definición de perfil del NIST porque pregunta sobre un patrón arquitectónico que abarca el recuperador, el generador y la forma en que ambos se entrenan conjuntamente. La recuperación arrastra un puñado de páginas a lo largo del cuerpo; el generador sintetiza un párrafo que los une, con un lapso citable. Al igual que con la ejecución del NIST, los cuatro indicadores permanecen limpios en este PDF bien estructurado.
4. Cuando se rompe el índice
La publicación Perspectivas de los mercados de productos básicos del Banco Mundial (publicación del Banco Mundial, edición de abril de 2024) tiene un índice de referencia incorporado, pero todos los títulos de las secciones dicen Página en blanco. Los marcadores se generaron sin títulos. El enrutador LLM TOC recibe un TOC donde cada entrada está vacía de contenido semántico, no selecciona nada y la canalización recurre únicamente a la recuperación de palabras clave. Una buena prueba de estrés de lo que sucede cuando uno de los cuatro ladrillos (análisis) devuelve un resultado degenerado. Una pregunta de una sola respuesta, sobre un informe de previsión:
El mismo camino, esta vez el ladrillo TOC no arroja nada útil:
Ladrillo 1, análisis. En: test4_pdf (CMO del Banco Mundial, abril de 2024). Salida: line_df, page_df, toc_df. El toc_df está degenerado: cada título dice Página en blanco porque los marcadores se generaron sin títulos.
Ladrillo 2, análisis de preguntas. En: la pregunta ruidosa. Fuera: el informe analizado.
{ "in": { "raw_question": "¿Cuál es la perspectiva del precio de la energía para 2024?" }, "out": { "raw_keywords": ["precio de la energía", "2024"], "corrected_keywords": ["precio de la energía", "2024"], "expert_keywords_added":[], "final_keywords": ["precio de la energía", "2024"], "expected_answer_shape": "único" } }
Ladrillo 3, recuperación. En: palabras_clave_finales + página_df + toc_df. Fuera: el estado de recuperación.
{ "in": { "final_keywords": ["perspectiva del precio de la energía", "2024"], "scope": "page_df + toc_df" }, "out": { "keyword_candidates": [ {"page": 1, "matched_keywords": ["2024"], "match_count": 1}, {"page": 3, "matched_keywords": ["2024"], "match_count": 1}, {"page": 4, "matched_keywords": ["2024"], "match_count": 1} ], "toc_routing": { "section_ids":[], "reasoning": "Ninguna de las secciones enumeradas en la tabla de contenido proporciona…", "selected_sections":[]}, "páginas_fusionadas": [1, 3, 4] } }
La auditoría TOC por sección hace que el error de análisis sea visible de un vistazo:
Ladrillo 4, generación. En: pregunta + las líneas en merged_pages. Disponible: una AnswerWithEvidence que resume las perspectivas del precio de la energía, con un período citable. El oleoducto aún produjo una respuesta limpia a pesar del fracaso del TOC.
{ "in": { "question": "¿Cuál es la perspectiva del precio de la energía para 2024?", "merged_pages": [1, 3, 4], "filtered_line_df": "47 filas" }, "out": { "answer": "NA", "start_page_num": null, "start_line_num": null, "end_page_num": null, "end_line_num": null, "confidence": 0.0, "justification": "Ninguna de las líneas proporcionadas analiza el precio de la energía…", "quotes":[], "caveats": [ "No hay contenido sustancial de Commodity Markets Outlook r…" ], "complete_answer_found": false, "context_structured": true, "llm_discovered_keywords": ["Commodity Markets Outlook", "fecha límite de datos", "licencia"] } }
No hay lapso para dibujar. El enrutador TOC vio que todos los títulos eran páginas en blanco y no eligió nada (toc_routing.selected_sections:[]), por lo que la recuperación recayó en palabras clave. En este documento, la palabra clave 2024 coincidió solo con las páginas principales, no con la sección de energía, por lo que la generación leyó páginas que no contenían pronósticos, no encontró nada que citar y devolvió la respuesta: NA con respuesta_completa: falsa con confianza 0.0.
Ese es el punto, no un error en la demostración. Dado el contexto que no contiene la respuesta, el oleoducto declina en lugar de inventar un número. Un RAG ingenuo en la misma recuperación rota habría tomado el texto inicial y escrito a partir de él un pronóstico que sonara confiado. La solución está en sentido ascendente, en el análisis, no en la generación: el TOC de recuperación de la ruta del cuerpo del Artículo 10 (análisis adaptativo) reconstruye una tabla de contenido utilizable cuando el incrustado está degenerado, por lo que la siguiente ejecución se dirige a la sección de energía y responde con un lapso citable.
Se ejercitaron cuatro documentos, ambas formas de respuesta: el documento de Atención como una pregunta de lista (un elemento por opción), NIST y el documento RAG como preguntas de respuesta única (un párrafo, un lapso) y CMO como la pregunta de respuesta única que la canalización rechazó correctamente cuando la recuperación regresó sin el pronóstico. La misma función de envoltura, los mismos cuatro ladrillos, el mismo registro de auditoría; lo único que cambia es qué generación de esquema Pydantic regresa y si puede completarlo honestamente. La canalización nunca tuvo que saber qué documento estaba leyendo y nunca tuvo que saber qué esquema estaba a punto de completar. Cada prueba es por sí sola como una demostración de caja negra y todas coinciden en cómo es una pista de auditoría.
Donde la tubería aún puede fallar, cada falla se muestra en un indicador específico:
un PDF sin un índice de contenido utilizable (índice de contenido en el texto que el analizador omitió, o ninguna página de índice de contenido): toc_sections_matched vacío. un documento escaneado donde el analizador entregó texto codificado en primer lugar: context_structured=false. una pregunta cuyo vocabulario no aparece en absoluto en el corpus: complete_answer_found=false o elementos vacíos.
El artículo 10 (análisis adaptativo) comienza a partir de ahí: primero el análisis barato, el análisis más profundo a pedido y qué hacer cuando la recuperación vuelve vacía.
5. Qué hace un canal ingenuo en los casos difíciles
El proceso se realizó en todos los documentos anteriores, respondiendo tres y rechazando honestamente el cuarto. La pregunta justa: ¿un RAG ingenuo (la línea de base del Artículo 1 (RAG mínimo), la concordancia de palabras clave o las páginas incrustadas, manténgase las primeras, pregunte) lo habría hecho también? Ejecutamos pdf_qa_baseline contra pdf_qa en las mismas preguntas, además de algunos estándares más para ver dónde divergen los dos.
Sea honesto acerca del resultado: en los dos artículos limpios de arXiv, la línea de base ingenua también responde correctamente. Son breves y bien estructurados, y la respuesta coincide con las palabras clave. La brecha no está en los insumos fáciles. Se abre sobre los estándares. En NIST CSF 2.0, cuando se le pregunta "¿Cómo se define un perfil?", ingenuo recupera páginas llenas de la palabra Perfil pero nunca la que lo define, y devuelve "no definido en estas líneas" en 0.10. En el catálogo NIST SP 800-53 de más de 400 páginas, se solicita un control, no recupera nada utilizable y devuelve “NA” en 0,00. En NIST SP 800-207, devuelve tres de los siete principios de confianza cero, con una confianza de 0,95 en que una lista parcial es la respuesta completa. En FIPS 199 define solo el nivel de impacto alto y admite que el nivel bajo y moderado nunca estuvieron en su contexto. Nuestro canal encamina cada pregunta en la propia tabla de contenidos del documento, fija la sección correcta y devuelve la respuesta completa y citada cada vez.
Ese patrón lleva el argumento. Un RAG ingenuo es una apuesta de palabra clave o coseno, y vale la pena hasta que el documento sea lo suficientemente largo, o su vocabulario esté lo suficientemente alejado de la pregunta, como para que la respuesta caiga por debajo del límite superior k. Luego, al modelo se le entrega un contexto que no contiene la respuesta y hace una de dos cosas: dice “no encontrado” (el caso honesto de 0,10 o NA) o inventa una respuesta plausible a partir de las páginas equivocadas (la lista de principios parcial y segura). El segundo es lo que los equipos reportan como una alucinación. Rara vez es el modelo que inventa de la nada. Por lo general, se trata de responder fielmente al contexto equivocado y, a menudo, a ambas cosas a la vez: al pasar páginas que no contienen la respuesta, llena el vacío con algo plausible. El artículo 7quinquies (la mayoría de las alucinaciones RAG son fallos de recuperación) plantea ese caso en el nivel de recuperación; Aquí se muestra de punta a punta.
Es por eso que los cuatro ladrillos son ingeniería de contexto, no ajuste de recuperación. Cada ladrillo da forma a lo que finalmente ve el modelo: el análisis mantiene la estructura, el análisis de preguntas amplía el vocabulario, las rutas de recuperación en el propio mapa del documento, la generación vincula la respuesta a un intervalo citable. Obtenga el contexto correcto y una respuesta incorrecta y segura no tendrá de dónde venir. La ingeniería rápida no es suficiente: cómo cuatro ladrillos de ingeniería contextual detienen las alucinaciones de RAG (Artículo 9bis, enlace a continuación) lleva este contraste mucho más allá, una falla por ladrillo, con una línea de base ingenua construida para romperse exactamente en ese ladrillo. Esta sección es la versión corta; ese artículo es el diagnóstico completo.
6. Por qué los ladrillos se mantienen independientes
Las tres ejecuciones anteriores funcionaron sin cambiar una sola línea de código debido a cómo se descompone la canalización. Cada bloque tiene un trabajo y una salida escrita, por lo que intercambiar el documento cambia lo que fluye a través de los bloques, nunca los bloques en sí.
Cada ladrillo tiene un contrato tipificado con sus vecinos. El análisis devuelve un pequeño conjunto relacional de DataFrames (line_df, page_df, toc_df) con esquemas conocidos. El análisis de preguntas devuelve un resumen estructurado (palabras clave corregidas, expansión de expertos, forma de respuesta esperada). La recuperación devuelve un conjunto de páginas fusionadas y las filas line_df filtradas en esas páginas. La generación devuelve un objeto Pydantic escrito cuyo esquema depende de la forma de la respuesta, que contiene los elementos y los cuatro indicadores de calidad. Cada salida intermedia es un objeto con nombre, inspeccionable y que se puede volcar a JSON.
Como los contratos son explícitos, cada ladrillo se puede intercambiar sin necesidad de volver a cablear el resto. Las cuatro actualizaciones que construyeron este artículo son la prueba:
El artículo 5B (el modelo de datos relacionales) agregó toc_df al resultado del análisis. Los otros tres ladrillos no cambiaron; La recuperación recogió el nuevo DataFrame e ignoró el cambio. El artículo 6 (análisis de preguntas) agregó corrección de errores tipográficos y palabras clave de expertos al escrito. La firma del análisis de preguntas creció, la recuperación recibió palabras clave más ricas, nada más se movió. El artículo 7 (recuperación) agregó la coincidencia de TOC con la recuperación. La salida de recuperación mantuvo la misma forma, la generación leyó el mismo filtered_line_df. El artículo 8 (generación) añadió los cuatro indicadores de calidad al esquema de respuesta. El esquema de salida de Generation creció, la persona que llama decidió si leer los nuevos campos.
Cuatro actualizaciones, cuatro ladrillos, cero reescrituras cruzadas.
Esto se generaliza más allá de RAG. Una tarea compleja que se resiste a la composición suele ser aquella en la que los tipos intermedios están implícitos, se nombran de manera inconsistente o no son persistentes. Descomponerlo en ladrillos con contratos limpios y mecanografiados cuesta pensarlo desde el principio y se amortiza con cada actualización posterior. La tubería que usted enviaría es aquella en la que un colega puede reescribir un ladrillo sin romper los demás.
7. Conclusión
El mismo documento, la misma pregunta que el artículo 1 (DAR mínimo), cuatro ladrillos en su nivel de la Parte II. El contrato estructurado entre ladrillos hace que la canalización sea componible: marcos de datos fuera de análisis y recuperación, esquemas Pydantic fuera de discusión y generación. Un equipo puede adoptar las actualizaciones un bloque a la vez sin volver a cablear el resto, y un auditor puede reproducir cada paso desde el dictado de procedencia.
El artículo 10 (análisis adaptativo) continúa desde donde termina este. La canalización supone que el análisis creó un toc_df limpio; cuando el análisis falla (escaneos sin OCR, marcadores rotos, diseños que la heurística omite), la recuperación tiene que recurrir a señales solo del cuerpo. El siguiente artículo analiza el patrón de análisis barato primero y análisis más profundo bajo demanda.
8. Fuentes y lecturas adicionales
El artículo compone los cuatro bloques actualizados (de los artículos 5 a 8) de principio a fin en tres documentos: el documento Atención es todo lo que necesita, el Marco de ciberseguridad del NIST y el documento RAG original. El patrón respuestas.parse(text_format=Schema) en los límites de generación y análisis de preguntas utiliza los resultados estructurados de OpenAI (agosto de 2024). El artículo publicado más cercano a nivel de producción de este tipo de canalización es Contextual Retrieval de Anthropic (septiembre de 2024). La ruta de actualización agente sobre los mismos cuatro ladrillos es un trabajo de seguimiento; la procedencia por ladrillo mantiene las elecciones del agente auditables.
Al principio de la serie:
Qué funciona, qué se rompe
El Enterprise RAG mínimo que nunca miente sobre su fuente: PDF de entrada, respuesta resaltada de salida. El canal de cuatro ladrillos de un extremo a otro: PDF de entrada, respuesta resaltada de salida. Las incrustaciones no son mágicas: los modos de falla predecibles de la recuperación de RAG. Dónde gana la incorporación de similitud (sinónimos, errores tipográficos, paráfrasis), dónde predeciblemente se rompe (términos desconocidos, negación, relevancia de término versus respuesta) y cómo usarlo de todos modos. RAG no es aprendizaje automático y el conjunto de herramientas de ML resuelve el problema equivocado. Por qué los barridos y ajustes de tamaño de fragmentos optimizan lo incorrecto; en su lugar, ruta por tipo de pregunta. De expresiones regulares a modelos de visión: qué técnica RAG se adapta a qué problema. Dos ejes, complejidad documental y control de preguntas, que seleccionan la técnica para cada caso.
Análisis de documentos
Más allá de extract_text: las dos capas de un PDF que impulsan la calidad RAG. La primera mitad del bloque de análisis: la naturaleza del documento, las señales y el resumen. Deje de devolver texto plano desde un PDF: las tablas relacionales que RAG necesita. La segunda mitad del bloque de análisis: las tablas relacionales que lee cada bloque posterior. Cuando PyMuPDF no puede ver la tabla: analice archivos PDF para RAG con Azure Layout. Las mismas tablas de Azure Layout: celdas de tabla nativas, OCR, roles de párrafo. Analice archivos PDF para RAG localmente con Docling: tablas enriquecidas, sin carga en la nube. Las mismas tablas calculadas localmente con Docling: celdas de TableFormer, nada sale de la máquina. Los Vision LLM también son analizadores de PDF: leen cuadros y diagramas para RAG. Visión como analizador: las imágenes se convierten en texto buscable. Analice archivos PDF escaneados para RAG con EasyOCR: el OCR gratuito le proporciona palabras, no un documento. Donde termina el OCR tradicional: texto recuperado, estructura perdida. Hacer que las imágenes de un PDF puedan buscarse en RAG, sin pagar para leerlas todas. La cascada de imágenes: filtrar barato, clasificar, describir sólo lo que vale la pena leer. Reconstruir la tabla de contenido que un PDF olvidó enviar, para que RAG pueda analizarlo por sección. Reconstruir toc_df cuando el PDF imprime una página de contenido pero no incluye ningún esquema.
análisis de preguntas
Las preguntas de RAG también deben analizarse: convierta la cadena del usuario en resúmenes para su recuperación y generación. La tesis del análisis de preguntas: por qué una cadena de usuario necesita el mismo análisis que un documento y cómo se divide en un resumen de recuperación y un resumen de generación. Lo que el analizador de preguntas extrae de una cadena de usuario: palabras clave, alcance, forma, descomposición, aclaración. Las cinco familias de columnas que el analizador lee directamente de la pregunta del usuario, con el código que completa cada una. Envío de la pregunta RAG analizada: estrategia de fragmentos, nivel de modelo, activaciones, auditoría. Las decisiones que toma el analizador sobre la cadena de usuario, utilizando el perfil del documento: envío, activaciones, esquema completo, seguimiento de auditoría (pipeline_trace.json) y un recorrido por el corpus del corredor.
Recuperación
Generación
Haga que la generación RAG devuelva un contrato mecanografiado: citas, valores mecanografiados y autoverificaciones (enlace por venir). El esquema de respuesta como contrato: valores escritos, elementos con tramos de evidencia, campos de autoevaluación y la señal de integridad que el propio proceso calcula. Reúna cada mensaje de generación de RAG a partir de un mensaje básico más las reglas que necesita cada pregunta. El despachador: un mensaje BASE fijo más las reglas que necesita cada pregunta, el esquema seleccionado del registro y el seguimiento completo de cada llamada. Validar la respuesta de RAG antes de que el usuario la vea: intervalos, citas y ciclo de retroalimentación (enlace por venir). El validador de posgeneración (intervalos, citas textuales, formatos), no encontrado como respuesta de primera clase y los bucles de retroalimentación que cierran el proceso.
Canalizaciones de un solo documento
Un canal de producción RAG para archivos PDF: análisis relacional, recuperación de TOC, respuestas escritas (enlace por venir). Cada uno de los cuatro ladrillos actualizó un contrato a la vez: análisis relacional, preguntas basadas en corpus, recuperación enrutada por TOC, respuestas escritas.
Misma dirección que el artículo:
Recuperación antrópica y contextual (puesto de ingeniería de septiembre de 2024). El artículo de actualización “mínimo pero de grado de producción” publicado más cercano; aterriza en recuperación híbrida + reclasificación, complementa la actualización de ladrillos con reconocimiento de TOC en este artículo. OpenAI, resultados estructurados. El patrón respuestas.parse(text_format=Schema) utilizado en los límites de generación y análisis de preguntas. Vaswani et al., Todo lo que necesita es atención, NeurIPS 2017 (arXiv:1706.03762). El periódico en el que ejecutamos el oleoducto; primer caso de prueba en la sección 1.1. Licencia de distribución no exclusiva de arXiv, declarada en la página de resumen de arXiv. NIST, The NIST Cybersecurity Framework (CSF) 2.0, NIST CSWP 29, febrero de 2024 (DOI 10.6028/NIST.CSWP.29). El documento de cumplimiento utilizado en la sección 2. Trabajo del gobierno de EE. UU., dominio público en EE. UU., consulte la declaración de derechos de autor del NIST. Lewis et al., Generación aumentada de recuperación para tareas de PNL con uso intensivo de conocimiento, NeurIPS 2020 (arXiv:2005.11401). El documento RAG en sí, la tercera prueba en la sección 3. Licencia de distribución no exclusiva de arXiv, declarada en la página de resumen de arXiv. Banco Mundial, Commodity Markets Outlook, edición de abril de 2024. La prueba de estrés de TOC degenerado (títulos de marcadores en blanco) en la sección 4. CC BY 3.0 IGO, como se declara en la página de publicación de OKR de abril de 2024.
Las rutas de código ejecutables llaman a los servicios de OpenAI que se rigen por los Términos de uso de OpenAI.
Ángulo diferente, contexto diferente:
Yao et al., ReAct: Sinergia del razonamiento y la actuación en modelos lingüísticos, ICLR 2023 (arXiv:2210.03629). Papel fundacional de Agentic RAG. El contexto es la selección de herramientas de uso general en tiempo de ejecución. Desarrollar esta línea, donde los cuatro ladrillos mejorados se convierten en el conjunto de herramientas auditado del agente, es un trabajo de seguimiento. Lee et al., ¿Pueden los modelos de lenguaje de contexto largo incluir la recuperación, RAG, SQL y más?, 2024 (arXiv:2406.13121). La ruta de actualización de RAG que reemplaza el contexto largo: omitir el análisis, omitir la recuperación, volcar todo el documento. Datos empíricos sobre dónde funciona esto y dónde falla.