O MongoDB oferece vários recursos para criar agentes de IA. Como um banco de dados de vetores e documento , o MongoDB oferece suporte a vários métodos de pesquisa para RAG de agentes, além de armazenar interações de agente no mesmo banco de dados para memória de agente de curto e longo prazo.
O que é um agente de AI?
No contexto da IA generativa, um agente de AI geralmente se refere a um sistema que pode completar uma tarefa de forma autônoma ou semiautônoma, combinando modelos de AI, como LLMs com um conjunto de ferramentas predefinidas.
Agentes de AI podem usar ferramentas para reunir contexto, realizar interação com sistemas externos e executar ações. Eles podem definir seu próprio fluxo de execução (planejamento) e lembrar interações anteriores para informar suas respostas (memória). Portanto, os agentes de AI são mais adequados para tarefas complexas que exigem raciocínio, planejamento e tomada de decisões.
Arquitetura
Um agente de AI normalmente inclui uma combinação dos seguintes componentes:
Percepção | Sua informação para o agente. Informações em texto são o mecanismo de percepção mais comum para agentes de AI, mas também podem ser de áudio, imagens ou dados multimodais. |
Planejamento | Como o agente determina o que fazer a seguir. Esse componente normalmente inclui LLMs e prompts, utilizando ciclos de feedback e várias técnicas de engenharia de prompts, como cadeia de pensamento e reAct, para ajudar o LLM a raciocinar sobre tarefas complexas. Os agentes de AI podem consistir em um único LLM como tomador de decisões, um LLM com vários prompts, múltiplos LLMs trabalhando juntos ou qualquer combinação dessas abordagens. |
Ferramentas | Como o agente reúne contexto para uma tarefa. As ferramentas permitem que os agentes interajam com sistemas externos e realizem ações como pesquisa vetorial, pesquisa na web ou chamadas de APIs de outros serviços. |
Memória | Um sistema para armazenar interações do agente, de forma que ele possa aprender com experiências passadas para informar suas respostas. A memória pode ser de curto termo (para a sessão atual) ou de longo termo (persistida entre as sessões). |
Observação
Os agentes de AI variam em padrão de design, função e complexidade. Para aprender mais sobre outras arquiteturas de agentes, incluindo sistemas multiagentes, consulte Padrões de design de agentes.
Crie agentes de AI com o MongoDB
O MongoDB é compatível com os seguintes componentes para criar agentes de IA:
Ferramentas: aproveite os recursos de pesquisa do MongoDB como ferramentas para seu agente recuperar informações relevantes e implementar RAG de agente.
Memória: armazene interações de agentes em coleções MongoDB para memória de curto e longo prazo.
Ferramentas do Agente
No contexto de agentes de AI, uma ferramenta é qualquer recurso que possa ser definido e invocado programaticamente pelo agente. As ferramentas ampliam as funcionalidades do agente além da geração de textos, permitindo a interação com sistemas externos, a recuperação de informações e a execução de ações. As ferramentas são tipicamente definidas com uma interface específica que inclui:
Um nome e uma descrição que ajudam o agente a entender quando usar a ferramenta.
Parâmetros obrigatórios e seus formatos esperados.
Uma função que realiza a operação efetiva quando chamada.
O agente utiliza suas capacidades de raciocínio para determinar qual ferramenta empregar, quando utilizá-la e quais parâmetros fornecer, com base na entrada do usuário e na tarefa em questão.
Além das queries padrão do MongoDB , o MongoDB fornece vários recursos de pesquisa que você pode implementar como FERRAMENTAS para seu agente.
Vector Search do MongoDB: execute pesquisa vetorial para recuperar o contexto relevante com base no significado e similaridade semântica. Para saber mais, consulte Visão geral da Vector Search do MongoDB.
MongoDB Search: realize pesquisas de texto completo para recuperar o contexto relevante com base na correspondência de palavras-chave e na pontuação de relevância. Para saber mais, consulte Visão geral da pesquisa do MongoDB.
Pesquisa híbrida: combine a Vector Search do MongoDB com a pesquisa do MongoDB para aproveitar os pontos fortes de ambas as abordagens. Para saber mais, consulte Como realizar pesquisas híbridas.
Você pode definir ferramentas manualmente ou usando frameworks como LangChain e LangGraph, que fornecem abstrações integradas para criação e chamada de ferramentas.
As ferramentas são definidas como funções que o agente pode chamar para executar tarefas específicas. Por exemplo, a sintaxe a seguir ilustra como você pode definir uma ferramenta que executa uma query de pesquisa vetorial:
async function vectorSearchTool(query) { const pipeline = [ { $vectorSearch: { // Vector search query pipeline... } } ]; const results = await collection.aggregate(pipeline).toArray(); return results; }
def vector_search_tool(query: str) -> str: pipeline = [ { "$vectorSearch": { # Vector search query pipeline... } } ] results = collection.aggregate(pipeline) array_of_results = [] for doc in results: array_of_results.append(doc) return array_of_results
As chamadas de ferramenta são o que o agente usa para executar o FERRAMENTAS. Você pode definir como processar chamadas de ferramentas em seu agente ou usar uma estrutura para lidar com isso para você. Eles normalmente são definidos como objetos JSON que incluem o nome da ferramenta e outros argumentos a serem passados para a ferramenta, para que o agente possa chamar a ferramenta com os parâmetros apropriados. Por exemplo, a seguinte sintaxe ilustra como um agente pode chamar a ferramenta de pesquisa vetorial:
{ "tool": "vector_search_tool", "args": { "query": "What is MongoDB?" }, "id": "call_H5TttXb423JfoulF1qVfPN3m" }
RAG agêntica
Ao usar o MongoDB como um banco de dados vetorial, você pode criar FERRAMENTAS de recuperação que implementam o RAG agente, que é uma forma avançada de RAG que permite orquestrar dinamicamente o processo de recuperação e geração por meio de um agente de IA.
Essa abordagem permite fluxos de trabalho e interações com o usuário mais complexos. Por exemplo, você pode configurar seu agente de IA para determinar a ferramenta de recuperação ideal com base na tarefa, como usar o MongoDB Vector Search para pesquisa semântica e o MongoDB Search para pesquisa de texto completo. Você também pode definir diferentes FERRAMENTAS de recuperação para diferentes coleções para personalizar ainda mais os recursos de recuperação do agente.
Memória de agente
A memória para agentes envolve armazenar informações sobre interações anteriores, para que o agente possa aprender com experiências passadas e fornecer respostas mais relevantes e personalizadas. Isso é particularmente importante para tarefas que exigem contexto, como agentes conversacionais, em que o agente precisa se lembrar das interações anteriores na conversa para fornecer respostas coerentes e relevantes ao contexto. Existem dois tipos primários de memória de agente:
Memória de curto prazo: armazena informações para a sessão atual, como as últimas interações e o contexto da tarefa ativa.
Memória de longo prazo: persiste informações entre sessões, podendo incluir conversas passadas e preferências personalizadas ao longo do tempo.
Como o MongoDB também é um banco de dados de documento , você pode implementar memória para agentes armazenando suas interações em uma coleção do MongoDB . O agente pode então consultar ou atualizar essa coleção conforme necessário. Há várias maneiras de implementar a memória do agente com o MongoDB:
Para a memória de curto prazo, você pode incluir um campo
session_idpara identificar uma sessão específica ao armazenar interações e, em seguida, fazer uma query de interações com o mesmo ID para passar ao agente como contexto.Para memória de longo prazo, você pode processar várias interações com um LLM para extrair informações relevantes, como preferências do usuário ou contexto importante, e então armazenar essas informações em uma coleção separada que o agente pode consultar quando necessário.
Para criar sistemas robustos de gerenciamento de memória que permitam uma recuperação mais eficiente e complexa de histórico de conversas, aproveite o MongoDB Search ou o MongoDB Vector Search para armazenar, indexar e consultar interações importantes entre sessões.
Um documento em uma coleção que armazena memória de curto prazo pode ser semelhante ao seguinte:
{ "session_id": "123", "user_id": "jane_doe", "interactions": [ { "role": "user", "content": "What is MongoDB?", "timestamp": "2025-01-01T12:00:00Z" }, { "role": "assistant", "content": "MongoDB is the world's leading modern database.", "timestamp": "2025-01-01T12:00:05Z" } ] }
Um documento em uma coleção que armazena memória de longo prazo pode ser semelhante ao seguinte:
{ "user_id": "jane_doe", "last_updated": "2025-05-22T09:15:00Z", "preferences": { "conversation_tone": "casual", "custom_instructions": [ "I prefer concise answers." ], }, "facts": [ { "interests": ["AI", "MongoDB"], } ] }
Os seguintes frameworks também oferecem abstrações diretas para a memória de agente com MongoDB:
Framework | Características |
|---|---|
LangChain |
Para aprender mais, consulte o tutorial. |
LangGraph |
Para aprender mais, veja LangGraph e LangGraph.js. |
Começar
O tutorial a seguir demonstra como criar um agente de IA usando o MongoDB para RAG e memória de agente, sem uma estrutura de agente .
➤ Use o menu suspenso Selecione seu idioma para definir o idioma para este tutorial.
Trabalhe com uma versão executável deste tutorial como um notebook Python.
Pré-requisitos
Para concluir este tutorial, você deve ter o seguinte:
Um dos seguintes tipos de cluster MongoDB :
Um cluster do Atlas executando a versão 6.0.11 do MongoDB, 7.0.2, ou posterior. Certifique-se de que seu endereço IP esteja incluído na lista de acesso do 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.
Uma chave de API OpenAI.
Observação
Este tutorial usa modelos da Voyage AI e da OpenAI, mas você pode alterar o código para utilizar os modelos de sua preferência.
Procedimento
Esse agente de AI pode ser usado para responder a perguntas sobre uma fonte de dados personalizada e realizar cálculos. Ele também pode lembrar de interações anteriores para informar suas respostas. Ele usa os seguintes componentes:
Percepção: entradas de texto.
Planejamento: um LLM e várias instruções para raciocinar sobre a tarefa.
Ferramentas: uma ferramenta de pesquisa vetorial e uma ferramenta de cálculo.
Memória: armazena as interações em uma coleção do MongoDB.
Configure o ambiente.
Inicialize o projeto e instale dependências.
Crie um novo diretório de projeto e, em seguida, instale as dependências necessárias:
mkdir mongodb-ai-agent cd mongodb-ai-agent npm init -y npm install --quiet dotenv mongodb voyageai openai langchain @langchain/community @langchain/core mathjs pdf-parse Observação
Seu projeto usará a seguinte estrutura:
mongodb-ai-agent ├── .env ├── config.js ├── ingest-data.js ├── tools.js ├── memory.js ├── planning.js └── index.js Configure o ambiente.
Crie um arquivo de ambiente denominado
.envem seu projeto. Esse arquivo conterá suas chaves de API para o agente , a string de conexão do MongoDB e os nomes do banco de dados e da collection do MongoDB .Substitua os valores do espaço reservado por sua string de conexão do MongoDB e suas chaves de API Voyage AI e OpenAI.
MONGODB_URI="<mongodb-connection-string>" VOYAGE_API_KEY="<voyage-api-key>" OPENAI_API_KEY= "<openai-api-key>" 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.
Configure o agente.
Crie um arquivo denominado config.js em seu projeto. Este arquivo lerá em suas variáveis de ambiente e conectará o aplicação a serviços como o banco de dados do MongoDB e o OpenAI.
import dotenv from 'dotenv'; import { MongoClient } from 'mongodb'; import OpenAI from "openai"; // Load environment variables from .env file dotenv.config(); // MongoDB cluster configuration export const MONGODB_URI = process.env.MONGODB_URI; export const mongoClient = new MongoClient(MONGODB_URI); export const agentDb = mongoClient.db("ai_agent_db"); export const vectorCollection = agentDb.collection("embeddings"); export const memoryCollection = agentDb.collection("chat_history"); // Model Configuration export const OPENAI_MODEL = "gpt-4o"; export const VOYAGE_MODEL = "voyage-3-large"; export const VOYAGE_API_KEY = process.env.VOYAGE_API_KEY; // Initialize OpenAI Client export const openAIClient = new OpenAI({ apiKey: process.env.OPENAI_API_KEY,});
Use MongoDB como um banco de dados vetorial.
Crie um arquivo denominado ingest-data.js em seu projeto. Esse script ingere um PDF de amostra que contém um relatório de rendimentos recente do MongoDB em uma collection no MongoDB usando o modelo de incorporação voyage-3-large. Este código também inclui uma função para criar um índice de pesquisa vetorial em seus dados, se eles ainda não existirem.
Para aprender mais, consulte Ingestão.
import { PDFLoader } from "@langchain/community/document_loaders/fs/pdf"; import { RecursiveCharacterTextSplitter } from "langchain/text_splitter"; import { vectorCollection } from "./config.js"; import { VOYAGE_API_KEY, VOYAGE_MODEL } from "./config.js"; import { VoyageAIClient } from "voyageai"; import { MONGODB_URI } from "./config.js"; import * as fs from 'fs'; import fetch from 'node-fetch'; console.log("Connecting to MongoDB:", MONGODB_URI); const EMBEDDING_DIMENSIONS = 1024; // Use Voyage AI Client SDK to get embeddings export async function getEmbedding(data, input_type) { if (!VOYAGE_API_KEY) { throw new Error("VOYAGE_API_KEY is not set in environment variables."); } try { const client = new VoyageAIClient({ apiKey: VOYAGE_API_KEY }); const response = await client.embed({ input: [data], model: VOYAGE_MODEL, input_type: input_type // "document" or "query" }); if (response.data && response.data.length > 0) { return response.data[0].embedding; } throw new Error("No embedding data found from Voyage AI response."); } catch (error) { console.error("Error generating Voyage AI embedding:", error); return null; } } // Ingest data from a PDF, generate embeddings, and store in MongoDB export async function ingestData() { try { // download PDF const rawData = await fetch("https://investors.mongodb.com/node/13176/pdf"); const pdfBuffer = await rawData.arrayBuffer(); fs.writeFileSync("investor-report.pdf", Buffer.from(pdfBuffer)); // load and split PDF const loader = new PDFLoader("investor-report.pdf"); const data = await loader.load(); const textSplitter = new RecursiveCharacterTextSplitter({ chunkSize: 400, chunkOverlap: 20, }); const docs = await textSplitter.splitDocuments(data); console.log(`Chunked PDF into ${docs.length} documents.`); // generate embeddings and insert const insertDocuments = await Promise.all(docs.map(async doc => ({ document: doc, embedding: await getEmbedding(doc.pageContent, "document"), }))); const result = await vectorCollection.insertMany(insertDocuments, { ordered: false }); console.log("Inserted documents:", result.insertedCount); } catch (err) { console.error("Ingestion error:", err); } } // Create a vector search index export async function createVectorIndex() { try { // check if the index already exists const existingIndexes = await vectorCollection.listSearchIndexes().toArray(); if (existingIndexes.some(index => index.name === "vector_index")) { console.log("Vector index already exists. Skipping creation."); return; } // define your Vector Search index const index = { name: "vector_index", type: "vectorSearch", definition: { "fields": [ { "type": "vector", "path": "embedding", "numDimensions": EMBEDDING_DIMENSIONS, "similarity": "cosine", } ] } } // run the helper method to ensure the index is created const result = await vectorCollection.createSearchIndex(index); console.log(`New index named ${result} is building.`); // wait for the index to be ready to query console.log("Polling to check if the index is ready. This may take up to a minute.") let isQueryable = false; while (!isQueryable) { const cursor = vectorCollection.listSearchIndexes(); for await (const index of cursor) { if (index.name === result) { if (index.queryable) { console.log(`${result} is ready for querying.`); isQueryable = true; } else { await new Promise(resolve => setTimeout(resolve, 5000)); } } } } } catch (err) { console.error("Error creating vector index:", err); throw err; } }
Defina as ferramentas para o agente.
Crie um arquivo chamado tools.js em seu projeto. Esse arquivo define as ferramentas que o agente pode usar para dar resposta às perguntas. Neste exemplo, você define as seguintes ferramentas:
vectorSearchTool: executa uma query de pesquisa vetorial para recuperar documentos relevantes da sua coleção.calculatorTool: usa a bibliotecamathjspara operações matemáticas básicas.
import { getEmbedding } from './ingest-data.js'; import { vectorCollection } from './config.js'; import { evaluate } from 'mathjs'; // Vector search tool export async function vectorSearchTool(userInput) { const queryEmbedding = await getEmbedding(userInput, "query"); const pipeline = [ { $vectorSearch: { index: "vector_index", queryVector: queryEmbedding, path: "embedding", exact: true, limit: 5 } }, { $project: { _id: 0, "document.pageContent": 1 } } ]; const cursor = vectorCollection.aggregate(pipeline); const results = await cursor.toArray(); return results; } // Simple calculator tool export function calculatorTool(userInput) { try { const result = evaluate(userInput); return String(result); } catch (e) { return `Error: ${e.message}`; } }
Adicione memória ao agente.
Crie um arquivo chamado memory.js em seu projeto. Esse arquivo define o sistema que o agente utiliza para armazenar suas interações. Neste exemplo, você implementa a memória de curto prazo ao definir as seguintes funções:
storeChatMessage: para armazenar informações sobre uma interação em uma coleção do MongoDB.retrieveSessionHistory: para obter todas as interações de uma sessão específica usando o camposession_id.
import { memoryCollection } from './config.js'; /** * Store a chat message in the memory collection. * @param {string} sessionId - unique identifier for the chat session * @param {string} role - role of the sender (user or system) * @param {string} content - content of the message */ export async function storeChatMessage(sessionId, role, content) { const message = { session_id: sessionId, role, content, timestamp: new Date(), // use JS date for timestamp }; await memoryCollection.insertOne(message); } /** * Retrieve the chat history for a session. * @param {string} sessionId - unique identifier for the chat session * @returns {Promise<Array<{role: string, content: string}>>} */ export async function retrieveSessionHistory(sessionId) { const cursor = memoryCollection .find({ session_id: sessionId }) .sort({ timestamp: 1 }); const messages = []; await cursor.forEach(msg => { messages.push({ role: msg.role, content: msg.content }); }); return messages; }
Defina o planejamento do agente.
Crie um arquivo chamado planning.js em seu projeto. Esse arquivo incluirá vários prompts e chamadas LLM para determinar o fluxo de execução do agente. Neste exemplo, você define as seguintes funções:
openAIChatCompletion: Função auxiliar para chamar a API OpenAI para gerar respostas.toolSelector: determina como o LLM seleciona a ferramenta apropriada para uma tarefa.generateAnswer: orquestra o fluxo de execução do agente utilizando ferramentas, chamando o LLM e processando os resultados.getLLMResponse: função de assistente para geração de resposta LLM.
import { vectorSearchTool, calculatorTool } from './tools.js'; import { storeChatMessage, retrieveSessionHistory } from './memory.js'; import { openAIClient, OPENAI_MODEL } from './config.js'; // OpenAI chat completion helper export async function openAIChatCompletion(messages) { try { const completion = await openAIClient.chat.completions.create({ model: OPENAI_MODEL, messages, max_tokens: 1024, }); return completion.choices[0].message.content; } catch (error) { console.error("Error in openAIChatCompletion:", error); throw error; } } // Tool selector function to determine which tool to use based on user input and session history export async function toolSelector(userInput, sessionHistory = []) { const systemPrompt = ` Select the appropriate tool from the options below. Consider the full context of the conversation before deciding. Tools available: - vector_search_tool: Retrieve specific context about recent MongoDB earnings and announcements - calculator_tool: For mathematical operations - none: For general questions without additional context Process for making your decision: 1. Analyze if the current question relates to or follows up on a previous vector search query 2. For follow-up questions, incorporate context from previous exchanges to create a comprehensive search query 3. Only use calculator_tool for explicit mathematical operations 4. Default to none only when certain the other tools won't help When continuing a conversation: - Identify the specific topic being discussed - Include relevant details from previous exchanges - Formulate a query that stands alone but preserves conversation context Return a JSON object only: {"tool": "selected_tool", "input": "your_query"} `.trim(); const messages = [ { role: "system", content: systemPrompt }, ...sessionHistory, { role: "user", content: userInput } ]; try { const response = await openAIChatCompletion(messages); let toolCall; try { toolCall = JSON.parse(response); } catch { try { toolCall = eval(`(${response})`); } catch { return { tool: "none", input: userInput }; } } return { tool: toolCall.tool || "none", input: toolCall.input || userInput }; } catch (err) { console.error("Error in toolSelector:", err); return { tool: "none", input: userInput }; } } // Function to get LLM response based on messages and system message content async function getLlmResponse(messages, systemMessageContent) { const systemMessage = { role: "system", content: systemMessageContent }; let fullMessages; if (messages.some(msg => msg.role === "system")) { fullMessages = [...messages, systemMessage]; } else { fullMessages = [systemMessage, ...messages]; } const response = await openAIChatCompletion(fullMessages); return response; } // Function to generate response based on user input export async function generateResponse(sessionId, userInput) { await storeChatMessage(sessionId, "user", userInput); const sessionHistory = await retrieveSessionHistory(sessionId); const llmInput = [...sessionHistory, { role: "user", content: userInput }]; const { tool, input: toolInput } = await toolSelector(userInput, sessionHistory); console.log("Tool selected:", tool); let response; if (tool === "vector_search_tool") { const contextResults = await vectorSearchTool(toolInput); const context = contextResults.map(doc => doc.document?.pageContent || JSON.stringify(doc)).join('\n---\n'); const systemMessageContent = ` Answer the user's question based on the retrieved context and conversation history. 1. First, understand what specific information the user is requesting 2. Then, locate the most relevant details in the context provided 3. Finally, provide a clear, accurate response that directly addresses the question If the current question builds on previous exchanges, maintain continuity in your answer. Only state facts clearly supported by the provided context. If information is not available, say 'I DON'T KNOW'. Context: ${context} `.trim(); response = await getLlmResponse(llmInput, systemMessageContent); } else if (tool === "calculator_tool") { response = calculatorTool(toolInput); } else { const systemMessageContent = "You are a helpful assistant. Respond to the user's prompt as best as you can based on the conversation history."; response = await getLlmResponse(llmInput, systemMessageContent); } await storeChatMessage(sessionId, "system", response); return response; }
Teste o agente.
Por fim, crie um arquivo chamado index.js em seu projeto. Esse arquivo executa o agente e permite a interação com ele.
import readline from 'readline'; import { mongoClient } from './config.js'; import { ingestData, createVectorIndex } from './ingest-data.js'; import { generateResponse } from './planning.js'; // Prompt for user input async function prompt(question) { const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); return new Promise(resolve => rl.question(question, answer => { rl.close(); resolve(answer); })); } async function main() { try { await mongoClient.connect(); const runIngest = await prompt("Ingest sample data? (y/n): "); if (runIngest.trim().toLowerCase() === 'y') { await ingestData(); console.log("\nAttempting to create/verify Vector Search Index..."); await createVectorIndex(); } else { await createVectorIndex(); // ensure index exists even if not ingesting data } const sessionId = await prompt("Enter a session ID: "); while (true) { const userQuery = await prompt("\nEnter your query (or type 'quit' to exit): "); if (userQuery.trim().toLowerCase() === 'quit') break; if (!userQuery.trim()) { console.log("Query cannot be empty. Please try again."); continue; } const answer = await generateResponse(sessionId, userQuery); console.log("\nAnswer:"); console.log(answer); } } finally { await mongoClient.close(); } } main();
Salve seu projeto e execute o seguinte comando. Quando você executar o agente:
Caso ainda não tenha feito, instrua o agente a ingerir os dados de amostra.
Digite um ID de sessão para começar uma nova sessão ou continuar uma já existente.
Faça perguntas. O agente gera uma resposta com base nas suas ferramentas, nas interações anteriores e nos prompts definidos na fase de planejamento.
Consulte o exemplo de saída para uma interação de amostra:
node index.js
Ingest sample data? (y/n): y Chunked PDF into 100 documents. Inserted documents: 100 Attempting to create/verify Vector Search Index... New index named vector_index is building. Polling to check if the index is ready. This may take up to a minute. vector_index is ready for querying. Enter a session ID: 123 Enter your query (or type 'quit' to exit): What was MongoDB's latest acquisition? Tool selected: vector_search_tool Answer: MongoDB recently acquired Voyage AI, a pioneer in embedding and reranking models that power next-generation AI applications. Enter your query (or type 'quit' to exit): What do they do? Tool selected: vector_search_tool Answer: Voyage AI is a company that specializes in state-of-the-art embedding and reranking models designed to power next-generation AI applications. These technologies help organizations build more advanced and trustworthy AI capabilities. Enter your query (or type 'quit' to exit): What is 123+456? Tool selected: calculator_tool Answer: 579
Dica
Se estiver usando o Atlas, você poderá verificar suas incorporações e interações navegando até o namespace ai_agent_db.embeddings na UI do Atlas.
Continue a construir.
Agora que você possui um agente básico de AI, você pode continuar a desenvolvê-lo da seguinte maneira:
Melhorando o desempenho das suas ferramentas de pesquisa vetorial e pelo ajuste fino dos seus pipelines RAG.
Adicionar mais ferramentas ao agente, como ferramentas híbridas ou de pesquisa de texto completo.
Aprimorando a fase de planejamento ao utilizar prompts mais avançados e chamadas de LLM.
Implementação de memória de longo prazo e sistemas de memória mais avançados usando o MongoDB Search e o MongoDB Vector Search para armazenar e recuperar interações importantes entre sessões.
Configure o ambiente.
Inicialize o projeto e instale dependências.
Crie um novo diretório de projeto e, em seguida, instale as dependências necessárias:
mkdir mongodb-ai-agent cd mongodb-ai-agent pip install --quiet --upgrade pymongo voyageai openai langchain langchain-mongodb langchain-community python-dotenv Observação
Seu projeto usará a seguinte estrutura:
mongodb-ai-agent ├── .env ├── config.py ├── ingest_data.py ├── tools.py ├── memory.py ├── planning.py ├── main.py Configure o ambiente.
Crie um arquivo de ambiente denominado
.envem seu projeto. Esse arquivo conterá suas chaves de API para o agente , a string de conexão do MongoDB e os nomes do banco de dados e da collection do MongoDB .Substitua os valores do espaço reservado por sua string de conexão do MongoDB e suas chaves de API Voyage AI e OpenAI.
MONGODB_URI="<mongodb-connection-string>" VOYAGE_API_KEY="<voyage-api-key>" OPENAI_API_KEY= "<openai-api-key>" 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.
Configure o agente.
Crie um arquivo denominado config.py em seu projeto. Este arquivo lerá em suas variáveis de ambiente e conectará o aplicação a serviços como o banco de dados do MongoDB e o OpenAI.
from pymongo import MongoClient from openai import OpenAI import voyageai from dotenv import load_dotenv import os # Load environment variables from .env file load_dotenv() # Environment variables (private) MONGODB_URI = os.getenv("MONGODB_URI") VOYAGE_API_KEY = os.getenv("VOYAGE_API_KEY") OPENAI_API_KEY = os.getenv("OPENAI_API_KEY") # MongoDB cluster configuration mongo_client = MongoClient(MONGODB_URI) agent_db = mongo_client["ai_agent_db"] vector_collection = agent_db["embeddings"] memory_collection = agent_db["chat_history"] # Model configuration voyage_client = voyageai.Client(api_key=VOYAGE_API_KEY) client = OpenAI(api_key=OPENAI_API_KEY) VOYAGE_MODEL = "voyage-3-large" OPENAI_MODEL = "gpt-4o"
Use MongoDB como um banco de dados vetorial.
Crie um arquivo denominado ingest_data.py em seu projeto. Esse script ingere um PDF de amostra que contém um relatório de rendimentos recente do MongoDB em uma collection no MongoDB usando o modelo de incorporação voyage-3-large. Este código também inclui uma função para criar um índice de pesquisa vetorial em seus dados, se eles ainda não existirem.
Para aprender mais, consulte Ingestão.
from config import vector_collection, voyage_client, VOYAGE_MODEL from pymongo.operations import SearchIndexModel from langchain_community.document_loaders import PyPDFLoader from langchain.text_splitter import RecursiveCharacterTextSplitter import time # Define a function to generate embeddings def get_embedding(data, input_type = "document"): embeddings = voyage_client.embed( data, model = VOYAGE_MODEL, input_type = input_type ).embeddings return embeddings[0] # --- Ingest embeddings into MongoDB --- def ingest_data(): # Chunk PDF data loader = PyPDFLoader("https://investors.mongodb.com/node/13176/pdf") data = loader.load() text_splitter = RecursiveCharacterTextSplitter(chunk_size=400, chunk_overlap=20) documents = text_splitter.split_documents(data) print(f"Successfully split PDF into {len(documents)} chunks.") # Ingest chunked documents into collection print("Generating embeddings and ingesting documents...") docs_to_insert = [] for i, doc in enumerate(documents): embedding = get_embedding(doc.page_content) if embedding: docs_to_insert.append({ "text": doc.page_content, "embedding": embedding }) if docs_to_insert: result = vector_collection.insert_many(docs_to_insert) print(f"Inserted {len(result.inserted_ids)} documents into the collection.") else: print("No documents were inserted. Check embedding generation process.") # --- Create the vector search index --- index_name = "vector_index" search_index_model = SearchIndexModel( definition = { "fields": [ { "type": "vector", "numDimensions": 1024, "path": "embedding", "similarity": "cosine" } ] }, name=index_name, type="vectorSearch" ) try: vector_collection.create_search_index(model=search_index_model) print(f"Search index '{index_name}' creation initiated.") except Exception as e: print(f"Error creating search index: {e}") return # Wait for initial sync to complete print("Polling to check if the index is ready. This may take up to a minute.") predicate=None if predicate is None: predicate = lambda index: index.get("queryable") is True while True: indices = list(vector_collection.list_search_indexes(index_name)) if len(indices) and predicate(indices[0]): break time.sleep(5) print(index_name + " is ready for querying.")
Defina as ferramentas para o agente.
Crie um arquivo chamado tools.py em seu projeto. Esse arquivo define as ferramentas que o agente pode usar para dar resposta às perguntas. Neste exemplo, você define as seguintes ferramentas:
vector_search_tool: executa uma query de pesquisa vetorial para recuperar documentos relevantes da sua coleção.calculator_tool: usa a funçãoeval()para operações matemáticas básicas.
from config import vector_collection from ingest_data import get_embedding # Define a vector search tool def vector_search_tool(user_input: str) -> str: query_embedding = get_embedding(user_input) pipeline = [ { "$vectorSearch": { "index": "vector_index", "queryVector": query_embedding, "path": "embedding", "exact": True, "limit": 5 } }, { "$project": { "_id": 0, "text": 1 } } ] results = vector_collection.aggregate(pipeline) array_of_results = [] for doc in results: array_of_results.append(doc) return array_of_results # Define a simple calculator tool def calculator_tool(user_input: str) -> str: try: result = eval(user_input) return str(result) except Exception as e: return f"Error: {str(e)}"
Adicione memória ao agente.
Crie um arquivo chamado memory.py em seu projeto. Esse arquivo define o sistema que o agente utiliza para armazenar suas interações. Neste exemplo, você implementa a memória de curto prazo ao definir as seguintes funções:
store_chat_message: para armazenar informações sobre uma interação em uma coleção do MongoDB.retrieve_session_history: para obter todas as interações de uma sessão específica usando o camposession_id.
from config import memory_collection from datetime import datetime from typing import List def store_chat_message(session_id: str, role: str, content: str) -> None: message = { "session_id": session_id, # Unique identifier for the chat session "role": role, # Role of the sender (user or system) "content": content, # Content of the message "timestamp": datetime.now(), # Timestamp of when the message was sent } memory_collection.insert_one(message) def retrieve_session_history(session_id: str) -> List: # Query the collection for messages with a specific "session_id" in ascending order cursor = memory_collection.find({"session_id": session_id}).sort("timestamp", 1) # Iterate through the cursor and return a JSON object with the message role and content if cursor: messages = [{"role": msg["role"], "content": msg["content"]} for msg in cursor] else: messages = [] return messages
Defina o planejamento do agente.
Crie um arquivo chamado planning.py em seu projeto. Esse arquivo incluirá vários prompts e chamadas LLM para determinar o fluxo de execução do agente. Neste exemplo, você define as seguintes funções:
tool_selector: determina como o LLM seleciona a ferramenta apropriada para uma tarefa.generate_answer: orquestra o fluxo de execução do agente utilizando ferramentas, chamando o LLM e processando os resultados.get_llm_response: função de assistente para geração de resposta LLM.
from config import openai_client, OPENAI_MODEL from tools import vector_search_tool, calculator_tool from memory import store_chat_message, retrieve_session_history # Define a tool selector function that decides which tool to use based on user input and message history def tool_selector(user_input, session_history=None): messages = [ { "role": "system", "content": ( "Select the appropriate tool from the options below. Consider the full context of the conversation before deciding.\n\n" "Tools available:\n" "- vector_search_tool: Retrieve specific context about recent MongoDB earnings and announcements\n" "- calculator_tool: For mathematical operations\n" "- none: For general questions without additional context\n" "Process for making your decision:\n" "1. Analyze if the current question relates to or follows up on a previous vector search query\n" "2. For follow-up questions, incorporate context from previous exchanges to create a comprehensive search query\n" "3. Only use calculator_tool for explicit mathematical operations\n" "4. Default to none only when certain the other tools won't help\n\n" "When continuing a conversation:\n" "- Identify the specific topic being discussed\n" "- Include relevant details from previous exchanges\n" "- Formulate a query that stands alone but preserves conversation context\n\n" "Return a JSON object only: {\"tool\": \"selected_tool\", \"input\": \"your_query\"}" ) } ] if session_history: messages.extend(session_history) messages.append({"role": "user", "content": user_input}) response = openai_client.chat.completions.create( model=OPENAI_MODEL, messages=messages ).choices[0].message.content try: tool_call = eval(response) return tool_call.get("tool"), tool_call.get("input") except: return "none", user_input # Define the agent workflow def generate_response(session_id: str, user_input: str) -> str: # Store the user input in the chat history collection store_chat_message(session_id, "user", user_input) # Initialize a list of inputs to pass to the LLM llm_input = [] # Retrieve the session history for the current session and add it to the LLM input session_history = retrieve_session_history(session_id) llm_input.extend(session_history) # Append the user message in the correct format user_message = { "role": "user", "content": user_input } llm_input.append(user_message) # Call the tool_selector function to determine which tool to use tool, tool_input = tool_selector(user_input, session_history) print("Tool selected: ", tool) # Process based on selected tool if tool == "vector_search_tool": context = vector_search_tool(tool_input) # Construct the system prompt using the retrieved context and append it to the LLM input system_message_content = ( f"Answer the user's question based on the retrieved context and conversation history.\n" f"1. First, understand what specific information the user is requesting\n" f"2. Then, locate the most relevant details in the context provided\n" f"3. Finally, provide a clear, accurate response that directly addresses the question\n\n" f"If the current question builds on previous exchanges, maintain continuity in your answer.\n" f"Only state facts clearly supported by the provided context. If information is not available, say 'I DON'T KNOW'.\n\n" f"Context:\n{context}" ) response = get_llm_response(llm_input, system_message_content) elif tool == "calculator_tool": # Perform the calculation using the calculator tool response = calculator_tool(tool_input) else: system_message_content = "You are a helpful assistant. Respond to the user's prompt as best as you can based on the conversation history." response = get_llm_response(llm_input, system_message_content) # Store the system response in the chat history collection store_chat_message(session_id, "system", response) return response # Helper function to get the LLM response def get_llm_response(messages, system_message_content): # Add the system message to the messages list system_message = { "role": "system", "content": system_message_content, } # If the system message should go at the end (for context-based queries) if any(msg.get("role") == "system" for msg in messages): messages.append(system_message) else: # For general queries, put system message at beginning messages = [system_message] + messages # Get response from LLM response = openai_client.chat.completions.create( model=OPENAI_MODEL, messages=messages ).choices[0].message.content return response
Teste 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 config import mongo_client from ingest_data import ingest_data from planning import generate_response if __name__ == "__main__": try: run_ingest = input("Ingest sample data? (y/n): ") if run_ingest.lower() == 'y': ingest_data() session_id = input("Enter a session ID: ") while True: user_query = input("\nEnter your query (or type 'quit' to exit): ") if user_query.lower() == 'quit': break if not user_query.strip(): print("Query cannot be empty. Please try again.") continue answer = generate_response(session_id, user_query) print("\nAnswer:") print(answer) finally: mongo_client.close()
Salve seu projeto e execute o seguinte comando. Quando você executar o agente:
Caso ainda não tenha feito, instrua o agente a ingerir os dados de amostra.
Digite um ID de sessão para começar uma nova sessão ou continuar uma já existente.
Faça perguntas. O agente gera uma resposta com base nas suas ferramentas, nas interações anteriores e nos prompts definidos na fase de planejamento.
Consulte o exemplo de saída para uma interação de amostra:
python main.py
Ingest sample data? (y/n): y Successfully split PDF into 104 chunks. Generating embeddings and ingesting documents... Inserted 104 documents into the collection. Search index 'vector_index' creation initiated. Polling to check if the index is ready. This may take up to a minute. vector_index is ready for querying. Enter a session ID: 123 Enter your query (or type 'quit' to exit): What was MongoDB's latest acquisition? Tool selected: vector_search_tool Answer: MongoDB's latest acquisition was Voyage AI. Enter your query (or type 'quit' to exit): What do they do? Tool selected: vector_search_tool Answer: Voyage AI is a company that specializes in state-of-the-art embedding and reranking models designed to power next-generation AI applications. These technologies help organizations build more advanced and trustworthy AI capabilities. Enter your query (or type 'quit' to exit): What is 123+456? Tool selected: calculator_tool Answer: 579
Dica
Se estiver usando o Atlas, você poderá verificar suas incorporações e interações navegando até o namespace ai_agent_db.embeddings na UI do Atlas.
Continue a construir.
Agora que você possui um agente básico de AI, você pode continuar a desenvolvê-lo da seguinte maneira:
Melhorando o desempenho das suas ferramentas de pesquisa vetorial e pelo ajuste fino dos seus pipelines RAG.
Adicionar mais ferramentas ao agente, como ferramentas híbridas ou de pesquisa de texto completo.
Aprimorando a fase de planejamento ao utilizar prompts mais avançados e chamadas de LLM.
Implementação de memória de longo prazo e sistemas de memória mais avançados usando o MongoDB Search e o MongoDB Vector Search para armazenar e recuperar interações importantes entre sessões.
Tutorials
Para mais tutoriais sobre a construção de agentes de AI com o MongoDB, consulte a tabela a seguir:
Frameworks | |
Plataformas de empresas | |
Ferramentas | |
Recursos adicionais |