MongoDB ofrece varias características para desarrollar agentes de IA. Como base de datos tanto de vectores como de documentos, MongoDB admite varios métodos de búsqueda para RAG agéntica, así como el almacenamiento de interacciones de agentes en la misma base de datos para la memoria a corto y largo plazo de los agentes.
¿Qué es un agente de IA?
En el contexto de la IA generativa, un agente de IA generalmente se refiere a un sistema que puede completar una tarea de forma autónoma o semiautónoma combinando modelos de IA como LLMcon un conjunto de herramientas predefinidas.
Los agentes de IA pueden utilizar herramientas para recopilar contexto, interactuar con sistemas externos y realizar acciones. Ellos pueden definir su propio flujo de ejecución (planificación) y recordar las interacciones anteriores para informar sus respuestas (memoria). Por lo tanto, los agentes de IA son los más adecuados para tareas complejas que requieren razonamiento, planificación y toma de decisiones.
Arquitectura
Un agente de IA suele incluir una combinación de los siguientes componentes:
Percepción | Su entrada para el agente. Las entradas de texto son el mecanismo de percepción más común para los agentes de IA, pero las entradas también pueden ser de audio, imágenes o datos multimodales. |
Planificación | Cómo el agente determina qué hacer a continuación. Este componente generalmente incluye LLM y avisos, utilizando bucles de retroalimentación y varios técnicas de ingeniería rápida como la cadena de pensamiento y reAct, para ayudar al LLM a razonar tareas complejas. Los agentes de IA pueden consistir en un solo LLM como responsable de la toma de decisiones, un LLM con múltiples indicaciones, múltiples LLM trabajando juntos, o cualquier combinación de estos enfoques. |
Herramientas | Cómo el agente recopila el contexto para una tarea. Las herramientas permiten la interacción de los agentes con sistemas externos y realizar acciones como la búsqueda vectorial, la búsqueda en la web o la llamada a APIs de otros servicios. |
Memoria | Un sistema para almacenar interacciones de agentes, de modo que el agente pueda aprender de experiencias pasadas para informar sus respuestas. La memoria puede ser de corto plazo (para la sesión actual) o de largo plazo (persistente a través de las sesiones). |
Nota
Los agentes de IA varían en el patrón de diseño, la función y la complejidad. Para aprender sobre otras arquitecturas de agentes, incluidos los sistemas multiagente, consultar Patrones de diseño Agentic.
Compila agentes de IA con MongoDB
MongoDB admite los siguientes componentes para desarrollar agentes de IA:
Herramientas: aprovechar las características de búsqueda de MongoDB como herramientas para que el agente recupere información relevante e implemente el RAG agente.
Memoria: almacenar las interacciones del agente en colecciones de MongoDB para la memoria a corto y largo término.
Herramientas del agente
En el contexto de los agentes de IA, una herramienta es cualquier cosa que pueda ser definida e invocada programáticamente por el agente. Las herramientas amplían las capacidades del agente más allá de generar texto, permitiéndole la interacción con sistemas externos, recuperar información y realizar acciones. Las herramientas suelen definirse con una interfaz específica que incluye:
Un nombre y una descripción que ayuden al agente a comprender cuándo debe usar la herramienta.
Parámetros requeridos y sus formatos esperados.
Una función que lleva a cabo la operación real al ser invocada.
El agente utiliza sus capacidades de razonamiento para determinar qué herramienta debe usar, cuándo debe usarla y qué parámetros debe proporcionar, basándose en la entrada del usuario y la tarea en cuestión.
Además de las queries estándar de MongoDB, MongoDB proporciona varias capacidades de búsqueda que se pueden implementar como herramientas para el agente.
Búsqueda vectorial de MongoDB: Realice una búsqueda vectorial para recuperar el contexto relevante según el significado semántico y la similitud. Para obtener más información, consulte Descripción general de la búsqueda vectorial de MongoDB.
MongoDB búsqueda: realice búsquedas de texto completo para recuperar el contexto relevante según la coincidencia de palabras clave y la puntuación de relevancia. Para obtener más información, consulta Descripción general de la búsqueda en MongoDB.
Búsqueda híbrida: combina la búsqueda vectorial de MongoDB con la búsqueda de MongoDB para aprovechar las fortalezas de ambos enfoques. Para aprender más, consulta Cómo realizar una búsqueda híbrida.
Se puede definir herramientas manualmente o utilizando frameworks como LangChain y LangGraph, que proporcionan abstracciones de funcionalidad incorporada para la creación y uso de herramientas.
Las herramientas se definen como funciones que el agente puede llamar para llevar a cabo tareas específicas. Por ejemplo, la siguiente sintaxis ilustra cómo podría definir una herramienta que ejecute una query de búsqueda vectorial:
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
Las llamadas a herramientas son lo que el agente utiliza para ejecutar las herramientas. Se puede definir cómo procesar las llamadas a herramientas en el agente, o usar un framework para la gestión. Por lo general, se definen como objetos JSON que incluyen el nombre de la herramienta y otros argumentos para pasar a la herramienta, de modo que el agente pueda llamar a la herramienta con los parámetros adecuados. Por ejemplo, la siguiente sintaxis muestra cómo un agente podría llamar a la herramienta de búsqueda vectorial:
{ "tool": "vector_search_tool", "args": { "query": "What is MongoDB?" }, "id": "call_H5TttXb423JfoulF1qVfPN3m" }
Agentic RAG
Al utilizar MongoDB como base de datos vectorial, se pueden crear herramientas de recuperación que implementan RAG agéntica, que es una forma avanzada de RAG que permite orquestar dinámicamente el proceso de recuperación y generación a través de un agente de IA.
Este enfoque permite flujos de trabajo e interacciones de usuario más complejas. Por ejemplo, se puede configurar el agente de IA para determinar la herramienta óptima de recuperación según la tarea, como usar MongoDB Vector Search para búsqueda semántica y MongoDB Search para búsqueda en texto completo. También se puede definir distintas herramientas de recuperación para diferentes colecciones para personalizar aún más las capacidades de recuperación del agente.
Memoria de agente
La memoria de los agentes implica almacenar información sobre interacciones anteriores, para que el agente pueda aprender de experiencias pasadas y proporcionar respuestas más relevantes y personalizadas. Esto es particularmente importante para tareas que requieren contexto, como los agentes conversacionales, donde el agente necesita recordar los turnos anteriores de la conversación para proporcionar respuestas coherentes y contextualmente relevantes. Existen dos tipos primarios de memoria de agente:
Memoria a corto plazo: almacena información para la sesión actual, como los turnos recientes de conversación y el contexto de la tarea activa.
Memoria a largo plazo: persiste la información entre las sesiones, lo que puede incluir conversaciones pasadas y preferencias personalizadas a lo largo del tiempo.
Dado que MongoDB también es una base de datos de documentos, puedes implementar memoria para agentes almacenando tus interacciones en una colección de MongoDB. El agente puede entonces query o actualizar esta colección según sea necesario. Existen varias maneras de implementar la memoria del agente con MongoDB:
Para la memoria a corto plazo, podrías incluir una
session_idcampo para identificar una sesión específica al almacenar interacciones y luego consultar interacciones con el mismo ID para pasar al agente como contexto.Para la memoria a largo plazo, se podrían procesar varias interacciones con un LLM para extraer información relevante, como las preferencias del usuario o un contexto importante, y luego almacenar esta información en una colección separada que el agente pueda realizar una query cuando sea necesario.
Para construir sistemas robustos de gestión de memoria que permitan una recuperación más eficiente y compleja de historiales de conversaciones, aprovecha MongoDB Search o MongoDB Vector Search para almacenar, indexar y consultar interacciones importantes a lo largo de las sesiones.
Un documento en una colección que almacena memoria a corto plazo podría parecerse a lo siguiente:
{ "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" } ] }
Un documento en una colección que almacena memoria a largo plazo podría parecerse a lo siguiente:
{ "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"], } ] }
Los siguientes frameworks también proporcionan abstracciones directas para la memoria de los agentes con MongoDB:
Marco | Características |
|---|---|
LangChain |
Para aprender más, consulta el tutorial. |
LangGraph |
Para obtener más información, consulta LangGraph y LangGraph.js. |
Empezar
El siguiente tutorial demuestra cómo compilar un agente de IA utilizando MongoDB para RAG agentic y memoria, sin un marco de agentes.
➤ Utiliza el menú desplegable Seleccionar su lenguaje para establecer el lenguaje de este tutorial.
Trabaja con una versión ejecutable de este tutorial como un cuaderno interactivo 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 que ejecuta la versión 6.0.11, 7.0.2 o posterior de MongoDB. Asegúrese de que su dirección IP esté incluida en la lista de acceso de su proyecto Atlas.
Una implementación local de Atlas creada usando Atlas CLI. Para obtener más información, consulta Crear una Implementación local de Atlas.
Un clúster de MongoDB Community o Enterprise con Search y Vector Search instalados.
Una clave API de Voyage IA.
Una clave de API de OpenAI.
Nota
Este tutorial utiliza modelos de Voyage IA y OpenAI, pero se puede modificar el código para usar los modelos que se prefieran.
Procedimiento
Este agente de IA puede utilizarse para responder preguntas sobre una fuente de datos personalizada y realizar cálculos. También puede recordar anteriores interacciones para informar sus respuestas. Utiliza los siguientes componentes:
Percepción: entradas de texto.
Planificación: un LLM y varios prompts para razonar a través de la tarea.
Herramientas: una herramienta de búsqueda vectorial y una herramienta de calculadora.
Memoria: almacena las interacciones en una colección de MongoDB.
Configura el entorno.
Inicialice el proyecto e instale las dependencias.
Cree un nuevo directorio de proyecto y luego instale las dependencias necesarias:
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 Nota
Su proyecto utilizará la siguiente estructura:
mongodb-ai-agent ├── .env ├── config.js ├── ingest-data.js ├── tools.js ├── memory.js ├── planning.js └── index.js Configura el entorno.
Se debe crear un archivo de entorno llamado
.enven el proyecto. Este archivo contendrá claves API para el agente, la cadena de conexión de MongoDB y los nombres de la base de datos y la colección de MongoDB.Se deben reemplazar los valores de marcador con la cadena de conexión de MongoDB y las claves de API de Voyage IA y OpenAI.
MONGODB_URI="<mongodb-connection-string>" VOYAGE_API_KEY="<voyage-api-key>" OPENAI_API_KEY= "<openai-api-key>" Nota
Se debe sustituir
<connection-string>por la cadena de conexión del clúster Atlas o de la implementación local de Atlas.Su cadena de conexión debe usar el siguiente formato:
mongodb+srv://<db_username>:<db_password>@<clusterName>.<hostname>.mongodb.net Para obtener más información,consulte Conectarse a un clúster a través de bibliotecas de cliente.
Su cadena de conexión debe usar el siguiente formato:
mongodb://localhost:<port-number>/?directConnection=true Para obtener más información, consulta Cadenas de conexión.
Configura el agente.
Cree un archivo llamado config.js en su proyecto. Este archivo leerá sus variables de entorno y conectará la aplicación a servicios como la base de datos MongoDB y 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,});
Utilice MongoDB como una base de datos vectorial.
Se debe crear un archivo llamado ingest-data.js en el proyecto. Este script ingiere un PDF de muestra que contiene un informe de ganancias reciente de MongoDB en una colección en MongoDB utilizando el modelo de incrustación voyage-3-large. Este código también incluye una función para crear un índice de búsqueda vectorial sobre los datos si aún no existe.
Para aprender más, consulta Ingestión.
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 herramientas para el agente.
Se debe crear un archivo llamado tools.js en el proyecto. Este archivo define las herramientas que el agente puede usar para responder preguntas. En este ejemplo, el usuario define las siguientes herramientas:
vectorSearchTool: se ejecuta una query de búsqueda vectorial para recuperar documentos relevantes de su colección.calculatorTool: usa la bibliotecamathjspara operaciones 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}`; } }
Añadir memoria al agente.
Se debe crear un archivo llamado memory.js en el proyecto. Este archivo define el sistema que el agente utiliza para almacenar sus interacciones. En este ejemplo, se implementa la memoria a corto plazo definiendo las siguientes funciones:
storeChatMessage: para almacenar información sobre una interacción en una colección de MongoDB.retrieveSessionHistory: para obtener todas las interacciones de una sesión específica usando el 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; }
Definir la planificación del agente.
Se debe crear un archivo llamado planning.js en el proyecto. Este archivo incluirá varias indicaciones y llamadas de LLM para determinar el flujo de ejecución del agente. En este ejemplo, se debe definir las siguientes funciones:
openAIChatCompletion: función asistente para llamar la API de OpenAI y generar respuestas.toolSelector: Determina cómo el LLM selecciona la herramienta adecuada para una tarea.generateAnswer: orquesta el flujo de ejecución del agente utilizando herramientas, llamando al LLM y procesando los resultados.getLLMResponse: función de asistencia para la generación de respuestas de 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; }
Pruebe el agente.
Por último, se debe crear un archivo llamado index.js en el proyecto. Este archivo ejecuta el agente y permite interactuar con él.
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();
Guardar el proyecto y luego ejecutar el siguiente comando. Cuando se ejecute el agente:
Si aún no lo ha hecho, instruya al agente para que ingiera los datos de muestra.
Introducir un ID de sesión para iniciar una nueva sesión o continuar una sesión existente.
Haz preguntas. El agente genera una respuesta basada en tus herramientas, las interacciones anteriores y las indicaciones definidas en la fase de planificación.
Consulte el ejemplo de salida para una interacción de muestra:
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
Tip
Si estás utilizando Atlas, puedes verificar tus incrustaciones e interacciones navegando al namespace ai_agent_db.embeddings en la Interfaz de Usuario de Atlas.
Continúa construyendo.
Ahora que tiene un agente de IA básico, puede seguir desarrollándolo mediante:
Mejorando el rendimiento de las herramientas de búsqueda vectorial y ajustando sus pipelines de RAG.
Añadiendo más herramientas al agente, como herramientas híbridas o herramientas de búsqueda de texto completo.
Se refine la fase de planificación mediante el uso de indicaciones más avanzadas y llamadas de LLM.
Implementación de la memoria a largo plazo y de sistemas de memoria más avanzados mediante el uso de MongoDB búsqueda y MongoDB búsqueda vectorial para almacenar y recuperar interacciones importantes entre sesiones.
Configura el entorno.
Inicialice el proyecto e instale las dependencias.
Cree un nuevo directorio de proyecto y luego instale las dependencias necesarias:
mkdir mongodb-ai-agent cd mongodb-ai-agent pip install --quiet --upgrade pymongo voyageai openai langchain langchain-mongodb langchain-community python-dotenv Nota
Su proyecto utilizará la siguiente estructura:
mongodb-ai-agent ├── .env ├── config.py ├── ingest_data.py ├── tools.py ├── memory.py ├── planning.py ├── main.py Configura el entorno.
Se debe crear un archivo de entorno llamado
.enven el proyecto. Este archivo contendrá claves API para el agente, la cadena de conexión de MongoDB y los nombres de la base de datos y la colección de MongoDB.Se deben reemplazar los valores de marcador con la cadena de conexión de MongoDB y las claves de API de Voyage IA y OpenAI.
MONGODB_URI="<mongodb-connection-string>" VOYAGE_API_KEY="<voyage-api-key>" OPENAI_API_KEY= "<openai-api-key>" Nota
Se debe sustituir
<connection-string>por la cadena de conexión del clúster Atlas o de la implementación local de Atlas.Su cadena de conexión debe usar el siguiente formato:
mongodb+srv://<db_username>:<db_password>@<clusterName>.<hostname>.mongodb.net Para obtener más información,consulte Conectarse a un clúster a través de bibliotecas de cliente.
Su cadena de conexión debe usar el siguiente formato:
mongodb://localhost:<port-number>/?directConnection=true Para obtener más información, consulta Cadenas de conexión.
Configura el agente.
Cree un archivo llamado config.py en su proyecto. Este archivo leerá sus variables de entorno y conectará la aplicación a servicios como la base de datos MongoDB y 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"
Utilice MongoDB como una base de datos vectorial.
Se debe crear un archivo llamado ingest_data.py en el proyecto. Este script ingiere un PDF de muestra que contiene un informe de ganancias reciente de MongoDB en una colección en MongoDB utilizando el modelo de incrustación voyage-3-large. Este código también incluye una función para crear un índice de búsqueda vectorial sobre los datos si aún no existe.
Para aprender más, consulta Ingestión.
from config import vector_collection, voyage_client, VOYAGE_MODEL from pymongo.operations import SearchIndexModel from langchain_community.document_loaders import PyPDFLoader from langchain_text_splitters 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 herramientas para el agente.
Se debe crear un archivo llamado tools.py en el proyecto. Este archivo define las herramientas que el agente puede usar para responder preguntas. En este ejemplo, el usuario define las siguientes herramientas:
vector_search_tool: se ejecuta una query de búsqueda vectorial para recuperar documentos relevantes de su colección.calculator_tool: se usa la funcióneval()para operaciones 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)}"
Añadir memoria al agente.
Se debe crear un archivo llamado memory.py en el proyecto. Este archivo define el sistema que el agente utiliza para almacenar sus interacciones. En este ejemplo, se implementa la memoria a corto plazo definiendo las siguientes funciones:
store_chat_message: para almacenar información sobre una interacción en una colección de MongoDB.retrieve_session_history: para obtener todas las interacciones de una sesión específica usando el 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
Definir la planificación del agente.
Se debe crear un archivo llamado planning.py en el proyecto. Este archivo incluirá varias indicaciones y llamadas de LLM para determinar el flujo de ejecución del agente. En este ejemplo, se debe definir las siguientes funciones:
tool_selector: Determina cómo el LLM selecciona la herramienta adecuada para una tarea.generate_answer: orquesta el flujo de ejecución del agente utilizando herramientas, llamando al LLM y procesando los resultados.get_llm_response: función de asistencia para la generación de respuestas de 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
Pruebe el agente.
Por último, se debe crear un archivo llamado main.py en el proyecto. Este archivo ejecuta el agente y permite interactuar con él.
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()
Guardar el proyecto y luego ejecutar el siguiente comando. Cuando se ejecute el agente:
Si aún no lo ha hecho, instruya al agente para que ingiera los datos de muestra.
Introducir un ID de sesión para iniciar una nueva sesión o continuar una sesión existente.
Haz preguntas. El agente genera una respuesta basada en tus herramientas, las interacciones anteriores y las indicaciones definidas en la fase de planificación.
Consulte el ejemplo de salida para una interacción de muestra:
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
Tip
Si estás utilizando Atlas, puedes verificar tus incrustaciones e interacciones navegando al namespace ai_agent_db.embeddings en la Interfaz de Usuario de Atlas.
Continúa construyendo.
Ahora que tiene un agente de IA básico, puede seguir desarrollándolo mediante:
Mejorando el rendimiento de las herramientas de búsqueda vectorial y ajustando sus pipelines de RAG.
Añadiendo más herramientas al agente, como herramientas híbridas o herramientas de búsqueda de texto completo.
Se refine la fase de planificación mediante el uso de indicaciones más avanzadas y llamadas de LLM.
Implementación de la memoria a largo plazo y de sistemas de memoria más avanzados mediante el uso de MongoDB búsqueda y MongoDB búsqueda vectorial para almacenar y recuperar interacciones importantes entre sesiones.
Tutorials
Para obtener más tutoriales sobre la creación de agentes de IA con MongoDB, consulte la siguiente tabla:
Frameworks | |
Plataformas empresariales | |
Herramientas | |
Recursos adicionales |