Analice archivos PDF para RAG localmente con Docling: tablas enriquecidas, sin carga en la nube

compañero de Enterprise Document Intelligence, la serie que construye un sistema RAG empresarial a partir de cuatro ladrillos. El artículo 5 (análisis de documentos) construyó el analizador con PyMuPDF (fitz). Este compañero mantiene el mismo objetivo y las mismas tablas relacionales, y cambia el motor por Docling, un paquete más completo que recupera las celdas de la tabla, el OCR y los subtítulos que Fitz pierde, y se ejecuta completamente en su propia máquina. Por qué es importante esa última parte es por donde comenzamos.

donde se encuentra este compañero: extiende el Artículo 5 (análisis de documentos), dentro de la Parte II (los cuatro ladrillos), con un motor de análisis diferente – Imagen del autor

El analizador más completo que puedes comprar lee la tabla, el escaneo y el texto atrapado dentro de una figura. También necesita que el documento se entregue a la nube de otra persona.

Para muchos trabajos empresariales, eso no es un comienzo. El contrato de seguro en su escritorio, el historial médico, la sala de datos de fusiones y adquisiciones, el contrato de trabajo firmado. Legal no permitirá que esos bytes salgan del edificio, y mucho menos cruzar una frontera hacia la nube de otra persona. El analizador más rico del mundo es inútil si el cumplimiento bloquea la carga.

Docling es la otra mitad de la respuesta. Es el analizador de documentos de código abierto de IBM Research (licencia MIT, declarada en el archivo LICENCIA del proyecto en GitHub): detección de diseño, OCR, orden de lectura y TableFormer (el modelo de aprendizaje profundo de IBM que detecta la estructura de la tabla (filas, columnas, encabezados) sin expresiones regulares). Todo ello como una instalación de pip. Se ejecuta en su propia máquina. La primera llamada descarga los modelos a un caché local; cada llamada posterior está fuera de línea. Sin clave API, sin cargo por página, el documento nunca sale del host.

Y el resultado son las mismas tablas relacionales que fitz y Azure. Al oleoducto aguas abajo no le importa qué motor produjo el dictado. Recuperación, generación, anotación de filas leídas. Nunca leen el PDF.

Las mismas tablas, Docling enriquece la mitad de ellas, todo en tu propia máquina – Imagen del autor

1. La nube es la limitación, no la capacidad

El artículo 5 bis abogaba por un análisis más completo. Tablas que mantienen sus columnas. OCR en páginas escaneadas. Texto recuperado del interior de figuras. Encabezados incluso cuando el PDF no tiene marcadores. Nada de ese argumento cambia aquí. Lo que cambia es donde ocurre el cálculo.

Azure DI es un servicio en la nube administrado. Le envías bytes, te devuelve la estructura. Para un artículo público de arXiv, eso está bien. Para los documentos que llenan un archivo empresarial real, a menudo no lo es:

Confidencialidad: Pólizas de seguros, registros médicos, contratos bajo NDA, cualquier cosa con datos personales. Enviarlos a una API de terceros es un evento de procesamiento de datos que el departamento legal debe aprobar y, con frecuencia, no lo hace. Residencia: "Los datos permanecen en esta región" es un término contractual en muchas industrias. Un analizador de nubes en la región equivocada lo rompe. Entornos con espacios aislados: algunas redes no tienen ninguna conexión a Internet saliente. Una llamada a la nube allí no es lenta, es imposible. Costo a escala: unos pocos centavos por página no son nada por mil páginas y una línea de pedido real por diez millones.

la capacidad es la misma; la diferencia es si el documento cruza el límite hacia una nube facturada o permanece en el host – Imagen del autor

Docling responde a las cuatro de la misma manera: el modelo se ejecuta donde ya está el documento. La compensación pasa del dinero y la confianza a la informática y la configuración. Paga en segundos de CPU y una descarga única del modelo en lugar de tarifas por página y una revisión de cumplimiento. Para un corpus confidencial, ese es el negocio que desea.

El resto de este artículo tiene la misma forma que el artículo 5 bis, porque el contrato es el mismo. Cuando Docling difiere de Azure en los detalles, la diferencia se destaca.

2. Mismo contrato, ejecutado localmente

Una llamada, las mismas tablas que el analizador Fitz, en la misma forma, todo desde una conversión Docling local. La llamada al SDK de Docling en sí es breve: cree un DocumentConverter, entréguele una ruta y vuelva a leer un DoclingDocument. La primera llamada descarga el diseño y los pesos de TableFormer a un caché local; cada llamada posterior está fuera de línea.

from docling.document_converter import DocumentConverter convertidor = DocumentConverter() # perezoso: no carga ningún modelo todavía resultado = convertidor.convert("data/paper/1706.03762v7.pdf") doc = result.document # un DoclingDocument # qué expone un DoclingDocument doc.export_to_markdown() # documento completo como markdown doc.tables # lista TableItem (cada uno lleva .data.table_cells) doc.pictures # Lista de elementos de imagen (bbox + ocr / clasificación opcional) doc.texts # Lista de elementos de texto, título etiquetado / encabezado de sección / párrafo / fórmula / título

Ese DoclingDocument es lo que lee cada constructor en este artículo. parse_pdf_docling envuelve la llamada anterior y convierte el documento en el mismo dictado de tablas que devuelven todos los demás motores, por lo que los bloques posteriores leen la salida sin saber qué motor se ejecutó. Así es como se llama al contenedor.

out = parse_pdf_docling("data/contracts/MyContract.pdf") out["line_df"] # elementos de texto + celdas de tabla + casillas de verificación out["page_df"] # una fila por página out["image_df"] # imágenes, ocr_text + clasificación out["toc_df"] # reconstruido a partir de etiquetas de diseño out["object_registry"] # subtítulos detectados por etiqueta out["cross_ref_df"] # menciones en el cuerpo del texto (regex) out["span_df"] # vacío (sin tipografía de sublínea) out["parsing_summary"] # dictado de síntesis a nivel de documento

parse_pdf_docling es el gemelo local de parse_pdf: la misma forma de llamada, el mismo dictado de tablas, por lo que cada bloque posterior lo lee sin saber qué motor está funcionando. Vale la pena ver el cuerpo, porque muestra la forma que sigue cada motor de la serie: convierta una vez, luego un pequeño constructor por tabla y reutilice los constructores independientes del motor para las tablas que solo necesitan line_df.

def parse_pdf_docling(pdf_path): doc = convert_pdf(pdf_path) # una conversión de Docling, línea compartida_df = docling_pdf_to_line_df(pdf_path, doc=doc) # texto + celdas de tabla image_df = build_image_df_docling(doc) # imágenes + ocr_text toc_df = build_toc_df_docling(doc) # título / encabezado de sección object_registry = build_object_registry_docling(doc) # etiquetas de título page_df = build_page_df(line_df) # constructor fitz reutilizado (solo line_df) cross_ref_df = build_cross_ref_df(line_df) # constructor fitz reutilizado (solo line_df) return {"line_df": line_df, "image_df": image_df, "toc_df": toc_df, "object_registry": object_registry, "page_df": page_df, "cross_ref_df": cross_ref_df, "span_df": pd.DataFrame(), "parsing_summary": parsing_summary}

Leyendo de arriba a abajo: un convert_pdf ejecuta los modelos una vez, luego hay un pequeño constructor por tabla (cada uno lee ese documento compartido), y las dos tablas que solo necesitan line_df, page_df y cross_ref_df, son producidas por los mismos constructores fitz que usa el analizador nativo. El dictado al final es el contrato que devuelve cada motor.

Las mismas tablas reflejan parse_pdf, con las formas reales de una ejecución de Docling en el documento Atención de 15 páginas – Imagen del autor

Lo que ejecuta esa conversión. Es tentador archivar Docling bajo “OCR”. No es OCR; OCR es una etapa opcional dentro de él. Un convert() ejecuta primero un modelo de diseño (encuentra las regiones, la tabla, la figura, el encabezado, el cuerpo y su orden de lectura), luego TableFormer en cada tabla detectada (la cuadrícula de filas, columnas y encabezados) y solo entonces, si la página es un escaneo sin capa de texto, un motor de OCR para leer los píxeles. En un PDF nacido digital, la etapa de OCR se omite por completo: el texto de la celda proviene de la capa de texto nativo. Entonces, la rebaja de una tabla es la estructura de TableFormer llena de texto de celda que, en un PDF nativo, ningún OCR jamás tocó. El motor de OCR que elija (EasyOCR, PaddleOCR, Tesseract, RapidOCR) solo cambia lo que sucede en los píxeles escaneados, y el control de calidad de las tablas en sí es el modo de TableFormer (rápido versus preciso), no el backend de OCR.

Docling es una canalización, no un contenedor de OCR: el diseño y TableFormer hacen la estructura; OCR solo lee píxeles escaneados – Imagen del autor

3. Qué gana cada mesa

Para mostrar esto en algo que pueda verificar, ejecutamos Docling en el artículo Attention Is All You Need (Vaswani et al. 2017; licencia de distribución no exclusiva de arXiv, declarada en la página de resumen de arXiv), el mismo PDF público de arXiv utilizado en toda la serie. Quince páginas, nacidas en formato digital, sin marcadores nativos, cuatro tablas reales, seis cifras, cinco ecuaciones en pantalla. Un documento donde a Fitz ya le va bien la prosa pero pierde las tablas y la estructura de las secciones. Introduzca su propio PDF y se ejecutarán los mismos constructores; los números a continuación son los que Docling arrojó en este caso.

3.1. line_df gana filas de celdas de tabla, texto de figura y casillas de verificación

El modelo TableFormer de Docling detecta cada tabla como una cuadrícula de celdas con índices de filas y columnas y banderas de encabezado. Aplanamos esa cuadrícula en filas de rebajas para que la tabla viva dentro de line_df como cualquier otro contenido, una línea por fila de la tabla, con un | — | separador después del encabezado. La tabla 1 del artículo (una comparación de complejidad de 5 filas y 4 columnas) presenta seis filas line_df: cinco filas de datos más | — | separador que sigue al encabezado.

El aplanamiento en sí es breve y vale la pena verlo porque es el truco completo: diseñe una cuadrícula de filas x columnas vacía, coloque cada celda de TableFormer en su ranura (fila, columna) y luego una cada fila en una línea de rebajas.

def table_to_markdown_rows(table): n_rows, n_cols = table.data.num_rows, table.data.num_cols grid = [[""] * n_cols for _ in range(n_rows)] header = set() for cell in table.data.table_cells: # las celdas que TableFormer encontró en la fila, col = cell.start_row_offset_idx, cell.start_col_offset_idx grid[row][col] = cell.text.strip() if cell.column_header: header.add(row) h = min(header) if header else 0 rows = ["| " + " | ".join(grid[h]) + " |", # fila de encabezado "| " + " | ".join(["—"] * n_cols) + " |"] # filas separadoras += ["| " + " | ".join(cuadrícula[r]) + " |" # filas de datos para r en el rango (n_rows) si r! = h] filas de retorno # una línea de rebajas por fila de origen -> una fila line_df cada una

Cada fila de origen se convierte en una fila line_df; la estructura de la columna se lleva dentro del texto de rebajas. Estas son las filas reales que Docling produjo para la Tabla 1 – Imagen del autor

Mantenemos las celdas dentro de line_df en lugar de agregar una tabla de celdas separada. Un DataFrame para que lo lea cada bloque posterior; Las líneas de párrafo y las filas de la tabla tienen el mismo aspecto al final. El costo: las consultas por celda necesitan un paso de análisis de rebajas. Para preguntas de RAG, esto está bien. El recuperador busca palabras clave en el texto de la fila. El modelo lee la rebaja directamente. Esta es la misma elección de diseño que hace el constructor de Azure, por lo que un fragmentador posterior trata las filas de las tablas Fitz, Azure y Docling de manera idéntica.

Dos fuentes más alimentan line_df. El texto que Docling encuentra dentro de una región de figura aparece como filas de texto ordinarias (recuperadas mediante diseño + OCR), por lo que se puede buscar una etiqueta representada dentro de un diagrama. Y los elementos de las casillas de verificación se convierten en líneas de un solo carácter, [x] para los seleccionados y [ ] para los no seleccionados, por lo que un campo de formulario con casillas de verificación se vuelve consultable. En el documento Atención, el número de líneas aumenta desde la prosa cruda a 560 filas una vez que se aplanan las cuatro tablas.

3.2. image_df gana ocr_text y una columna de clasificación

Misma fila, dos columnas nuevas. Para cada imagen detectada, recopilamos todos los elementos de texto cuyo bbox se encuentra dentro de la región de la figura en al menos un 50 % y los unimos como ocr_text. El diagrama de arquitectura de la página 3 y los dos diagramas de atención de la página 4 llevan sus etiquetas dentro de la figura; esas etiquetas aparecen en ocr_text y se vuelven recuperables.

Figuras del periódico Atención con sus etiquetas interiores expuestas – Imagen del autor

La segunda columna nueva es la clasificación. Docling incluye un clasificador de imágenes opcional que etiqueta cada figura (tipo de gráfico, logotipo, etc.). Cuando el clasificador está habilitado, la etiqueta llega a clasificación; cuando no es así, la columna está ahí para la paridad de formas pero permanece en blanco. Azure no tiene equivalente, por lo que este es un lugar donde Docling va más allá. La misma columna en un image_df producido por Fitz no existe en absoluto; fitz devuelve ancho_px/alto_px/image_hash y nunca realiza OCR de la imagen.

3.3. toc_df se reconstruye a partir de etiquetas de diseño

El documento de Atención no tiene marcadores nativos. Ejecute build_toc_df de fitz y obtendrá una tabla vacía, que es el caso empresarial común: exportaciones de Word, escaneos, cualquier cosa que no esté escrita en LaTeX con configuración de hiperreferencia. La generación pierde entonces la estructura de secciones.

Docling etiqueta cada encabezado directamente:

un elemento de título para el título del documento cuando detecta uno un elemento de encabezado de sección para cada encabezado de sección (en este documento Docling etiquetó incluso el título como encabezado de sección)

El constructor recorre ambas etiquetas, asigna un nivel y ensambla un TOC con las mismas columnas start_page, end_page, start_y y ruta de navegación que la ruta fitz. El pase retrospectivo que calcula end_page es idéntico al de Fitz y Azure; sólo difiere la fuente de las filas.

En el papel Atención recupera 28 encabezados donde fitz recupera cero. Ese número no está inflado: Docling etiquetó cada encabezado de sección una vez, incluidas las subsecciones de Método y Resultados, lo cual es correcto para este documento. En un documento con secciones más cortas y densas, el recuento sería menor.

28 títulos recuperados de etiquetas de diseño en un PDF sin marcadores nativos – Imagen del autor

La profundidad de la jerarquía depende del documento. Cuando el modelo de diseño de Docling asigna distintos niveles de encabezado, se obtiene un auténtico árbol de varios niveles; en este documento etiquetó los títulos en un solo nivel, por lo que el TOC reconstruido es en su mayor parte plano. De cualquier manera, es un índice de sección utilizable donde Fitz no daría nada. Azure hace el mismo truco con sus propias etiquetas de rol; los dos están parejos, con Docling ejecutándose localmente.

3.4. object_registry obtiene detección de etiqueta de título

Fitz detecta subtítulos mediante expresiones regulares ancladas al inicio de una línea, ^Figura d+b, ^Table d+b. Omite la Fig. 2 y los ajustes de varias líneas, y genera falsos positivos en una oración del cuerpo que comienza con "La Figura 2 muestra …".

Colocar etiquetas en bloques de títulos con una etiqueta de título durante el análisis de diseño. Leemos la etiqueta directamente, no se necesitan expresiones regulares para encontrar el título. La clave de unión (object_type, object_id) en cross_ref_df todavía se extrae del texto del título mediante la misma expresión regular que usan los constructores de Fitz y Azure, por lo que la unión funciona igual con cualquier motor. En el documento de Atención, esto coloca los nueve títulos (Figura 1 a 5, Tabla 1 a 4) en object_registry. La victoria es la recuperación: Docling capta los subtítulos que la expresión regular de inicio de línea de Fitz pasaría por alto.

3.5. parsing_summary obtiene estadísticas específicas de Docling

Tres cargos aterrizan en el dictado de síntesis a nivel de documento:

n_tables_detected: cuántas tablas encontró TableFormer (4 en el documento de atención). n_pictures: cuántas figuras identificó el modelo de diseño (6). n_formulas: cuántas ecuaciones se muestran en Docling etiquetadas como fórmula (5).

Estos facilitan el enrutamiento. Un documento con n_tables_detected = 18 parece un contrato donde la estructura de la tabla importa. Un documento con n_formulas en docenas es un documento con muchas matemáticas en el que es posible que desee un paso posterior que tenga en cuenta las fórmulas. Un documento con n_pictures = 0 es sólo de texto; No tiene sentido escanear figuras en busca de texto interno.

3.6. page_df y cross_ref_df: sin cambios

Dos mesas mantienen la misma forma. page_df y cross_ref_df se crean solo a partir de line_df, por lo que el motor que produjo line_df es irrelevante. Una implementación, tres motores, sin deriva.

span_df está vacío en Docling, exactamente como en Azure. El modelo de diseño no expone la tipografía de sublínea (negrita o cursiva por palabra). Cuando necesite intervalos para la detección de encabezados o el énfasis de términos, permanezca en fitz para ese documento. Los motores se complementan.

4. La columna parsing_method: procedencia del análisis adaptativo

Cada tabla por fila de parse_pdf_docling lleva parsing_method == "docling". Cada tabla por fila de parse_pdf lleva "fitz"; de parse_pdf_azure_layout, "azure_layout". Misma columna, mismo nombre, todos los motores. El punto está aguas abajo.

Contrato analizado con fitz, la página de la tabla analizada nuevamente con Docling; ambos motores coexisten en line_df a través de la columna parsing_method – Imagen del autor

Esto es lo que consume el análisis adaptativo (Artículo 10). El pase predeterminado usa fitz. Las páginas que no pasan una verificación previa al análisis (una región de tabla sin filas extraídas, una página con muchas imágenes y texto escaso, una capa de OCR con baja calidad) se vuelven a analizar con un motor más pesado. Con Docling, ese nuevo análisis es local, por lo que permanece disponible incluso cuando el documento no puede ir a la nube. Las filas analizadas nuevamente reemplazan o se agregan a las filas line_df originales, y la columna parsing_method mantiene el rastro.

La columna permite tres patrones posteriores:

Deduplicación: cuando la misma página obtuvo dos pases, mantenga las filas del motor más pesado sobre las de Fitz a través de un mapa de precedencia explícito. Auditoría: una fila con parsing_method == "docling" le indica que un modelo, no una extracción de texto sin formato, lo produjo; la ponderación de confianza de la respuesta puede usar eso. Contabilidad de enrutamiento: qué páginas necesitaban el camino pesado y cuánto tiempo tardaron.

5. Costo, latencia y configuración

Docling es libre de ejecutar, pero no libre de operar. Tres cosas importan.

Latencia: en la CPU, una página a través del proceso completo de Docling (diseño + TableFormer + OCR) tarda aproximadamente de 1 a 5 segundos, dependiendo de qué tan ocupada esté la página. El documento de atención de 15 páginas, con OCR activado, se analizó en menos de un par de minutos en la CPU de una computadora portátil. Una GPU reduce esto drásticamente. Fitz analiza el mismo documento en menos de un segundo. Entonces, la regla de enrutamiento es la misma que para Azure: analizar primero con fitz, escalar a Docling solo en las páginas que fitz manejó mal. La diferencia con Azure es que la escalada cuesta tiempo de CPU, no dinero ni un viaje de ida y vuelta por la red.

Configuración: la primera conversión descarga el diseño y los modelos de TableFormer (cientos de MB) a un caché local, y la instalación del documento extrae PyTorch, que es grande. Presupuesto para el disco y la descarga única. Después de eso, estará fuera de línea. En un entorno aislado, usted prepara previamente el caché del modelo; no hay llamada a casa en tiempo de ejecución.

Calcular, no tarifas por página: no hay ningún cargo por página. El costo es la máquina en la que lo ejecutas. Para diez millones de páginas al año de datos confidenciales, poseer la computadora suele ser más barato que una factura en la nube por página, y es la única opción cuando los datos no pueden salir en absoluto.

Estos números se mueven con las versiones de hardware y Docling. La forma es lo que importa: fitz es casi gratuito e instantáneo, Docling cuesta segundos de computación local y una configuración única, Azure cuesta centavos por página y un salto de red a una nube en la que debe confiar.

6. Cuándo llamar a cuál

Por defecto es fitz. Intensifique cuando una señal específica indique que Fitz no es suficiente y elija el motor pesado según el lugar donde se permite que vaya el documento.

fitz: cada análisis, por defecto. Archivos PDF digitales con texto seleccionable y diseño simple. Gratis, instantáneo, sin conexión. Docling: cuando Fitz falla (tablas, escaneos, texto de figuras, sin marcadores) y el documento es confidencial o el entorno está aislado. Local, libre de ejecutar, nada sale de la máquina. También es el valor predeterminado correcto cuando prefiere tener computación en lugar de pagar por página. Azure DI: cuando falla fitz y enviar el documento a una nube es aceptable y prefiere tener un servicio administrado que ejecutar modelos usted mismo. Costo por página, cero infraestructura que mantener, conexión más rápida.

Las señales que desencadenan la escalada son las mismas que enumera el Artículo 5 bis: una región de tabla detectada sin una estructura similar a una fila, una página con muchas imágenes y texto escaso, una puntuación de calidad de OCR baja o un documento sin TOC nativo donde la generación necesita contexto de sección. El artículo 10 construye el despachador que lee esas señales. La columna parsing_method es lo que permite que cada etapa posterior sepa qué motor se ejecutó en qué fila.

7. Conclusión

Las mismas tablas relacionales, sea cual sea el motor que las llene. Las disputas sobre capacidad son casi un empate entre Azure y Docling; las filas que deciden están operativas. Azure envía el documento a una nube y factura por página. Docling mantiene el documento en la máquina y no factura nada más que cálculos. Fitz no hace ninguna de las dos cosas y no cuesta nada.

Todas las capacidades que son importantes para RAG empresarial, además de dónde se ejecuta el cálculo, la velocidad y el costo: imagen del autor

8. Fuentes y lecturas adicionales

La documentación está documentada en el informe técnico de IBM Research (Auer et al. 2024), que describe el canal de diseño, el modelo de detección de celdas de TableFormer y el paso del orden de lectura. La extracción de tablas a nivel de celda que hereda Docling tiene su propio linaje de investigación (Smock et al. 2022, PubTables-1M / Table Transformer). La lectura cruzada correcta para este artículo es el Artículo 5bis (Azure DI), que ofrece la misma tabla de contrato de un servicio de nube pago: misma capacidad, diferente perfil operativo.

Misma dirección que el artículo:

Auer et al., Informe técnico Docling, IBM Research 2024 (arXiv:2408.09869). Arquitectura de referencia para la canalización de diseño local que utiliza este artículo: detección de diseño, TableFormer, orden de lectura, representación de documentos unificada. Smock, Pesala, Abraham, PubTables-1M / Table Transformer (TATR), CVPR 2022 (arXiv:2110.00061). El linaje de investigación detrás de la extracción de tablas a nivel de celda, Docling y Azure, se envían.

Ángulo diferente, contexto diferente:

Microsoft, inteligencia de documentos Azure AI. Modelo de diseño. Equivalente en nube de pago de la misma cascada (artículo 5bis). Contrato de la misma mesa; intercambia computación local por carga en la nube y costo por página. La elección correcta cuando el equipo operativo prefiere un servicio administrado en lugar de un modelo de alojamiento local.

La pregunta rara vez es "qué analizador es mejor", sino "qué puede hacer este documento y qué necesita esta página". Una página nacida digital con prosa limpia: fitz. Una página de tabla en un informe público: Azure si lo desea administrado, Docling si lo desea local. El artículo 10 cablea al despachador que realiza la llamada por página.

Al principio de la serie:

Document Intelligence: introducción a la serie. Qué construye la serie, ladrillo a ladrillo y en qué orden. 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. 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: la forma relacional que RAG necesita (enlace por venir). 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 (enlace por venir). Las mismas tablas de Azure Layout: celdas de tabla nativas, OCR, roles de párrafo.