LESSON

分析エージェントの設計

「モデルができた。だが、これをデータサイエンティストだけが使えるツールにしてどうする?」

田中VPoEが問いかける。

「営業やCSチームが『この顧客は離反しそうですか?理由は?どう対策すればいいですか?』と聞いたら、自然言語で答えてくれるAIエージェントにしたい。LangGraphを使って実装しよう。」

AIエージェントとは

AIエージェント = LLM + ツール + ワークフロー
- LLM: ユーザーの意図を理解し、自然言語で応答
- ツール: データ取得、推論、分析、可視化の実行
- ワークフロー: ツール呼び出しの順序と条件分岐を制御

離反分析エージェントの要件

機能入力出力
顧客の離反リスク予測顧客ID or 属性離反確率、リスクレベル
離反要因の説明顧客IDSHAP値に基づく要因Top5
リテンション施策の提案顧客ID具体的な施策リスト
セグメント分析セグメント条件セグメント別離反率、統計
バッチ予測顧客リストリスクスコア一覧

ツールの分解

エージェントが使用するツールを設計する。

# ツール一覧
tools = {
    "get_customer_data": {
        "description": "顧客IDからデータを取得する",
        "input": "customer_id: str",
        "output": "dict (顧客属性)",
    },
    "preprocess_data": {
        "description": "生データを前処理してモデル入力形式に変換する",
        "input": "raw_data: dict",
        "output": "np.ndarray (特徴量ベクトル)",
    },
    "predict_churn": {
        "description": "離反確率を予測する",
        "input": "features: np.ndarray",
        "output": "dict (probability, risk_level)",
    },
    "explain_prediction": {
        "description": "SHAP分析で予測の要因を説明する",
        "input": "features: np.ndarray",
        "output": "list[dict] (feature, shap_value, direction)",
    },
    "suggest_retention": {
        "description": "リテンション施策を提案する",
        "input": "shap_results: list, customer_data: dict",
        "output": "list[dict] (action, priority, expected_impact)",
    },
    "visualize_analysis": {
        "description": "分析結果を可視化する",
        "input": "analysis_results: dict",
        "output": "str (画像パス)",
    },
}

ワークフロー設計

ユーザー入力

[意図分類] → "個別顧客分析" / "セグメント分析" / "バッチ予測"

┌─────────────────────────────────┐
│ 個別顧客分析の場合:              │
│  1. get_customer_data           │
│  2. preprocess_data             │
│  3. predict_churn               │
│  4. explain_prediction          │
│  5. suggest_retention           │
│  6. visualize_analysis          │
│  7. 結果を自然言語で回答        │
└─────────────────────────────────┘

状態管理の設計

LangGraphではStateとして管理するデータ構造を定義する。

from typing import TypedDict, Optional, Annotated
from operator import add

class ChurnAnalysisState(TypedDict):
    # ユーザー入力
    messages: Annotated[list, add]
    query_type: Optional[str]  # "individual", "segment", "batch"

    # データ
    customer_id: Optional[str]
    raw_data: Optional[dict]
    processed_features: Optional[list]

    # 予測結果
    churn_probability: Optional[float]
    risk_level: Optional[str]  # "HIGH", "MEDIUM", "LOW"

    # 分析結果
    shap_explanations: Optional[list]
    retention_actions: Optional[list]
    visualization_path: Optional[str]

    # エラーハンドリング
    error: Optional[str]

ノード設計

# 各ノードの責務
nodes = {
    "classify_intent": "ユーザーの意図を分類する",
    "fetch_data": "顧客データを取得する",
    "preprocess": "データを前処理する",
    "predict": "離反確率を予測する",
    "explain": "SHAP分析で要因を説明する",
    "recommend": "リテンション施策を提案する",
    "visualize": "結果を可視化する",
    "respond": "自然言語で回答を生成する",
    "handle_error": "エラーを処理する",
}

条件分岐の設計

# 分岐ロジック
def route_by_intent(state: ChurnAnalysisState) -> str:
    """意図に応じて次のノードを決定"""
    if state.get("error"):
        return "handle_error"
    query_type = state.get("query_type")
    if query_type == "individual":
        return "fetch_data"
    elif query_type == "segment":
        return "segment_analysis"
    elif query_type == "batch":
        return "batch_prediction"
    return "handle_error"

def route_after_prediction(state: ChurnAnalysisState) -> str:
    """予測後の分岐"""
    if state.get("error"):
        return "handle_error"
    if state["risk_level"] == "HIGH":
        return "explain"  # 高リスクのみ詳細分析
    return "respond"  # 低リスクは即回答

エージェントのアーキテクチャ

                    ┌───────────┐
                    │ classify  │
                    │  intent   │
                    └─────┬─────┘
                ┌─────────┼─────────┐
                ▼         ▼         ▼
         ┌──────────┐ ┌──────┐ ┌───────┐
         │individual│ │segment│ │ batch │
         └────┬─────┘ └──┬───┘ └───┬───┘
              ▼           ▼         ▼
         ┌──────────┐     │         │
         │fetch_data│     │         │
         └────┬─────┘     │         │
              ▼           │         │
         ┌──────────┐     │         │
         │preprocess│     │         │
         └────┬─────┘     │         │
              ▼           │         │
         ┌──────────┐     │         │
         │ predict  │     │         │
         └────┬─────┘     │         │
         HIGH │ LOW        │         │
         ┌────┴────┐      │         │
         ▼         ▼      │         │
    ┌─────────┐    │      │         │
    │ explain │    │      │         │
    └────┬────┘    │      │         │
         ▼        │      │         │
    ┌──────────┐   │      │         │
    │recommend │   │      │         │
    └────┬─────┘   │      │         │
         ▼        ▼      ▼         ▼
         ┌──────────────────────────┐
         │        respond           │
         └──────────────────────────┘

まとめ

項目ポイント
エージェント構成LLM + ツール + ワークフロー
ツール数6つ(データ取得/前処理/推論/説明/施策/可視化)
State管理TypedDictで型安全に管理
条件分岐意図分類、リスクレベルで分岐
アーキテクチャDAG(有向非巡回グラフ)で設計

チェックリスト

  • AIエージェントの3要素(LLM/ツール/ワークフロー)を説明できる
  • 必要なツールを分解・定義できる
  • State構造を設計できる
  • 条件分岐のロジックを設計できる
  • ワークフローのDAGを描ける

次のステップへ

エージェントの設計ができた。次は各ツールを実装していこう。

推定読了時間: 30分