LangGraphとElasticsearchを使用したRAGワークフローの構築
Elasticsearch を使用して LangGraph 検索エージェント テンプレートを構成およびカスタマイズし、効率的なデータ取得と AI 駆動型応答のための RAG ワークフローを構築する方法を学習します。
LangGraph 検索エージェント テンプレートは、 LangGraph Studio で LangGraph を使用して検索ベースの質問応答システムの作成を容易にするために LangChain によって開発されたスターター プロジェクトです。このテンプレートは Elasticsearch とシームレスに統合するように事前構成されているため、開発者はドキュメントを効率的にインデックスして取得できるエージェントを迅速に構築できます。
このブログでは、LangGraph Studio と LangGraph CLI を使用して LangChain 検索エージェント テンプレートを実行およびカスタマイズすることに焦点を当てています。このテンプレートは、Elasticsearch などのさまざまな検索バックエンドを活用して、検索拡張生成 (RAG) アプリケーションを構築するためのフレームワークを提供します。
エージェントフローをカスタマイズしながら、Elastic を使用してテンプレートを効率的にセットアップ、環境の構成、実行する方法を説明します。
要件
続行する前に、以下がインストールされていることを確認してください。
Elasticsearch Cloud デプロイメントまたはオンプレミス Elasticsearch デプロイメント (または Elastic Cloud で 14 日間の無料トライアルを作成) - バージョン 8.0.0 以上
Python 3.9以上
Cohere (このガイドで使用)、 OpenAI 、 Anthropic/ClaudeなどのLLMプロバイダーへのアクセス
LangGraphアプリの作成
1. LangGraph CLIをインストールする
pip install --upgrade "langgraph-cli[inmem]"2. 検索エージェントテンプレートからLangGraphアプリを作成する
mkdir lg-agent-demo
cd lg-agent-demo
langgraph new lg-agent-demo利用可能なテンプレートのリストから選択できるインタラクティブ メニューが表示されます。以下に示すように、取得エージェントの場合は 4、Python の場合は 1 を選択します。

トラブルシューティング: 「urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: cannot get local issuer certificate (_ssl.c:1000)>」というエラーが発生した場合「
問題を解決するには、以下に示すように、Python の証明書インストール コマンドを実行してください。

3. 依存関係をインストールする
新しい LangGraph アプリのルートで仮想環境を作成し、依存関係をeditモードでインストールして、ローカルの変更がサーバーで使用されるようにします。
#For Mac
python3 -m venv lg-demo
source lg-demo/bin/activate
pip install -e .
#For Windows
python3 -m venv lg-demo
lg-demo\Scripts\activate
pip install -e .環境の設定
1. .environmentを作成するファイル
.envファイルには、アプリが選択した LLM および取得プロバイダーに接続できるようにするための API キーと構成が保持されます。サンプル設定を複製して新しい.envファイルを生成します。
cp .env.example .env2. .envを設定するファイル
.envファイルには、デフォルトの構成のセットが付属しています。設定に応じて必要な API キーと値を追加することで更新できます。ユースケースに関係のないキーは、変更せずにそのままにしておくことも、削除することもできます。
# To separate your traces from other applications
LANGSMITH_PROJECT=retrieval-agent
# LLM choice (set the API key for your selected provider):
ANTHROPIC_API_KEY=your_anthropic_api_key
FIREWORKS_API_KEY=your_fireworks_api_key
OPENAI_API_KEY=your_openai_api_key
# Retrieval provider (configure based on your chosen service):
## Elastic Cloud:
ELASTICSEARCH_URL=https://your_elastic_cloud_url
ELASTICSEARCH_API_KEY=your_elastic_api_key
## Elastic Local:
ELASTICSEARCH_URL=http://host.docker.internal:9200
ELASTICSEARCH_USER=elastic
ELASTICSEARCH_PASSWORD=changeme
## Pinecone:
PINECONE_API_KEY=your_pinecone_api_key
PINECONE_INDEX_NAME=your_pinecone_index_name
## MongoDB Atlas:
MONGODB_URI=your_mongodb_connection_string
# Cohere API key:
COHERE_API_KEY=your_cohere_api_keyサンプル
.envファイル (Elastic Cloud と Cohere を使用)
以下は、このブログで説明されているように、 Elastic Cloud を取得プロバイダーとして使用し、 Cohere をLLM として使用するためのサンプルの.env構成です。
# To separate your traces from other applications
LANGSMITH_PROJECT=retrieval-agent
#Retrieval Provider
# Elasticsearch configuration
ELASTICSEARCH_URL=elastic-url:443
ELASTICSEARCH_API_KEY=elastic_api_key
# Cohere API key
COHERE_API_KEY=cohere_api_key注: このガイドでは、レスポンス生成と埋め込みの両方にCohereを使用していますが、ユースケースに応じて、 OpenAI 、 Claude 、あるいはローカルLLMモデル などの他のLLMプロバイダーも自由に使用できます 。使用する予定の各キーが.env ファイル に存在し、正しく設定されていることを確認してください。
3. 設定ファイル -configuration.py を更新する
適切な API キーを使用して.envファイルを設定したら、次の手順ではアプリケーションのデフォルトのモデル構成を更新します。構成を更新すると、システムは.envファイルで指定したサービスとモデルを使用するようになります。
構成ファイルに移動します。
cd src/retrieval_graphconfiguration.pyファイルには、検索エージェントが 3 つの主なタスクに使用するデフォルトのモデル設定が含まれています。
埋め込みモデル– ドキュメントをベクトル表現に変換する
クエリモデル– ユーザーのクエリをベクトルに変換する
レスポンスモデル– 最終的なレスポンスを生成する
デフォルトでは、コードはOpenAI (例: openai/text-embedding-3-small ) とAnthropic (例: anthropic/claude-3-5-sonnet-20240620 and anthropic/claude-3-haiku-20240307 ) のモデルを使用します。このブログでは、Cohere モデルの使用に切り替えます。すでに OpenAI または Anthropic を使用している場合は、変更は必要ありません。
変更例(Cohere を使用):
configuration.pyを開き、以下のようにモデルのデフォルトを変更します。
…
embedding_model: Annotated[
str,
{"__template_metadata__": {"kind": "embeddings"}},
] = field(
default="cohere/embed-english-v3.0",
…
response_model: Annotated[str, {"__template_metadata__": {"kind": "llm"}}] = field(
default="cohere/command-r-08-2024",
…
query_model: Annotated[str, {"__template_metadata__": {"kind": "llm"}}] = field(
default="cohere/command-r-08-2024",
metadata={LangGraph CLI で取得エージェントを実行する
1. LangGraphサーバーを起動する
cd lg-agent-demo
langgraph devこれにより、LangGraph API サーバーがローカルで起動します。これが正常に実行されると、次のような画面が表示されます。

Studio UI URL を開きます。
利用可能なグラフは 2 つあります。
取得グラフ: Elasticsearch からデータを取得し、LLM を使用してクエリに応答します。
インデクサー グラフ: ドキュメントを Elasticsearch にインデックスし、LLM を使用して埋め込みを生成します。


2. インデクサーグラフの設定
インデクサー グラフを開きます。
アシスタントの管理をクリックします。
「新しいアシスタントを追加」をクリックし、指定どおりにユーザーの詳細を入力して、ウィンドウを閉じます。
{"user_id": "101"}

3. サンプル文書のインデックス作成
NoveTech という組織の仮想的な四半期レポートを表す次のサンプル ドキュメントにインデックスを付けます。
[
{ "page_content": "NoveTech Solutions Q1 2025 Report - Revenue: $120.5M, Net Profit: $18.2M, EPS: $2.15. Strong AI software launch and $50M government contract secured."
},
{
"page_content": "NoveTech Solutions Business Highlights - AI-driven analytics software gained 15% market share. Expansion into Southeast Asia with two new offices. Cloud security contract secured."
},
{
"page_content": "NoveTech Solutions Financial Overview - Operating expenses at $85.3M, Gross Margin 29.3%. Stock price rose from $72.5 to $78.3. Market Cap reached $5.2B."
},
{
"page_content": "NoveTech Solutions Challenges - Rising supply chain costs impacting hardware production. Regulatory delays slowing European expansion. Competitive pressure in cybersecurity sector."
},
{
"page_content": "NoveTech Solutions Future Outlook - Expected revenue for Q2 2025: $135M. New AI chatbot and blockchain security platform launch planned. Expansion into Latin America."
},
{
"page_content": "NoveTech Solutions Market Performance - Year-over-Year growth at 12.7%. Stock price increase reflects investor confidence. Cybersecurity and AI sectors remain competitive."
},
{
"page_content": "NoveTech Solutions Strategic Moves - Investing in R&D to enhance AI-driven automation. Strengthening partnerships with enterprise cloud providers. Focusing on data privacy solutions."
},
{
"page_content": "NoveTech Solutions CEO Statement - 'NoveTech Solutions continues to innovate in AI and cybersecurity. Our growth strategy remains strong, and we foresee steady expansion in the coming quarters.'"
}
]ドキュメントがインデックスされると、以下に示すように、スレッドに削除メッセージが表示されます。

4. 検索グラフの実行
検索グラフに切り替えます。
次の検索クエリを入力してください。
What was NovaTech Solutions total revenue in Q1 2025?
システムは関連するドキュメントを返し、インデックスされたデータに基づいて正確な回答を提供します。
検索エージェントをカスタマイズする
ユーザー エクスペリエンスを向上させるために、検索グラフにカスタマイズ ステップを導入し、ユーザーが次に尋ねる可能性のある 3 つの質問を予測します。この予測は以下に基づいています:
取得した文書のコンテキスト
以前のユーザーインタラクション
最後のユーザークエリ
クエリ予測機能を実装するには、次のコード変更が必要です。
1. graph.pyを更新する
predict_query関数を追加します:
async def predict_query(
state: State, *, config: RunnableConfig
) -> dict[str, list[BaseMessage]]:
logger.info(f"predict_query predict_querypredict_query predict_query predict_query predict_query") # Log the query
configuration = Configuration.from_runnable_config(config)
prompt = ChatPromptTemplate.from_messages(
[
("system", configuration.predict_next_question_prompt),
("placeholder", "{messages}"),
]
)
model = load_chat_model(configuration.response_model)
user_query = state.queries[-1] if state.queries else "No prior query available"
logger.info(f"user_query: {user_query}")
logger.info(f"statemessage: {state.messages}")
#human_messages = [msg for msg in state.message if isinstance(msg, HumanMessage)]
message_value = await prompt.ainvoke(
{
"messages": state.messages,
"user_query": user_query, # Use the most recent query as primary input
"system_time": datetime.now(tz=timezone.utc).isoformat(),
},
config,
)
next_question = await model.ainvoke(message_value, config)
return {"next_question": [next_question]}respond関数を変更して、メッセージの代わりにresponseオブジェクトを返します。
async def respond(
state: State, *, config: RunnableConfig
) -> dict[str, list[BaseMessage]]:
"""Call the LLM powering our "agent"."""
configuration = Configuration.from_runnable_config(config)
# Feel free to customize the prompt, model, and other logic!
prompt = ChatPromptTemplate.from_messages(
[
("system", configuration.response_system_prompt),
("placeholder", "{messages}"),
]
)
model = load_chat_model(configuration.response_model)
retrieved_docs = format_docs(state.retrieved_docs)
message_value = await prompt.ainvoke(
{
"messages": state.messages,
"retrieved_docs": retrieved_docs,
"system_time": datetime.now(tz=timezone.utc).isoformat(),
},
config,
)
response = await model.ainvoke(message_value, config)
# We return a list, because this will get added to the existing list
return {"response": [response]}グラフ構造を更新して、predict_query に新しいノードとエッジを追加します。
builder.add_node(generate_query)
builder.add_node(retrieve)
builder.add_node(respond)
builder.add_node(predict_query)
builder.add_edge("__start__", "generate_query")
builder.add_edge("generate_query", "retrieve")
builder.add_edge("retrieve", "respond")
builder.add_edge("respond", "predict_query")2. prompts.pyを更新する
prompts.pyでのクエリ予測のプロンプトを作成します:
PREDICT_NEXT_QUESTION_PROMPT = """Given the user query and the retrieved documents, suggest the most likely next question the user might ask.
**Context:**
- Previous Queries:
{previous_queries}
- Latest User Query: {user_query}
- Retrieved Documents:
{retrieved_docs}
**Guidelines:**
1. Do not suggest a question that has already been asked in previous queries.
2. Consider the retrieved documents when predicting the next logical question.
3. If the user's query is already fully answered, suggest a relevant follow-up question.
4. Keep the suggested question natural and conversational.
5. Suggest at least 3 question
System time: {system_time}"""3. configuration.pyを更新する
predict_next_question_prompt追加:
predict_next_question_prompt: str = field(
default=prompts.PREDICT_NEXT_QUESTION_PROMPT,
metadata={"description": "The system prompt used for generating responses."},
)4. state.pyを更新する
次の属性を追加します。
response: Annotated[Sequence[AnyMessage], add_messages]
next_question : Annotated[Sequence[AnyMessage], add_messages]5. 検索グラフを再実行する
次の検索クエリをもう一度入力してください。
What was NovaTech Solutions total revenue in Q1 2025?システムは入力を処理し、以下に示すように、ユーザーが尋ねる可能性のある 3 つの関連する質問を予測します。

まとめ
LangGraph Studio と CLI 内に取得エージェント テンプレートを統合すると、いくつかの重要な利点が得られます。
開発の加速: テンプレートと視覚化ツールにより、検索ワークフローの作成とデバッグが効率化され、開発時間が短縮されます。
シームレスな展開: API と自動スケーリングの組み込みサポートにより、環境間でのスムーズな展開が保証されます。
簡単な更新:ワークフローの変更、新しい機能の追加、追加のノードの統合が簡単なので、検索プロセスの拡張と強化が容易になります。
永続メモリ: システムはエージェントの状態と知識を保持し、一貫性と信頼性を向上させます。
柔軟なワークフロー モデリング: 開発者は、特定のユース ケースに合わせて検索ロジックと通信ルールをカスタマイズできます。
リアルタイムの対話とデバッグ: 実行中のエージェントと対話できるため、効率的なテストと問題解決が可能になります。
これらの機能を活用することで、組織はデータのアクセシビリティとユーザー エクスペリエンスを向上させる強力で効率的かつスケーラブルな検索システムを構築できます。
このプロジェクトの完全なソースコードはGitHubで入手できます。
よくあるご質問
RAG ワークフローとは何ですか?
RAG (Retrieval-Augmented Generation) ワークフローは、AI モデルにプライベート データへのアクセスを許可し、「幻覚」ではなく、正確で事実に基づいた回答を提供できるようにする方法です。
LangGraph エージェントのデータベースとして Elasticsearch を使用する理由は何ですか?
Elasticsearch はエージェントの「長期メモリ」として機能します。標準のデータベースとは異なり、ベクター検索 (意味の理解) とキーワード検索 (正確な用語の検索) を組み合わせたハイブリッド検索用に構築されています。これにより、「第 1 四半期の収益」を要求した場合でも、「財務成長」を要求した場合でも、Elasticsearch は LangGraph が処理するのに最も関連性の高いドキュメントを提供します。
LangGraph 検索エージェント テンプレートを使用してマルチユーザー システムを構築できますか?
はい。この記事では、user_id (「101」など) を使用したインデクサー グラフ構成を通じてこれを説明します。これにより、ドキュメントに特定の所有者のタグを付けることができるため、検索エージェントは特定のユーザーが表示を許可されている情報のみを検索できるようになります。




