LangChainとLangGraphのcreate_react_agentを比べてみた

> **注意:** この記事は、AIがLangChainとLangGraphのドキュメントおよびソースコードを解析して作成されています。情報の正確性については、必ず公式ドキュメントを併せてご確認ください。

## はじめに

AIエージェントを構築する際、ReAct（Reasoning and Acting）パターンは非常に有効な手法です。この記事では、LangChainとLangGraphが提供する`create_react_agent`関数を比較し、それぞれの特徴、使いどころ、違いについて詳しく解説します。

## ReActパターンとは

ReActは「Reasoning and Acting」の略で、大言語モデル（LLM）が思考（Thought）→行動（Action）→観察（Observation）のサイクルを繰り返すことで、複雑なタスクを段階的に解決するパターンです。このパターンは2022年の論文「[ReAct: Synergizing Reasoning and Acting in Language Models](https://arxiv.org/abs/2210.03629)」で提案されました。

```
Question: 質問
Thought: 何をすべきか考える
Action: 実行するアクション
Action Input: アクションへの入力
Observation: アクションの結果
... (必要に応じて繰り返し)
Final Answer: 最終回答
```

## LangChainのcreate_react_agent

### 特徴

LangChainの`create_react_agent`は、2022年の論文「ReAct: Synergizing Reasoning and Acting in Language Models」に基づいた**テキストベース**の実装です。

### アーキテクチャ

```mermaid
graph TB
    subgraph "LangChain create_react_agent"
        USER[User Input] --> AGENT[Agent]
        AGENT --> PROMPT[Text Prompt]
        PROMPT --> LLM[LLM]
        LLM --> PARSER[ReAct Text Parser]
        PARSER --> ACTION[AgentAction]
        ACTION --> TOOLS[Tools Execution]
        TOOLS --> OBSERVATION[Text Observation]
        OBSERVATION --> AGENT
    end
```

### 実装例

```python
from langchain.agents import create_react_agent
from langchain_core.tools import tool
from langchain_openai import ChatOpenAI

@tool
def calculator(expression: str) -> str:
    """数式を計算します"""
    return str(eval(expression))

llm = ChatOpenAI(model="gpt-4")
tools = [calculator]

agent = create_react_agent(
    llm=llm,
    tools=tools,
    prompt=default_prompt  # テキストベースのプロンプト
)
```

### メリット・デメリット

**メリット:**
- シンプルで理解しやすい
- 任意のLLMで動作（Function Call対応不要）
- 軽量な実装

**デメリット:**
- テキスト解析によるエラーが発生しやすい
- プロンプトエンジニアリングが重要
- Function Callを使用しないため、構造化が困難

## LangGraphのcreate_react_agent

### 特徴

LangGraphの`create_react_agent`は、**ステートフルなグラフベース**の実装で、より現代的で柔軟性の高いアプローチを採用しています。

### アーキテクチャ

```mermaid
graph TB
    subgraph "LangGraph create_react_agent"
        USER[User Input] --> AGENT_NODE[Agent Node]
        AGENT_NODE --> CONDITION{ツールコール?}
        CONDITION -->|Yes| TOOLS_NODE[Tools Node]
        CONDITION -->|No| END[End/Response]
        TOOLS_NODE --> AGENT_NODE
        
        subgraph "State Management"
            STATE[AgentState]
            MESSAGES[Messages History]
            TOOLS_RESULTS[Tool Results]
        end
        
        AGENT_NODE -.-> STATE
        TOOLS_NODE -.-> STATE
    end
```

### 実装例

```python
from langgraph.prebuilt import create_react_agent
from langchain_core.tools import tool

@tool
def calculator(expression: str) -> float:
    """数式を計算します"""
    return eval(expression)

@tool
def get_weather(city: str) -> str:
    """天気情報を取得します"""
    return f"{city}は晴れです"

agent = create_react_agent(
    model="anthropic:claude-3-7-sonnet-latest",
    tools=[calculator, get_weather],
    prompt="あなたは役立つアシスタントです"
)

# ステートフルな実行
result = agent.invoke({
    "messages": [{"role": "user", "content": "東京の天気と2+3の計算をして"}]
})
```

### メリット・デメリット

**メリット:**
- ステートフルな状態管理
- グラフベースで複雑なワークフローに対応
- 豊富な設定オプション（hooks、interrupts等）
- Function Callネイティブサポート
- チェックポイント機能
- 構造化レスポンス対応

**デメリット:**
- 学習コストが高い
- より重い実装
- LangGraphの理解が必要

## 詳細比較

### 1. 技術的な違い

| 項目 | LangChain | LangGraph |
|------|-----------|-----------|
| **実装方式** | テキストベース | グラフベース |
| **状態管理** | 各実行で独立 | ステートフル |
| **ツール表現** | テキスト形式の説明 | Function Call + JSON Schema |
| **パーサー** | `ReActSingleInputOutputParser` | 構造化パーサー |
| **エラー処理** | テキスト解析エラーが発生しやすい | 堅牢な構造化処理 |
| **実行制御** | 限定的 | フック、割り込み、チェックポイント |

### 2. 機能比較

#### LangChain create_react_agent
```python
# 基本的な関数シグネチャ
create_react_agent(
    llm: BaseLanguageModel,
    tools: Sequence[BaseTool],
    prompt: BasePromptTemplate,
    output_parser: Optional[AgentOutputParser] = None,
    tools_renderer: ToolsRenderer = render_text_description,
    stop_sequence: Union[bool, List[str]] = True,
)
```

#### LangGraph create_react_agent
```python
# より豊富なオプション
create_react_agent(
    model: Union[str, LanguageModelLike],
    tools: Union[Sequence[Union[BaseTool, Callable, dict]], ToolNode],
    prompt: Optional[Prompt] = None,
    response_format: Optional[StructuredResponseSchema] = None,
    pre_model_hook: Optional[RunnableLike] = None,
    post_model_hook: Optional[RunnableLike] = None,
    state_schema: Optional[StateSchemaType] = None,
    checkpointer: Optional[Checkpointer] = None,
    interrupt_before: Optional[list[str]] = None,
    interrupt_after: Optional[list[str]] = None,
    # その他多数のオプション...
)
```

### 3. 使用場面の違い

#### LangChainがおすすめの場面
- シンプルなReActエージェントが必要
- Function Call非対応のLLMを使用
- 学習コストを抑えたい
- 軽量な実装が求められる

#### LangGraphがおすすめの場面
- 複雑なワークフローが必要
- ステートフルな処理が重要
- Human-in-the-loopが必要
- 高度な実行制御が求められる
- チェックポイント機能が必要
- 構造化レスポンスが必要

## 実際のコード例での比較

### LangChain版

```python
from langchain.agents import create_react_agent, AgentExecutor
from langchain_core.tools import tool
from langchain_openai import ChatOpenAI
from langchain import hub

@tool
def calculator(expression: str) -> str:
    """数式を計算します"""
    return str(eval(expression))

# プロンプトを取得
prompt = hub.pull("hwchase17/react")

# エージェント作成
llm = ChatOpenAI(model="gpt-4")
agent = create_react_agent(llm, [calculator], prompt)

# エグゼキューター作成
agent_executor = AgentExecutor(agent=agent, tools=[calculator])

# 実行
result = agent_executor.invoke({"input": "2 + 3 × 4を計算して"})
```

### LangGraph版

```python
from langgraph.prebuilt import create_react_agent
from langchain_core.tools import tool

@tool
def calculator(expression: str) -> float:
    """数式を計算します"""
    return eval(expression)

# エージェント作成（より簡潔）
agent = create_react_agent(
    model="gpt-4",
    tools=[calculator],
    prompt="あなたは数学の専門家です"
)

# 実行
result = agent.invoke({
    "messages": [{"role": "user", "content": "2 + 3 × 4を計算して"}]
})
```

## パフォーマンスと運用面

### LangChain
- **起動速度**: 高速
- **メモリ使用量**: 少ない
- **デバッグ**: プロンプトベースなのでログが読みやすい
- **運用監視**: 基本的な機能のみ

### LangGraph  
- **起動速度**: やや低速（グラフ構築のため）
- **メモリ使用量**: 多め（状態管理のため）
- **デバッグ**: グラフの可視化、ステップごとの詳細ログ
- **運用監視**: 豊富な監視・制御機能

## まとめ

両者は同じReActパターンを実装していますが、アプローチが大きく異なります：

- **LangChain**: シンプル、軽量、テキストベース
- **LangGraph**: 高機能、ステートフル、グラフベース

選択の指針：
1. **プロトタイプや学習目的** → LangChain
2. **本格的なプロダクション** → LangGraph
3. **Function Call非対応LLM** → LangChain
4. **複雑なワークフロー** → LangGraph
5. **Human-in-the-loop** → LangGraph

どちらも優れたツールですが、用途や要件に応じて適切に選択することが重要です。LangGraphは学習コストが高い分、より柔軟で堅牢なエージェントを構築できます。

## 参考資料

- [ReAct: Synergizing Reasoning and Acting in Language Models](https://arxiv.org/abs/2210.03629)
- [LangChain Documentation](https://python.langchain.com/docs/)
- [LangGraph Documentation](https://langchain-ai.github.io/langgraph/)