Você pode integrar o MongoDB Vector Search ao LangChain para realizar a recuperação auto-consulta. Este tutorial demonstra como usar o retriever autoquery para executar queries do MongoDB Vector Search em linguagem natural com filtragem de metadados.
A recuperação autoconsulta usa um LLM para processar sua query de pesquisa para identificar possíveis filtros de metadados, forma uma query de pesquisa vetorial estruturada com os filtros e, em seguida, executa a consulta para recuperar os documentos mais relevantes.
Exemplo
Com uma consulta como "O que são filmes de ação depois de 2010 com classificações acima de 8?", O recuperador pode identificar filtros nos campos genre
, year
e rating
e usar esses filtros para recuperar documentos que correspondam à query.
Trabalhe com uma versão executável deste tutorial como um bloco de anotações Python.
Pré-requisitos
Para concluir este tutorial, você deve ter o seguinte:
Um dos seguintes tipos de cluster MongoDB :
Um Atlas cluster executando o MongoDB versão 6.0.11, 7.0.2 ou posterior. Garanta que seu endereço IP esteja incluído na lista de acessodo seu projeto Atlas.
Um sistema local do Atlas criado utilizando o Atlas CLI. Para saber mais, consulte Criar uma implantação de Atlas local.
Um cluster MongoDB Community ou Enterprise com Search e Vector Search instalados.
Uma chave de API do Voyage AI. Para saber mais, consulte Documentação da Voyage AI.
Uma chave de API da OpenAI. Você deve ter uma conta da OpenAI com créditos disponíveis para solicitações de API. Para aprender mais sobre como registrar uma conta OpenAI, consulte o website de API OpenAI.
Use o MongoDB como um armazenamento de vetores
Nesta seção, você cria uma instância de armazenamento de vetor usando seu cluster MongoDB como um banco de dados de vetor.
Configure o ambiente.
Configure o ambiente para este tutorial. Crie um bloco de anotações Python interativo salvando um arquivo com a extensão .ipynb
. Este bloco de anotações permite que você execute trechos de código Python individualmente, e você o usará para executar o código neste tutorial.
Para configurar seu ambiente de bloco de anotações:
Execute o seguinte comando no seu notebook:
pip install --quiet --upgrade langchain-mongodb langchain-voyageai langchain-openai langchain langchain-core lark Defina variáveis de ambiente.
Execute o seguinte código para definir as variáveis de ambiente para este tutorial. Forneça sua chave de API Voyage, chave de API OpenAI e a string de conexão SRV do cluster MongoDB.
import os os.environ["OPENAI_API_KEY"] = "<openai-key>" os.environ["VOYAGE_API_KEY"] = "<voyage-key>" MONGODB_URI = "<connection-string>" Observação
Substitua
<connection-string>
pela string de conexão do seu cluster do Atlas ou da implantação local do Atlas.Sua string de conexão deve usar o seguinte formato:
mongodb+srv://<db_username>:<db_password>@<clusterName>.<hostname>.mongodb.net Para saber mais, consulte Conectar a um cluster via drivers.
Sua string de conexão deve usar o seguinte formato:
mongodb://localhost:<port-number>/?directConnection=true Para saber mais, consulte Connection strings.
Instancie o armazenamento de vetores.
Execute o seguinte código em seu bloco de anotações para criar uma instância de armazenamento de vetor denominada vector_store
utilizando o namespace langchain_db.self_query
no 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" )
Adicione dados ao armazenamento de vetores.
Cole e execute o código a seguir em seu bloco de anotações para alimentar alguns documentos de exemplo com metadados em sua coleção no 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)
Se você estiver usando o Atlas, verifique suas incorporações vetoriais navegando até o namespace langchain_db.self_query
na UI do Atlas.
Crie o índice do MongoDB Vector Search com filtros.
Execute o código a seguir para criar o índice do MongoDB Vector Search com filtros para o armazenamento de vetores para ativar a pesquisa vetorial e a filtragem de metadados em seus dados:
# 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) )
O índice deve levar cerca de um minuto para ser criado. Enquanto ele é compilado, o índice está em um estado de sincronização inicial. Quando a construção estiver concluída, você poderá começar a fazer query nos dados em sua coleção.
Criar o recuperador autoconsultador
Nesta seção, você inicializa o recuperador de consulta automática para consultar dados de seu armazenamento de vetor.
Descrever os documentos e campos de metadados.
Para usar o recuperador de consulta automática, você deve descrever os documentos em sua coleção e os campos de metadados que deseja filtrar. Essas informações ajudam o LLM a entender a estrutura de seus dados e como filtrar os resultados com base nas queries do usuário.
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" ), ]
Inicialize o recuperador com consulta automática.
Execute o código a seguir para criar um recuperador de consulta automática usando o 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 )
Execute queries com o auto-querying Retriever
Execute as seguintes queries para ver como o retriever com auto-query executa diferentes tipos de query:
# 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")]
Utilize o retriever no seu pipeline RAG
Você pode usar o retriever autoquery em seu pipeline RAG. Cole e execute o seguinte código em seu bloco de anotações para implementar um exemplo de pipeline RAG que executa a recuperação por meio de autoconsulta.
Este código também configura o recuperador para usar o parâmetro enable_limit
, que permite ao LLM limitar o número de documentos retornados pelo recuperador, se necessário. A resposta gerada pode 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")]