---
layout: default
title: "Decodificador Universal de Documentos"
parent: "Spanish (Beta)"
---
# Decodificador Universal de Documentos
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
## Título
Decodificador universal de documentos impulsado por `unstructured`: ingrese cualquier formato de documento común
a través de un servicio único con un registro completo de la procedencia y la integración de la biblioteca,
registrando las posiciones de origen como metadatos del gráfico de conocimiento para
la trazabilidad de extremo a extremo.
## Problema
Actualmente, TrustGraph tiene un decodificador específico para PDF. Para admitir formatos adicionales
(DOCX, XLSX, HTML, Markdown, texto plano, PPTX, etc.), es necesario
escribir un nuevo decodificador por formato o adoptar una biblioteca de extracción universal.
Cada formato tiene una estructura diferente; algunos son basados en páginas, otros no,
y la cadena de procedencia debe registrar de dónde se originó cada parte del texto extraído
en el documento original.
## Enfoque
### Biblioteca: `unstructured`
Utilice `unstructured.partition.auto.partition()`, que detecta automáticamente el formato
a partir del tipo MIME o la extensión del archivo y extrae elementos estructurados
(Título, TextoNarrativo, Tabla, ElementoLista, etc.). Cada elemento lleva
metadatos que incluyen:
`page_number` (para formatos basados en páginas como PDF, PPTX)
`element_id` (único para cada elemento)
`coordinates` (cuadro delimitador para PDF)
`text` (el contenido de texto extraído)
`category` (tipo de elemento: Título, TextoNarrativo, Tabla, etc.)
### Tipos de Elemento
`unstructured` extrae elementos tipados de los documentos. Cada elemento tiene
una categoría y metadatos asociados:
**Elementos de texto:**
`Title` — encabezados de sección
`NarrativeText` — párrafos del cuerpo
`ListItem` — elementos de lista con viñetas/numerados
`Header`, `Footer` — encabezados/pies de página
`FigureCaption` — leyendas para figuras/imágenes
`Formula` — expresiones matemáticas
`Address`, `EmailAddress` — información de contacto
`CodeSnippet` — bloques de código (de Markdown)
**Tablas:**
`Table` — datos tabulares estructurados. `unstructured` proporciona tanto
`element.text` (texto plano) como `element.metadata.text_as_html`
(HTML completo `
` con filas, columnas y encabezados conservados).
Para formatos con una estructura de tabla explícita (DOCX, XLSX, HTML),
la extracción es muy fiable. Para PDF, la detección de tablas depende de
la estrategia de `hi_res` con el análisis de diseño.
**Imágenes:**
`Image` — imágenes integradas detectadas mediante el análisis de diseño (requiere
la estrategia de `hi_res`). Con `extract_image_block_to_payload=True`,
devuelve los datos de la imagen como base64 en `element.metadata.image_base64`.
El texto OCR de la imagen está disponible en `element.text`.
### Manejo de Tablas
Las tablas son una salida de primera clase. Cuando el decodificador encuentra un elemento `Table`,
conserva la estructura HTML en lugar de aplanarla a texto plano. Esto proporciona
a la biblioteca de extracción LLM descendente una mejor entrada para extraer conocimiento
estructurado de los datos tabulares.
El texto de la página/sección se ensambla de la siguiente manera:
Elementos de texto: texto plano, unido con saltos de línea
Elementos de tabla: marcado de tabla HTML de `text_as_html`, envuelto en un
marcador `` para que el LLM pueda distinguir las tablas del texto narrativo.
Por ejemplo, una página con un encabezado, un párrafo y una tabla produce:
```
Financial Overview
Revenue grew 15% year-over-year driven by enterprise adoption.
| Quarter | Revenue | Growth |
| Q1 | $12M | 12% |
| Q2 | $14M | 17% |
```
Esto preserva la estructura de la tabla mediante la segmentación y en la
canalización de extracción, donde el LLM puede extraer relaciones directamente de
celdas estructuradas en lugar de adivinar la alineación de columnas a partir de
espacios en blanco.
### Manejo de imágenes
Las imágenes se extraen y se almacenan en la biblioteca como documentos
secundarios con un `document_type="image"` y un ID `urn:image:{uuid}`. Obtienen
tripletas de procedencia con el tipo `tg:Image`, vinculadas a su página/sección
principal a través de `prov:wasDerivedFrom`. Los metadatos de la imagen (coordenadas,
dimensiones, element_id) se registran en la procedencia.
**Es crucial que las imágenes NO se emitan como salidas de TextDocument.** Se
almacenan únicamente; no se envían a la canalización de segmentación ni a ningún
proceso de texto. Esto es intencional:
1. Todavía no existe una canalización de procesamiento de imágenes (la integración
del modelo de visión es un trabajo futuro).
2. Alimentar datos de imagen en base64 o fragmentos de OCR en la
canalización de extracción de texto produciría tripletas de KG basura.
Las imágenes también se excluyen del texto de la página ensamblada; cualquier `Image`
elemento se omite silenciosamente al concatenar los textos de los elementos para una
página/sección. La cadena de procedencia registra que las imágenes existen y dónde
aparecieron en el documento, por lo que pueden ser recuperadas por una futura
canalización de procesamiento de imágenes sin volver a importar el documento.
#### Trabajo futuro
Enviar `tg:Image` entidades a un modelo de visión para descripción,
interpretación de diagramas o extracción de datos de gráficos.
Almacenar las descripciones de las imágenes como documentos de texto secundarios que se integran en
la canalización estándar de fragmentación/extracción.
Vincular el conocimiento extraído de nuevo a las imágenes de origen a través de la procedencia.
### Estrategias de sección
Para formatos basados en páginas (PDF, PPTX, XLSX), los elementos siempre se agrupan
por página/diapositiva/hoja primero. Para formatos no basados en páginas (DOCX, HTML, Markdown,
etc.), el decodificador necesita una estrategia para dividir el documento en
secciones. Esto se puede configurar en tiempo de ejecución a través de `--section-strategy`.
Cada estrategia es una función de agrupación sobre la lista de `unstructured`
elementos. La salida es una lista de grupos de elementos; el resto de la
canalización (ensamblaje de texto, almacenamiento en la biblioteca, procedencia,
emisión de TextDocument) es idéntico independientemente de la estrategia.
#### `whole-document` (predeterminado)
Emite todo el documento como una sola sección. Permite que el
fragmentador (chunker) posterior gestione todas las divisiones.
Enfoque más simple, buena línea de base
Puede producir un TextDocument muy grande para archivos grandes, pero el
fragmentador se encarga de eso.
Mejor cuando se desea el máximo contexto por sección.
#### `heading`
Divide en elementos de encabezado (`Title`). Cada sección es un encabezado más
todo el contenido hasta el siguiente encabezado de igual o mayor nivel. Los
encabezados anidados crean secciones anidadas.
Produce unidades temáticamente coherentes.
Funciona bien para documentos estructurados (informes, manuales, especificaciones).
Proporciona al LLM de extracción el contexto del encabezado junto con el contenido.
Retrocede a `whole-document` si no se encuentran encabezados.
#### `element-type`
Divide cuando el tipo de elemento cambia significativamente; específicamente,
comienza una nueva sección en las transiciones entre texto narrativo y tablas.
Los elementos consecutivos de la misma categoría general (texto, texto, texto o
tabla, tabla) permanecen agrupados.
Mantiene las tablas como secciones independientes.
Bueno para documentos con contenido mixto (informes con tablas de datos).
Las tablas reciben una atención de extracción dedicada.
#### `count`
Agrupa un número fijo de elementos por sección. Configurable a través de
`--section-element-count` (predeterminado: 20).
Simple y predecible.
No respeta la estructura del documento.
Útil como alternativa o para la experimentación.
#### `size`
Acumula elementos hasta que se alcanza un límite de caracteres, luego comienza una
nueva sección. Respeta los límites de los elementos; nunca los divide a la mitad.
Configurable a través de `--section-max-size` (por defecto: 4000 caracteres).
Produce tamaños de sección aproximadamente uniformes.
Respeta los límites de los elementos (a diferencia del fragmentador posterior).
Buen compromiso entre estructura y control de tamaño.
Si un solo elemento excede el límite, se convierte en su propia sección.
#### Interacción con formatos basados en páginas
Para formatos basados en páginas, el agrupamiento de páginas siempre tiene prioridad.
Las estrategias de sección opcionalmente se pueden aplicar *dentro* de una página si es muy
grande (por ejemplo, una página PDF con una tabla enorme), controlado por
`--section-within-pages` (por defecto: falso). Cuando es falso, cada página es
siempre una sección, independientemente del tamaño.
### Detección de formato
El decodificador necesita conocer el tipo MIME del documento para pasarlo a
`unstructured`'s `partition()`. Dos caminos:
**Ruta del bibliotecario** (`document_id` configurado): primero, recupera los metadatos del documento
del bibliotecario; esto nos da el `kind` (tipo MIME)
que se registró en el momento de la carga. Luego, recupera el contenido del documento.
Dos llamadas al bibliotecario, pero la recuperación de metadatos es ligera.
**Ruta integrada** (compatibilidad con versiones anteriores, `data` configurado): no hay metadatos
disponibles en el mensaje. Usa `python-magic` para detectar el formato
a partir de los bytes del contenido como una opción alternativa.
No se necesitan cambios en el esquema `Document`; el bibliotecario ya almacena el tipo MIME.
### Arquitectura
Un único servicio `universal-decoder` que:
1. Recibe un mensaje `Document` (en línea o a través de una referencia a la biblioteca).
2. Si la ruta es a través de la biblioteca: recupera los metadatos del documento (obtiene el tipo MIME), luego
recupera el contenido. Si la ruta es en línea: detecta el formato a partir de los bytes del contenido.
3. Llama a `partition()` para extraer los elementos.
4. Agrupa elementos: por página para formatos basados en páginas, por estrategia de sección configurada para formatos no basados en páginas.
sección.
5. Para cada página/sección:
Genera un ID `urn:page:{uuid}` o `urn:section:{uuid}`
Ensambla el texto de la página: el texto narrativo como texto plano, las tablas como HTML,
imágenes omitidas
Calcula los desplazamientos de caracteres para cada elemento dentro del texto de la página.
Guarda en el sistema de gestión de documentos como documento hijo.
Emite triples de procedencia con metadatos de posición.
Envía `TextDocument` a la siguiente etapa para la segmentación.
6. Para cada elemento de imagen:
Genera un ID `urn:image:{uuid}`.
Guarda los datos de la imagen en el sistema de gestión de documentos como documento hijo.
Emite triples de procedencia (almacenados solo, no enviados a la siguiente etapa).
### Manejo de formatos
| Formato | Tipo MIME | Basado en páginas | Notas |
|----------|------------------------------------|------------|--------------------------------|
| PDF | application/pdf | Sí | Agrupación por página |
| DOCX | application/vnd.openxmlformats... | No | Utiliza estrategia de secciones |
| PPTX | application/vnd.openxmlformats... | Sí | Agrupación por diapositiva |
| XLSX/XLS | application/vnd.openxmlformats... | Sí | Agrupación por hoja |
| HTML | text/html | No | Utiliza estrategia de secciones |
| Markdown | text/markdown | No | Utiliza estrategia de secciones |
| Texto plano | text/plain | No | Utiliza estrategia de secciones |
| CSV | text/csv | No | Utiliza estrategia de secciones |
| RST | text/x-rst | No | Utiliza estrategia de secciones |
| RTF | application/rtf | No | Utiliza estrategia de secciones |
| ODT | application/vnd.oasis... | No | Utiliza estrategia de secciones |
| TSV | text/tab-separated-values | No | Utiliza estrategia de secciones |
### Metadatos de procedencia
Cada entidad de página/sección registra metadatos de posición como metadatos de procedencia
en `GRAPH_SOURCE`, lo que permite una trazabilidad completa desde las triples del grafo de conocimiento
hasta las posiciones del documento de origen.
#### Campos existentes (ya están en `derived_entity_triples`)
`page_number` — número de página/hoja/diapositiva (indexado desde 1, solo para páginas)
`char_offset` — desplazamiento de caracteres de esta página/sección dentro del
texto completo del documento.
`char_length` — longitud de caracteres del texto de esta página/sección.
#### Nuevos campos (extender `derived_entity_triples`)
`mime_type` — formato original del documento (por ejemplo, `application/pdf`)
`element_types` — lista separada por comas de categorías de elementos `unstructured`
encontradas en esta página/sección (por ejemplo, "Título,TextoNarrativo,Tabla")
`table_count` — número de tablas en esta página/sección.
`image_count` — número de imágenes en esta página/sección.
Estos requieren nuevos predicados del espacio de nombres TG:
```
TG_SECTION_TYPE = "https://trustgraph.ai/ns/Section"
TG_IMAGE_TYPE = "https://trustgraph.ai/ns/Image"
TG_ELEMENT_TYPES = "https://trustgraph.ai/ns/elementTypes"
TG_TABLE_COUNT = "https://trustgraph.ai/ns/tableCount"
TG_IMAGE_COUNT = "https://trustgraph.ai/ns/imageCount"
```
Esquema URN de imagen: `urn:image:{uuid}`
(`TG_MIME_TYPE` ya existe.)
#### Nuevo tipo de entidad
Para formatos que no son de página (DOCX, HTML, Markdown, etc.) donde el decodificador
emite todo el documento como una sola unidad en lugar de dividirlo por
página, la entidad obtiene un nuevo tipo:
```
TG_SECTION_TYPE = "https://trustgraph.ai/ns/Section"
```
Esto distingue las secciones de las páginas al consultar el origen:
| Entidad | Tipo | Cuándo se utiliza |
|----------|-----------------------------|----------------------------------------|
| Documento | `tg:Document` | Archivo original subido |
| Página | `tg:Page` | Formatos basados en páginas (PDF, PPTX, XLSX) |
| Sección | `tg:Section` | Formatos que no son de página (DOCX, HTML, MD, etc.) |
| Imagen | `tg:Image` | Imágenes incrustadas (almacenadas, no procesadas) |
| Fragmento | `tg:Chunk` | Resultado del fragmentador |
| Subgrafo | `tg:Subgraph` | Resultado de la extracción del grafo de conocimiento |
El tipo se establece por el decodificador según si se está agrupando por página
o emitiendo una sección de todo el documento. `derived_entity_triples` obtiene
un parámetro booleano opcional `section`; cuando es verdadero, la entidad se
clasifica como `tg:Section` en lugar de `tg:Page`.
#### Cadena completa de origen
```
KG triple
→ subgraph (extraction provenance)
→ chunk (char_offset, char_length within page)
→ page/section (page_number, char_offset, char_length within doc, mime_type, element_types)
→ document (original file in librarian)
```
Cada enlace es un conjunto de triples en el grafo denominado `GRAPH_SOURCE`.
### Configuración del servicio
Argumentos de línea de comandos:
```
--strategy Partitioning strategy: auto, hi_res, fast (default: auto)
--languages Comma-separated OCR language codes (default: eng)
--section-strategy Section grouping: whole-document, heading, element-type,
count, size (default: whole-document)
--section-element-count Elements per section for 'count' strategy (default: 20)
--section-max-size Max chars per section for 'size' strategy (default: 4000)
--section-within-pages Apply section strategy within pages too (default: false)
```
Además de los argumentos estándar de `FlowProcessor` y la cola del bibliotecario.
### Integración del flujo
El decodificador universal ocupa la misma posición en el flujo de procesamiento
que el decodificador PDF actual:
```
Document → [universal-decoder] → TextDocument → [chunker] → Chunk → ...
```
Se registra:
`input` consumidor (esquema de documento)
`output` productor (esquema de TextDocument)
`triples` productor (esquema de Triples)
Solicitud/respuesta del bibliotecario (para la recuperación y el almacenamiento de documentos secundarios)
### Despliegue
Nuevo contenedor: `trustgraph-flow-universal-decoder`
Dependencia: `unstructured[all-docs]` (incluye PDF, DOCX, PPTX, etc.)
Puede ejecutarse junto con o reemplazar el decodificador PDF existente, dependiendo de
la configuración del flujo.
El decodificador PDF existente permanece disponible para entornos donde
las dependencias de `unstructured` son demasiado pesadas.
### ¿Qué Cambia?
| Component | Change |
|------------------------------|-------------------------------------------------|
| `provenance/namespaces.py` | Add `TG_SECTION_TYPE`, `TG_IMAGE_TYPE`, `TG_ELEMENT_TYPES`, `TG_TABLE_COUNT`, `TG_IMAGE_COUNT` |
| `provenance/triples.py` | Add `mime_type`, `element_types`, `table_count`, `image_count` kwargs |
| `provenance/__init__.py` | Export new constants |
| New: `decoding/universal/` | New decoder service module |
| `setup.cfg` / `pyproject` | Add `unstructured[all-docs]` dependency |
| Docker | New container image |
| Flow definitions | Wire universal-decoder as document input |
### What Doesn't Change
Chunker (receives TextDocument, works as before)
Downstream extractors (receive Chunk, unchanged)
Librarian (stores child documents, unchanged)
Schema (Document, TextDocument, Chunk unchanged)
Query-time provenance (unchanged)
## Risks
`unstructured[all-docs]` has heavy dependencies (poppler, tesseract,
libreoffice for some formats). Container image will be larger.
Mitigation: offer a `[light]` variant without OCR/office deps.
Some formats may produce poor text extraction (scanned PDFs without
OCR, complex XLSX layouts). Mitigation: configurable `strategy`
parameter, and the existing Mistral OCR decoder remains available
for high-quality PDF OCR.
`unstructured` version updates may change element metadata.
Mitigation: pin version, test extraction quality per format.