Ingesta de datos

Explore más de lo que ofrece el libro de recetas RAG para obtener perspectivas más profundas de las soluciones RAG actuales

Un espacio principal recoloreado que utiliza como base el espacio principal watsonx para atención al cliente.
Visión general

La ingestión es el proceso de análisis sintáctico de la información procedente de los documentos fuente, de modo que pueda incorporarse a un espacio de búsqueda para su posterior recuperación. Aunque se trata de un proceso sencillo para el texto sin formato, surgen complicaciones cuando los documentos fuente están en formatos que no son de "texto", p. ej.  Microsoft Word o PDF, y cuando contienen un formato complejo como encabezados y pies de página repetidos, texto en varias columnas o tablas.

Esta sección contiene consejos, técnicas, aceleradores y enlaces a los activos que ayudan a superar estos desafíos.

Por dónde empezar.

 

Si es un usuario no técnico, sus documentos son relativamente sencillos y necesita una solución sin código, use Watsonx Orchestrate.

 

Si es un usuario técnico y sus documentos son relativamente sencillos y tiene acceso a Watson Discovery, empiece por ahí. Watson Discovery tiene una buena interfaz de usuario con una mínima necesidad de codificación. Para documentos complejos, puede utilizar Watson Discovery para anotar y extraer partes específicas de sus documentos, ya sea para su pipeline de backend RAG o para frontend y para resaltar los textos obteniendo la posición exacta de un párrafo dentro de sus documentos.

 

Sin embargo, Watson Discovery tiene sus limitaciones. Si sus documentos superan los 50 MB, no podrá cargarlos en Watson Discovery. Si el documento es demasiado complejo (es decir, incluye tablas anidadas o formatos de tabla irregulares), es posible que Watson Discovery no capture toda la estructura del documento. Es posible que desee implementar un pipeline de ingesta de datos personalizado utilizando bibliotecas de código abierto para estos casos.

 

En lo que respecta a las bibliotecas de código abierto, LangChain y LlamaIndex son muy similares en términos de capacidades de ingesta de datos. Sin embargo, LangChain sería más fácil de usar que LlamaIndex en términos de documentación e integración con bases de datos vectoriales y otras aplicaciones. Tanto LangChain como LlamaIndex tienen funciones auxiliares que pueden convertir un objeto Document de uno a otro, por lo que el cambio entre LangChain y LlamaIndex se puede realizar en cualquier punto de su pipeline.

Ingesta de documentos con tablas complejas

Las siguientes notas incluyen varias lecciones aprendidas para la ingesta de documentos que incluyen tablas complejas y diferentes enfoques que se probaron durante uno de los proyectos. Tenga en cuenta que algunas de las observaciones pueden variar de un proyecto a otro; sin embargo, la mayoría de las conclusiones deberían ser similares en los proyectos que incluyen documentos con tablas anidadas y complejas.

Watson Discovery

Watson Discovery no admite documentos de más de 50 MB. En los casos en los que el gran tamaño se debe al hecho de que los documentos originales están en formato Word, necesitamos convertir los documentos originales de Word a PDF para poder utilizar Watson Discovery. Sin embargo, al utilizar este enfoque, Watson Discovery a veces no puede capturar los formatos de tabla correctamente, especialmente en casos de tablas complejas o anidadas.

Para la ingesta con Watson Discovery se pueden probar dos enfoques diferentes: un modelo preentrenado y un modelo de usuario entrenado anotando manualmente algunas páginas a través de la comprensión inteligente de documentos de Discovery. A continuación se analizan las lecciones aprendidas de estos dos enfoques para uno de los proyectos que incluía tablas anidadas complejas.

  • modelo preentrenadol
    • Pros: 
      • La output de Discovery a menudo podía capturar mejor la estructura de las tablas que un modelo entrenado por el usuario (SDU)
    • Contras: 
      • Discovery seguía teniendo dificultades para detectar tablas anidadas. En algunos casos sólo vería la tabla más interna como una tabla y capturaría las tablas externas como texto, perdiendo la estructura de datos.
    • Al utilizar Watson Discovery, el uso del texto sin procesar puede dar mejores resultados en comparación con el uso de outputs HTML.  

  • modelo definido por el usuario
    • Pros: 
      • Muy fácil de anotar y bueno para documentos simples en los que le gustaría filtrar secciones específicas más adelante.
    • Desventajas:
      • No se pudieron detectar las estructuras de tablas anidadas incluso si anotamos todas las tablas dentro de las tablas.
      • Hasta en las tablas sencillas, tenía problemas para detectarlas en los documentos nuevos, incluso después de anotar manualmente 20 páginas de más de 7 documentos.

Aunque los resultados de Watson Discovery no fueron tan precisos como los de otras librerías personalizadas mencionadas más abajo para tablas complejas y anidadas, los resultados incluían muchos metadatos como números de página y coordenadas de los textos, que son útiles para mostrar los puntos destacados de la IU. Estos metadatos pueden ser realmente útiles para añadir filtros adicionales durante la recuperación o incluso para dividir los documentos en función de determinadas secciones HTML.

PyPDFLoader vs. PyMuPDF

La biblioteca PyMuPDF es mucho más rápida y produce resultados más precisos, especialmente en datos más grandes. Al utilizar las dos funciones siguientes en un conjunto de datos de 50,6 MB, PyMuPDF tardó 0,131 segundos frente a 0,366 segundos para PypdfLoader de LangChain. Así que para archivos grandes y si no quiere extraer secciones separadas del documento como secciones separadas, use la biblioteca PyMuPdf.

def pdf_to_text(path: str,
                        start_page: int = 1,
                        end_page: Optional[int | None] = None) -> (list[str], list[str], list[dict]):
    """
    Convierte PDF a texto sin formato.

    Parámetros:
        path (str): Ruta al archivo PDF.
        start_page (int): página para empezar a recibir texto.
        end_page (int): última página para obtener texto.
   
"""
    logger.debug("Processing PDF %s".format(path))

    from langchain_community.document_loaders import PyPDFLoader

    loader = PyPDFLoader(path)
    pages = loader.load()
    total_pages = len(pages)
    logger.debug(f'Total pages: {total_pages}')
    _ids = []
    _metadata = []
    _file_name = Path(path).name

    if end_page is None:
        end_page = len(pages)

    _text_list = []
    for index in range(start_page - 1, end_page):
        text = pages[index].page_content
        text = text.replace('\n', ' ')
        text = re.sub(r'\s+', ' ', text)
        _text_list.append(text)
        _ids.append(f'page_{index + 1}')
        _metadata.append({
            "id": index + 1,
            "file_name": _file_name,
            "page": f'page {index + 1}'
        })

    return _text_list, _ids, _metadata

def large_pdf_to_text(path: str,
                        start_page: int = 1,
                        end_page: Optional[int | None] = None,
                        remove_string_list=None) -> (list[str], list[str], list[dict]):
    """
        Convierte PDF a texto sin formato utilizando PyMuPDF, impresionante velocidad de ejecución, lo que lo hace adecuado para el
        procesamiento de PDF a gran escala. Aunque no ofrece funciones dedicadas de extracción de tablas, puede
        utilizarse para analizar la estructura PDF y extraer datos tabulares con pasos de procesamiento adicionales
        si es necesario.

        50,6MB -> 0,131 segundos (PyMuPDF) frente a 0,366 segundos (pypdf)

        Parámetros:
            file_stream (stream): transmite al archivo PDF.
            path (STR): ruta al PDF
            start_page (int): página para empezar a recibir texto.
            end_page (int): última página para obtener texto.
            remove_string_list (list[str]): elimina la lista de cadenas.
        """
    logger.debug("Processing PDF %s".format(path))
    if remove_string_list is None:
        remove_string_list = []

    import fitz

    # pdf_reader = fitz.open(stream = file_stream, filetype = "pdf")
    pdf_reader = fitz.open(path)
    if end_page is None:
        end_page = pdf_reader.page_count

    _text_list = []
    _ids = []
    _metadata = []
    _file_name = Path(path).name
    for index in range(start_page - 1, end_page):
        text = pdf_reader[index].get_text("text")
        text = text.replace('\n', ' ')
        text = re.sub(r'\s+', ' ', text)
        for remove_string in remove_string_list:
            re_compile = re.compile(remove_string)
            text = re_compile.sub('', text)
            _metadata.append({
                "id": index + 1,
                "file_name": _file_name,
                "page": f'page {index + 1}'
            })
        _ids.append(f'page_{index + 1}')
        _text_list.append(texto)

    return _text_list, _ids, _metadata

Cargador de PDF no estructurado para la ingesta de html UnstructuredPDFLoader de LangChain

  • Pros: 
    • Incluía muchos metadatos, como los números de página y las coordenadas x, y de los textos, similares a los de Watson Discovery, que podrían resultar útiles para mostrar los puntos destacados en el futuro.
  • Contras: 
    • No se pueden capturar correctamente muchas tablas anidadas o complejas. Además, para este enfoque necesitaríamos convertir cada uno de los formatos docx originales a PDF.

Cargador de Word no estructurado para la ingesta de HTML UnstructuredWordDocumentLoader de LangChain

  • Pros: 
    • El uso de Docs dio como resultado una mejor captura de las tablas y ayuda a un mejor contexto para que los LLM generen respuestas.
  • Contras: 
    • Los metadatos, como los números de página, no se capturaban correctamente incluso después de añadir saltos de página en comparación con el cargador de PDF.

Resumen de tablas HTML

En un intento por preservar la estructura de las tablas, introducimos elementos de tabla del HTML extraído (utilizando la biblioteca no estructurada) en un LLM (Mixtral para tablas largas es una buena opción debido a su tamaño de contexto), luego podemos crear una instrucción para resumir las tablas o utilizar el aprendizaje few shot para convertir las tablas a un formato que creemos que podría ser más comprensible para los modelos de lenguaje de gran tamaño.

  • Pros: 
    • El texto de output sería más fácil de fragmentar e ingerir, y preservaría la estructura de las tablas
  • Contras: 
    • Para tablas de gran tamaño de varias páginas, para la instrucción de resumen podemos perder algo de información, así que los pocos intentos de aprender a convertir las tablas en lugar de resumirlas podrían dar mejores resultados.

También se probaron otras bibliotecas de lectores de tablas, como camelot y tabula, pero estas bibliotecas no eran tan precisas como las no estructuradas para tablas complejas y, dado que solo detectan tablas dentro de un documento, podría ser necesario más preprocesamiento para crear fragmentos significativos para pasar a modelos de lenguaje de gran tamaño.

Para concluir, aunque Watson Discovery sería una forma fácil y rápida de consumir documentos y capturar muchos metadatos adicionales que pueden ser útiles para crear la interfaz de usuario (para resaltar los pasajes, por ejemplo), la biblioteca "no estructurada" (que tiene envoltorios tanto en LlamaIndex como LangChain) podría capturar las tablas complejas dentro de los documentos con mayor precisión en comparación con Discovery. Así pues, una combinación de ambos enfoques puede resultar útil para proyectos que incluyan tablas complejas en sus documentos.

Herramientas IBM

Ingestión con Watsonx Orchestrate

La ingestión sin una interfaz gráfica puede ser difícil para los usuarios empresariales, ya que requiere experiencia y conocimientos técnicos. Watsonx Orchestrate elimina la frustración de los usuarios empresariales mediante la implementación de una interfaz de usuario (IU) de arrastrar y soltar. Al hacer clic en el botón azul de carga, iniciamos la capacidad de cargar y almacenar documentos directamente en Watsonx Discovery (también conocido como Elasticsearch).

Captura de pantalla del portal de arrastrar y soltar de watsonx Orchestrate

Esto permite al usuario cargar directamente en Elasticsearch su documentación para crear su propia base de conocimientos personalizada.

Captura de pantalla de la pantalla de carga de documentos en watsonx Orchestrate

En lugar de ingerir directamente los documentos en Watsonx Discovery, también tiene la opción de conectarse a Watson Discovery a través de Watsonx Orchestrate. Puede encontrar más información sobre cómo ingerir datos a través de Watson Discovery a continuación.

Watson Discovery

Otra de las herramientas internas que se pueden utilizar para la ingesta es Watson Discovery. Watson Discovery no es puramente una herramienta de ingesta y con ella puede ingerir, normalizar, enriquecer y buscar sus datos no estructurados. La siguiente imagen muestra los componentes y capacidades principales de Watson Discovery.

Ilustración de las funciones principales de Watson Discovery

Como puede ver arriba, una de las capacidades principales de Watson Discovery es absorber datos estructurados y no estructurados en diferentes formatos como JSON, HTML, PDF, Word y más, y Smart Document Understanding.

Si tiene Watson Discovery provisionado en su entorno, puede ingerir documentos fácilmente creando primero un proyecto y luego una colección donde pueda subir sus datos desde almacenamiento local o desde una ubicación en la nube, como un bucket de almacenamiento de objetos.

Una vez que cree su colección, puede ir a la pestaña Gestionar colecciones en el menú de hamburguesas y, en Campos de Identidad, elegir qué método quiere usar para procesar los documentos.

Captura de pantalla de la pantalla de procesamiento de documentos de Watson Discovery

Hay tres opciones:

  • Solo extracción de texto: que extrae solo textos de los documentos.
  • Modelos entrenados por el usuario: donde puede anotar diferentes partes de su documento con etiquetas personalizadas y entrenar sus propios modelos basados en patrones visuales repetidos dentro de sus documentos
  • modelos preentrenados: que pueden extraer texto e identificar tablas, listas y secciones utilizando modelos ibm preentrenados.

Puede pasar un tiempo hasta que se procesen todos sus documentos. Después de eso, puede usar la API de Watson Discovery para leer y usar sus datos en su código.

A continuación se muestra un código de ejemplo que muestra cómo puede utilizar la API para leer los datos de su colección:

from langchain.docstore.document import Document
import os
import logging
import time
from ibm_watson import DiscoveryV2
from ibm_cloud_sdk_core.authenticators import IAMAuthenticator

WD_PAGE_SIZE = 200
MAX_RETRIES = 2
def get_documents_from_wd(collection_ids=[WD_COLLECTION_ID]):
    
    print("Fetching documents from Watson Discovery")
    documents = []
    
    print("Configuring the WD client")
    authenticator = IAMAuthenticator(WD_API_KEY)
    wd_client = DiscoveryV2(
        version="2023-03-31",
        authenticator=authenticator
    )
    
    print("Setting the WD service URL")
    wd_client.set_service_url(WD_SERVICE_URL)
    
    print("Fetching documents from WD")
    page_id = 0
    retries = 0
    while True:
        try:
            print("Fetching page: " + str(page_id))
            response = wd_client.query(
                project_id=WD_PROJECT_ID,
                collection_ids=collection_ids,
                return_=["text"],
                count=WD_PAGE_SIZE,
                offset=page_id*WD_PAGE_SIZE
            ).get_result()
            if response is None or not isinstance(response, dict):
                print("No query result")
                raise ValueError("No query result")
            if "results" not in response or response["results"] is None or not isinstance(response["results"], list):
                print("No query result 2")
                raise ValueError("No query result")
            results = response["results"]
            if len(results) == 0:
                print("No more results")
                break
            print("Fetched " + str(len(results)) + " documents")
            documents.extend(list(map(lambda result: Document(page_content=result["text"][0],  
                                                              metadata= {"collection_id": WD_COLLECTION_ID, "document_id" : result['document_id']}), results)))
            page_id += 1
        except Exception as error:
            logging.error("Failed to fetch documents from WD", str(error))
            retries += 1
            time.sleep(5)
            if retries > MAX_RETRIES:
                break
            print("Retrying...")
    print("Fetched " + str(len(documents)) + " documents")
    return documents

 

Rastreo web en Watson Discovery

Al crear un proyecto en Watson Discovery, puede programar un rastreo web para obtener información de una URL especificada. Todo lo que necesita hacer es seleccionar el rastreo web al seleccionar la fuente de datos y luego especificar la URL y el cronograma de rastreo.

Pantalla de configuración del rastreador web de Watson Discovery.
Captura de pantalla del programador del rastreador web de Watson Discovery

Después de eso, puede hacer los pasos mencionados arriba para gestionar su colección y usar la API para leer los datos de la misma. Para ver más detalles sobre cómo configurar el rastreo web en Watson Discovery, puede ver este vídeo.

Para obtener más información y características, puede consultar la página para desarrolladores de Watson Discovery.

Deep Search

Deep Search es el kit de herramientas de código abierto de IBM para la investigación de la ingestión. Deep Search aprovecha métodos de IA de última generación para recopilar, convertir, enriquecer y enlazar continuamente grandes colecciones de documentos. Puede utilizarlo tanto para documentos PDF públicos como propietarios.

Deep Search convierte documentos PDF no estructurados en archivos JSON estructurados con precisión y facilidad. Le permite automatizar la extracción de conocimientos, así como afinar sus modelos fundacionales y modelos de lenguaje de gran tamaño.

Puede encontrar más información sobre Deep Search aquí.

Deep Search puede ser una buena herramienta interna para leer documentos complejos en lugar de bibliotecas no estructuradas u otras bibliotecas de código abierto. También puede encontrar muy buena documentación en el repositorio con diferentes tipos de ejemplos como notebooks de Python:

Notebooks de ejemplos de Deep Search

Ingesta de tablas desde archivos PDF

Deep Search proporciona buenos resultados al extraer tablas de archivos PDF en formato JSON.

Para las pruebas, hemos utilizado un documento PDF parcial del CIPP, que incluye tres páginas, cada una de las cuales muestra datos de tablas. El mejor rendimiento de RAG en este caso se logra utilizando Deep Search para extraer tablas en formato JSON y luego convertirlas a HTML para usarlas en Watson Discovery / watsonx Discovery en lugar de usar directamente PDF, convertir PDF a HTML sin Deep Search, o solo utilizando JSON de Deep Search en Watson Discovery / watsonx Discovery. Descubrimos que Watson Discovery selecciona la respuesta incorrecta de la celda incorrecta de la tabla en algunos casos pero más rápido, y en el mismo caso, Watson Discovery puede identificar la respuesta exacta dentro de la cuadrícula de la tabla.

IBM Datacap

IBM Datacap es una solución integral para la captura de documentos y datos que ofrece escaneo, clasificación, reconocimiento, validación y exportación rápidos, precisos y rentables de datos e imágenes de documentos. Captura documentos, extrae datos relevantes y los integra en procesos empresariales posteriores.

Datacap adquiere documentos en papel a través de escáneres, impresoras multifunción o dispositivos móviles e importa documentos electrónicos desde sistemas de archivos, fax o servidores de correo electrónico. Mejora la extracción de datos con funciones de procesamiento de imágenes como la corrección y eliminación de líneas, manchas y bordes.

Datacap utiliza el reconocimiento óptico de caracteres (OCR) y el reconocimiento inteligente de caracteres (ICR) para la escritura a mano, el reconocimiento óptico de marcas (OMR) para las marcas y la lectura de códigos de barras para extraer datos de manera eficiente.

Para instrucciones detalladas de instalación y uso, consulte la documentación de IBM Datacap.

Herramientas de código abierto

Cargadores de datos de LangChain

LangChain admite diferentes tipos de cargadores de documentos que cargan datos de una fuente como objeto Document de LangChain. Un objeto Document es un fragmento de texto y metadatos asociados que se pueden utilizar fácilmente para fragmentarlos y recuperarlos más adelante en el pipeline.

Actualmente, LangChain soporta cargadores para cargar un directorio completo o diferentes tipos de archivos como:

  • CSV
  • HTML
  • JSON
  • Markdown
  • Microsoft Office
  • PDF

Puede utilizar estos cargadores en pocas líneas en Python. Por ejemplo, para cargar un PDF puede utilizar el siguiente código:

from langchain_community.document_loaders import PyPDFLoader

loader = PyPDFLoader("example_data/layout-parser-paper.pdf")
pages = loader.load_and_split()

Consulte la documentación de LangChain para ver cómo utilizar estos cargadores.

Además de los mencionados en el enlace anterior, puede encontrar cargadores adicionales que pueden cargar datos directamente desde aplicaciones específicas como correo electrónico, Github, Google Drive, etc. Puede encontrar la lista de todos los diferentes cargadores aquí.

En los casos en los que tenga documentos con estructuras, formatos y tablas complejas, puede utilizar los cargadores no estructurados de LangChain. Estos cargadores bajo el capó utilizan la biblioteca no estructurada, que es una de las mejores bibliotecas para documentos complejos (en diferentes formatos como PDF, MSWord, Power Point, etc.), y para dividir los documentos en diferentes componentes: LangChain UnstructuredLoader

Cargadores de datos de LlamaIndex

Al igual que LangChain, LlamaIndex también admite diferentes tipos de cargadores. Una de las maneras más sencillas de cargar datos con LlamaIndex es utilizar SimpleDirectoryReader. SimpleDirectoryReader admite los siguientes tipos:

  • .csv: valores separados por comas
  • .docx: Microsoft Word
  • .epub: formato de ebook EPUB
  • .hwp: procesador de textos Hangul
  • .ipynb: Jupyter Notebook
  • .jpeg, .jpg : imagen JPEG
  • .mbox: archivo de correo electrónico MBOX
  • .md: Markdown
  • .mp3, .mp4 : audio y vídeo
  • .pdf: formato de documento portátil
  • .png: gráficos de red portátiles
  • .ppt, .pptm, .pptx : Microsoft PowerPoint

Puede utilizar el SimpleDirectoryLoader usando el siguiente fragmento de código:

from llama_index.core import SimpleDirectoryReader

reader = SimpleDirectoryReader(input_dir="path/to/directory")
documents = reader.load_data()

También puede agregar extensiones específicas para leer solo esas extensiones del directorio:

SimpleDirectoryReader(
   input_dir="path/to/directory", required_exts=[".pdf", ".docx"]
)

Para obtener más información sobre cómo utilizar los cargadores LlamaIndex, consulte su documentación.

También de forma similar a Huggingface, puede crear sus propios cargadores personalizados o utilizar los cargadores personalizados de otras personas en llamahub.ai.

Sin embargo, una desventaja de LlamaIndex en comparación con LangChain es que la documentación y el soporte de la comunidad no son tan buenos como los de LangChain, por lo que depurar el código puede ser más difícil.

No estructurados

En casos en los que carga documentos complejos, también puede usar directamente la biblioteca no estructurada. La biblioteca no estructurada es realmente buena para leer y analizar tablas.

La biblioteca no estructurada también es compatible con los envoltorios LangChain y LlamaIndex, por lo que podría ser más fácil utilizarla para los pipelines RAG en el futuro, ya que crearán y devolverán automáticamente los objetos Document. Sin embargo, si su proyecto necesita más personalización y desea utilizar directamente la biblioteca no estructurada, puede consultar la siguiente documentación: Unstructured.

Explorar más

Obtenga las últimas tecnologías, arquitecturas de soluciones, y publicaciones de arquitectura de IBM.

  1. Ir al IBM Architecture Center
Colaboradores