Construyendo una tubería RAG para datos semi-estructurados con Langchain

Desarrollando una tubería RAG para datos semi-estructurados con Langchain

Introducción

La Generación con Recuperación Mejorada ha estado aquí por un tiempo. Se están construyendo muchas herramientas y aplicaciones en torno a este concepto, como tiendas de vectores, marcos de recuperación y LLMs, lo que facilita trabajar con documentos personalizados, especialmente Datos Semiestructurados con Langchain. Trabajar con textos largos y densos nunca ha sido tan fácil y divertido. El enfoque convencional RAG funciona bien con archivos pesados de texto no estructurado como DOC, PDF, etc. Sin embargo, este enfoque no es adecuado para datos semiestructurados, como tablas incrustadas en PDF.

Mientras se trabaja con datos semiestructurados, generalmente hay dos problemas.

  • Los métodos convencionales de extracción y división de texto no tienen en cuenta las tablas en PDF. Por lo general, terminan dividiendo las tablas. Por lo tanto, se produce pérdida de información.
  • La incrustación de tablas puede no traducirse en una búsqueda semántica precisa.

Entonces, en este artículo, construiremos un pipeline de generación por recuperación para datos semiestructurados con Langchain para abordar estos dos problemas con datos semiestructurados.

Objetivos de Aprendizaje

  • Comprender la diferencia entre datos estructurados, no estructurados y semiestructurados.
  • Un breve repaso sobre Generación con Recuperación Mejorada y Langchain.
  • Aprender cómo construir un recuperador de vectores múltiples para manejar datos semiestructurados con Langchain.

Este artículo fue publicado como parte del Data Science Blogathon.

Tipos de Datos

Normalmente hay tres tipos de datos. Datos estructurados, semiestructurados y no estructurados.

  • Datos Estructurados: Los datos estructurados son datos estandarizados. Los datos siguen un esquema predefinido, como filas y columnas. Bases de datos SQL, hojas de cálculo, marcos de datos, etc.
  • Datos No Estructurados: Los datos no estructurados, a diferencia de los datos estructurados, no siguen un modelo de datos. Los datos son tan aleatorios como pueden ser. Por ejemplo, PDF, textos, imágenes, etc.
  • Datos Semiestructurados: Es la combinación de los tipos de datos anteriores. A diferencia de los datos estructurados, no tiene un esquema predefinido rígido. Sin embargo, los datos aún mantienen un orden jerárquico basado en algunos marcadores, a diferencia de los tipos no estructurados. Por ejemplo, CSV, HTML, tablas incrustadas en PDF, XML, etc.

¿Qué es RAG?

RAG significa Recuperación Mejorada por Generación. Es la forma más sencilla de alimentar a los modelos de lenguaje grande con información novedosa. Así que, hagamos un breve repaso sobre RAG.

En un pipeline de RAG típico, tenemos fuentes de conocimiento, como archivos locales, páginas web, bases de datos, etc, un modelo de incrustación, una base de datos de vectores y un LLM. Recopilamos los datos de diversas fuentes, dividimos los documentos, obtenemos las incrustaciones de trozos de texto y las almacenamos en una base de datos de vectores. Ahora, pasamos las incrustaciones de las consultas a la tienda de vectores, recuperamos los documentos de la tienda de vectores y finalmente generamos respuestas con el LLM.

Este es un flujo de trabajo de un RAG convencional y funciona bien con datos no estructurados como textos. Sin embargo, cuando se trata de datos semiestructurados, por ejemplo, tablas incrustadas en un PDF, a menudo no funciona tan bien. En este artículo, aprenderemos cómo manejar estas tablas incrustadas.

¿Qué es Langchain?

Langchain es una plataforma de código abierto para construir aplicaciones basadas en LLM. Desde su lanzamiento, el proyecto ha obtenido una amplia adopción entre los desarrolladores de software. Proporciona una amplia gama de herramientas y tecnologías unificadas para construir aplicaciones de IA más rápidamente. Langchain cuenta con herramientas como tiendas de vectores, cargadores de documentos, recuperadores, modelos de incrustación, separadores de texto, etc. Es una solución integral para construir aplicaciones de IA. Pero hay dos propuestas de valor fundamentales que lo hacen destacar.

  • Cadenas LLM: Langchain proporciona múltiples cadenas. Estas cadenas encadenan varias herramientas para realizar una sola tarea. Por ejemplo, ConversationalRetrievalChain encadena un LLM, recuperador de almacenamiento vectorial, modelo de incrustación y un objeto de historial de chat para generar respuestas a una consulta. Las herramientas están codificadas directamente y deben ser definidas explícitamente.
  • Agentes LLM: A diferencia de las cadenas LLM, los agentes de IA no tienen herramientas codificadas directamente. En lugar de encadenar una herramienta tras otra, dejamos que el LLM decida cuál seleccionar y cuándo, en función de las descripciones de texto de las herramientas. Esto lo hace ideal para construir aplicaciones complejas de LLM que involucren razonamiento y toma de decisiones.

Construyendo el pipeline de RAG

Ahora que hemos tenido una introducción a los conceptos, discutamos el enfoque para construir el pipeline. Trabajar con datos semi-estructurados puede ser complicado, ya que no siguen un esquema convencional para almacenar información. Y para trabajar con datos no estructurados, necesitamos herramientas especializadas hechas a medida para extraer información. Por lo tanto, en este proyecto, utilizaremos una herramienta llamada “unstructured”; es una herramienta de código abierto para extraer información de diferentes formatos de datos no estructurados, como tablas en PDF, HTML, XML, etc. Unstructured utiliza Tesseract y Poppler internamente para procesar múltiples formatos de datos en archivos. Así que configuremos nuestro entorno e instalemos las dependencias antes de sumergirnos en la parte del código.

Configurar el entorno de desarrollo

Como cualquier otro proyecto de Python, abre un entorno de Python e instala Poppler y Tesseract.

!sudo apt install tesseract-ocr!sudo apt-get install poppler-utils

Ahora, instalemos las dependencias que necesitaremos en nuestro proyecto.

!pip install "unstructured[all-docs]" Langchain openai

Extraer utilizando Unstructured

Ahora que hemos instalado las dependencias, vamos a extraer datos de un archivo PDF.

from unstructured.partition.pdf import partition_pdfpdf_elements = partition_pdf(    "mistral7b.pdf",     chunking_strategy="by_title",     extract_images_in_pdf=True,     max_characters=3000,    new_after_n_chars=2800,    combine_text_under_n_chars=2000,    image_output_dir_path="./"    )

Al ejecutar esto, se instalarán varias dependencias como YOLOx que se necesitan para OCR y se devolverán tipos de objeto basados en los datos extraídos. Al habilitar extract_images_in_pdf, unstructured puede extraer imágenes incrustadas de los archivos. Esto puede ayudar a implementar soluciones multimodales.

Ahora, exploremos las categorías de elementos de nuestro PDF.

# Crear un diccionario para almacenar el recuento de cada tipocategory_counts = {}for element in pdf_elements:    category = str(type(element))    if category in category_counts:        category_counts[category] += 1    else:        category_counts[category] = 1# unique_categories contendrá elementos únicosunique_categories = set(category_counts.keys())category_counts

Al ejecutar esto, se mostrarán las categorías de elementos y su recuento.

Ahora, separamos los elementos para facilitar su manejo. Creamos un tipo de elemento que hereda del tipo Document de Langchain. Esto es para asegurar datos más organizados, que sean más fáciles de manejar.

from unstructured.documents.elements import CompositeElement, Tablefrom langchain.schema import Documentclass Element(Document):    type: str# Categorizamos por tipocategorized_elements = []for element in pdf_elements:    if isinstance(element, Table):        categorized_elements.append(Element(type="table", page_content=str(element)))    elif isinstance(element, CompositeElement):        categorized_elements.append(Element(type="text", page_content=str(element)))# Elementos de tablatable_elements = [e for e in categorized_elements if e.type == "table"]# Elementos de textotext_elements = [e for e in categorized_elements if e.type == "text"]

Recuperador multi-vector

Ya tenemos elementos de tabla y texto. Ahora, hay dos formas de manejarlos. Podemos almacenar los elementos brutos en un almacén de documentos o almacenar resúmenes de los textos. Las tablas pueden plantear un desafío para la búsqueda semántica; en ese caso, creamos los resúmenes de las tablas y los almacenamos en un almacén de documentos junto con las tablas brutos. Para lograr esto, utilizaremos MultiVectorRetriever. Este recuperador administrará un almacén vectorial donde almacenaremos las incrustaciones de los textos resumidos y un almacén de documentos sencillo en memoria para almacenar los documentos brutos.

Primero, construya una cadena resumen para resumir los datos de la tabla y el texto que extrajimos anteriormente.

from langchain.chat_models import coherefrom langchain.prompts import ChatPromptTemplatefrom langchain.schema.output_parser import StrOutputParserprompt_text = """Eres un asistente encargado de resumir tablas y texto. \ Dé un resumen conciso de la tabla o el texto. Tabla o fragmento de texto: {elemento} """prompt = ChatPromptTemplate.from_template(prompt_text)modelo = cohere.ChatCohere(cohere_api_key="tu_clave")cadena_resumen = {"elemento": lambda x: x} | prompt | modelo | StrOutputParser()tablas = [i.page_content para i en table_elements]table_summaries = cadena_resumen.batch(tablas, {"max_concurrency": 5})textos = [i.page_content para i en text_elements]text_summaries = cadena_resumen.batch(textos, {"max_concurrency": 5})

He utilizado Cohere LLM para resumir datos; puedes utilizar modelos de OpenAI como GPT-4. Los mejores modelos darán mejores resultados. A veces, los modelos pueden no capturar perfectamente los detalles de la tabla. Por lo tanto, es mejor utilizar modelos capaces.

Ahora, creamos el MultivectorRetriever.

from langchain.retrievers import MultiVectorRetrieverfrom langchain.prompts import ChatPromptTemplateimport uuidfrom langchain.embeddings import OpenAIEmbeddingsfrom langchain.schema.document import Documentfrom langchain.storage import InMemoryStorefrom langchain.vectorstores import Chroma# El vectorstore a utilizar para indexar los fragmentos hijovectorstore = Chroma(collection_name="colección",
                     embedding_function=OpenAIEmbeddings(openai_api_key="cláve_api"))# La capa de almacenamiento para los documentos primariosalmacenamiento = InMemoryStore()id_key = "id"# El retrieverretriever = MultiVectorRetriever(    vectorstore=vectorstore,    docstore=store,    id_key=id_key)# Añadir textosids_doc = [str(uuid.uuid4()) para _ en textos]summary_texts = [    Document(page_content=s, metadata={id_key: ids_doc[i]})    for i, s en enumerate(text_summaries)]retriever.vectorstore.add_documents(summary_texts)retriever.docstore.mset(list(zip(ids_doc, textos)))# Añadir tablasids_tabla = [str(uuid.uuid4()) para _ en tablas]summary_tables = [    Document(page_content=s, metadata={id_key: ids_tabla[i]})    for i, s en enumerate(table_summaries)]retriever.vectorstore.add_documents(summary_tables)retriever.docstore.mset(list(zip(ids_tabla, tablas)))

Hemos utilizado el vectorstore Chroma para almacenar resúmenes incrustados de textos y tablas y un almacenamiento de documentos en memoria para almacenar los datos en bruto.

RAG

Ahora que nuestro retriever está listo, podemos construir un pipeline RAG usando el Lenguaje de Expresión de Langchain.

from langchain.schema.runnable import RunnablePassthrough# Plantilla de preguntaplantilla = """Responde a la pregunta basándote únicamente en el siguiente contexto, que puede incluir texto y tablas::{contexto}Pregunta: {pregunta}"""prompt = ChatPromptTemplate.from_template(template)# Modelo LLMmodelo = ChatOpenAI(temperature=0.0, openai_api_key="cláve_api")# RAG pipelinecadena = (    {"contexto": retriever, "pregunta": RunnablePassthrough()}    | prompt    | modelo    | StrOutputParser())

Ahora, podemos hacer preguntas y recibir respuestas basadas en los embeddings recuperados del vectorstore.

cadena.invoke(input = "¿Cuál es el puntaje de banco MT de Llama 2 y Mistral 7B Instruct??")

Conclusión

Una gran cantidad de información permanece oculta en el formato de datos semiestructurados. Y es un desafío extraer y realizar RAG convencional en estos datos. En este artículo, pasamos de extraer textos y tablas incrustadas en el PDF a construir un multi-vector retriever y un pipeline RAG con Langchain. Entonces, aquí están las conclusiones clave del artículo.

Puntos clave

  • El RAG convencional a menudo enfrenta desafíos al tratar con datos semiestructurados, como dividir las tablas durante la división de texto y búsquedas semánticas imprecisas.
  • Unstructured, una herramienta de código abierto para datos semiestructurados, puede extraer tablas incrustadas de PDFs u otros datos semiestructurados similares.
  • Con Langchain, podemos construir un multi-vector retriever para almacenar tablas, textos y resúmenes en almacenes de documentos para una búsqueda semántica mejorada.

Preguntas frecuentes

Los medios mostrados en este artículo no son propiedad de Analytics Vidhya y se utilizan a discreción del autor.

We will continue to update Zepes; if you have any questions or suggestions, please contact us!

Share:

Was this article helpful?

93 out of 132 found this helpful

Discover more

Inteligencia Artificial

Mirando hacia adentro

La biosensibilidad lleva los diagnósticos médicos a un nivel más profundo.

Inteligencia Artificial

Perplejidad revela dos nuevos modelos de LLM en línea 'pplx-7b-online' y 'pplx-70b-online

Perplexity, una innovadora startup de IA, ha introducido una solución para transformar los sistemas de recuperación d...

Inteligencia Artificial

Técnica de Machine Learning Mejor para Predecir Tasas de Cura del Cáncer

Un modelo de aprendizaje automático desarrollado por investigadores de la Universidad de Texas en Arlington (UTA) pue...

Inteligencia Artificial

Sobre el aprendizaje en presencia de grupos subrepresentados

Déjame presentarte nuestro último trabajo, que ha sido aceptado por ICML 2023 Cambio es Difícil Un Vistazo más Detall...

Inteligencia Artificial

Acélere los resultados comerciales con mejoras del 70% en el rendimiento del procesamiento de datos, entrenamiento e inferencia con Amazon SageMaker Canvas

Amazon SageMaker Canvas es una interfaz visual que permite a los analistas de negocios generar predicciones precisas ...