LESSON

演習:カスタマーサポートエージェントを構築しよう

「設計は整った。LangGraphでカスタマーサポートエージェントを組み上げよう。」

田中VPoEが開発環境を開く。

「問い合わせの自動分類、FAQ検索、回答生成、エスカレーション判断まで一気通貫で実装してくれ。」

ミッション概要

LangGraphを使って、NetShop社カスタマーサポート向けのAIエージェントを構築する。

前提条件

  • Python 3.10+
  • LangGraph, LangChain, OpenAI API
  • 分類モデル(BERT Fine-tuning済み)

Mission 1: ツール実装(40分)

以下のツールを実装せよ。

  1. classify_inquiry: BERT分類 + LLMフォールバック
  2. search_faq: セマンティック検索
  3. analyze_sentiment: 感情分析
  4. generate_response: RAGベース回答生成
解答例
from langchain_core.tools import tool

@tool
def classify_inquiry(text: str) -> dict:
    """問い合わせを分類"""
    # BERT分類
    result = classifier.classify(text)
    if result['confidence'] < 0.7:
        # LLMフォールバック
        llm_result = llm_classify_fallback(text)
        result['category'] = llm_result['category']
        result['fallback'] = True
    return result

@tool
def search_faq(query: str, category: str = "") -> list:
    """FAQ検索"""
    return faq_engine.search(query, category, top_k=3)

@tool
def analyze_sentiment(text: str) -> dict:
    """感情分析"""
    llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
    prompt = f"問い合わせの感情を分析: {text}"
    # 構造化出力で sentiment, urgency, frustration_level を返す
    return {"sentiment": "negative", "urgency": "medium", "frustration_level": 2}

@tool
def generate_response(inquiry: str, category: str, faq_context: str) -> str:
    """回答生成"""
    llm = ChatOpenAI(model="gpt-4o-mini", temperature=0.3)
    prompt = f"カテゴリ: {category}\nFAQ: {faq_context}\n問い合わせ: {inquiry}\n回答:"
    return llm.invoke(prompt).content

Mission 2: LangGraphワークフロー構築(40分)

以下を実装せよ。

  1. SupportAgentState の定義
  2. 各ノード(分類、感情分析、エスカレーション判断、FAQ検索、回答生成)
  3. conditional_edges によるエスカレーション分岐
  4. グラフのコンパイルと実行
解答例
from langgraph.graph import StateGraph, END

def classify_node(state):
    result = classify_inquiry.invoke({"text": state['inquiry_text']})
    return {'category': result['category'], 'confidence': result['confidence']}

def sentiment_node(state):
    result = analyze_sentiment.invoke({"text": state['inquiry_text']})
    return {'sentiment': result}

def escalation_node(state):
    needs = (
        state['confidence'] < 0.5
        or state['sentiment'].get('frustration_level', 0) >= 4
    )
    return {
        'needs_escalation': needs,
        'escalation_reason': '確信度低/感情ネガティブ' if needs else None,
    }

def faq_node(state):
    results = search_faq.invoke({"query": state['inquiry_text'], "category": state['category']})
    return {'faq_results': results}

def response_node(state):
    faq_text = "\n".join([f"Q: {f['question']}\nA: {f['answer']}" for f in (state['faq_results'] or [])])
    response = generate_response.invoke({
        "inquiry": state['inquiry_text'],
        "category": state['category'],
        "faq_context": faq_text,
    })
    return {'draft_response': response}

def route_escalation(state):
    return "escalate" if state['needs_escalation'] else "faq_search"

graph = StateGraph(SupportAgentState)
graph.add_node("classify", classify_node)
graph.add_node("sentiment", sentiment_node)
graph.add_node("escalation_check", escalation_node)
graph.add_node("faq_search", faq_node)
graph.add_node("generate_response", response_node)
graph.add_node("escalate", lambda s: {'messages': [AIMessage(content="エスカレーション通知を送信しました")]})

graph.set_entry_point("classify")
graph.add_edge("classify", "sentiment")
graph.add_edge("sentiment", "escalation_check")
graph.add_conditional_edges("escalation_check", route_escalation)
graph.add_edge("faq_search", "generate_response")
graph.add_edge("generate_response", END)
graph.add_edge("escalate", END)

app = graph.compile()

Mission 3: テストとエッジケース対応(40分)

以下を実施せよ。

  1. 5つ以上の問い合わせシナリオでテスト
  2. エスカレーション発動ケースの確認
  3. 品質レポートの作成
解答例
=== テストシナリオ ===

1. 通常問合せ: 「注文した商品はいつ届きますか」→ 配送カテゴリ → FAQ回答
2. 返品要望: 「商品が壊れていたので返品したい」→ 返品・交換 → 手順回答
3. 怒りの問合せ: 「3回目の問い合わせだ!いい加減にしろ!」→ エスカレーション
4. 法的言及: 「消費者庁に相談する」→ 法務エスカレーション
5. 曖昧な問合せ: 「なんかよくわからないんですけど」→ 確信度低 → エスカレーション

=== 品質レポート ===
| シナリオ | 分類正答 | エスカ判断 | 回答品質 |
|---------|---------|-----------|---------|
| 通常 | OK | 不要(正しい) | 適切 |
| 返品 | OK | 不要(正しい) | 適切 |
| 怒り | OK | 発動(正しい) | - |
| 法的 | OK | 発動(正しい) | - |
| 曖昧 | 低確信度 | 発動(正しい) | - |

達成度チェック

  • 4つのツールを実装した
  • LangGraphワークフローをコンパイル・実行できた
  • エスカレーション分岐が正しく動作した
  • 5つ以上のシナリオでテストした
  • 品質レポートを作成した

推定所要時間: 120分