MongoDB Atlas は、AI エージェントを構築するためのいくつかのAI機能を提供します。ベクトルおよびドキュメントデータベースとして、AtlasはエージェントRAGの様々な検索方法をサポートし、短期および長期のエージェントメモリのために同じデータベースにエージェントのインタラクションを保存します。
AIエージェントとは何ですか?
生成系AIのコンテキストでは、AIエージェントとは通常、LLMなどのAIモデルと事前定義されたツールのセットを組み合わせて、タスクを自律的または半自律的に完了できるシステムを指します。
AIエージェントはツールを使用してコンテキストを収集し、外部システムと交流し、アクションを実行できます。彼らは独自の実行フロー(計画)を定義し、前のやり取りを記憶して応答に活かすことができます。したがって、AIエージェントは、推論、計画、意思決定を必要とする複雑なタスクに最適です。
アーキテクチャ
AIエージェントには通常、以下のコンポーネントの組み合わせが含まれます。
認識 | エージェントへの入力。テキスト入力はAIエージェントの最も一般的な知覚メカニズムですが、入力は音声、画像、またはマルチモーダルデータであることもあります。 |
計画 | エージェントが次に何をすべきかを決定する方法。このコンポーネントには通常、LLMとプロンプトが含まれ、フィードバックループとさまざまなプロンプトエンジニアリング技術、チェーン・オブ・ソートやreActなどを使用して、LLMが複雑なタスクを推論するのを支援します。 AI エージェントは、意思決定者としての単一のLLM、複数のプロンプトを備えたLLM、連携して動作する複数のLLM、またはこれらのアプローチの任意の組み合わせで構成できます。 |
ツール | エージェントがタスクのコンテキストを収集する方法。ツールを使用することで、エージェントは外部システムと交流し、ベクトル検索、ウェブ検索、他のサービスからのAPI呼び出しなどのアクションを実行できます。 |
メモリ | エージェントのやり取りを保存するシステムです。これにより、エージェントは過去の経験から学び、応答に役立てることができます。メモリは短期(現在のセッション用)または長期(セッション間で保持される)にすることができます。 |
注意
AI エージェントは設計パターン、機能、複雑さが異なります。他のエージェントアーキテクチャ(マルチエージェントシステムを含む)について学ぶには、エージェンティックデザインパターンを参照してください。
MongoDBを使用してAIエージェントをビルドする
MongoDB Atlas は、AIエージェントを構築するための以下のコンポーネントをサポートしています。
ツール:MongoDB の検索機能を活用して、エージェントが関連情報を取得し、エージェント型 RAG を実装するためのツールとして使用します。
メモリ:エージェントのインタラクションを短期および長期のメモリの両方の MongoDB コレクションに保存します。
エージェントツール
AIエージェントのコンテキストでは、ツールとは、エージェントがプログラムで定義し、呼び出すことができるものを指します。ツールは、テキストの生成だけでなく、外部システムとの対話、情報の取得、アクションの実行など、エージェントの機能を拡張します。ツールは通常、以下を含む特定のインターフェースで定義されます。
エージェントがツールを使用するタイミングを理解するのに役立つ名前と説明。
必須パラメーターとその期待される形式。
呼び出された際に実際の操作を実行する関数です。
エージェントは推論機能を使用して、ユーザーの入力と現在のタスクに基づいて、どのツールを使用するか、いつ使用するか、どのパラメーターを提供するかを決定します。
標準の MongoDB クエリに加えて、Atlas はエージェントのツールとして実装できるいくつかの検索機能を提供します。
Atlas Vector Search:意味と類似性に基づいて関連性の高いコンテキストをベクトル検索で取得します。詳細については、Atlas Vector Searchの概要を参照してください。
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 をベクトルデータベースとして使用することで、エージェント型 RAG を実装する検索ツールを作成できます。エージェント型 RAG は、AI エージェントを介して検索および生成プロセスを動的に調整できるRAGの高度な形式です。
このアプローチにより、より複雑なワークフローとユーザーインタラクションが可能になります。例、セマンティック検索には Atlas ベクトル検索を使用し、全文検索には Atlas Search を使用するなど、タスクに基づいて最適な取得ツールを決定するようにAIエージェントを構成できます。また、エージェントの取得機能をさらにカスタマイズするために、異なるコレクションごとに異なる取得ツールを定義することも可能です。
エージェント メモリー
エージェントのメモリに以前のやり取りに関する情報を保存することで、エージェントは過去の経験から学ぶことができ、より関連性の高いパーソナライズされた応答を提供できるようになります。これは、文脈を必要とするタスク、例えば会話エージェントにとって特に重要です。こうしたエージェントは、首尾一貫して文脈に適した応答を提供するために、会話の前のターンを記憶しておく必要があります。エージェントメモリには、主に 2 つのタイプがあります。
短期メモリ:最近のやり取りやアクティブなタスクコンテキストなど、現在のセッションの情報を保存します。
長期メモリ:セッション間で情報を保持し、過去の会話や時間の経過に伴うパーソナライズされた設定などを含みます。
Atlas はドキュメントデータベースでもあるため、MongoDB コレクションにインタラクションを保存することでエージェントのメモリを実装できます。その後、エージェントは必要に応じてこのコレクションをクエリまたは更新することができます。MongoDB を使用してエージェントメモリを実装する方法はいくつかあります。
短期メモリの場合、インタラクションを保存する際に特定のセッションを識別するための
session_idフィールドを含め、その後、同じ ID を持つインタラクションをクエリしてエージェントにコンテキストとして渡すことができます。長期メモリの場合、LLM を使用して複数のインタラクションを処理し、ユーザーの好みや重要なコンテキストなどの関連情報を抽出し、その情報をエージェントが必要に応じてクエリできる別のコレクションに保存することができます。
チャット履歴をより効率的かつ複雑に取得できる堅牢なメモリ管理システムを構築するには、Atlas Search または Atlas ベクトル検索を活用して、保存されたインタラクションのインデックスとクエリを実行します。
短期メモリを保存するコレクション内のドキュメントは次のように表示される可能性があります。
{ "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 |
詳細については、LangGraph および LangGraph.js をご覧ください。 |
はじめる
次のチュートリアルでは、エージェントフレームワークを使用せずに、Atlas を用いてエージェント RAG とメモリのための AI エージェントを構築する方法を示します。
このチュートリアルの実行可能なバージョンを Python エディタとして作業します。
前提条件
Atlas の サンプル データ セット からの映画データを含むコレクションを使用します。
Atlas アカウントで、MongoDB バージョン 6.0.11 または7.0.2 以降(RCs を含む)のクラスターを実行している。IP アドレスが Atlas プロジェクトのアクセスリストに含まれていることを確認してください。詳細については、クラスターの作成を参照してください。
Voyage AI API キー。
OpenAI API キー。
注意
このチュートリアルでは、Voyage AI と OpenAI のモデルを使用していますが、コードを変更して、任意のモデルを使用できます。
手順
この AI エージェントを使用して、カスタムデータソースに関する質問に回答し、計算を実行できます。また、前のやり取りを記憶して、応答に反映させることもできます。次のコンポーネントを使用します。
認識:テキスト入力。
計画:タスクを推論するための LLM とさまざまなプロンプト。
ツール:ベクトル検索ツールと計算ツール。
メモリ:インタラクションを 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という名前のファイルを作成します。このファイルには、エージェントの API キー、Atlas 接続文字列、MongoDB データベースおよびコレクション名が含まれます。プレースホルダー値を 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 という名前のファイルを作成します。このスクリプトは、voyage-3-large 埋め込みモデルを使用して、最近の MongoDB の収益報告書を含むサンプル PDF を Atlas のコレクションに取り込みます。
詳細については、「取り込み」をご覧ください。
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 という名前のファイルを作成します。このファイルには、エージェントの実行フローを決定するためのさまざまなプロンプトと LLM 呼び出しが含まれます。この例では、次の関数を定義します。
tool_selector:LLMがタスクに適したツールを選択する方法を決定します。generate_answer: ツールを使用し、LLM を呼び出し、結果をプロセシングすることで、エージェントの実行フローを調整します。get_llm_response: 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
エージェントをテストします。
最後に、プロジェクトに「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
クラスター内のai_agent_dbデータベースに移動し、embeddingsまたはchat_historyコレクションを選択することで、Atlas UI で埋め込みとインタラクションを表示できます。
Tutorials
MongoDB を使用して AI エージェントを構築する詳細なチュートリアルについては、次の表を参照してください。
フレームワーク | |
エンタープライズプラットフォーム | |
追加リソース |