Generación mejorada por recuperación (RAG) De la teoría a la implementación de LangChain

Generación mejorada a través de la recuperación (RAG) De la teoría a la implementación de LangChain

Desde la teoría del artículo académico original hasta su implementación en Python con OpenAI, Weaviate y LangChain

Flujo de trabajo de generación mejorada con recuperación

Desde que se descubrió que se puede potenciar los modelos de lenguaje grande (LLMs) con datos propietarios, ha existido cierta discusión sobre cómo unir de manera más efectiva el conocimiento general de LLM y los datos propietarios. Ha habido mucho debate sobre si el ajuste fino o la generación mejorada con recuperación (RAG) es más adecuado para esto (spoiler: es ambos).

Este artículo se enfoca primero en el concepto de RAG y cubre su teoría. Luego, muestra cómo se puede implementar una tubería RAG simple utilizando LangChain para la orquestación, modelos de lenguaje de OpenAI y una base de datos de vectores Weaviate.

Qué es la generación mejorada con recuperación

La generación mejorada con recuperación (RAG) es el concepto de proporcionar a los LLMs información adicional de una fuente de conocimiento externa. Esto les permite generar respuestas más precisas y contextuales al reducir las alucinaciones.

Problema

Los LLMs de vanguardia se entrenan con grandes cantidades de datos para lograr un amplio espectro de conocimiento general almacenado en los pesos de la red neural (memoria paramétrica). Sin embargo, al solicitar a un LLM que genere un resultado que requiere conocimiento que no fue incluido en sus datos de entrenamiento, como información más reciente, propia o específica del dominio, puede conducir a inexactitudes factuales (alucinaciones), como se ilustra en la siguiente captura de pantalla:

Respuesta de ChatGPT a la pregunta, “¿Qué dijo el presidente sobre Justice Breyer?”

Por lo tanto, es importante cerrar la brecha entre el conocimiento general de LLM y cualquier contexto adicional para ayudar al LLM a generar resultados más precisos y contextuales al reducir las alucinaciones.

Solución

Tradicionalmente, las redes neuronales se adaptan a información específica del dominio o propietaria mediante el ajuste fino del modelo. Aunque esta técnica es efectiva, también requiere mucha capacidad de cálculo, es costosa y requiere experiencia técnica, lo que dificulta la adaptación a la información en constante evolución.

En 2020, Lewis et al. propusieron una técnica más flexible llamada generación mejorada con recuperación (RAG) en el artículo Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks [1]. En este artículo, los investigadores combinaron un modelo generativo con un módulo recuperador para proporcionar información adicional de una fuente de conocimiento externa que se puede actualizar con mayor facilidad.

En términos sencillos, RAG es para LLMs lo que un examen con libros abiertos es para los humanos. En un examen con libros abiertos, los estudiantes pueden llevar materiales de referencia, como libros de texto o apuntes, que pueden utilizar para buscar información relevante y responder una pregunta. La idea detrás de un examen de libros abiertos es que el enfoque se centra en las habilidades de razonamiento de los estudiantes en lugar de su capacidad para memorizar información específica.

De manera similar, el conocimiento factual se separa de la capacidad de razonamiento de LLM y se almacena en una fuente de conocimiento externa, que se puede acceder y actualizar fácilmente:

  • Conocimiento paramétrico: Aprendido durante el entrenamiento y almacenado implícitamente en los pesos de la red neural.
  • Conocimiento no paramétrico: Almacenado en una fuente de conocimiento externa, como una base de datos de vectores.

(Por cierto, no se me ocurrió esta brillante comparación. Hasta donde sé, esta comparación fue mencionada por primera vez por JJ durante la competencia Kaggle – LLM Science Exam.)

El flujo de trabajo de RAG de vainilla se ilustra a continuación:

Flujo de trabajo de generación con recuperación mejorada
  1. Recuperar: Se utiliza la consulta del usuario para recuperar el contexto relevante de una fuente de conocimiento externa. Para esto, la consulta del usuario se incrusta en un modelo de incrustación en el mismo espacio vectorial que el contexto adicional en la base de datos vectorial. Esto permite realizar una búsqueda de similitud y se devuelven los k objetos de datos más cercanos de la base de datos vectorial.
  2. Agregar: Se introduce la consulta del usuario y el contexto adicional recuperado en una plantilla de enunciado.
  3. Generar: Finalmente, se alimenta el enunciado con recuperación y aumento al LLM.

Implementación de generación con recuperación mejorada utilizando LangChain

Esta sección implementa una tubería RAG en Python utilizando un LLM de OpenAI en combinación con una base de datos vectorial de Weaviate y un modelo de incrustación de OpenAI. Se utiliza LangChain para la orquestación.

Si no está familiarizado con LangChain o Weaviate, es posible que desee consultar los siguientes dos artículos:

Puesta en marcha de LangChain: Una guía para principiantes para construir aplicaciones con LLM

Un tutorial de LangChain para construir cualquier cosa con modelos de lenguaje en Python

towardsdatascience.com

Puesta en marcha de Weaviate: Una guía para principiantes para búsqueda con bases de datos vectoriales

Cómo utilizar bases de datos vectoriales para búsqueda semántica, respuesta a preguntas y búsqueda generativa en Python con OpenAI y…

towardsdatascience.com

Prerrequisitos

Asegúrese de haber instalado los paquetes de Python requeridos:

  • langchain para la orquestación
  • openai para el modelo de incrustación y el LLM
  • weaviate-client para la base de datos vectorial
#!pip install langchain openai weaviate-client

Además, defina sus variables de entorno relevantes en un archivo .env en su directorio raíz. Para obtener una clave de API de OpenAI, necesita una cuenta de OpenAI y luego “Crear nueva clave secreta” en claves de API.

OPENAI_API_KEY="<TU_CLAVE_API_DE_OPENAI>"

Luego, ejecute el siguiente comando para cargar las variables de entorno relevantes.

import dotenvdotenv.load_dotenv()

Preparación

Como paso de preparación, debe preparar una base de datos vectorial como fuente de conocimiento externa que contenga toda la información adicional. Esta base de datos vectorial se llena siguiendo estos pasos:

  1. Recopile y cargue sus datos
  2. Divida sus documentos
  3. Inserte y almacene las divisiones

El primer paso es recopilar y cargar tus datos — Para este ejemplo, utilizarás el discurso del Estado de la Unión del Presidente Biden de 2022 como contexto adicional. El documento de texto sin procesar está disponible en el repositorio de GitHub de LangChain. Para cargar los datos, puedes utilizar uno de los muchos DocumentLoader incorporados en LangChain. Un Document es un diccionario con texto y metadatos. Para cargar el texto, utilizarás el TextLoader de LangChain.

import requestsfrom langchain.document_loaders import TextLoaderurl = "https://raw.githubusercontent.com/langchain-ai/langchain/master/docs/docs/modules/state_of_the_union.txt"res = requests.get(url)with open("state_of_the_union.txt", "w") as f:    f.write(res.text)loader = TextLoader('./state_of_the_union.txt')documents = loader.load()

A continuación, fragmenta tus documentos — Debido a que el Document, en su estado original, es demasiado largo para caber en la ventana de contexto del LLM, debes fragmentarlo en trozos más pequeños. LangChain cuenta con muchos divisores de texto incorporados para este propósito. Para este ejemplo sencillo, puedes usar el CharacterTextSplitter con un chunk_size de aproximadamente 500 y un chunk_overlap de 50 para mantener la continuidad del texto entre los fragmentos.

from langchain.text_splitter import CharacterTextSplittertext_splitter = CharacterTextSplitter(chunk_size=500, chunk_overlap=50)chunks = text_splitter.split_documents(documents)

Por último, incrusta y guarda los fragmentos — Para permitir la búsqueda semántica en los fragmentos de texto, debes generar los vectores de embeddings para cada fragmento y luego almacenarlos junto con sus embeddings. Puedes utilizar el modelo de embedding de OpenAI para generar los vectores de embeddings y utilizar la base de datos vectorial Weaviate para almacenarlos. Al llamar a .from_documents(), la base de datos vectorial se poblara automáticamente con los fragmentos.

from langchain.embeddings import OpenAIEmbeddingsfrom langchain.vectorstores import Weaviateimport weaviatefrom weaviate.embedded import EmbeddedOptionsclient = weaviate.Client(  embedded_options = EmbeddedOptions())vectorstore = Weaviate.from_documents(    client = client,        documents = chunks,    embedding = OpenAIEmbeddings(),    by_text = False)

Paso 1: Recuperar

Una vez que la base de datos vectorial esté poblada, puedes definirla como el componente recuperador, que recupera el contexto adicional en función de la similitud semántica entre la consulta del usuario y los fragmentos incrustados.

retriever = vectorstore.as_retriever()

Paso 2: Ampliar

A continuación, para ampliar la consulta con el contexto adicional, debes preparar una plantilla de consulta. La consulta se puede personalizar fácilmente a partir de una plantilla de consulta, como se muestra a continuación.

from langchain.prompts import ChatPromptTemplatetemplate = """Eres un asistente para tareas de pregunta-respuesta. Utiliza los siguientes fragmentos de contexto recuperado para responder la pregunta. Si no sabes la respuesta, simplemente di que no lo sabes. Utiliza como máximo tres frases y sé conciso en la respuesta.Pregunta: {question} Contexto: {context} Respuesta:"""prompt = ChatPromptTemplate.from_template(template)print(prompt)

Paso 3: Generar

Finalmente, puedes construir una cadena para la tubería RAG, encadenando el recuperador, la plantilla de consulta y el LLM. Una vez que la cadena RAG está definida, puedes invocarla.

from langchain.chat_models import ChatOpenAIfrom langchain.schema.runnable import RunnablePassthroughfrom langchain.schema.output_parser import StrOutputParserllm = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0)rag_chain = (    {"context": retriever,  "question": RunnablePassthrough()}     | prompt     | llm    | StrOutputParser() )query = "¿Qué dijo el presidente sobre el juez Breyer?"rag_chain.invoke(query)

"El presidente agradeció al juez Breyer por su servicio y reconoció su dedicación al servicio del país. El presidente también mencionó que nominó a la jueza Ketanji Brown Jackson como sucesora para continuar el legado de excelencia del juez Breyer."

Puedes ver el resultado del pipeline de RAG para este ejemplo específico ilustrado a continuación:

Flujo de trabajo de Generación Aumentada de Recuperación

Resumen

Este artículo cubrió el concepto de RAG, el cual fue presentado en el artículo Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks [1] de 2020. Después de cubrir algo de teoría detrás del concepto, incluyendo motivación y solución del problema, este artículo convirtió su implementación en Python. Este artículo implementó un pipeline de RAG utilizando un OpenAI LLM en combinación con una base de datos vectorial de Weaviate y un modelo de inserción de OpenAI. LangChain se utilizó para la orquestación.

¿Disfrutaste esta historia?

Suscríbete gratis para recibir notificaciones cuando publique una nueva historia.

Recibe un correo electrónico cada vez que Leonie Monigatti publique.

Recibe un correo electrónico cada vez que Leonie Monigatti publique. Al registrarte, crearás una cuenta en VoAGI si aún no lo has hecho…

VoAGI.com

Encuéntrame en LinkedIn, Twitter, y Kaggle!

Descargo de responsabilidad

Soy un Defensor del Desarrollador en Weaviate en el momento de la redacción de este artículo. Además de este artículo, también he agregado el mismo ejemplo al cuaderno de Weaviate en la documentación de LangChain. Alternativamente, puedes comenzar siguiendo la plantilla rag-weaviate en LangChain.

Referencias

Literatura

[1] Lewis, P., et al. (2020). Retrieval-augmented generation for knowledge-intensive NLP tasks. Avances en Procesamiento de Información Neural, 33, 9459–9474.

Imágenes

Si no se indica lo contrario, todas las imágenes fueron creadas por el 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

Aprendiendo el lenguaje de las moléculas para predecir sus propiedades

Este sistema de IA solo necesita una pequeña cantidad de datos para predecir propiedades moleculares, lo que podría a...

Inteligencia Artificial

Meta AI presenta AnyMAL el futuro de los modelos de lenguaje multimodal que conecta texto, imágenes, videos, audio y datos de sensores de movimiento.

En inteligencia artificial, uno de los desafíos fundamentales ha sido permitir que las máquinas comprendan y generen ...

Inteligencia Artificial

Cómo implementar la IA adaptativa en tu negocio.

La inteligencia artificial ha surgido como una tecnología poderosa que puede impulsar transformaciones sustanciales e...