LLM + RAG: Crear un asistente de lector de archivos con IA

Introducción

AI está en todas partes.

Es difícil no interactuar al menos una vez al día con un modelo de lenguaje grande (LLM). Los chatbots están aquí para quedarse. Están en sus aplicaciones, lo ayudan a escribir mejor, componen correos electrónicos, leen correos electrónicos … bueno, hacen mucho.

Y no creo que eso sea malo. De hecho, mi opinión es la otra forma, al menos hasta ahora. Defiendo y abogo por el uso de IA en nuestra vida diaria porque, de acuerdo, hace que todo sea mucho más fácil.

No tengo que pasar el tiempo de lectura doble para encontrar problemas o tipos de puntuación. Ai hace eso por mí. No pierdo el tiempo escribiendo ese correo electrónico de seguimiento todos los lunes. Ai hace eso por mí. ¡No necesito leer un contrato enorme y aburrido cuando tengo una IA para resumir las principales conclusiones y puntos de acción para mí!

Estos son solo algunos de los grandes usos de AI. Si desea conocer más casos de uso de LLM para facilitarnos la vida, escribí un libro completo sobre ellos.

Ahora, pensar como científico de datos y mirar el lado técnico, no todo es tan brillante y brillante.

Los LLM son excelentes para varios casos de uso general que se aplican a cualquiera o cualquier empresa. Por ejemplo, codificar, resumir o responder preguntas sobre el contenido general creado hasta la fecha de corte de capacitación. Sin embargo, cuando se trata de aplicaciones comerciales específicas, para un solo propósito, o algo nuevo que no llegó a la fecha de corte, es cuando los modelos no serán tan útiles si se usan listón – Es decir, no sabrán la respuesta. Por lo tanto, necesitará ajustes.

Entrenar un modelo LLM puede llevar meses y millones de dólares. Lo que es aún peor es que si no ajustamos y sintonizamos el modelo a nuestro propósito, habrá resultados o alucinaciones insatisfactorias (cuando la respuesta del modelo no tenga sentido dada nuestra consulta).

Entonces, ¿cuál es la solución, entonces? ¿Gastar mucho dinero en requisito del modelo para incluir nuestros datos?

No precisamente. Ahí es cuando la generación de recuperación aumentada (RAG) se vuelve útil.

RAG es un marco que combina la obtención de información de una base de conocimiento externa con modelos de idiomas grandes (LLM). Ayuda a los modelos de IA a producir respuestas más precisas y relevantes.

Aprendamos más sobre Rag A continuación.

¿Qué es el trapo?

Déjame contarte una historia para ilustrar el concepto.

Amo las películas. Durante algún tiempo en el pasado, supe qué películas estaban compitiendo por la mejor categoría de películas en los Oscar o los mejores actores y actrices. Y ciertamente sabría cuáles obtuvieron la estatua para ese año. Pero ahora estoy oxidado en ese tema. Si me preguntaras quién estaba compitiendo, no lo sabría. E incluso si intentara responderte, te daría una respuesta débil.

Entonces, para proporcionarle una respuesta de calidad, haré lo que todos los demás hagan: buscar la información en línea, obtenerla y luego dártela. Lo que acabo de hacer es la misma idea que el trapo: obtuve datos de una base de datos externa para darle una respuesta.

Cuando mejoramos el LLM con un tienda de contenido a donde puede ir y recuperar datos aumentar (aumentar) su base de conocimiento, ese es el marco de trapo en acción.

Rag es como crear una tienda de contenido donde el modelo puede mejorar su conocimiento y responder con mayor precisión.

Solicitud del usuario sobre Content C. LLM recupera contenido externo para agregar a la respuesta. Imagen del autor.

Resumen:

  1. Utiliza algoritmos de búsqueda para consultar fuentes de datos externas, como bases de datos, bases de conocimiento y páginas web.
  2. Preprocesos la información recuperada.
  3. Incorpora la información preprocesada en el LLM.

¿Por qué usar trapo?

Ahora que sabemos cuál es el marco de RAG, comprendamos por qué deberíamos usarlo.

Estos son algunos de los beneficios:

  • Mejora la precisión objetiva haciendo referencia a datos reales.
  • RAG puede ayudar a LLMS a procesar y consolidar el conocimiento para crear respuestas más relevantes
  • RAG puede ayudar a LLMS a acceder a bases de conocimiento adicionales, como datos de organización internos
  • Rag puede ayudar a LLM a crear contenido más preciso específico de dominio
  • El trapo puede ayudar a reducir las brechas de conocimiento y la alucinación de IA

Como se explicó anteriormente, me gusta decir que con el marco RAG, estamos dando un motor de búsqueda interno para el contenido que queremos que agregue a la base de conocimiento.

Bien. Todo eso es muy interesante. Pero veamos una aplicación de trapo. Aprenderemos a crear un asistente de lector PDF con AI.

Proyecto

Esta es una aplicación que permite a los usuarios cargar un documento PDF y hacer preguntas sobre su contenido utilizando herramientas de procesamiento del lenguaje natural con IA (PNL).

  • La aplicación usa Streamlit como la parte delantera.
  • LangchainModelo GPT-4 de OpenAi, y FAISS (Búsqueda de similitud de AI de Facebook) para la recuperación de documentos y la respuesta de las preguntas en el backend.

Rompamos los pasos para una mejor comprensión:

  1. Cargando un archivo PDF y dividiéndolo en trozos de texto.
    1. Esto hace que los datos sean optimizados para la recuperación
  2. Presente los trozos a una herramienta de incrustación.
    1. Los incrustaciones son representaciones vectoriales numéricas de datos utilizados para capturar relaciones, similitudes y significados de una manera que las máquinas puedan entender. Son ampliamente utilizados en el procesamiento del lenguaje natural (PNL), los sistemas de recomendación y los motores de búsqueda.
  3. A continuación, ponemos esos trozos de texto e incrustaciones en el mismo DB para la recuperación.
  4. Finalmente, lo ponemos a disposición del LLM.

Preparación de datos

Preparando un tienda de contenido Para el LLM tomará algunos pasos, como acabamos de ver. Entonces, comencemos creando una función que pueda cargar un archivo y dividirlo en fragmentos de texto para una recuperación eficiente.

# Imports
from  langchain_community.document_loaders import PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter

def load_document(pdf):
    # Load a PDF
    """
    Load a PDF and split it into chunks for efficient retrieval.

    :param pdf: PDF file to load
    :return: List of chunks of text
    """

    loader = PyPDFLoader(pdf)
    docs = loader.load()

    # Instantiate Text Splitter with Chunk Size of 500 words and Overlap of 100 words so that context is not lost
    text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=100)
    # Split into chunks for efficient retrieval
    chunks = text_splitter.split_documents(docs)

    # Return
    return chunks

A continuación, comenzaremos a construir nuestra aplicación de transmisión, y usaremos esa función en el siguiente script.

Aplicación web

Comenzaremos a importar los módulos necesarios en Python. La mayoría de ellos vendrán de los paquetes de Langchain.

FAISS se usa para la recuperación de documentos; OpenAIEmbeddings Transforma los fragmentos de texto en puntajes numéricos para un mejor cálculo de similitud por parte de LLM; ChatOpenAI es lo que nos permite interactuar con la API Operai; create_retrieval_chain es lo que realmente hace el trapo, recuperar y aumentar el LLM con esos datos; create_stuff_documents_chain pega el modelo y el chatpromptTemplate.

Nota: necesitará Generar una llave de OpenAI poder ejecutar este script. Si es la primera vez que crea su cuenta, obtiene algunos créditos gratuitos. Pero si lo tiene durante algún tiempo, es posible que tenga que agregar 5 dólares en créditos para poder acceder a la API de OpenAI. Una opción es usar la incrustación de Hugging Face.

# Imports
from langchain_community.vectorstores import FAISS
from langchain_openai import OpenAIEmbeddings
from langchain.chains import create_retrieval_chain
from langchain_openai import ChatOpenAI
from langchain.chains.combine_documents import create_stuff_documents_chain
from langchain_core.prompts import ChatPromptTemplate
from scripts.secret import OPENAI_KEY
from scripts.document_loader import load_document
import streamlit as st

Este primer fragmento de código creará el título de la aplicación, creará un cuadro para la carga de archivos y preparará el archivo que se agregará al load_document() función.

# Create a Streamlit app
st.title("AI-Powered Document Q&A")

# Load document to streamlit
uploaded_file = st.file_uploader("Upload a PDF file", type="pdf")

# If a file is uploaded, create the TextSplitter and vector database
if uploaded_file :

    # Code to work around document loader from Streamlit and make it readable by langchain
    temp_file = "./temp.pdf"
    with open(temp_file, "wb") as file:
        file.write(uploaded_file.getvalue())
        file_name = uploaded_file.name

    # Load document and split it into chunks for efficient retrieval.
    chunks = load_document(temp_file)

    # Message user that document is being processed with time emoji
    st.write("Processing document... :watch:")

Las máquinas entienden los números mejor que el texto, por lo que al final, tendremos que proporcionar al modelo una base de datos de números que puede comparar y verificar la similitud al realizar una consulta. Ahí es donde el embeddings Será útil para crear el vector_dben este siguiente código.

# Generate embeddings
    # Embeddings are numerical vector representations of data, typically used to capture relationships, similarities,
    # and meanings in a way that machines can understand. They are widely used in Natural Language Processing (NLP),
    # recommender systems, and search engines.
    embeddings = OpenAIEmbeddings(openai_api_key=OPENAI_KEY,
                                  model="text-embedding-ada-002")

    # Can also use HuggingFaceEmbeddings
    # from langchain_huggingface.embeddings import HuggingFaceEmbeddings
    # embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2")

    # Create vector database containing chunks and embeddings
    vector_db = FAISS.from_documents(chunks, embeddings)

A continuación, creamos un objeto Retriever para navegar en el vector_db.

# Create a document retriever
    retriever = vector_db.as_retriever()
    llm = ChatOpenAI(model_name="gpt-4o-mini", openai_api_key=OPENAI_KEY)

Entonces, crearemos el system_promptque es un conjunto de instrucciones para el LLM sobre cómo responder, y crearemos una plantilla de aviso, preparándola para agregar al modelo una vez que obtengamos la entrada del usuario.

# Create a system prompt
    # It sets the overall context for the model.
    # It influences tone, style, and focus before user interaction starts.
    # Unlike user inputs, a system prompt is not visible to the end user.

    system_prompt = (
        "You are a helpful assistant. Use the given context to answer the question."
        "If you don't know the answer, say you don't know. "
        "{context}"
    )

    # Create a prompt Template
    prompt = ChatPromptTemplate.from_messages(
        [
            ("system", system_prompt),
            ("human", "{input}"),
        ]
    )

    # Create a chain
    # It creates a StuffDocumentsChain, which takes multiple documents (text data) and "stuffs" them together before passing them to the LLM for processing.

    question_answer_chain = create_stuff_documents_chain(llm, prompt)

Continuando, creamos el núcleo del marco de trapo, pegando juntos el retriever objeto y el prompt. Este objeto agrega documentos relevantes de una fuente de datos (por ejemplo, una base de datos vectorial) y lo prepara para procesarse utilizando un LLM para generar una respuesta.

# Creates the RAG
     chain = create_retrieval_chain(retriever, question_answer_chain)

Finalmente, creamos la variable question para la entrada del usuario. Si este cuadro de preguntas está lleno de una consulta, la pasamos a la chainque llama a la LLM para procesar y devolver la respuesta, que se imprimirá en la pantalla de la aplicación.

# Streamlit input for question
    question = st.text_input("Ask a question about the document:")
    if question:
        # Answer
        response = chain.invoke({"input": question})['answer']
        st.write(response)

Aquí hay una captura de pantalla del resultado.

Captura de pantalla de las preguntas y respuestas de documentos con IA
Captura de pantalla de la aplicación final. Imagen del autor.

Y este es un gif para que vea al lector de archivos Asistente de IA ¡en acción!

GIF del asistente de IA del lector de archivos en acción
Archivo Reader AI Asistente en acción. Imagen del autor.

Antes de que te vayas

En este proyecto, aprendimos cuál es el marco de trapo y cómo ayuda al LLM Para desempeñarse mejor y también desempeñarse bien con un conocimiento específico.

La IA puede alimentarse con el conocimiento de un manual de instrucciones, bases de datos de una empresa, algunos archivos financieros o contratos, y luego ajustarse a responder con precisión a consultas de contenido específicas de dominio. La base de conocimiento es aumentado con una tienda de contenido.

Para recapitular, así es como funciona el marco:

1minte⃣ Consulta de usuario → Se recibe el texto de entrada.

2minte⃣ Recuperar documentos relevantes → Búsqueda de una base de conocimiento (por ejemplo, una base de datos, tienda vectorial).

3️⃣ Contexto de aumento → Los documentos recuperados se agregan a la entrada.

4minte⃣ Generar respuesta → Un LLM procesa la entrada combinada y produce una respuesta.

Repositorio de Github

https://github.com/gurezende/basic-rag

Acerca de mí

Si le gustó este contenido y desea obtener más información sobre mi trabajo, aquí está mi sitio web, donde también puede encontrar todos mis contactos.

https://gustavorsantos.me

Referencias

https://cloud.google.com/use-cases/rrieval-ommented-generation

https://www.ibm.com/think/topics/retrieval-ommented-generation

https://youtu.be/t-d1ofcdw1m?si=G0UWFH5-WZNMU0NW

https://python.langchain.com/docs/introduction

https://www.geeksforgeeks.org/how-to-get-your-own-openai-api- key