LangChain 学習ノート
LangChain フレームワークのコアコンセプトを整理:何を解決するのか、コアコンポーネントは何か、LangGraph・RAG との違いは何か。
一、なぜ LangChain が必要なのか?
1.1 LLM 単体利用の限界
GPT、Gemini、Claude などの大規模言語モデル(LLM)は、本質的に一つのことしかできない:入力テキストから出力テキストを生成する。
これは以下を意味する:
- 「会話」はできるが「行動」はできない:LLM は直接データベースにクエリを投げたり、API を呼び出したり、ファイルを操作したりできない
- リアルタイムデータにアクセスできない:モデルの知識は学習データのカットオフ日で止まっている
- ベンダーごとに API 形式が異なる:OpenAI、Google、Anthropic それぞれ独自のインターフェース仕様がある
例えば、LLM に「今日の天気は?」と聞いても、実際に天気 API を呼び出すことはできず、学習データに基づいた古い情報や作り話を返すしかない。
1.2 LangChain が解決する問題
LangChain の公式ポジショニング:
“The easiest way to start building agents and applications powered by LLMs.”
(LLM 駆動アプリケーションを構築する最も簡単な方法)
主に以下の問題を解決する:
| 問題 | LangChain の解決策 |
|---|---|
| LLM の API 形式がベンダーごとに異なる | 統一された Model インターフェースを提供、モデル切り替えは1行変更のみ |
| LLM は外部操作を実行できない | Tool(ツール)機構を提供、LLM が外部機能を呼び出せるようにする |
| インテリジェントアプリの構築が複雑 | Agent(エージェント)抽象を提供、開発フローを簡素化 |
二、LangChain のコアコンセプト
LangChain には4つのコアコンセプトがある:Model、Tool、Agent、Memory。この4つを理解すれば、LangChain の 80% を理解したことになる。
2.1 Model(モデル層)
役割:異なる LLM の呼び出しインターフェースを統一する。
異なる LLM プロバイダー(OpenAI、Google、Anthropic)は異なる API 形式を持つ。LangChain はこれらを統一インターフェースに抽象化し、モデルの切り替えを容易にする。
# OpenAI を使用
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-4")
# Google Gemini に切り替え、変更はこの2行のみ
from langchain_google_genai import ChatGoogleGenerativeAI
llm = ChatGoogleGenerativeAI(model="gemini-2.0-flash")
# 以降のコードは全く同じ
response = llm.invoke("こんにちは、自己紹介をお願いします")
print(response.content)
メリット:ベンダーロックインを回避し、コストやパフォーマンスに応じて柔軟にモデルを切り替えられる。
2.2 Tool(ツール)
役割:LLM に「実行能力」を与える。
LLM が「脳」だとすれば、Tool は「手足」である。Tool を通じて、LLM は以下が可能になる:
- データベースへのクエリ
- 外部 API の呼び出し
- ファイルの読み書き
- 計算の実行
from langchain_core.tools import tool
@tool
def get_weather(city: str) -> str:
"""指定された都市の天気情報を取得する"""
# ここで実際の天気 API を呼び出せる
return f"{city}は今日晴れ、気温 25°C"
@tool
def calculate(expression: str) -> str:
"""数式を計算する"""
return str(eval(expression))
# ツールリストを定義
tools = [get_weather, calculate]
2.3 Agent(エージェント)
役割:LLM が自律的に判断し、どのツールをどの順序で実行するかを決定できるようにする。
これが LangChain の最もコアなコンセプトである。
通常の LLM vs Agent の違い:
| 通常の LLM | Agent |
|---|---|
| 聞かれたことに答える | 何をすべきか自分で判断する |
| 一問一答 | 複数ステップで実行できる |
| 会話のみ | ツールを呼び出してタスクを完了できる |
Agent の動作モード(ReAct):
思考(Reasoning)→ 行動(Acting)→ 観察(Observation)→ 繰り返し...
例:ユーザーが「東京の今日の天気は?25+17 は?」と質問した場合
Agent 思考: ユーザーは2つの質問をした、それぞれ処理する必要がある
↓
Agent 行動: get_weather("東京") を呼び出す
↓
Agent 観察: 「東京は今日晴れ、気温 25°C」を返す
↓
Agent 思考: 最初の質問は解決、2つ目を処理
↓
Agent 行動: calculate("25+17") を呼び出す
↓
Agent 観察: 「42」を返す
↓
Agent 思考: 両方の質問が解決、最終回答を生成
↓
最終回答: 「東京は今日晴れ、気温 25°C です。25+17=42 です。」
Agent 作成のコード例:
from langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent
# 1. LLM を初期化
llm = ChatOpenAI(model="gpt-4")
# 2. Agent を作成(ツールをバインド)
agent = create_react_agent(llm, tools)
# 3. 実行
result = agent.invoke({
"messages": [("user", "東京の今日の天気は?25+17 は?")]
})
print(result["messages"][-1].content)
2.4 Memory(メモリ)
役割:Agent が会話履歴を「記憶」できるようにする。
- 短期記憶:現在の会話のコンテキスト、Agent が「それ」が何を指すか理解できるようにする
- 長期記憶:会話をまたいだ永続化ストレージ、ユーザーの好みなどを記憶
2.5 コンセプト関係図
ユーザー入力: 「東京の天気を調べて」
│
▼
┌─────────┐
│ Agent │ ← 判断中心:天気ツールを呼び出す必要があると判断
└────┬────┘
│ 呼び出し
▼
┌─────────┐
│ Tool │ ← 実行能力:get_weather("東京")
└────┬────┘
│ 使用
▼
┌─────────┐
│ Model │ ← LLM 推論:結果を整理し、回答を生成
└────┬────┘
│
▼
出力: 「東京は今日晴れ、気温 25°C」
三、LangGraph とは?
3.1 なぜ LangGraph が必要なのか
LangChain の Agent は線形の ReAct モードを採用している:
思考 → 行動 → 観察 → 思考 → 行動 → 観察 → ...
これは単純なタスクには十分だが、複雑なシナリオでは問題が生じる:
- 並列処理ができない:複数のツールを同時に実行できない
- 分岐が難しい:条件に応じて異なるパスを取れない
- 状態管理が不足:長いフローのタスクを扱いにくい
- エラー復旧が困難:中断すると、中断点から再開できない
3.2 LangGraph のコア思想
LangGraph はグラフ(Graph) を使ってワークフローを編成する:
- ノード(Node):1つの処理ステップ
- エッジ(Edge):ステップ間の接続
- 状態(State):ノード間で渡されるデータ
┌─────────┐
│ 開始 │
└────┬────┘
│
▼
┌─────────┐
│ 意図理解 │
└────┬────┘
│
┌──────┴──────┐
▼ ▼
┌─────────┐ ┌─────────┐
│ 天気取得 │ │ 計算 │ ← 並列実行可能!
└────┬────┘ └────┬────┘
│ │
└──────┬──────┘
▼
┌─────────┐
│ 回答生成 │
└────┬────┘
│
▼
┌─────────┐
│ 終了 │
└─────────┘
3.3 LangGraph の6つの特徴
| 特徴 | 説明 |
|---|---|
| 並列化 | 複数のノードを同時に実行できる |
| ストリーミング出力 | リアルタイムで結果を返し、UX を改善 |
| チェックポイント | 実行状態を保存し、エラー時に中断点から再開可能 |
| Human-in-the-loop | 重要なステップで一時停止し、人間の確認を待てる |
| トレーシング | 各ステップの実行過程を記録し、デバッグを容易に |
| タスクキュー | 非同期タスク管理 |
3.4 LangChain vs LangGraph
| 観点 | LangChain | LangGraph |
|---|---|---|
| フロー構造 | 線形(ReAct ループ) | グラフ構造(任意のトポロジー) |
| 並列実行 | 非対応 | ネイティブ対応 |
| 複雑さ | シンプル、10行のコードで開始 | より複雑だが、より柔軟 |
| 適用シナリオ | シンプルな Agent、クイックプロトタイプ | 複雑なワークフロー、本番アプリケーション |
| 公式推奨 | 入門学習、シンプルなタスク | 本番環境、複雑な要件 |
両者の関係:
- LangGraph は LangChain エコシステムの一部
- LangChain の Agent は内部で LangGraph を使って実装されている
- シンプルな要件は LangChain、複雑な要件は直接 LangGraph を使用
四、Agent vs RAG の違い
LLM アプリケーション開発を学ぶ際、よく2つのコンセプトを耳にする:Agent と RAG。これらは異なるアーキテクチャパターンで、異なる問題を解決する。
4.1 2つのアーキテクチャパターン
RAG(Retrieval-Augmented Generation、検索拡張生成):
ユーザー質問 → 関連ドキュメントをベクトル検索 → ドキュメント + 質問を LLM に送信 → 回答を生成
Agent ツール呼び出し:
ユーザー質問 → LLM がどのツールを呼び出すか判断 → ツールを実行 → 結果を整理して回答を生成
4.2 比較表
| 観点 | RAG | Agent ツール呼び出し |
|---|---|---|
| コア技術 | ベクトル埋め込み + セマンティック検索 | LLM 判断 + ツール実行 |
| データタイプ | 非構造化データ(ドキュメント、記事) | 構造化データ(データベース、API) |
| 検索方法 | ベクトル類似度検索 | SQL クエリ、API 呼び出し |
| 典型的なシナリオ | ナレッジベース Q&A、ドキュメント検索 | データ分析、タスク自動化 |
| ベクトルDBが必要か | はい | いいえ |
4.3 具体例
RAG に適した質問:
- 「会社の休暇ポリシーは?」(社内ドキュメントの検索)
- 「この論文の主要な主張は?」(ドキュメント理解)
Agent に適した質問:
- 「先月の売上データを調べて」(データベースクエリ)
- 「東京の今日の天気は?」(API 呼び出し)
4.4 両者の組み合わせ
Agent は RAG を1つの Tool として使用できる:
@tool
def search_knowledge_base(query: str) -> str:
"""ナレッジベースから関連情報を検索する"""
# ここで RAG 検索ロジックを実装
return "検索された関連ドキュメントの内容..."
# Agent は RAG 機能と他のツールを同時に持てる
tools = [search_knowledge_base, query_database, get_weather]
これにより Agent は「知識も検索でき、データも取得できる」ようになる。
五、実践での考察:データ分析 Agent を例に
実際のプロジェクトで、LangChain ベースのデータ分析 Agent アプリケーションの開発に参加した。ここでは実践での考察を共有する。
5.1 プロジェクトの背景
これは対話型データ分析ツールで、ユーザーは自然言語で質問し、Agent が自動的にデータベースをクエリして分析結果と可視化グラフを生成する。
典型的なユーザーの質問:
- 「先月の売上はいくら?」
- 「地域別に今四半期の注文数を集計して、棒グラフを描いて」
- 「昨年同期のユーザー成長と比較して」
5.2 なぜ RAG ではなく Agent を選んだのか?
| 要件の特徴 | 技術選択 |
|---|---|
| データはデータベースに保存(構造化) | → Agent |
| 最新データをリアルタイムでクエリする必要がある | → Agent |
| SQL を動的に生成する必要がある | → Agent |
| グラフを生成する必要がある | → Agent(可視化ツールを呼び出し) |
静的ドキュメント(製品マニュアル、ポリシー文書など)を検索するなら RAG が適している。しかしリアルタイムデータ分析には、Agent + ツール呼び出しがより良い選択である。
5.3 プロジェクトでの LangChain の活用
Model 層の価値
プロジェクトは LangChain の統一モデルインターフェースを使用した。ある LLM から別の LLM に切り替える際、初期化コードを変更するだけで、ビジネスロジックは全く変更不要だった。
これは実際の開発で非常に便利——安価なモデルで開発・デバッグし、本番では効果の高いモデルに切り替えられる。
Tool の設計
プロジェクトでは複数のツールを定義した:
| ツール | 役割 |
|---|---|
| データクエリツール | SQL を実行し、クエリ結果を返す |
| 可視化ツール | データからグラフを生成 |
| 要約ツール | 分析結果の簡潔な要約を生成 |
重要な設計判断:Tool は単一責任であるべき。例えば「データクエリ」と「グラフ描画」は2つの独立したツールであり、「クエリしてグラフ描画」という1つのツールにまとめない。これにより Agent が柔軟に組み合わせられる。
なぜ LangGraph の create_react_agent を使ったのか
プロジェクトは自前で Agent ロジックを実装するのではなく、langgraph.prebuilt.create_react_agent を使用した。理由は:
- すぐに使える:ReAct パターンがすでにカプセル化されており、ツール呼び出しループを自分で処理する必要がない
- ストリーミング出力対応:ユーザーが Agent の思考過程と中間結果をリアルタイムで見られる
- エラー処理:組み込みのリトライ機構があり、ツール呼び出し失敗時に自動リトライ
5.4 遭遇した問題と考察
問題 1:システムプロンプトが長すぎる
今プロジェクトのシステムプロンプトは800行を超え、以下を含む:
- 出力フォーマット規範(Markdown フォーマット要件)
- 複数ツールの詳細な使用説明(BigQuery、GA4、Google Ads など)
- SQL の日付処理、累積値計算など様々なエッジケースのガイドライン
- エラー処理とリトライロジックの説明
これにより各リクエストのトークン消費が高くなり、パフォーマンスとコストに影響した。
考察:動的ロードを検討できる——ユーザーが現在接続しているツールに応じて、関連する指示部分のみをロードし、すべてを詰め込まない。この精確マッチングのシナリオでは RAG(セマンティック検索)は不要で、シンプルな設定テーブルや条件分岐で十分である。
問題 2:複雑なクエリには複数ステップが必要
ユーザーが「今年と昨年の売上トレンドを比較して」と質問した場合、Agent は以下が必要:
- 今年のデータをクエリ
- 昨年のデータをクエリ
- データを結合
- 比較グラフを生成
これこそが Agent の価値——複数のステップを自動的に計画・実行でき、ユーザーが問題を分解する必要がない。
5.5 経験のまとめ
- まず問題の本質を理解する:データ分析は「データを取得する」のであって「ドキュメントを検索する」のではない、だから RAG ではなく Agent を選ぶ
- Tool は単一責任で設計する:小さく専門的なツールの方が、大きく汎用的なツールより柔軟
- プロンプトエンジニアリングが重要:Agent の動作品質はシステムプロンプトに大きく依存する
六、まとめ
LangChain とは何か
一言で:LangChain は LLM アプリケーション開発の「レゴブロック」。
組み合わせ可能な一連のモジュール(Model、Tool、Agent、Memory)を提供し、レゴブロックのように LLM アプリケーションを構築できる。
コアバリュー
| 価値 | 説明 |
|---|---|
| 統一インターフェース | 異なる LLM ベンダーの差異を吸収 |
| Agent 抽象 | LLM が自律的に判断し、ツールを呼び出せるようにする |
| ツールエコシステム | 豊富なプリセットツールとカスタマイズ機能 |
発展トレンド
LangChain(シンプル、すぐに始められる)
↓
LangGraph(複雑、本番レベル)
2025年、LangChain 公式の推奨:
- シンプルな要件は引き続き LangChain を使用
- 新しい複雑な Agent アプリケーションは LangGraph を推奨
参考資料
本記事は LangChain 公式ドキュメントとブログを基に整理しました。誤りがあればご指摘ください。


コメント