MongoDB Atlas は、 AIエージェントを構築するためのいくつかの機能を提供します。ベクトルとドキュメントデータベースの両方として、Atlas はエージェント的 RG のさまざまな検索方法、また、短期間および長期のエージェントメモリ用に同じデータベースにエージェントインタラクションを保存します。
AIエージェントとは
生成系AIのコンテキストでは、 AIエージェントとは通常、 LM などのAIモデルと事前定義されたツールのセットを組み合わせて、タスクを自律的にまたは半自動的に完了できるシステムを指します。
AIエージェントは、ツールを使用してコンテキストを収集し、外部システムと交流し、アクションを実行できます。独自の実行フロー(プラン作成)を定義し、以前のインタラクションを記憶して応答(メモリ)を通知できます。したがって、 AIエージェントは、理由付け、計画、決定権を必要とする複雑なタスクに最適です。
アーキテクチャ
AIエージェントには通常、次のコンポーネントの組み合わせが含まれます。
知覚 | エージェントの入力。テキスト入力はAIエージェントの最も一般的な認識メカニズムですが、言語、画像、またはマルチモーダル データにすることもできます。 |
計画 | エージェントが次の操作を決定する方法。このコンポーネントには通常、LDM とプロンプトが含まれ、フィードバックループや考えの連鎖や reAction などのさまざまな プロンプトエンジニアリング メソッド を使用して、複雑なタスクを実行する際に LM の理由を支援します。 AIエージェントは、決定権を持つ単一の LM 、複数のプロンプトを持つ LM、複数の LM が連携する、またはこれらのアプローチの任意の組み合わせで構成できます。 |
ツール | エージェントがタスクのコンテキストを収集する方法。ツールを使用すると、エージェントは外部システムと交流し、ベクトル検索、ウェブ検索、または他のサービスから API を呼び出すなどのアクションを実行できます。 |
メモリ | エージェントの相互作用を保存するためのシステムで、エージェントは過去の経験から学び、応答に情報を与えられます。メモリは、短期間(現在のセッション用)または長期(セッション全体で永続的)の場合があります。 |
注意
AIエージェントは、設計パターン、機能、複雑度が異なります。マルチエージェント システムを含むその他のエージェントアーキテクチャについては、「 エージェント デザイン パターン 」を参照してください。
MongoDBでAIエージェントを構築
MongoDB Atlas は、 AIエージェントを構築するための次のコンポーネントをサポートしています。
ツール : MongoDB Search 機能をエージェントが関連情報を取得し、エージェント RG を実装するツールとして活用します。
メモリ :エージェントのインタラクションを短期間メモリと長期メモリの両方でMongoDBコレクションに保存します。
エージェント ツール
AIエージェントのコンテキストでは、 ツール とは、エージェントによってプログラム的に定義され、呼び出されるすべてのツールを指します。ツールを使用すると、テキストの生成以外のエージェントの機能が拡張され、外部システムと交流し、情報を取得し、アクションを実行できるようになります。ツールは通常、次のような特定のインターフェースを使用して定義されます。
エージェントがツールを使用するタイミングを理解するのに役立つ名前と説明。
必要なパラメーターとその形式。
呼び出されるときに実際の操作を実行する関数。
エージェントは推論機能を使用して、ユーザーの入力と現在のタスクに基づいて、使用するツール、いつ使用するか、またどのパラメータを提供するかを決定します。
標準のMongoDBクエリに加えて、Atlas はエージェントのツールとして実装できるいくつかの検索機能を提供します。
Atlas ベクトル検索 :ベクトル検索を実行して、セマンティック意味と類似性に基づいて関連するコンテキストを検索します。詳細については、 Atlas ベクトル検索 の概要 を参照してください。
Atlas Search : キーワード一致と関連性スコアリングに基づいて関連コンテキストを取得するには、全文検索を実行します。詳しくは、「 Atlas Search の概要 」を参照してください。
ハイブリッド検索 : Atlas ベクトル検索と Atlas Search を組み合わせて、両方のアプローチの長さを活用します。詳しくは、「 ハイブリッド検索の実行方法 」を参照してください。
ツールは、手動で、またはツールの作成と呼び出しのための組み込みの抽象化を提供する LgChallenge や LingGraph などのフレームワークを使用して定義できます。
ツールは、エージェントが特定のタスクを実行するために呼び出すことができる関数として定義されます。例、次の構文は、ベクトル検索クエリーを実行するツールを定義する方法を示しています。
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
ツール呼び出しは、エージェントがツールを実行するために使用するものです。エージェント内でツール呼び出しを処理する方法を定義することも、フレームワークを使用してこれを処理することもできます。これらは通常、ツール名とツールに渡すその他の引数を含むJSONオブジェクトとして定義されるため、エージェントは適切なパラメーターを使用してツールを呼び出すことができます。例、次の構文は、エージェントが vector_search_tool
を呼び出す方法を示しています。
{ "tool": "vector_search_tool", "args": { "query": "What is MongoDB?" }, "id": "call_H5TttXb423JfoulF1qVfPN3m" }
エージェント RAG
Atlas をベクトルデータベースとして使用することで、 エージェント Atlas を実装する取得ツールを作成できます。これは、 AIエージェントを通じて取得と生成プロセスを動的にオーケストレーションできる RG の高度な形式です。
このアプローチにより、より複雑なワークフローとユーザー インタラクションが可能になります。例、セマンティック検索には Atlas ベクトル検索を使用し、全文検索には Atlas Search を使用するなど、タスクに基づいて最適な取得ツールを決定するようにAIエージェントを構成できます。また、エージェントの取得機能をさらにカスタマイズするために、さまざまなコレクションに対してさまざまな取得ツールを定義することもできます。
エージェント メモリ
エージェントのメモリには、エージェントが過去の経験から学習し、より関連的でパーソナライズされた応答を提供できるようにするために、以前のインタラクションに関する情報が保存されているものが含まれます。これは、一貫性がありコンテキストに関連する応答を提供するために、エージェントがセッションの以前のタームを覚えておく必要があるタスクなど、コンテキストを必要とするタスクにとって特に重要です。エージェントのメモリには、次の 2 つのプライマリタイプがあります。
短期間メモリ : 最近のやり取りやアクティブなタスクコンテキストなど、現在のセッションの情報を保存します。
長期メモリ : セッション間で情報を保持します。これには、過去のセッションやパーソナライズされた設定が一定期間含まれる可能性があります。
Atlas はドキュメントデータベースでもあるため、 MongoDBコレクションにインタラクションを保存することでエージェントのメモリを実装できます。その後、エージェントは必要に応じてこのコレクションをクエリまたはアップデートできます。 MongoDBでエージェントメモリを実装するにはいくつかの方法があります。
session_id
短期間メモリを使用する場合は、インタラクションを保存するときに特定のフィールドを識別し、同じIDを持つインタラクションをクエリして、コンテキストとしてエージェントに渡すことができます。長期メモリの場合、LDM を使用していくつかのインタラクションを処理してユーザーの優先順位や重要なコンテキストなどの関連情報を抽出し、その情報を別のコレクションに保存し、必要な場合にエージェントがクエリできるようにできます。
やり取り履歴をより効率的かつ複雑に取得できる堅牢なメモリ管理システムを構築するには、Atlas Search を活用して保存されたインタラクションのインデックスとクエリを実行します。
短期間のメモリを保存するコレクション内のドキュメントは、次のようになります。
{ "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" } ] }
長期メモリを保存するコレクション内のドキュメントは、次のようになります。
{ "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"], } ] }
次のフレームワークも、 MongoDBのエージェントメモリの直接抽象化を提供します。
フレームワーク | 主な機能 |
---|---|
LgChuin |
詳しくは、 チュートリアルを参照してください。 |
LangGraph |
詳しくは、 LongGraph と LgGraph.js を参照してください。 |
はじめる
次のチュートリアルでは、エージェントフレームワークなしで、Atlas を使用してエージェント用 RAG とメモリ用にAIエージェントを構築する方法を説明します。
このチュートリアルの実行可能なバージョンを Python エディタとして作業します。
前提条件
Atlas の サンプル データ セット からの映画データを含むコレクションを使用します。
Atlas アカウントで、MongoDB バージョン 6.0.11 または7.0.2 以降(RCs を含む)のクラスターを実行している。IP アドレスが Atlas プロジェクトのアクセスリストに含まれていることを確認してください。詳細については、クラスターの作成を参照してください。
投票AI APIキー。
OpenAI APIキー。
注意
このチュートリアルでは、Voyage AIと OpenAI のモデルを使用していますが、コードを変更して、お好みのモデルを使用できます。
手順
このAIエージェントは、カスタムデータソースに関する質問に答え、計算を実行するために使用できます。また、以前の相互作用を記憶して、応答を通知することもできます。次のコンポーネントを使用します。
認識 : テキスト入力。
計画 :タスクを実行するための LM とさまざまなプロンプト。
ツール :ベクトル検索ツールと計算ツール。
メモリ : インタラクションをMongoDBコレクションに保存します。
環境を設定します。
プロジェクトを初期化し、依存関係をインストールします。
新しいプロジェクトディレクトリを作成し、必要な依存関係をインストールします。
mkdir mongodb-ai-agent cd mongodb-ai-agent pip install --quiet --upgrade pymongo voyageai openai langchain langchain_mongodb langchain_community 注意
プロジェクトでは、次の構造を使用します。
mongodb-ai-agent ├── config.py ├── ingest-data.py ├── tools.py ├── memory.py ├── planning.py ├── main.py 環境を構成します。
プロジェクトに
config.py
という名前のファイルを作成します。このファイルには、エージェント、 Atlas接続文字列、 MongoDBデータベースとコレクション名のAPIキーが含まれます。プレースホルダー値を、Atlas接続文字列と、Vorage AIおよび OpenAI APIキーで置き換えます。
from pymongo import MongoClient from openai import OpenAI import voyageai MONGODB_URI = "<connection-string>" VOYAGE_API_KEY = "<voyage-api-key>" OPENAI_API_KEY = "<openai-api-key>" # MongoDB Atlas 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" 注意
接続stringには、次の形式を使用する必要があります。
mongodb+srv://<db_username>:<db_password>@<clusterName>.<hostname>.mongodb.net
Atlas をベクトルデータベースとして使用します。
ingest-data.py
プロジェクトに という名前のファイルを作成します。このスクリプトは、 埋め込みモデルを使用して、最近のMongoDB収益レポートを含むサンプルPDF を Atlasvoyage-3-large
のコレクションに取り込みます。
詳細については、「 取り込み 」を参照してください。
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 Atlas --- 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.")
エージェントのツールを定義します。
プロジェクトに tools.py
という名前のファイルを作成します。このファイルは、エージェントが質問に答えるために使用できるツールを定義します。この例では、次のツールを定義しています。
vector_search_tool
:ベクトル検索クエリーを実行して、コレクションから関連するドキュメントを検索します。calculator_tool
: 基本的な数学演算にeval()
関数を使用します。
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)}"
エージェントにメモリを追加します。
プロジェクトに memory.py
という名前のファイルを作成します。このファイルは、エージェントがインタラクションを保存するために使用するシステムを定義します。この例では、次の関数を定義して短期間メモリを実装します。
store_chat_message
: インタラクションに関する情報をMongoDBコレクションに保存します。retrieve_session_history
:session_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
エージェントのプランを定義します。
プロジェクトに planning.py
という名前のファイルを作成します。このファイルには、エージェントの実行フローを決定するためのさまざまなプロンプトと LM 呼び出しが含まれます。この例では、次の関数を定義しています。
tool_selector
: LM がタスクに適したツールを選択する方法を決定します。generate_answer
: ツールを使用し、LVM を呼び出し、結果を処理することで、エージェントの実行フローを調整します。get_llm_response
: LM 応答生成用のヘルパー関数。
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
エージェントをテストします。
最後に、プロジェクトに main.py
という名前のファイルを作成します。このファイルはエージェントを実行し、そのエージェントを操作できるようにします。
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()
プロジェクトを保存し、次の コマンドを実行します。エージェントを実行する場合
まだ行っていない場合は、エージェントにサンプルデータを取り込むように指示します。
セッションIDを入力して、新しいセッションを開始するか、既存のセッションを続行します。
質問する。エージェントは、ツール、以前のインタラクション、および計画フェーズで定義されたプロンプトに基づいて応答を生成します。サンプルインタラクションについては、 出力の例を参照してください。
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
クラスターの データベースに移動し、 または コレクションを選択すると、Atlas UIで埋め込みとインタラクションを表示できます。ai_agent_db
embeddings
chat_history
構築を続行します。
基本的なAIエージェントが用意できたら、次の方法で開発を続けることができます。
より高度なプロンプトと LM 呼び出しを使用して、プランニング フェーズを絞り込みます。
Atlas Search を使用して、長期メモリとより高度なメモリ システムを実装します。
Tutorials
MongoDBを使用してAIエージェントを構築する方法の詳細なチュートリアルについては、次の表を参照してください。
フレームワーク | |
エンタープライズ プラットフォーム | |
追加リソース |