Puede integrar MongoDB Vector Search con LangChain para realizar Recuperación con autoconsulta. Este tutorial muestra cómo usar el recuperador con autoconsulta para ejecutar consultas de búsqueda vectorial de MongoDB en lenguaje natural con filtrado de metadatos.
La recuperación con autoconsulta utiliza un LLM para procesar tu consulta de búsqueda, identificar posibles filtros de metadatos, formar una consulta estructurada de búsqueda vectorial con los filtros y luego ejecutar la query para recuperar los documentos más relevantes.
Ejemplo
Con una query como "¿Cuáles son las películas de suspenso posteriores a 2010 con puntuaciones superiores a 8?", el recuperador puede identificar filtros sobre el genre, year, y rating campos, y usa esos filtros para recuperar los documentos que cumplen con la query.
Trabaja con una versión ejecutable de este tutorial como Cuaderno de Python.
Requisitos previos
Para completar este tutorial, debes tener lo siguiente:
Uno de los siguientes tipos de clúster de MongoDB:
Un clúster de Atlas ejecutando la versión 6.0.11 de MongoDB, 7.0.2, o posterior. Asegúrate de que tu La dirección IP está incluida en la lista de accesode tu 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 de API de Voyage AI. Para obtener más información, consulta la Documentación de Voyage AI.
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.
Usa MongoDB como Vector Store
En esta sección, crearás una instancia de almacenamiento vectorial usando tu clúster de MongoDB como base de datos vectorial.
Configura el entorno.
Configura el entorno para este tutorial. Cree un cuaderno interactivo de Python guardando un archivo con la extensión .ipynb. Este cuaderno te permite ejecutar snippets de código Python de forma individual y lo utilizarás para ejecutar el código en este tutorial.
Para configurar el entorno de su portátil:
Ejecuta el siguiente comando en tu notebook:
pip install --quiet --upgrade langchain-mongodb langchain-voyageai langchain-openai langchain langchain-core lark 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, consulta Conectar a un clúster a través de bibliotecas de clientes.
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 la tienda de vectores.
Ejecuta el siguiente código en tu notebook para crear una instancia de vector store llamada vector_store utilizando el espacio de nombres langchain_db.self_query 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.self_query", text_key = "page_content" )
Añade datos al almacén vectorial.
Pegue y ejecute el siguiente código en su cuaderno para ingerir algunos documentos de muestra con metadatos en su colección en MongoDB.
from langchain_core.documents import Document docs = [ Document( page_content="A bunch of scientists bring back dinosaurs and mayhem breaks loose", metadata={"year": 1993, "rating": 7.7, "genre": "action"}, ), Document( page_content="A fight club that is not a fight club, but is a fight club", metadata={"year": 1994, "rating": 8.7, "genre": "action"}, ), Document( page_content="Leo DiCaprio gets lost in a dream within a dream within a dream within a ...", metadata={"year": 2010, "genre": "thriller", "rating": 8.2}, ), Document( page_content="A bunch of normal-sized women are supremely wholesome and some men pine after them", metadata={"year": 2019, "rating": 8.3, "genre": "drama"}, ), Document( page_content="Three men walk into the Zone, three men walk out of the Zone", metadata={"year": 1979, "rating": 9.9, "genre": "science fiction"}, ), Document( page_content="A psychologist / detective gets lost in a series of dreams within dreams within dreams and Inception reused the idea", metadata={"year": 2006, "genre": "thriller", "rating": 9.0}, ), Document( page_content="Toys come alive and have a blast doing so", metadata={"year": 1995, "genre": "animated", "rating": 9.3}, ), Document( page_content="The toys come together to save their friend from a kid who doesn't know how to play with them", metadata={"year": 1997, "genre": "animated", "rating": 9.1}, ), ] # Add data to the vector store, which automaticaly embeds the documents vector_store.add_documents(docs)
Si se utiliza Atlas, se pueden verificar las incrustaciones vectoriales navegando hasta el namespace langchain_db.self_query en la Interfaz de usuario de Atlas.
Cree el índice de búsqueda vectorial de MongoDB con filtros.
Ejecute el siguiente código para crear el índice de MongoDB Vector Search con filtros para el vector store y habilite la búsqueda vectorial y el filtrado de metadatos 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 filters = [ "genre", "rating", "year" ], # The metadata fields to be indexed for filtering wait_until_complete = 60 # Number of seconds to wait for the index to build (can take around a minute) )
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.
Crear el recuperador de autoconsultas
En esta sección, inicializas el recuperador de auto-querying para query datos de tu almacén vectorial.
Describa los documentos y los campos de metadatos.
Para usar el recuperador de auto-consulta, debes describir los documentos en tu colección y los campos de metadatos sobre los que deseas filtrar. Esta información ayuda al LLM a comprender la estructura de tus datos y cómo filtrar los resultados en función de las consultas de los usuarios.
from langchain.chains.query_constructor.schema import AttributeInfo # Define the document content description document_content_description = "Brief summary of a movie" # Define the metadata fields to filter on metadata_field_info = [ AttributeInfo( name="genre", description="The genre of the movie", type="string", ), AttributeInfo( name="year", description="The year the movie was released", type="integer", ), AttributeInfo( name="rating", description="A 1-10 rating for the movie", type="float" ), ]
Inicializa el recuperador de auto-consulta.
Ejecútese el siguiente código para crear un recuperador de autosolicitudes utilizando el método MongoDBAtlasSelfQueryRetriever.from_llm.
from langchain_mongodb.retrievers import MongoDBAtlasSelfQueryRetriever from langchain_openai import ChatOpenAI llm = ChatOpenAI(model="gpt-4o") retriever = MongoDBAtlasSelfQueryRetriever.from_llm( llm=llm, vectorstore=vector_store, metadata_field_info=metadata_field_info, document_contents=document_content_description )
Ejecuta consultas con el recuperador de auto-consulta
Ejecuta las siguientes consultas para ver cómo el recuperador de consultas automáticas ejecuta diferentes tipos de consultas:
# This example specifies a filter (rating > 9) retriever.invoke("What are some highly rated movies (above 9)?")
[Document(id='686e84de13668e4048bf9ff3', metadata={'_id': '686e84de13668e4048bf9ff3', 'year': 1979, 'rating': 9.9, 'genre': 'science fiction'}, page_content='Three men walk into the Zone, three men walk out of the Zone'), Document(id='686e84de13668e4048bf9ff5', metadata={'_id': '686e84de13668e4048bf9ff5', 'year': 1995, 'genre': 'animated', 'rating': 9.3}, page_content='Toys come alive and have a blast doing so'), Document(id='686e84de13668e4048bf9ff6', metadata={'_id': '686e84de13668e4048bf9ff6', 'year': 1997, 'genre': 'animated', 'rating': 9.1}, page_content="The toys come together to save their friend from a kid who doesn't know how to play with them")]
# This example specifies a semantic search and a filter (rating > 9) retriever.invoke("I want to watch a movie about toys rated higher than 9")
[Document(id='686e84de13668e4048bf9ff5', metadata={'_id': '686e84de13668e4048bf9ff5', 'year': 1995, 'genre': 'animated', 'rating': 9.3}, page_content='Toys come alive and have a blast doing so'), Document(id='686e84de13668e4048bf9ff6', metadata={'_id': '686e84de13668e4048bf9ff6', 'year': 1997, 'genre': 'animated', 'rating': 9.1}, page_content="The toys come together to save their friend from a kid who doesn't know how to play with them"), Document(id='686e84de13668e4048bf9ff3', metadata={'_id': '686e84de13668e4048bf9ff3', 'year': 1979, 'rating': 9.9, 'genre': 'science fiction'}, page_content='Three men walk into the Zone, three men walk out of the Zone')]
# This example specifies a composite filter (rating >= 9 and genre = thriller) retriever.invoke("What's a highly rated (above or equal 9) thriller film?")
[Document(id='686e84de13668e4048bf9ff4', metadata={'_id': '686e84de13668e4048bf9ff4', 'year': 2006, 'genre': 'thriller', 'rating': 9.0}, page_content='A psychologist / detective gets lost in a series of dreams within dreams within dreams and Inception reused the idea')]
# This example specifies a query and composite filter (year > 1990 and year < 2005 and genre = action) retriever.invoke( "What's a movie after 1990 but before 2005 that's all about dinosaurs, " + "and preferably has the action genre" )
[Document(id='686e84de13668e4048bf9fef', metadata={'_id': '686e84de13668e4048bf9fef', 'year': 1993, 'rating': 7.7, 'genre': 'action'}, page_content='A bunch of scientists bring back dinosaurs and mayhem breaks loose'), Document(id='686e84de13668e4048bf9ff0', metadata={'_id': '686e84de13668e4048bf9ff0', 'year': 1994, 'rating': 8.7, 'genre': 'action'}, page_content='A fight club that is not a fight club, but is a fight club')]
# This example only specifies a semantic search query retriever.invoke("What are some movies about dinosaurs")
[Document(id='686e84de13668e4048bf9fef', metadata={'_id': '686e84de13668e4048bf9fef', 'year': 1993, 'rating': 7.7, 'genre': 'action'}, page_content='A bunch of scientists bring back dinosaurs and mayhem breaks loose'), Document(id='686e84de13668e4048bf9ff5', metadata={'_id': '686e84de13668e4048bf9ff5', 'year': 1995, 'genre': 'animated', 'rating': 9.3}, page_content='Toys come alive and have a blast doing so'), Document(id='686e84de13668e4048bf9ff1', metadata={'_id': '686e84de13668e4048bf9ff1', 'year': 2010, 'genre': 'thriller', 'rating': 8.2}, page_content='Leo DiCaprio gets lost in a dream within a dream within a dream within a ...'), Document(id='686e84de13668e4048bf9ff6', metadata={'_id': '686e84de13668e4048bf9ff6', 'year': 1997, 'genre': 'animated', 'rating': 9.1}, page_content="The toys come together to save their friend from a kid who doesn't know how to play with them")]
Utiliza el recuperador en tu pipeline RAG
Puedes usar el recuperador de auto-consulta en tu pipeline RAG. Pega y ejecuta el siguiente código en tu notebook para implementar un pipeline de RAG de muestra que realice una recuperación mediante auto-consulta.
Este código también configura el recuperador para usar el parámetro enable_limit, que permite al LLM limitar el número de documentos devueltos por el recuperador si es necesario. La respuesta generada puede variar.
import pprint from langchain_core.output_parsers import StrOutputParser from langchain_core.prompts import PromptTemplate from langchain_core.runnables import RunnablePassthrough from langchain_openai import ChatOpenAI llm = ChatOpenAI(model="gpt-4o") # Configure self-query retriever with a document limit retriever = MongoDBAtlasSelfQueryRetriever.from_llm( llm, vector_store, document_content_description, metadata_field_info, enable_limit=True ) # Define a prompt template template = """ Use the following pieces of context to answer the question at the end. {context} Question: {question} """ prompt = PromptTemplate.from_template(template) # Construct a chain to answer questions on your data chain = ( { "context": retriever, "question": RunnablePassthrough()} | prompt | llm | StrOutputParser() ) # Prompt the chain question = "What are two movies about toys after 1990?" # year > 1990 and document limit of 2 answer = chain.invoke(question) print("Question: " + question) print("Answer: " + answer) # Return source documents documents = retriever.invoke(question) print("\nSource documents:") pprint.pprint(documents)
Question: What are two movies about toys after 1990? Answer: The two movies about toys after 1990 are: 1. The 1995 animated movie (rated 9.3) where toys come alive and have fun. 2. The 1997 animated movie (rated 9.1) where toys work together to save their friend from a kid who doesn’t know how to play with them. Source documents: [Document(id='686e84de13668e4048bf9ff5', metadata={'_id': '686e84de13668e4048bf9ff5', 'year': 1995, 'genre': 'animated', 'rating': 9.3}, page_content='Toys come alive and have a blast doing so'), Document(id='686e84de13668e4048bf9ff6', metadata={'_id': '686e84de13668e4048bf9ff6', 'year': 1997, 'genre': 'animated', 'rating': 9.1}, page_content="The toys come together to save their friend from a kid who doesn't know how to play with them")]