Você pode integrar o MongoDB Atlas ao LangGraph para criar agentes de IA. Este tutorial demonstra como criar um agente de IA que responde a perguntas sobre dados de amostra no MongoDB.
Especificamente, o agente usa a integração para implementar o RAG agente e a memória do agente. Ele usa pesquisa semântica e pesquisa de texto completo FERRAMENTAS para recuperar informações relevantes e responder a perguntas sobre os dados. Ele também implementa memória de curto e longo prazo usando o MongoDB , armazenando o histórico de conversas e interações importantes em coleções separadas.
O código nesta página cria um aplicação de exemplo completo . Você também pode trabalhar no código como um bloco de notas Python se preferir aprender passo a passo.
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 aprender mais, consulte Chave de API e cliente Python.
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.
Observação
Verifique os requisitos do pacote langchain-voyageai para garantir que você esteja usando uma versão compatível do Python.
Configurar o ambiente
Para configurar o ambiente, conclua as seguintes etapas:
Inicialize o projeto e instale dependências.
Crie um novo diretório de projeto e, em seguida, instale as dependências necessárias:
mkdir langgraph-mongodb-ai-agent cd langgraph-mongodb-ai-agent pip install --quiet --upgrade python-dotenv langgraph langgraph-checkpoint-mongodb langgraph-store-mongodb langchain langchain-mongodb langchain-voyageai langchain-openai pymongo
Observação
Seu projeto usará a seguinte estrutura:
langgraph-mongodb-ai-agent ├── .env ├── config.py ├── search-tools.py ├── memory-tools.py ├── agent.py ├── main.py
Defina variáveis de ambiente.
Crie um arquivo .env no seu projeto e especifique as seguintes variáveis. Substitua os valores de espaço reservado por chaves de API válidas e pela string de conexão do cluster MongoDB .
VOYAGE_API_KEY = "<voyage-api-key>" OPENAI_API_KEY = "<openai-api-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.
Usar MongoDB como banco de dados vetorial
Para configurar o MongoDB como um banco de dados vetorial para armazenamento e recuperação, complete as seguintes etapas:
Carregue os dados de amostra.
Para este tutorial, utilize um dos nossos conjuntos de dados de amostra como fonte de dados. Caso ainda não tenha feito isso, complete as etapas para carregar dados de amostra em seu Atlas cluster.
Especificamente, você usará o conjunto de dados embedded_movies, que contém documentos sobre filmes, incluindo as incorporações vetoriais de seus enredos.
Observação
Se você deseja usar seus próprios dados, veja Introdução ao LangChain ou Como criar incorporações vetoriais para aprender como ingerir incorporações vetoriais no Atlas.
Configure o armazenamento de vetores e índices.
Crie um arquivo denominado config.py em seu projeto. Este arquivo configura o MongoDB como o armazenamento de vetores para seu agente. Ele também cria os índices para habilitar a pesquisa vetorial e a pesquisa de texto completo nos dados de amostra.
import os from pymongo import MongoClient from langchain_mongodb import MongoDBAtlasVectorSearch from langchain_mongodb.index import create_fulltext_search_index from langchain_voyageai import VoyageAIEmbeddings from langchain_openai import ChatOpenAI from dotenv import load_dotenv # Load environment variables load_dotenv() # Get required environment variables MONGODB_URI = os.getenv("MONGODB_URI") if not MONGODB_URI: raise ValueError("MONGODB_URI environment variable is required") # Initialize models embedding_model = VoyageAIEmbeddings( model="voyage-3-large", output_dimension=2048 ) llm = ChatOpenAI("gpt-4o") # MongoDB setup mongo_client = MongoClient(MONGODB_URI) collection = mongo_client["sample_mflix"]["embedded_movies"] # LangChain vector store setup vector_store = MongoDBAtlasVectorSearch.from_connection_string( connection_string=MONGODB_URI, namespace="sample_mflix.embedded_movies", embedding=embedding_model, text_key="plot", embedding_key="plot_embedding_voyage_3_large", relevance_score_fn="dotProduct", ) # Create indexes on startup print("Setting up vector store and indexes...") try: existing_indexes = list(collection.list_search_indexes()) vector_index_exists = any(idx.get('name') == 'vector_index' for idx in existing_indexes) if vector_index_exists: print("Vector search index already exists, skipping creation...") else: print("Creating vector search index...") vector_store.create_vector_search_index( dimensions=2048, # The dimensions of the vector embeddings to be indexed wait_until_complete=60 # Number of seconds to wait for the index to build (can take around a minute) ) print("Vector search index created successfully!") except Exception as e: print(f"Error creating vector search index: {e}") try: fulltext_index_exists = any(idx.get('name') == 'search_index' for idx in existing_indexes) if fulltext_index_exists: print("Search index already exists, skipping creation...") else: print("Creating search index...") create_fulltext_search_index( collection=collection, field="title", index_name="search_index", wait_until_complete=60 # Number of seconds to wait for the index to build (can take around a minute) ) print("Search index created successfully!") except Exception as e: print(f"Error creating search index: {e}")
Definir pesquisa FERRAMENTAS
Crie um arquivo search_tools.py em seu projeto. Neste arquivo, você define os FERRAMENTAS de pesquisa que o agente usa para executar o RAG agente.
plot_search: Esta ferramenta utiliza o objeto de armazenamento de vetor como um recuperador. Nos mínimos detalhes, o recuperador executa uma query do MongoDB Vector Search para recuperar documentos semanticamente semelhantes. Em seguida, a ferramenta retorna os títulos e gráficos dos documentos de filme recuperados.title_search: essa ferramenta usa o recuperador de pesquisa de texto completo para recuperar documentos de filme que correspondam ao título de filme especificado. Em seguida, a ferramenta retorna o gráfico do filme especificado.
from langchain.agents import tool from langchain_mongodb.retrievers.full_text_search import MongoDBAtlasFullTextSearchRetriever from config import vector_store, collection def plot_search(user_query: str) -> str: """ Retrieve information on the movie's plot to answer a user query by using vector search. """ retriever = vector_store.as_retriever( search_type="similarity", search_kwargs={"k": 5} # Retrieve top 5 most similar documents ) results = retriever.invoke(user_query) # Concatenate the results into a string context = "\n\n".join([f"{doc.metadata['title']}: {doc.page_content}" for doc in results]) return context def title_search(user_query: str) -> str: """ Retrieve movie plot content based on the provided title by using full-text search. """ # Initialize the retriever retriever = MongoDBAtlasFullTextSearchRetriever( collection=collection, # MongoDB Collection search_field="title", # Name of the field to search search_index_name="search_index", # Name of the MongoDB Search index top_k=1, # Number of top results to return ) results = retriever.invoke(user_query) for doc in results: if doc: return doc.metadata["fullplot"] else: return "Movie not found" # List of search tools SEARCH_TOOLS = [ plot_search, title_search ]
Observação
Você pode definir qualquer ferramenta que precise para executar uma tarefa específica. Você também pode definir ferramentas para outros métodos de recuperação, como pesquisa híbrida ou recuperação de documento pai.
Definir memória FERRAMENTAS
Crie um arquivo memory_tools.py em seu projeto. Nesse arquivo, você define as FERRAMENTAS que o agente pode usar para armazenar e recuperar interações importantes entre sessões para implementar a memória de longo prazo.
store_memory: esta ferramenta usa o armazenamento MongoDB MongoDB para armazenar interações importantes em uma coleção MongoDB.retrieve_memory: essa ferramenta usa o armazenamento MongoDB do MongoDB para recuperar interações relevantes com base na query usando a pesquisa semântica.
from langchain.agents import tool from langgraph.store.mongodb import MongoDBStore, create_vector_index_config from config import embedding_model, MONGODB_URI # Vector search index configuration for memory collection index_config = create_vector_index_config( embed=embedding_model, dims=2048, relevance_score_fn="dotProduct", fields=["content"] ) def save_memory(content: str) -> str: """Save important information to memory.""" with MongoDBStore.from_conn_string( conn_string=MONGODB_URI, db_name="sample_mflix", collection_name="memories", index_config=index_config, auto_index_timeout=60 # Wait a minute for vector index creation ) as store: store.put( namespace=("user", "memories"), key=f"memory_{hash(content)}", value={"content": content} ) return f"Memory saved: {content}" def retrieve_memories(query: str) -> str: """Retrieve relevant memories based on a query.""" with MongoDBStore.from_conn_string( conn_string=MONGODB_URI, db_name="sample_mflix", collection_name="memories", index_config=index_config ) as store: results = store.search(("user", "memories"), query=query, limit=3) if results: memories = [result.value["content"] for result in results] return f"Retrieved memories:\n" + "\n".join(memories) return "No relevant memories found." MEMORY_TOOLS = [save_memory, retrieve_memories]
Construa o agente com persistência
Crie um arquivo agent.py em seu projeto. Neste arquivo, você constrói o gráfico que orquestra o fluxo de trabalho do agente. Esse agente usa o componente MongoDB Checkpointer para implementar memória de curto prazo, permitindo várias conversas simultâneas com históricos separados.
O agente usa o seguinte fluxo de trabalho para responder às queries:
Início: o agente recebe uma query do usuário.
Nó do agente: o LLM vinculado à ferramenta analisa a query e determina se os FERRAMENTAS são necessários.
Nó FERRAMENTAS (se necessário): Executa a pesquisa ou memória FERRAMENTAS apropriada.
End: o LLM gera uma resposta final usando a saída do FERRAMENTAS.
A implementação do agente consiste em vários componentes:
LangGraphAgent: classe de agente principal que orquestra o fluxo de trabalhobuild_graph: Constrói o fluxo de trabalho do LangGraph e configura o checkpointerMongoDBSaverpara a persistência da memória de curto prazoagent_node: Principal tomador de decisões que processa mensagens e determina o uso da ferramentatools_node: Executa FERRAMENTAS solicitados e retorna resultadosroute_tools: Função de roteamento condicional que determina a direção do fluxo de trabalhoexecute: ponto de entrada principal que aceita um parâmetrothread_idpara rastreamento de thread de conversa
from typing import Annotated, Dict, List from typing_extensions import TypedDict from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder from langchain_core.messages import ToolMessage from langgraph.graph import StateGraph, START, END from langgraph.graph.message import add_messages from langgraph.checkpoint.mongodb import MongoDBSaver from config import llm, mongo_client from search_tools import SEARCH_TOOLS from memory_tools import MEMORY_TOOLS # Define the graph state class GraphState(TypedDict): messages: Annotated[list, add_messages] # Define the LangGraph agent class LangGraphAgent: def __init__(self): # Combine search tools with memory tools self.tools = SEARCH_TOOLS + MEMORY_TOOLS self.tools_by_name = {tool.name: tool for tool in self.tools} # Create prompt template self.prompt = ChatPromptTemplate.from_messages([ ( "system", "You are a helpful AI chatbot." " You are provided with tools to answer questions about movies." " Think step-by-step and use these tools to get the information required to answer the user query." " Do not re-run tools unless absolutely necessary." " If you are not able to get enough information using the tools, reply with I DON'T KNOW." " You have access to the following tools: {tool_names}." ), MessagesPlaceholder(variable_name="messages"), ]) # Provide the tool names to the prompt self.prompt = self.prompt.partial(tool_names=", ".join([tool.name for tool in self.tools])) # Prepare the LLM with tools bind_tools = llm.bind_tools(self.tools) self.llm_with_tools = self.prompt | bind_tools # Build the graph self.app = self._build_graph() def _build_graph(self): """Build and compile the LangGraph workflow.""" # Instantiate the graph graph = StateGraph(GraphState) # Add nodes graph.add_node("agent", self._agent_node) graph.add_node("tools", self._tools_node) # Add edges graph.add_edge(START, "agent") graph.add_edge("tools", "agent") # Add conditional edge graph.add_conditional_edges( "agent", self._route_tools, {"tools": "tools", END: END}, ) # Use the MongoDB checkpointer for short-term memory checkpointer = MongoDBSaver(mongo_client, db_name = "sample_mflix") return graph.compile(checkpointer=checkpointer) def _agent_node(self, state: GraphState) -> Dict[str, List]: """Agent node that processes messages and decides on tool usage.""" messages = state["messages"] result = self.llm_with_tools.invoke(messages) return {"messages": [result]} def _tools_node(self, state: GraphState) -> Dict[str, List]: """Tools node that executes the requested tools.""" result = [] messages = state["messages"] if not messages: return {"messages": result} last_message = messages[-1] if not hasattr(last_message, "tool_calls") or not last_message.tool_calls: return {"messages": result} tool_calls = last_message.tool_calls # Show which tools the agent chose to use tool_names = [tool_call["name"] for tool_call in tool_calls] print(f"🔧 Agent chose to use tool(s): {', '.join(tool_names)}") for tool_call in tool_calls: try: tool_name = tool_call["name"] tool_args = tool_call["args"] tool_id = tool_call["id"] print(f" → Executing {tool_name}") if tool_name not in self.tools_by_name: result.append(ToolMessage(content=f"Tool '{tool_name}' not found", tool_call_id=tool_id)) continue tool = self.tools_by_name[tool_name] observation = tool.invoke(tool_args) result.append(ToolMessage(content=str(observation), tool_call_id=tool_id)) except Exception as e: result.append(ToolMessage(content=f"Tool error: {str(e)}", tool_call_id=tool_id)) return {"messages": result} def _route_tools(self, state: GraphState): """ Uses a conditional_edge to route to the tools node if the last message has tool calls. Otherwise, route to the end. """ messages = state.get("messages", []) if len(messages) > 0: ai_message = messages[-1] else: raise ValueError(f"No messages found in input state to tool_edge: {state}") if hasattr(ai_message, "tool_calls") and len(ai_message.tool_calls) > 0: return "tools" return END def execute(self, user_input: str, thread_id: str) -> str: """Execute the graph with user input.""" input_data = {"messages": [("user", user_input)]} config = {"configurable": {"thread_id": thread_id}} outputs = list(self.app.stream(input_data, config)) # Get the final answer if outputs: final_output = outputs[-1] for _, value in final_output.items(): if "messages" in value and value["messages"]: return value["messages"][-1].content return "No response generated."
Este gráfico inclui os seguintes componentes principais:
Estado do Gráfico: mantém dados compartilhados em todo o fluxo de trabalho, rastreando as mensagens do agente, incluindo queries de usuários, respostas LLM e resultados de chamadas de ferramentas.
Nó do agente: processa mensagens, invoca o LLM e atualiza o estado com respostas LLM
Nó FERRAMENTAS: processa chamadas de ferramentas e atualiza o histórico de conversas com resultados
Edges, que conectam nós:
Limites normais: Rota do início ao nó do agente e do agente para o nó FERRAMENTAS
Edge condicional: Roteamentos condicionalmente dependendo da necessidade de FERRAMENTAS
Persistência: usa o checkpointer
MongoDBSaverpara salvar o estado da conversa em threads específicos, ativando a memória de curto prazo entre sessões. Você pode encontrar os dados do thread nas coleçõescheckpointsecheckpoint_writes.
Dica
Para saber mais sobre persistência, memória de curto prazo e o checkpointer do MongoDB , consulte os seguintes recursos:
Execute o agente
Por fim, crie um arquivo chamado main.py em seu projeto. Esse arquivo executa o agente e permite a interação com ele.
from agent import LangGraphAgent from config import mongo_client def main(): """LangGraph and MongoDB agent with tools and memory.""" # Initialize agent (indexes are created during config import) agent = LangGraphAgent() thread_id = input("Enter a session ID: ").strip() print("Ask me about movies! Type 'quit' to exit.") try: while True: user_query = input("\nYour question: ").strip() if user_query.lower() == 'quit': break # Get response from agent answer = agent.execute(user_query, thread_id) print(f"\nAnswer: {answer}") finally: mongo_client.close() if __name__ == "__main__": main()
Salve seu projeto e execute o seguinte comando. Quando você executar o agente:
O agente inicializa o armazenamento de vetor e cria os índices se eles ainda não existirem.
Você pode inserir uma ID de sessão para iniciar uma nova sessão ou continuar uma sessão existente. Cada sessão é persistente e você sempre pode retomar uma conversa anterior.
Faça perguntas sobre filmes. O agente gera uma resposta com base em suas FERRAMENTAS e interações anteriores.
A seguinte saída demonstra uma interação de amostra:
python main.py
Creating vector search index... Vector search index created successfully! Creating search index... Search index created successfully! Enter a session ID: 123 Ask me about movies! Type 'quit' to exit. Your query: What are some movies that take place in the ocean? 🔧 Agent chose to use tool(s): plot_search → Executing plot_search Answer: Here are some movies that take place in the ocean: 1. **20,000 Leagues Under the Sea** - A marine biologist, his daughter, and a mysterious Captain Nemo explore the ocean aboard an incredible submarine. 2. **Deep Rising** - A group of armed hijackers board a luxury ocean liner in the South Pacific Ocean, only to fight man-eating, tentacled sea creatures. ... (truncated) Your query: What is the plot of the Titanic? 🔧 Agent chose to use tool(s): title_search → Executing title_search Answer: The plot of *Titanic* involves the romantic entanglements of two couples aboard the doomed ship's maiden voyage ... (truncated) Your query: What movies are like the movie I just mentioned? 🔧 Agent chose to use tool(s): plot_search → Executing plot_search Answer: Here are some movies similar to *Titanic*: 1. **The Poseidon Adventure** - A group of passengers struggles to survive when their ocean liner capsizes at sea. 2. **Pearl Harbor** - Focused on romance and friendship amidst the backdrop of a historical tragedy, following two best friends and their love lives during wartime. ... (truncated) Your query: I don't like sad movies. 🔧 Agent chose to use tool(s): save_memory → Executing save_memory Answer: Got it—I'll keep that in mind. Let me know if you'd like recommendations that focus more on uplifting or happy themes! (In different session) Enter a session ID: 456 Your query: Recommend me a movie based on what you know about me. 🔧 Agent chose to use tool(s): retrieve_memories → Executing retrieve_memories Answer: Based on what I know about you—you don't like sad movies—I'd recommend a fun, uplifting, or action-packed film. Would you be interested in a comedy, adventure, or family-friendly movie? Your query: Sure! 🔧 Agent chose to use tool(s): plot_search, plot_search, plot_search → Executing plot_search → Executing plot_search → Executing plot_search Answer: Here are some movie recommendations from various uplifting genres that suit your preferences: ### Comedy: 1. **Showtime** (2002): A spoof of buddy cop movies where two very different cops are forced to team up on a new reality-based TV cop show. It's packed with laughs and action! 2. **The Big Bus** (1976): A hilarious disaster film parody featuring a nuclear-powered bus going nonstop from New York to Denver, plagued by absurd disasters. ### Adventure: 1. **Journey to the Center of the Earth** (2008): A scientist, his nephew, and their mountain guide discover a fantastic and dangerous lost world at the earth's core. 2. **Jason and the Argonauts** (1963): One of the most legendary adventures in mythology, brought to life in this epic saga of good versus evil. ### Family-Friendly: 1. **The Incredibles** (2004): A family of undercover superheroes is forced into action to save the world while living in quiet suburban life. 2. **Mary Poppins** (1964): A magical nanny brings joy and transformation to a cold banker's unhappy family. 3. **Chitty Chitty Bang Bang** (1968): A whimsical adventure featuring an inventor, his magical car, and a rescue mission filled with fantasy.