出力品質評価
「エージェントは動いた。だが、動くことと信頼できることは別だ。」
田中VPoEが品質管理の重要性を説く。
「営業チームがこのエージェントの出力を信じてアクションを起こす。もし出力が不正確だったら、顧客との関係が壊れる。品質評価の仕組みが必要だ。」
出力品質の3つの軸
エージェント出力の品質評価:
1. 正確性(Accuracy) → 予測値と分析が事実に基づいているか
2. 有用性(Usefulness) → ビジネスアクションにつながるか
3. 一貫性(Consistency) → 同じ入力に同じ出力を返すか
正確性の評価
MLモデルの精度
from sklearn.metrics import roc_auc_score, precision_recall_curve
import numpy as np
def evaluate_model_accuracy(model, X_test, y_test):
"""モデルの精度を多角的に評価"""
y_proba = model.predict_proba(X_test)[:, 1]
y_pred = model.predict(X_test)
metrics = {
"AUC-ROC": roc_auc_score(y_test, y_proba),
"Precision@50%Recall": None,
"Recall@50%Precision": None,
}
# Precision-Recall曲線から特定の閾値での性能を計算
precision, recall, thresholds = precision_recall_curve(y_test, y_proba)
# Recall 50%時のPrecision
idx = np.argmin(np.abs(recall - 0.5))
metrics["Precision@50%Recall"] = precision[idx]
# Precision 50%時のRecall
idx = np.argmin(np.abs(precision - 0.5))
metrics["Recall@50%Precision"] = recall[idx]
return metrics
metrics = evaluate_model_accuracy(model, X_test, y_test)
for k, v in metrics.items():
print(f" {k}: {v:.4f}")
SHAP分析の妥当性検証
def validate_shap_explanations(model, X_test, y_test, n_samples=100):
"""SHAP分析の妥当性を検証"""
import shap
explainer = shap.TreeExplainer(model)
# 一貫性チェック: SHAP値の合計 ≈ 予測値 - ベースライン
errors = []
for i in range(min(n_samples, len(X_test))):
sample = X_test.iloc[i:i+1]
sv = explainer.shap_values(sample)
if isinstance(sv, list):
shap_sum = sv[1][0].sum()
base = explainer.expected_value[1]
else:
shap_sum = sv[0].sum()
base = explainer.expected_value
pred = model.predict_proba(sample)[0][1]
# ロジスティック変換を考慮した近似チェック
error = abs(pred - (base + shap_sum))
errors.append(error)
print(f"SHAP一貫性チェック:")
print(f" 平均誤差: {np.mean(errors):.6f}")
print(f" 最大誤差: {np.max(errors):.6f}")
print(f" 判定: {'OK' if np.mean(errors) < 0.01 else 'NG'}")
有用性の評価
施策提案の評価フレームワーク
def evaluate_action_usefulness(actions, ground_truth_actions=None):
"""施策提案の有用性を評価"""
criteria = {
"具体性": {
"score": 0,
"check": lambda a: len(a.get("action", "")) > 20,
"description": "施策が具体的で実行可能か",
},
"根拠の明確さ": {
"score": 0,
"check": lambda a: "trigger" in a or "rationale" in a,
"description": "なぜその施策を提案するのか根拠があるか",
},
"優先度の明示": {
"score": 0,
"check": lambda a: "priority" in a,
"description": "優先度が付いているか",
},
}
for action in actions:
for criterion_name, criterion in criteria.items():
if criterion["check"](action):
criterion["score"] += 1
total = len(actions) if actions else 1
results = {k: v["score"] / total for k, v in criteria.items()}
return results
LLM応答の評価
def evaluate_response_quality(response: str) -> dict:
"""LLM応答の品質を評価"""
checks = {
"リスクレベルの明示": any(
level in response for level in ["HIGH", "MEDIUM", "LOW", "高", "中", "低"]
),
"確率値の含有": any(
char.isdigit() for char in response
),
"要因の説明": any(
keyword in response for keyword in ["要因", "理由", "原因", "なぜ"]
),
"施策の提案": any(
keyword in response for keyword in ["提案", "施策", "対策", "推奨", "アクション"]
),
"適切な長さ": 100 < len(response) < 2000,
}
score = sum(checks.values()) / len(checks)
return {"checks": checks, "overall_score": score}
一貫性の評価
def evaluate_consistency(app, query: str, n_runs: int = 5) -> dict:
"""同一入力に対する出力の一貫性を評価"""
results = []
probabilities = []
for _ in range(n_runs):
result = app.invoke({"query": query})
results.append(result.get("response", ""))
if result.get("probability"):
probabilities.append(result["probability"])
consistency = {
"probability_std": np.std(probabilities) if probabilities else None,
"risk_level_consistent": len(set(
r.get("risk_level") for r in results if isinstance(r, dict)
)) <= 1,
"response_similarity": None, # 応答テキストの類似度
}
# 予測値の一貫性(MLモデル部分は完全に決定的であるべき)
if consistency["probability_std"] is not None:
consistency["prediction_deterministic"] = consistency["probability_std"] < 0.001
return consistency
品質ダッシュボード
def quality_dashboard(model, app, X_test, y_test):
"""品質の全体像を表示"""
print("=" * 50)
print("品質ダッシュボード")
print("=" * 50)
# 1. モデル精度
print("\n[1] モデル精度")
metrics = evaluate_model_accuracy(model, X_test, y_test)
for k, v in metrics.items():
status = "OK" if v and v > 0.7 else "要改善"
print(f" {k}: {v:.4f} [{status}]")
# 2. SHAP妥当性
print("\n[2] SHAP分析の妥当性")
validate_shap_explanations(model, X_test, y_test)
# 3. 応答品質(サンプル)
print("\n[3] 応答品質")
sample_result = app.invoke({"query": "顧客 7590-VHVEG の離反リスクは?"})
quality = evaluate_response_quality(sample_result.get("response", ""))
for k, v in quality["checks"].items():
print(f" {k}: {'OK' if v else 'NG'}")
print(f" 総合スコア: {quality['overall_score']:.0%}")
まとめ
| 項目 | ポイント |
|---|---|
| 正確性 | AUC-ROC + SHAP一貫性チェック |
| 有用性 | 施策の具体性・根拠・優先度 |
| 一貫性 | 同一入力への出力の安定性 |
| 自動評価 | チェック関数で定期的に検証 |
| ダッシュボード | 品質の全体像を一覧表示 |
チェックリスト
- MLモデルの精度を多角的に評価できる
- SHAP分析の妥当性を検証できる
- 施策提案の有用性を評価できる
- LLM応答の品質チェックを実装できる
- 出力の一貫性を検証できる
次のステップへ
品質評価の仕組みができた。次はHuman-in-the-Loop設計で、人間のフィードバックを取り込む仕組みを構築しよう。
推定読了時間: 30分