演習:診断支援エージェントを構築しよう
「設計は整った。LangGraphで診断支援エージェントを組み上げよう。」
田中VPoEが開発環境を開く。
「画像分類、所見生成、リスク判定、レポート生成まで一気通貫のエージェントを実装してくれ。」
ミッション概要
LangGraphを使って、画像診断支援AIエージェントを構築する。Kaggle Chest X-Ray / Plant Pathologyデータセットで動作確認する。
前提条件
- Python 3.10+、PyTorch、LangGraph
- 画像分類モデル(ResNet Fine-tuning済み)
- OpenAI API(GPT-4o)
Mission 1: ツール実装(40分)
以下のツールを実装せよ。
classify_image: ResNet分類 + Grad-CAM生成generate_findings: VLMによる構造化所見assess_risk: リスクレベル判定
解答例
@tool
def classify_image(image_path: str) -> dict:
"""画像を分類"""
result = classifier.predict(image_path)
grad_cam = generate_grad_cam(image_path, classifier.model)
result['grad_cam_path'] = grad_cam
return result
@tool
def generate_findings(image_path: str, classification_json: str) -> str:
"""所見を生成"""
import json
classification = json.loads(classification_json)
prompt = f"分類: {classification['class']}(確信度: {classification['confidence']})\n構造化された所見を生成"
return call_vlm(image_path, prompt)
@tool
def assess_risk(severity: int, confidence: float) -> dict:
"""リスク判定"""
risk_score = severity * 0.6 + (1 - confidence) * 0.4 * 3
if risk_score >= 2.5:
return {'risk_level': 'critical', 'urgency': '即時'}
elif risk_score >= 1.5:
return {'risk_level': 'high', 'urgency': '優先'}
elif risk_score >= 0.8:
return {'risk_level': 'medium', 'urgency': '通常'}
return {'risk_level': 'low', 'urgency': '経過観察'}
Mission 2: LangGraphワークフロー構築(40分)
以下を実装せよ。
- DiagnosisAgentState の定義
- 各ノード(分類、所見、リスク、レポート生成)
- conditional_edges による専門家レビュー分岐
- グラフのコンパイルと実行
解答例
from langgraph.graph import StateGraph, END
def classify_node(state):
result = classify_image.invoke({"image_path": state['image_path']})
return {'classification': result}
def findings_node(state):
findings = generate_findings.invoke({
"image_path": state['image_path'],
"classification_json": json.dumps(state['classification']),
})
return {'findings': findings}
def risk_node(state):
result = assess_risk.invoke({
"severity": 2, "confidence": state['classification']['confidence'],
})
needs_review = result['risk_level'] in ('critical', 'high')
return {'risk_level': result['risk_level'], 'needs_expert_review': needs_review}
def report_node(state):
report = f"""
=== 診断支援レポート ===
分類: {state['classification']['class']}
確信度: {state['classification']['confidence']}
リスク: {state['risk_level']}
所見: {state['findings']}
"""
return {'report': report}
def route_review(state):
return "expert_review" if state['needs_expert_review'] else "report"
graph = StateGraph(DiagnosisAgentState)
graph.add_node("classify", classify_node)
graph.add_node("findings", findings_node)
graph.add_node("risk", risk_node)
graph.add_node("report", report_node)
graph.add_node("expert_review", lambda s: {'messages': [AIMessage(content="専門家レビューを要請")]})
graph.set_entry_point("classify")
graph.add_edge("classify", "findings")
graph.add_edge("findings", "risk")
graph.add_conditional_edges("risk", route_review)
graph.add_edge("report", END)
graph.add_edge("expert_review", "report")
app = graph.compile()
Mission 3: テストと品質検証(40分)
以下を実施せよ。
- 正常画像、軽度異常、重度異常の各ケースでテスト
- Grad-CAMの注目領域と所見の整合性を確認
- リスク判定の妥当性を検証
解答例
=== テスト結果 ===
| ケース | 分類 | 確信度 | リスク | 専門家レビュー | Grad-CAM整合 |
|--------|------|--------|--------|---------------|-------------|
| 正常 | normal | 0.95 | low | 不要 | OK |
| 軽度 | mild | 0.82 | medium | 不要 | OK |
| 重度 | severe | 0.91 | critical | 必要 | OK |
| 不明瞭 | mild | 0.45 | high | 必要(低確信度) | 要確認 |
所見: 4ケース中4ケースで構造化フォーマットに準拠
Grad-CAM: 3ケースで注目領域と所見が整合、1ケースは追加確認が必要
リスク判定: 全ケースで妥当な判定
達成度チェック
- 3つのツールを実装した
- LangGraphワークフローをコンパイル・実行できた
- 専門家レビュー分岐が正しく動作した
- 3ケース以上でテスト・検証した
- Grad-CAMと所見の整合性を確認した
推定所要時間: 120分