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](https://ai.miximages.com/miro.medium.com/v2/resize:fit:640/format:webp/1*kSkeaXRvRzbJ9SrFZaMoOg.png)
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:
- TSMixer El último modelo de pronóstico de Google
- Perspectivas de expertos sobre el desarrollo de marcos de IA seguros, confiables y confiables
- De la Ficción a la Realidad ChatGPT y el Sueño de Ciencia Ficción de una Verdadera Conversación de AI
![Respuesta de ChatGPT a la pregunta, “¿Qué dijo el presidente sobre Justice Breyer?”](https://ai.miximages.com/miro.medium.com/v2/resize:fit:640/format:webp/1*4PuXxZJra3Ki1GE1aKqvIQ.png)
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](https://ai.miximages.com/miro.medium.com/v2/resize:fit:640/format:webp/1*kSkeaXRvRzbJ9SrFZaMoOg.png)
- 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.
- Agregar: Se introduce la consulta del usuario y el contexto adicional recuperado en una plantilla de enunciado.
- 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ónopenai
para el modelo de incrustación y el LLMweaviate-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:
- Recopile y cargue sus datos
- Divida sus documentos
- 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](https://ai.miximages.com/miro.medium.com/v2/resize:fit:640/format:webp/1*EF7wzF_mTbT-CK0OwEGzyQ.png)
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!
Was this article helpful?
93 out of 132 found this helpful
Related articles
- Microsoft Azure Potenciando el futuro de la computación en la nube
- ¿Puede la generación sintética de texto clínico revolucionar las tareas de IA clínica? Conozca a ClinGen un modelo de IA que implica la extracción de conocimientos clínicos y la generación de indicaciones de LLM informadas por contexto.
- ¿Se pueden simplificar los bloques de transformador sin comprometer la eficiencia? Este artículo de inteligencia artificial de ETH Zurich explora el equilibrio entre la complejidad del diseño y el rendimiento.
- Repositorios de tendencias de IA en GitHub semana del 13 de noviembre de 2023
- OpenAI busca financiamiento adicional para la Inteligencia Artificial General
- Un hombre con Parkinson recuperó la capacidad de caminar, gracias a un implante espinal
- Una nueva investigación de Microsoft AI propone HMD-NeMo un nuevo enfoque que aborda la generación de movimientos de cuerpo completo plausibles y precisos incluso cuando las manos puedan estar parcialmente visibles.