Generación de recuperación aumentada (RAG): de la teoría a la implementación de LangChain |  de Leonie Monigatti |  noviembre de 2023

El primer paso es recoger y cargar sus datos — Para este ejemplo, utilizará Discurso sobre el estado de la Unión del presidente Biden de 2022 como contexto adicional. El documento de texto sin formato está disponible en Repositorio GitHub de LangChain. Para cargar los datos, puede utilizar uno de los muchos integrados de LangChain. DocumentLoaders. A Document es un diccionario con texto y metadatos. Para cargar texto, utilizará LangChain TextLoader.

import requests
from langchain.document_loaders import TextLoader

url = "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()

Próximo, fragmenta tus documentos – Porque el Document, en su estado original, es demasiado largo para caber en la ventana contextual del LLM, es necesario dividirlo en partes más pequeñas. LangChain viene con muchos integrados divisores de texto para este propósito. Para este ejemplo sencillo, puede utilizar el CharacterTextSplitter con un chunk_size de unos 500 y un chunk_overlap de 50 para preservar la continuidad del texto entre los fragmentos.

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

Por último, incrustar y almacenar los trozos — Para habilitar la búsqueda semántica en los fragmentos de texto, debe generar las incrustaciones de vectores para cada fragmento y luego almacenarlas junto con sus incrustaciones. Para generar incrustaciones de vectores, puede usar el modelo de incrustación de OpenAI y, para almacenarlas, puede usar la base de datos de vectores Weaviate. Llamando .from_documents() la base de datos de vectores se completa automáticamente con los fragmentos.

from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import Weaviate
import weaviate
from weaviate.embedded import EmbeddedOptions

client = weaviate.Client(
embedded_options = EmbeddedOptions()
)

vectorstore = Weaviate.from_documents(
client = client,
documents = chunks,
embedding = OpenAIEmbeddings(),
by_text = False
)

Paso 1: recuperar

Una vez que se completa la base de datos vectorial, puede 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: aumentar

A continuación, para aumentar el mensaje con contexto adicional, debe preparar una plantilla de mensaje. El mensaje se puede personalizar fácilmente desde una plantilla de mensaje, como se muestra a continuación.

from langchain.prompts import ChatPromptTemplate

template = """You are an assistant for question-answering tasks.
Use the following pieces of retrieved context to answer the question.
If you don't know the answer, just say that you don't know.
Use three sentences maximum and keep the answer concise.
Question: {question}
Context: {context}
Answer:
"""
prompt = ChatPromptTemplate.from_template(template)

print(prompt)

Paso 3: Generar

Finalmente, puede construir una cadena para la canalización RAG, encadenando el recuperador, la plantilla de aviso y el LLM. Una vez definida la cadena RAG, puede invocarla.

from langchain.chat_models import ChatOpenAI
from langchain.schema.runnable import RunnablePassthrough
from langchain.schema.output_parser import StrOutputParser

llm = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0)

rag_chain = (
{"context": retriever, "question": RunnablePassthrough()}
| prompt
| llm
| StrOutputParser()
)

query = "What did the president say about Justice Breyer"
rag_chain.invoke(query)

"The president thanked Justice Breyer for his service and acknowledged his dedication to serving the country. 
The president also mentioned that he nominated Judge Ketanji Brown Jackson as a successor to continue Justice Breyer's legacy of excellence."

Puede ver la canalización RAG resultante para este ejemplo específico que se ilustra a continuación:

Flujo de trabajo de recuperación de generación aumentada (RAG) desde la consulta del usuario
Flujo de trabajo de generación aumentada de recuperación

Este artículo cubrió el concepto de RAG, que se presentó en el artículo. Generación de recuperación aumentada para tareas de PNL con uso intensivo de conocimiento [1] de 2020. Después de cubrir algo de teoría detrás del concepto, incluida la motivación y la solución de problemas, este artículo convirtió su implementación en Python. Este artículo implementó una tubería RAG utilizando un Abierto AI LLM en combinación con un Weaviate base de datos vectorial y una Abierto AI modelo de incrustación. LangChain Fue utilizado para la orquestación.