Ladrillo de análisis de preguntas de Enterprise Document Intelligence, una serie que construye un sistema RAG empresarial a partir de cuatro bloques: análisis, análisis de preguntas, recuperación y generación.
El análisis de preguntas es el segundo ladrillo. Esta es la primera de sus tres partes:
por qué existe, qué produce y la escisión que motiva al resto. La siguiente parte cubre lo que el analizador extrae de una cadena de usuario (Artículo 6 B, extracción) y cómo se envía la fila analizada para su recuperación y generación (Artículo 6 C, envío).
El artículo 1 (RAG mínimo) mostró el patrón básico: tomar la pregunta del usuario, enviarla a un LLM y obtener una respuesta.
La serie fue un paso más allá con ingeniería rápida, pidiendo al LLM que devolviera un objeto JSON con la respuesta más los pasajes fuente que utilizó. Con un documento bien analizado y un resultado estructurado, encontrar de dónde viene la respuesta ya no es la parte difícil.
Ese es el punto de partida. Lo que queda es la pregunta misma, y ahí es donde termina viviendo la mayor parte del trabajo en un oleoducto RAG real. En los proyectos empresariales aparecen tres niveles de “trabajar la cuestión”, y tienden a aparecer en este orden.
1. Preguntas naturales de los usuarios. Un usuario escribe lo que se le viene a la mente: "¿Cuál es el límite de responsabilidad?", "Cuénteme sobre las exclusiones", "¿Cómo se compara esto con la póliza del año pasado?" El sistema tiene que dar sentido a una cadena que no creó, en un vocabulario que no es necesariamente el del documento. Este es el caso que muestran la mayoría de las demostraciones y el que tiene la mayor variación en el lado de la entrada.
2. Plantillas que el desarrollador escribe con anticipación. Muy rápidamente, el equipo se da cuenta de que las mismas preguntas vuelven una y otra vez. Para cada contrato alguien quiere saber quién es el cliente, quién es el asegurador, la prima anual, las garantías, las exclusiones, la fecha de renovación. En lugar de esperar a que los usuarios los escriban uno por uno, el desarrollador los escribe una vez, junto con el equipo empresarial propietario de los documentos, y los ejecuta en todo el corpus. El resultado es un registro JSON por documento. En la práctica, esto es lo que la mayoría de las empresas construyen primero; El chat de forma libre tiende a aparecer más tarde, además de esta base.
3. Ayudar a los usuarios a formular. Un patrón que aparece una vez que un sistema está frente a usuarios reales: los equipos de negocios saben lo que buscan, pero tienen problemas para expresarlo de manera estricta. “¿Cuál es el límite?” deja mucho abierto. El sistema puede intervenir y preguntar: "¿te refieres a responsabilidad, indemnización, deducible o prima?" La misma maquinaria que los otros dos niveles (un objeto escrito con campos con nombre), pero ahora los campos vacíos generan un pequeño diálogo con el usuario.
Los tres niveles comparten la misma maquinaria: convertir la pregunta en un objeto estructurado, luego encaminar las partes hacia la recuperación y la generación. Lo que cambia es quién llena la estructura (el usuario, el desarrollador o ambos en el diálogo) y qué hace el sistema cuando un campo está vacío (continuar con los valores predeterminados, fallar en voz alta o volver a preguntar).
Un usuario escribe una cadena en el cuadro de chat. "¿Cuál es el monto máximo de cobertura? No lo confunda con el deducible, a menudo aparecen juntos".
Hay mucho en esa cadena. Un tema (monto máximo de cobertura). Una forma esperada (una cantidad, un número). Una señal negativa (no confundir con deducible). Una pista sobre cómo el documento presenta la respuesta (a menudo enumeradas juntas). Si entrega toda la cadena para su recuperación, ninguna de esas partes aterriza donde debería: la incrustación acerca las líneas deducibles, la sugerencia de formato nunca llega a la generación, la desambiguación se incrusta con el resto o se elimina en el preprocesamiento. El resultado es una respuesta incorrecta segura (el número del deducible, no el de la cobertura) y un recuperador que ningún panel de observabilidad puede depurar.
La solución es analizar la pregunta primero. Convierta la ruidosa cadena de usuario en un resumen estructurado y escrito sobre el que puedan actuar los ladrillos posteriores. Luego divida el informe en dos: el bloque de recuperación lee sobre qué puede actuar (tema, reescrituras, alcance), el bloque de generación lee sobre qué puede actuar (la redacción original, la restricción de formato, la desambiguación). Ninguno de los ladrillos se confunde con la señal del otro. Ambos se mantienen centrados en lo que mejor saben hacer.
1. El análisis de preguntas refleja el análisis de documentos
1.1 Mismo enfoque: un conjunto relacional de tablas
El análisis de documentos produce un conjunto relacional: line_df con una fila por línea de texto, page_df con una fila por página, toc_df con una fila por entrada TOC, además de algunos satélites.
El análisis de preguntas tiene el mismo objetivo: convertir la entrada no estructurada en un formato estructurado antes de que se ejecuten los siguientes pasos. El artefacto es el mismo tipo de cosa: un conjunto relacional.
La forma diverge de una manera obvia. Un documento llena line_df con cientos o miles de filas. Una pregunta es una sola cadena, por lo que llena una fila en una tabla question_df. Las columnas de esa fila son lo que calcula el analizador: el texto con corrección ortográfica, las palabras clave extraídas, el tipo de respuesta esperada, las páginas o secciones que mencionó el usuario, el patrón de descomposición, las activaciones que debe activar el despachador. Agregar una capacidad de análisis es agregar una columna.
La otra mitad de la imagen relacional son las tablas satélite a las que se vincula la fila de preguntas. Son tan abiertos como las columnas mismas: un proyecto comienza con las que necesita y agrega otras a medida que surgen nuevos casos.
El más común es el diccionario experto de palabras clave del proyecto, dividido en dos: conceptos_df (una fila por concepto, con su definición) y concept_keywords_df (una fila por (concepto, idioma, palabra clave)). Juntos mantienen los sinónimos específicos del dominio: premium → prime, cotisation, tarif annuel; no competencia → pacto restrictivo; efectos secundarios → eventos adversos. Otro que veremos más adelante es answer_types_df, que registra los tipos de respuestas que las preguntas pueden esperar (cantidad, fecha, iban,…).
Los proyectos reales suelen crecer más:
a regulaciones_df que asignan códigos legales a sus textos para un RAG legal una entidad_alias_df para variantes de nombres de empresas en un corpus corporativo a unit_conversions_df en uno científico
Las columnas de la pregunta se vinculan a estos satélites de la misma manera que line_df se vincula a image_df en el análisis de documentos.
Este marco relacional es importante en la práctica. Una vez que las preguntas son filas en una tabla, puede utilizar SQL: "¿Cuántas preguntas de tipo cantidad hicieron los usuarios el mes pasado?", "¿Qué preguntas provocaron una solicitud de aclaración?", "¿Qué entradas del diccionario de expertos fueron consultadas con mayor frecuencia?". El historial de preguntas se convierte en datos de operaciones, no solo en un archivo de registro. Un capítulo de almacenamiento de seguimiento desarrolla el diseño que hace de question_df una tabla de primera clase.
Una nota sobre terminología. Los nombres habituales para esto son "comprensión de consultas" y "comprensión de preguntas". Ambos son vagos: sugieren que el sistema comprende la pregunta, lo que no dice mucho. Pregunta al analizar nombres qué sucede: toma una cadena, devuelve una fila relacional enriquecida.
1.2 Dónde encaja esto en pdf_qa
El artículo 1 (RAG mínimo) introdujo la llamada de nivel superior como una única función: resultado = pdf_qa(contrato_pdf, pregunta="¿Cuál es el importe máximo de cobertura?"). El usuario pasa una ruta PDF y una pregunta y obtiene una respuesta JSON estructurada. El nombre sigue la convención _: pdf es el formato, qa la intención. El volumen 2 abre ambos ejes (excel_qa, pdf_translate,…) con un despachador doc_qa; El Volumen 1 llama directamente al manejador.
En el interior, pdf_qa conecta los cuatro ladrillos en secuencia: parse_pdf → parse_question(question, doc_profile=…) → recuperar → generar, luego envuelve la respuesta con un bloque _meta auditoría. El complemento de extracción (Artículo 6_b) detalla qué columnas completa el analizador a partir de la cadena de usuario; el compañero de despacho (artículo 6_c) detalla cómo se encamina cada columna hasta el ladrillo que la consume.
El resto de este artículo cubre la tesis: por qué dividir la fila analizada en dos informes al consumidor es la decisión correcta, y el único caso específico que lo demuestra (señales negativas como “no es el deducible”).
2. Dos informes para el consumidor de una fila analizada
La fila de preguntas en question_df contiene todo lo que la canalización podría necesitar, pero la recuperación y la generación no necesitan el mismo subconjunto. El analizador emite dos vistas derivadas de la fila, cada una diseñada para la etapa que la consume: RetrievalQuery y GenerationBrief. ¿Por qué dividirlos y no simplemente entregarles la fila completa a ambos?
2.1 La división entre recuperación y generación
Porque los dos ladrillos de consumo tienen puntos fuertes muy diferentes:
La recuperación es coincidencia de similitudes: es buena para encontrar lo que está cerca de la consulta. Malo para rechazar precisamente. No puede decirle qué está relacionado con la consulta, pero no es igual a ella. Generar es leer y razonar: Bueno para distinguir, excluir, contrastar. Puede tener en mente ambos conceptos, compararlos y seleccionar uno. Es la única etapa del proceso que puede hacer esto.
Cada vista derivada contiene solo las columnas sobre las que su consumidor puede actuar. El resumen de recuperación obtiene el tema, reescribe el vocabulario del documento, las palabras clave ancla (códigos, ID) y los filtros de alcance que filtran previamente el espacio candidato. El resumen de generación obtiene la pregunta original (para que se conserve la intención del usuario), la restricción de formato, las pistas de desambiguación y cualquier distractor que el LLM no deba confundir con la respuesta real.
El error más común es enviar todo a ambos. El lado de la recuperación se confunde con “no confundir con deducible” (no tiene forma de actuar ante una negación); el lado de generación se confunde con las reescrituras (debe responder en los términos del usuario, no en los del documento). Las dos vistas derivadas mantienen cada etapa enfocada en lo que puede hacer.
2.2 Por qué las exclusiones pertenecen a la generación, no a la recuperación
Un reflejo natural, cuando un usuario dice "no incluir X", es filtrar X al recuperarlo. No. Casi siempre es un paso en falso.
Tomemos un ejemplo concreto. El usuario pregunta:
“¿Cuál es el límite por reclamo, no el deducible, en este contrato?”
El enfoque ingenuo es eliminar de la recuperación cualquier pasaje que mencione "deducible". Tres problemas, uno para cada nivel en el que podría intentar excluir:
Problema 1: exclusión a nivel de línea: suponga que excluye cualquier línea que contenga "deducible". Luego pierdes líneas como:
“El límite por siniestro es de 1.500.000€, con una franquicia de 1.000€”.
Esa línea es la respuesta. La exclusión simplemente lo eliminó. El límite y el deducible a menudo se indican uno al lado del otro precisamente porque están relacionados: esa es la razón por la que el usuario le advirtió sobre la confusión.
Problema 2: exclusión a nivel de página: aún peor. La página que contiene el límite también contiene el deducible (en la misma tabla, en la misma sección). Excluir la página descarta la respuesta por completo.
Problema 3: exclusión a nivel de sección: lo peor de todo. La sección “Límites y Deducibles” es, por su nombre, exactamente la sección que contiene la respuesta. Excluirlo elimina todo lo relevante.
Más allá de la granularidad, hay un problema mayor. Las incrustaciones no excluyen. Agregar "NO deducible" a la cadena de consulta no funciona. Las incrustaciones ignoran la negación, un modo de falla analizado con mediciones en el Artículo 2 (modos de falla de las incrustaciones). El vector de “límite por siniestro NO deducible” es casi idéntico al de “límite por siniestro deducible”. No has excluido nada. Acabas de agregar una palabra. El BM25 con consultas negativas también es frágil. Puede escribir query = "límite por reclamo" Y NO "deducible" en algunos motores de recuperación. Pero esto excluye cualquier pasaje donde aparezcan ambas palabras, incluidos los pasajes exactos que contienen la respuesta junto con su contraste.
La respuesta correcta es simple: recuperar ampliamente, excluir en la generación. La recuperación recupera cualquier pasaje donde se menciona "límite", "deducible" o "reclamo". El paso de generación los recibe todos, más la instrucción explícita “el usuario pregunta por el límite, no por el deducible”. Luego, el LLM lee los pasajes, identifica el límite, lee el deducible e informa solo lo que se solicitó.
El patrón se repite: detecta la señal de desambiguación en el analizador, enrútala al resumen de generación y deja que el LLM la aplique.
Una vez que esta división hace clic, la misma lógica se aplica a casi cualquier instrucción negativa: “…no de la versión anterior” → recuperar todas las versiones, filtrar en la generación. “…excepto las cláusulas opcionales” → recuperar todo, filtrar en la generación. “…sin el lenguaje de marketing” → recuperar todo, resumir limpiamente en generación.
La recuperación debe ser amplia. La generación debe ser selectiva.
3. ¿Qué viene después?
La pregunta está analizada. Los dos informes del consumidor están listos. Dos artículos de seguimiento cierran el ladrillo:
El artículo 6 B (extracción) recorre lo que el analizador extrae de una cadena de usuario. Palabras clave (con varias fuentes combinadas), forma y tipo de respuesta esperada, sugerencias de alcance, descomposición para preguntas compuestas y campo de aclaración para entradas vagas. Cada uno se convierte en una columna en question_df. El artículo 6 C (despacho) explica cómo se enruta la fila analizada. Las decisiones de envío (estrategia de fragmentos, modelo, contexto de respuesta) que toma el analizador además de lo que dijo el usuario, utilizando el perfil del documento. Los indicadores de activación que adaptan el pipeline al documento. Y el bloque _meta de auditoría que registra cada decisión para su reproducción.
Cada uno de esos dos artículos se basa en la tesis de éste: analizar primero, ruta por breve, nunca permitir que una señal de sólo una generación contamine la recuperación.
4. Fuentes y lecturas adicionales
La forma de dos breves que defiende este artículo es un refinamiento del análisis de preguntas de “estilo de llamada de función” en el que convergen la mayoría de los sistemas RAG de producción una vez que el chat de formato libre llega a sus primeros cien usuarios. La lectura cruzada correcta es el artículo original sobre el fracaso de la incrustación (donde la negación del lado de la recuperación se desmorona empíricamente) y los manuales de producción de RAG que convergieron de forma independiente en la misma respuesta: recuperación amplia, generación estricta.
Misma dirección que el artículo:
Ángulo diferente:
La mayoría de los tutoriales de RAG en un día tratan la pregunta como una caja negra que se pasa palabra por palabra al incrustador. La tesis aquí es la opuesta: la pregunta conlleva una estructura (tema, alcance, forma, desambiguación) que las etapas de recuperación y generación deben leer por separado. Adoptar esa visión es lo que hace que el ladrillo exista.
Al principio de la serie:
Parte I:
Baseline Enterprise RAG, desde PDF hasta respuesta resaltada. 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. Los rerankers tampoco son mágicos: cuando la capa de codificador cruzado vale la pena. Lo que agrega un codificador cruzado sobre las incorporaciones de codificador doble, medido y cuándo vale la pena la latencia. 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. 10 errores comunes de RAG que seguimos viendo en producción. Diez errores de producción, organizados ladrillo por ladrillo, con la solución para cada uno.
Parte II: