Este tutorial demuestra cómo mejorar su AplicacionesRAG agregando memoria de conversación y almacenamiento en caché semántico mediante la integración LangChain MongoDB.
La memoria le permite mantener el contexto de la conversación a lo largo de múltiples interacciones de usuarios.
El almacenamiento en caché semántico reduce la latencia de respuesta al almacenar en caché consultas semánticamente similares.
Trabaje con una versión ejecutable de este tutorial como Cuaderno de Python.
Requisitos previos
Antes de comenzar, asegúrate de tener lo siguiente:
Uno de los siguientes tipos de clúster de MongoDB:
An Clúster Atlas con MongoDB 6.0.11 versión, 7.0.2 o posterior. Asegúrese de que su dirección IP esté incluida en la lista de acceso de su proyecto Atlas.
Una implementación local de Atlas creada usando Atlas CLI. Para obtener más información, consulta Crear una Implementación local de Atlas.
Un clúster de MongoDB Community o Enterprise con Search y Vector Search instalados.
Una clave API de Voyage AI. Para crear una clave API, consulta Claves API de modelos.
Una llave de API de OpenAI. Debes tener una cuenta de OpenAI con créditos disponibles para las solicitudes de API. Para obtener más información sobre cómo registrar una cuenta de OpenAI, consulta el sitio web de la API de OpenAI.
Un entorno para ejecutar cuadernos interactivos de Python como Colab.
Utilice MongoDB como almacén de vectores
En esta sección, creará una instancia de tienda de vectores utilizando su clúster MongoDB como base de datos de vectores.
Configura el entorno.
Configura el entorno para este tutorial. Crea un cuaderno interactivo de Python guardando un archivo con el .ipynb Extensión. Este cuaderno te permite ejecutar fragmentos de código Python individualmente y lo usarás para ejecutar el código en este tutorial.
Para configurar el entorno de su portátil:
Ejecute el siguiente comando en su cuaderno:
pip install --quiet --upgrade langchain langchain-community langchain-core langchain-mongodb langchain-voyageai langchain-openai pypdf Establecer variables de entorno.
Ejecute el siguiente código para establecer las variables de entorno para este tutorial. Proporcione su clave de API de Voyage, la clave de API de OpenAI y la SRV cadena de conexión.del clúster de MongoDB
import os os.environ["OPENAI_API_KEY"] = "<openai-key>" os.environ["VOYAGE_API_KEY"] = "<voyage-key>" MONGODB_URI = "<connection-string>" Nota
Se debe sustituir
<connection-string>por la cadena de conexión del clúster Atlas o de la implementación local de Atlas.Su cadena de conexión debe usar el siguiente formato:
mongodb+srv://<db_username>:<db_password>@<clusterName>.<hostname>.mongodb.net Para obtener más información,consulte Conectarse a un clúster a través de bibliotecas de cliente.
Su cadena de conexión debe usar el siguiente formato:
mongodb://localhost:<port-number>/?directConnection=true Para obtener más información, consulta Cadenas de conexión.
Instanciar el almacén de vectores.
Pegue y ejecute el siguiente código en su cuaderno para crear una instancia de almacén de vectores denominada vector_store utilizando el espacio de nombres langchain_db.rag_with_memory en MongoDB:
from langchain_mongodb import MongoDBAtlasVectorSearch from langchain_voyageai import VoyageAIEmbeddings # Use the voyage-3-large embedding model embedding_model = VoyageAIEmbeddings(model="voyage-3-large") # Create the vector store vector_store = MongoDBAtlasVectorSearch.from_connection_string( connection_string = MONGODB_URI, embedding = embedding_model, namespace = "langchain_db.rag_with_memory" )
Añade datos al almacén de vectores.
Pegue y ejecute el siguiente código en su cuaderno para ingerir un PDF de muestra que contiene un informe de ganancias reciente de MongoDB en la tienda de vectores.
Este código utiliza un divisor de texto para fragmentar los datos PDF en documentos principales más pequeños. Especifica el tamaño del fragmento (número de caracteres) y la superposición de fragmentos (número de caracteres superpuestos entre fragmentos consecutivos) para cada documento.
from langchain_community.document_loaders import PyPDFLoader from langchain_text_splitters import RecursiveCharacterTextSplitter # Load the PDF loader = PyPDFLoader("https://investors.mongodb.com/node/13176/pdf") data = loader.load() # Split PDF into documents text_splitter = RecursiveCharacterTextSplitter(chunk_size=200, chunk_overlap=20) docs = text_splitter.split_documents(data) # Add data to the vector store vector_store.add_documents(docs)
Tip
Después de ejecutar este código, si estás usando Atlas, puedes verificar tus incrustaciones vectoriales navegando al langchain_db.rag_with_memory namespace en la Interfaz de Usuario de Atlas.
Crea el índice de búsqueda vectorial de MongoDB.
Ejecute el siguiente código para crear el índice de búsqueda vectorial de MongoDB para el almacén de vectores para habilitar la búsqueda vectorial en sus datos:
# Use LangChain helper method to create the vector search index vector_store.create_vector_search_index( dimensions = 1024 # The dimensions of the vector embeddings to be indexed )
El índice debería tardar aproximadamente un minuto en crearse. Mientras se crea, el índice está en un estado de sincronización inicial. Cuando termine de crearse, se pueden empezar a realizar los query en los datos de la colección.
Implementar RAG con memoria
Esta sección demuestra cómo implementar RAG con memoria de conversación utilizando la integración LangChain MongoDB.
Define una función para obtener el historial de mensajes de chat.
Para mantener el historial de conversaciones en múltiples interacciones, use la MongoDBChatMessageHistory clase. Esta le permite almacenar mensajes de chat en una base de datos MongoDB y extenderlos a su cadena RAG para gestionar el contexto de la conversación.
Pegue y ejecute el siguiente código en su notebook para crear una función llamada get_session_history que devuelva una instancia MongoDBChatMessageHistory. Esta instancia recupera el historial de chat de una sesión específica.
from langchain_mongodb.chat_message_histories import MongoDBChatMessageHistory from langchain_core.runnables.history import RunnableWithMessageHistory from langchain_core.prompts import MessagesPlaceholder def get_session_history(session_id: str) -> MongoDBChatMessageHistory: return MongoDBChatMessageHistory( connection_string=MONGODB_URI, session_id=session_id, database_name="langchain_db", collection_name="rag_with_memory" )
Crea una cadena RAG que maneje el historial de mensajes de chat.
Pegue y ejecute los siguientes fragmentos de código para crear la cadena RAG:
Especifique el LLM a utilizar.
from langchain_openai import ChatOpenAI # Define the model to use for chat completion llm = ChatOpenAI(model = "gpt-4o") Define un mensaje que resuma el historial de chat del retriever.
from langchain_core.prompts import ChatPromptTemplate from langchain_core.output_parsers import StrOutputParser # Create a prompt to generate standalone questions from follow-up questions standalone_system_prompt = """ Given a chat history and a follow-up question, rephrase the follow-up question to be a standalone question. Do NOT answer the question, just reformulate it if needed, otherwise return it as is. Only return the final standalone question. """ standalone_question_prompt = ChatPromptTemplate.from_messages( [ ("system", standalone_system_prompt), MessagesPlaceholder(variable_name="history"), ("human", "{question}"), ] ) # Parse output as a string parse_output = StrOutputParser() question_chain = standalone_question_prompt | llm | parse_output Construya una cadena de recuperación que procese el historial de chat y recupere documentos.
from langchain_core.runnables import RunnablePassthrough # Create a retriever retriever = vector_store.as_retriever(search_type="similarity", search_kwargs={ "k": 5 }) # Create a retriever chain that processes the question with history and retrieves documents retriever_chain = RunnablePassthrough.assign(context=question_chain | retriever | (lambda docs: "\n\n".join([d.page_content for d in docs]))) Define un mensaje para generar una respuesta basada en el historial de chat y el contexto recuperado.
# Create a prompt template that includes the retrieved context and chat history rag_system_prompt = """Answer the question based only on the following context: {context} """ rag_prompt = ChatPromptTemplate.from_messages( [ ("system", rag_system_prompt), MessagesPlaceholder(variable_name="history"), ("human", "{question}"), ] ) Implementar RAG con memoria.
Combine los componentes que definió en una cadena RAG completa:
# Build the RAG chain rag_chain = ( retriever_chain | rag_prompt | llm | parse_output ) # Wrap the chain with message history rag_with_memory = RunnableWithMessageHistory( rag_chain, get_session_history, input_messages_key="question", history_messages_key="history", )
Pon a prueba tu implementación de RAG.
Invoque la cadena para responder preguntas. Esta cadena mantiene el contexto de la conversación y devuelve respuestas relevantes que consideran las interacciones previas. Sus respuestas pueden variar.
# First question response_1 = rag_with_memory.invoke( {"question": "What was MongoDB's latest acquisition?"}, {"configurable": {"session_id": "user_1"}} ) print(response_1)
MongoDB's latest acquisition was Voyage AI, a pioneer in state-of-the-art embedding and reranking models for next-generation AI applications.
# Follow-up question that references the previous question response_2 = rag_with_memory.invoke( {"question": "Why did they do it?"}, {"configurable": {"session_id": "user_1"}} ) print(response_2)
MongoDB acquired Voyage AI to enable organizations to easily build trustworthy AI applications by integrating advanced embedding and reranking models into their technology. This acquisition aligns with MongoDB's goal of helping businesses innovate at "AI speed" using its flexible document model and seamless scalability.
Agregar almacenamiento en caché semántico
Esta sección añade almacenamiento en caché semántico a la cadena RAG. El almacenamiento en caché semántico recupera las solicitudes almacenadas en caché según la similitud semántica entre las consultas.
Nota
Puede utilizar el almacenamiento en caché semántico independientemente de la memoria de conversación, pero para este tutorial utilice ambas funciones juntas.
Para ver un video tutorial de esta función, consulte Aprender mirando.
Configurar la caché semántica.
Ejecute el siguiente código para configurar el caché semántico utilizando la clase MongoDBAtlasSemanticCache:
from langchain_mongodb.cache import MongoDBAtlasSemanticCache from langchain_core.globals import set_llm_cache # Configure the semantic cache set_llm_cache(MongoDBAtlasSemanticCache( connection_string = MONGODB_URI, database_name = "langchain_db", collection_name = "semantic_cache", embedding = embedding_model, index_name = "vector_index", similarity_threshold = 0.5 # Adjust based on your requirements ))
Pruebe la caché semántica con su cadena RAG.
La caché semántica almacena automáticamente tus indicaciones. Ejecuta las siguientes consultas de ejemplo; deberías observar una reducción significativa en el tiempo de respuesta para la segunda consulta. Tus respuestas y tiempos de respuesta pueden variar.
Tip
Puede ver sus indicaciones almacenadas en caché en la colección semantic_cache. La caché semántica almacena solo la entrada al LLM. Al usarla en cadenas de recuperación, tenga en cuenta que los documentos recuperados pueden cambiar entre ejecuciones, lo que provoca errores de caché para consultas semánticamente similares.
%%time # First query (not cached) rag_with_memory.invoke( {"question": "What was MongoDB's latest acquisition?"}, {"configurable": {"session_id": "user_2"}} )
CPU times: user 54.7 ms, sys: 34.2 ms, total: 88.9 ms Wall time: 7.42 s "MongoDB's latest acquisition was Voyage AI, a pioneer in state-of-the-art embedding and reranking models that power next-generation AI applications."
%%time # Second query (cached) rag_with_memory.invoke( {"question": "What company did MongoDB acquire recently?"}, {"configurable": {"session_id": "user_2"}} )
CPU times: user 79.7 ms, sys: 24 ms, total: 104 ms Wall time: 3.87 s 'MongoDB recently acquired Voyage AI.'
Aprende observando
Sigue este video tutorial para aprender más sobre el almacenamiento en caché semántico con LangChain y MongoDB.
Duración: 30 minutos