Agentの評価
adk-eval crateは、agentの挙動をテストおよび検証するための包括的なツールを提供します。従来のソフトウェアテストとは異なり、agentの評価では、LLMの確率的な性質を考慮しつつ、意味のある品質シグナルを提供する必要があります。
概要
ADK-Rustにおけるagentの評価は、複数の評価戦略をサポートしています。
- Trajectory Evaluation: agentが予期されたツールを正しい順序で呼び出すことを検証します。
- Response Similarity: さまざまなアルゴリズム(Jaccard、Levenshtein、ROUGE)を使用してagentの応答を比較します。
- LLM-Judged Evaluation: 別のLLMを使用して、意味的類似性と品質を評価します。
- Rubric-Based Scoring: 重み付けされたスコアリングでカスタム基準に対して評価します。
クイックスタート
use adk_eval::{Evaluator, EvaluationConfig, EvaluationCriteria};
use std::sync::Arc;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create your agent
let agent = create_my_agent()?;
// Configure evaluator with criteria
let config = EvaluationConfig::with_criteria(
EvaluationCriteria::exact_tools()
.with_response_similarity(0.8)
);
let evaluator = Evaluator::new(config);
// Run evaluation against test file
let report = evaluator
.evaluate_file(agent, "tests/my_agent.test.json")
.await?;
// Check results
if report.all_passed() {
println!("All {} tests passed!", report.summary.total);
} else {
println!("{}", report.format_summary());
}
Ok(())
}
テストファイル形式
テストケースは、.test.json拡張子を持つJSONファイルで定義されます。
{
"eval_set_id": "weather_agent_tests",
"name": "Weather Agent Tests",
"description": "Test weather agent functionality",
"eval_cases": [
{
"eval_id": "test_current_weather",
"conversation": [
{
"invocation_id": "inv_001",
"user_content": {
"parts": [{"text": "What's the weather in NYC?"}],
"role": "user"
},
"final_response": {
"parts": [{"text": "The weather in NYC is 65°F and sunny."}],
"role": "model"
},
"intermediate_data": {
"tool_uses": [
{
"name": "get_weather",
"args": {"location": "NYC"}
}
]
}
}
]
}
]
}
評価基準
ツール軌跡の一致度
エージェントが期待されるツールを正しい順序で呼び出すことを検証します。
let criteria = EvaluationCriteria {
tool_trajectory_score: Some(1.0), // Require 100% match
tool_trajectory_config: Some(ToolTrajectoryConfig {
strict_order: true, // Tools must be called in exact order
strict_args: false, // Allow extra arguments in tool calls
}),
..Default::default()
};
オプション:
strict_order: 正確なシーケンスの一致を要求します。strict_args: 正確な引数の一致を要求します(余分な引数は許可されません)。- 設定可能なしきい値による部分一致。
応答の類似性
様々なアルゴリズムを使用して応答テキストを比較します。
let criteria = EvaluationCriteria {
response_similarity: Some(0.8), // 80% similarity required
response_match_config: Some(ResponseMatchConfig {
algorithm: SimilarityAlgorithm::Jaccard,
ignore_case: true,
normalize: true,
..Default::default()
}),
..Default::default()
};
利用可能なアルゴリズム:
| Algorithm | 説明 |
|---|---|
Exact | 完全な文字列一致 |
Contains | 部分文字列の確認 |
Levenshtein | 編集距離 |
Jaccard | 単語の重複 (デフォルト) |
Rouge1 | ユニグラムの重複 |
Rouge2 | バイグラムの重複 |
RougeL | 最長共通部分列 |
LLMによる意味的マッチング評価
LLMを使用して意味的な等価性を評価します。
use adk_eval::{Evaluator, EvaluationConfig, EvaluationCriteria, LlmJudge};
use adk_model::GeminiModel;
// Create evaluator with LLM judge
let judge_model = Arc::new(GeminiModel::new(&api_key, "gemini-2.0-flash")?);
let config = EvaluationConfig::with_criteria(
EvaluationCriteria::semantic_match(0.85)
);
let evaluator = Evaluator::with_llm_judge(config, judge_model);
LLM judgeは以下を評価します。
- 意味的な等価性(異なる単語でも同じ意味)
- 事実の正確性
- 応答の完全性
ルーブリックに基づく評価
重み付けされたスコアリングを用いてカスタム基準に対して評価します。
use adk_eval::{Rubric, EvaluationCriteria};
let criteria = EvaluationCriteria::default()
.with_rubrics(0.7, vec![
Rubric::new("Accuracy", "Response is factually correct")
.with_weight(0.5),
Rubric::new("Helpfulness", "Response addresses user's needs")
.with_weight(0.3),
Rubric::new("Clarity", "Response is clear and well-organized")
.with_weight(0.2),
]);
各ルーブリックはLLM judgeによって0-1でスコア付けされ、その後重みを使用して結合されます。
安全性と幻覚の検出
応答の安全性問題と幻覚をチェックします。
let criteria = EvaluationCriteria {
safety_score: Some(0.95), // Require high safety score
hallucination_score: Some(0.9), // Require low hallucination rate
..Default::default()
};
結果レポート
評価レポートは詳細な結果を提供します。
let report = evaluator.evaluate_file(agent, "tests/agent.test.json").await?;
// サマリー統計
println!("Total: {}", report.summary.total);
println!("Passed: {}", report.summary.passed);
println!("Failed: {}", report.summary.failed);
println!("Pass Rate: {:.1}%", report.summary.pass_rate * 100.0);
// 詳細な失敗
for result in report.failures() {
println!("Failed: {}", result.eval_id);
for failure in &result.failures {
println!(" - {}: {} (expected: {}, actual: {})",
failure.criterion,
failure.message,
failure.expected,
failure.actual
);
}
}
// CI/CD用にJSONにエクスポート
let json = report.to_json()?;
std::fs::write("eval_results.json", json)?;
バッチ評価
並行評価
複数のテストケースを並行して評価します。
let results = evaluator
.evaluate_cases_parallel(agent, &cases, 4) // 4 concurrent evaluations
.await;
ディレクトリ評価
ディレクトリ内のすべてのテストファイルを評価します。
let reports = evaluator
.evaluate_directory(agent, "tests/eval_cases")
.await?;
for (file, report) in reports {
println!("{}: {} passed, {} failed",
file,
report.summary.passed,
report.summary.failed
);
}
cargo testとの統合
標準のRustテストで評価を使用します。
#[tokio::test]
async fn test_weather_agent() {
let agent = create_weather_agent().unwrap();
let evaluator = Evaluator::new(EvaluationConfig::with_criteria(
EvaluationCriteria::exact_tools()
));
let report = evaluator
.evaluate_file(agent, "tests/weather_agent.test.json")
.await
.unwrap();
assert!(report.all_passed(), "{}", report.format_summary());
}
例
# Basic evaluation
cargo run --example eval_basic
# Trajectory validation
cargo run --example eval_trajectory
# LLM-judged semantic matching
cargo run --example eval_semantic
# Rubric-based scoring
cargo run --example eval_rubric
# Response similarity algorithms
cargo run --example eval_similarity
# Report generation
cargo run --example eval_report
ベストプラクティス
- シンプルに始める: 意味的チェックを追加する前に、trajectory validationから始めます
- 代表的なケースを使用する: テストファイルは、エッジケースと一般的なシナリオをカバーするべきです
- しきい値を調整する: 緩いしきい値から始め、Agentが改善するにつれて厳しくします
- 基準を組み合わせる: 包括的な評価のために複数のcriteriaを使用します
- テストファイルをバージョン管理する: Agentコードと並行してテストファイルをバージョン管理下に置きます
- CI/CD統合: regressionを捕捉するためにCIで評価を実行します
前へ: ← A2A Protocol | 次へ: Access Control →