LangChain 1.0とmilvus:本物の長期記憶を持つプロダクション対応エージェントを構築する方法
LangChainは、大規模な言語モデル(LLM)を利用したアプリケーションを開発するためのオープンソースのフレームワークです。推論やツールを使うエージェントを構築し、モデルを外部データに接続し、インタラクションフローを管理するためのモジュラーツールキットを提供します。
LangChain 1.0のリリースにより、このフレームワークは、より生産に適したアーキテクチャへの一歩を踏み出しました。新バージョンでは、以前のチェーンベースの設計を標準化されたReActループ(Reason → Tool Call → Observe → Decide)に置き換え、実行、制御、安全性を管理するミドルウェアを導入しました。
しかし、推論だけでは十分ではない。エージェントには、情報を保存し、呼び出し、再利用する機能も必要だ。そこで、オープンソースのベクトルデータベースであるMilvusが重要な役割を果たすことができる。Milvusはスケーラブルで高性能なメモリレイヤーを提供し、エージェントが意味的類似性によって効率的に情報を保存、検索、取得できるようにします。
この投稿では、LangChain 1.0がエージェントアーキテクチャをどのように更新し、Milvusを統合することでエージェントが推論を超えること、つまり実世界のユースケースのための永続的でインテリジェントなメモリをどのように実現するかを探ります。
なぜチェーンベースの設計では不十分なのか
初期の頃(バージョン0.x)、LangChainのアーキテクチャはChainが中心でした。各チェーンは固定されたシーケンスを定義し、LLMオーケストレーションをシンプルかつ高速にするテンプレートがあらかじめ用意されていました。このデザインは、素早くプロトタイプを作るには最適でした。しかし、LLMエコシステムが進化し、実際のユースケースがより複雑になるにつれ、このアーキテクチャに亀裂が入り始めた。
1.柔軟性の欠如
LangChainの初期バージョンは、SimpleSequentialChainやLLMChainのようなモジュラー・パイプラインを提供し、それぞれが固定された直線的なフロー(プロンプト作成→モデル呼び出し→出力処理)に従っていました。この設計は、単純で予測可能なタスクではうまく機能し、迅速にプロトタイプを作成しやすかった。
しかし、アプリケーションがよりダイナミックになるにつれ、このような硬直したテンプレートは制限的に感じられるようになりました。ビジネスロジックが定義済みのシーケンスにうまく収まらなくなると、2つの不満足な選択肢が残ります。
2.プロダクション・グレードのコントロールの欠如
デモではうまくいっていたことが、本番では壊れてしまうことがよくある。チェーンには、大規模で、永続的で、機密性の高いアプリケーションに必要なセーフガードは含まれていなかった。よくある問題は以下の通り:
コンテキストのオーバーフロー:長い会話はトークンの制限を超え、クラッシュやサイレント・トランケーションを引き起こす。
機密データの漏洩:個人を特定できる情報(電子メールやIDなど)が、不注意でサードパーティのモデルに送信される可能性がある。
監視されていない操作:エージェントが人間の承認なしにデータを削除したり、メールを送信したりする可能性がある。
3.モデル間の互換性の欠如
各LLMプロバイダー(OpenAI、Anthropic、多くの中国モデル)は、推論とツール呼び出しのための独自のプロトコルを実装しています。プロバイダーを切り替えるたびに、統合レイヤー(プロンプトテンプレート、アダプター、レスポンスパーサー)を書き直す必要がありました。この繰り返しの作業は開発を遅らせ、実験を苦痛なものにしていた。
LangChain 1.0:オールインReActエージェント
LangChainチームが何百ものプロダクショングレードのエージェント実装を分析したとき、一つの洞察が際立ちました。
マルチエージェントシステムであろうと、深い推論を行う単一のエージェントであろうと、同じ制御ループが浮かび上がります:短い推論ステップとターゲットとなるツールの呼び出しを交互に行い、エージェントが最終的な答えを出せるようになるまで、観察結果をその後の決定に反映させます。
この実績のある構造を基に、LangChain 1.0はReActループをアーキテクチャの中核に置き、信頼性が高く、解釈可能で、生産可能なエージェントを構築するためのデフォルトの構造としています。
単純なエージェントから複雑なオーケストレーションまでをサポートするために、LangChain 1.0は、使いやすさと正確な制御を兼ね備えたレイヤデザインを採用しています:
標準シナリオ標準シナリオ: create_agent()関数から始めましょう - 推論とツールコールをすぐに処理する、クリーンで標準化されたReActループです。
拡張シナリオ:ミドルウェアを追加することで、きめ細かい制御が可能になります。ミドルウェアは、エージェント内部で起こることを検査または変更することができます - 例えば、PII検出、人間承認チェックポイント、自動再試行、または監視フックを追加します。
複雑なシナリオ:ステートフルなワークフローや複数エージェントのオーケストレーションには、グラフベースの実行エンジンであるLangGraphを使用します。LangGraphは、ロジックフロー、依存関係、実行状態を正確に制御することができます。
それでは、エージェント開発をよりシンプルに、より安全に、そしてモデル間でより一貫したものにする3つの主要なコンポーネントを分解してみましょう。
1.create_agent():よりシンプルなエージェント構築方法
LangChain 1.0での重要なブレークスルーは、エージェントを構築する複雑さを一つの関数 - create_agent()- に集約したことです。状態管理、エラー処理、ストリーミング出力を手動で処理する必要がなくなりました。これらのプロダクションレベルの機能は、LangGraphランタイムが自動的に管理します。
たった3つのパラメータで、完全に機能するエージェントを起動することができます:
model- モデル識別子(文字列)またはインスタンス化されたモデルオブジェクト。
tools- エージェントに能力を与える関数のリスト。
system_prompt- エージェントの役割、トーン、動作を定義する命令。
create_agent()は、標準的なエージェントのループで実行されます - モデルを呼び出し、実行するツールを選択させ、ツールが不要になったら終了します:
また、状態の永続化、中断の回復、ストリーミングといったLangGraphの組み込み機能も継承しています。かつては何百行ものオーケストレーションコードが必要だったタスクが、今では単一の宣言的APIで処理されます。
from langchain.agents import create_agent
agent = create_agent(
model="openai:gpt-4o",
tools=[get_weather, query_database],
system_prompt="You are a customer service assistant who helps users check the weather and order information."
)
result = agent.invoke({
"messages": [{"role": "user", "content": "What’s the weather like in Shanghai today?"}]
})
2.ミドルウェア:プロダクション・レディな制御のためのコンポーザブル・レイヤー
ミドルウェアは、LangChainをプロトタイプからプロダクションに移行させる重要な橋渡し役です。エージェントの実行ループの戦略的なポイントでフックを公開し、コアとなるReActプロセスを書き換えることなくカスタムロジックを追加できるようにします。
エージェントのメインループは、モデル→ツール→終了という3段階の決定プロセスに従います:
LangChain 1.0は、一般的なパターンに対応するいくつかのミドルウェアをあらかじめ用意しています。以下に4つの例を挙げます。
- PII検出:機密性の高いユーザーデータを扱うアプリケーション
from langchain.agents import create_agent
from langchain.agents.middleware import PIIMiddleware
agent = create_agent(
model=“gpt-4o”,
tools=[], # Add tools as needed
middleware=[
# Redact emails in user input
PIIMiddleware(“email”, strategy=“redact”, apply_to_input=True),
# Mask credit cards (show last 4 digits)
PIIMiddleware(“credit_card”, strategy=“mask”, apply_to_input=True),
# Custom PII type with regex
PIIMiddleware(
“api_key”,
detector=r"sk-[a-zA-Z0-9]{32}",
strategy=“block”, # Raise error if detected
),
],
)
- 要約:トークン制限に近づいた時に、会話履歴を自動的に要約する。
from langchain.agents import create_agent
from langchain.agents.middleware import SummarizationMiddleware
agent = create_agent(
model=“gpt-4o”,
tools=[weather_tool, calculator_tool],
middleware=[
SummarizationMiddleware(
model=“gpt-4o-mini”, #Summarize using a cheaper model
max_tokens_before_summary=4000, # Trigger summarization at 4000 tokens
messages_to_keep=20, # Keep last 20 messages after summary
),
],
)
- ツールの再試行:設定可能な指数バックオフを使用して、失敗したツールコールを自動的に再試行します。
from langchain.agents import create_agent
from langchain.agents.middleware import ToolRetryMiddleware
agent = create_agent(
model="gpt-4o",
tools=[search_tool, database_tool],
middleware=[
ToolRetryMiddleware(
max_retries=3, # Retry up to 3 times
backoff_factor=2.0, # Exponential backoff multiplier
initial_delay=1.0, # Start with 1 second delay
max_delay=60.0, # Cap delays at 60 seconds
jitter=True, # Add random jitter to avoid thundering herd (±25%)
),
],
)
- カスタムミドルウェア
公式のビルド済みミドルウェアオプションに加えて、デコレータベースまたはクラスベースの方法でカスタムミドルウェアを作成することもできます。
例えば、以下のスニペットは、実行前にモデルコールをログに記録する方法を示しています:
from langchain.agents.middleware import before_model
from langchain.agents.middleware import AgentState
from langgraph.runtime import Runtime
@before_model
def log_before_model(state: AgentState, runtime: Runtime) -> dict | None:
print(f"About to call model with {len(state['messages'])} messages")
return None # Returning None means the normal flow continues
agent = create_agent(
model="openai:gpt-4o",
tools=[...],
middleware=[log_before_model],
)
3.構造化出力:データを扱う標準化された方法
従来のエージェント開発では、構造化出力の管理は常に困難でした。例えば、OpenAIはネイティブの構造化出力APIを提供していますが、他のプロバイダはツールコールを通して間接的に構造化応答をサポートしているだけです。これはしばしば、各プロバイダ用にカスタムアダプタを書くことを意味し、余分な作業を増やし、メンテナンスに必要以上に手間をかけます。
LangChain 1.0では、構造化出力はcreate_agent()のresponse_formatパラメータを通して直接扱われます。 データスキーマを一度定義するだけです。LangChainは、あなたが使っているモデルに基づいて、自動的に最適な実施戦略を選びます。余分なセットアップやベンダー固有のコードは必要ありません。
from langchain.agents import create_agent
from pydantic import BaseModel, Field
class WeatherReport(BaseModel):
location: str = Field(description="City name")
temperature: float = Field(description="Temperature (°C)")
condition: str = Field(description="Weather condition")
agent = create_agent(
model="openai:gpt-4o",
tools=[get_weather],
response_format=WeatherReport # Use the Pydantic model as the response schema
)
result = agent.invoke({"role": "user", "content": "What’s the weather like in Shanghai today??"})
weather_data = result['structured_response'] # Retrieve the structured response
print(f"{weather_data.location}: {weather_data.temperature}°C, {weather_data.condition}")
LangChainは構造化出力のために2つの戦略をサポートします:
1.プロバイダ戦略:一部のモデルプロバイダは、APIを通じて構造化出力をネイティブにサポートしています(OpenAIやGrokなど)。そのようなサポートが利用可能な場合、LangChainはプロバイダの組み込みスキーマ強制を直接利用します。このアプローチは、モデル自身が出力フォーマットを保証するため、最高レベルの信頼性と一貫性を提供します。
2.ツール呼び出し戦略:ネイティブの構造化出力をサポートしないモデルの場合、LangChainはツール呼び出しを使って同じ結果を得ます。
フレームワークがモデルの能力を検出し、自動的に適応します。この抽象化により、ビジネスロジックを変更することなく、モデルプロバイダを自由に切り替えることができます。
Milvusがエージェントのメモリを強化する方法
プロダクショングレードのエージェントにとって、パフォーマンスのボトルネックは推論エンジンではなく、メモリシステムです。LangChain 1.0では、ベクトルデータベースがエージェントの外部メモリとして機能し、意味検索による長期的な記憶を提供します。
Milvusは現在利用可能なオープンソースのベクトルデータベースの中で最も成熟したものの一つで、AIアプリケーションにおける大規模なベクトル検索のために構築されています。LangChainとネイティブに統合されているため、ベクトル化、インデックス管理、類似検索を手動で処理する必要がありません。langchain_milvusパッケージは、Milvusを標準的なVectorStoreインターフェイスとしてラップし、わずか数行のコードでエージェントに接続できるようにします。
そうすることで、Milvusはスケーラブルで信頼性の高いエージェントメモリシステムを構築する上での3つの重要な課題に対処します:
1.膨大な知識ベースからの高速検索
エージェントが何千もの文書、過去の会話、製品マニュアルを処理する必要がある場合、単純なキーワード検索では不十分です。Milvusはベクトル類似性検索を使用し、クエリの文言が異なっていても、意味的に関連する情報を数ミリ秒で検索します。これにより、エージェントはテキストの完全一致だけでなく、意味に基づいて知識を呼び出すことができます。
from langchain.agents import create_agent
from langchain_milvus import Milvus
from langchain_openai import OpenAIEmbeddings
# Initialize the vector database as a knowledge base
vectorstore = Milvus(
embedding=OpenAIEmbeddings(),
collection_name="company_knowledge",
connection_args={"uri": "http://localhost:19530"} #
)
# Convert the retriever into a Tool for the Agent
agent = create_agent(
model="openai:gpt-4o",
tools=[vectorstore.as_retriever().as_tool(
name="knowledge_search",
description="Search the company knowledge base to answer professional questions"
)],
system_prompt="You can retrieve information from the knowledge base to answer questions."
)
2.永続的な長期記憶
LangChainのSummarizationMiddlewareは、会話履歴が長くなりすぎた場合、それを要約することができます。milvusはそれらを保持する。すべての会話、ツールコール、推論ステップはベクトル化され、長期参照用に保存されます。必要なとき、エージェントはセマンティック検索によって関連する記憶を素早く取り出すことができ、セッションを超えた真の継続性を可能にする。
from langchain_milvus import Milvus
from langchain.agents import create_agent
from langchain.agents.middleware import SummarizationMiddleware
from langgraph.checkpoint.memory import InMemorySaver
# Long-term memory storage(Milvus)
long_term_memory = Milvus.from_documents(
documents=[], # Initially empty; dynamically updated at runtime
embedding=OpenAIEmbeddings(),
connection_args={"uri": "./agent_memory.db"}
)
# Short-term memory management(LangGraph Checkpointer + Summarization)
agent = create_agent(
model="openai:gpt-4o",
tools=[long_term_memory.as_retriever().as_tool(
name="recall_memory",
description="Retrieve the agent’s historical memories and past experiences"
)],
checkpointer=InMemorySaver(), # Short-term memory
middleware=[
SummarizationMiddleware(
model="openai:gpt-4o-mini",
max_tokens_before_summary=4000 # When the threshold is exceeded, summarize and store it in Milvus
)
]
)
3.マルチモーダルコンテンツの統合管理
最新のエージェントはテキストだけでなく、画像、音声、ビデオも扱います。Milvusはマルチベクターストレージとダイナミックスキーマをサポートしており、複数のモダリティのエンベッディングを一つのシステムで管理することができます。これにより、マルチモーダルエージェントに統一されたメモリ基盤を提供し、異なるタイプのデータ間で一貫した検索を可能にします。
# Filter retrievals by source (e.g., search only medical reports)
vectorstore.similarity_search(
query="What is the patient's blood pressure reading?",
k=3,
expr="source == 'medical_reports' AND modality == 'text'" # Milvus scalar filtering
)
LangChainとLangGraphの比較:エージェントに合ったものを選ぶ方法
LangChain 1.0へのアップグレードは、プロダクショングレードのエージェントを構築するための重要なステップです。適切なフレームワークを選択することで、これらの機能をいかに早く、実用的で保守可能なシステムに組み込めるかが決まります。
実際、LangChain 1.0とLangGraph 1.0は同じレイヤースタックの一部であり、お互いを置き換えるのではなく、一緒に働くように設計されています:LangChainは標準的なエージェントを素早く構築するのに役立ち、LangGraphは複雑なワークフローをきめ細かく制御します。言い換えれば、LangChainは高速化を支援し、LangGraphは深化を支援します。
以下に、両者の技術的な位置づけの違いを簡単に比較します:
| 寸法 | LangChain 1.0 | LangChain 1.0 |
|---|---|---|
| 抽象度 | 高レベルの抽象化、標準的なエージェントシナリオ向けに設計 | 複雑なワークフロー用に設計された低レベルのオーケストレーションフレームワーク |
| コア機能 | 標準的なReActループ(Reason → Tool Call → Observation → Response) | カスタムステートマシンと複雑な分岐ロジック(StateGraph + 条件ルーティング) |
| 拡張メカニズム | プロダクショングレードの機能のためのミドルウェア | ノード、エッジ、状態遷移の手動管理 |
| 基盤となる実装 | ノード、エッジ、状態遷移の手動管理 | 永続性とリカバリを組み込んだネイティブランタイム |
| 典型的な使用例 | 標準的なエージェントシナリオの80 | マルチエージェントコラボレーションと長期ワークフローオーケストレーション |
| 学習曲線 | 10行程度のコードでエージェントを構築 | ステートグラフとノードオーケストレーションの理解が必要 |
エージェントを構築するのが初めての方や、プロジェクトを素早く立ち上げたい方は、LangChainから始めましょう。複雑なオーケストレーション、複数エージェントの連携、長期的なワークフローを必要とするユースケースであれば、LangGraphから始めましょう。
LangChainでシンプルに始めて、システムがよりコントロールと柔軟性を必要とするときにLangGraphを導入すればいいのです。重要なのは、ワークフローの各部分に適したツールを選ぶことです。
結論
年前、LangChainはLLMを呼び出すための軽量ラッパーとして始まりました。現在では、完全なプロダクショングレードのフレームワークに成長した。
コアとなるミドルウェア層は、安全性、コンプライアンス、観測性を提供します。LangGraphは永続的な実行、制御フロー、状態管理を提供する。Milvusは、スケーラブルで信頼性の高い長期メモリを提供し、エージェントがコンテキストを取得し、履歴を推論し、時間の経過とともに改善することを可能にします。
LangChain、LangGraph、そしてMilvusは、信頼性やパフォーマンスを犠牲にすることなく、ラピッドプロトタイピングとエンタープライズスケールのデプロイメントの橋渡しをします。
🚀 エージェントに信頼性の高い長期的なメモリを持たせる準備はできていますか?LangChainエージェントのインテリジェントな長期記憶をどのように実現するか、Milvusをご覧ください。
ご質問がある場合、または機能について深く知りたい場合は、Discordチャンネルにご参加ください。私たちのDiscordチャンネルに参加するか、GitHubに課題を提出してください。また、Milvusオフィスアワーを通して、20分間の1対1のセッションを予約し、洞察やガイダンス、質問への回答を得ることもできます。
Try Managed Milvus for Free
Zilliz Cloud is hassle-free, powered by Milvus and 10x faster.
Get StartedLike the article? Spread the word



