에이전트 평가

adk-eval crate는 에이전트 동작을 테스트하고 검증하기 위한 포괄적인 도구를 제공합니다. 기존 소프트웨어 테스트와 달리 에이전트 평가는 LLM의 확률적 특성을 고려해야 하며, 동시에 의미 있는 품질 신호를 제공해야 합니다.

개요

ADK-Rust의 에이전트 평가는 여러 평가 전략을 지원합니다:

  • Trajectory Evaluation: 에이전트가 예상되는 도구를 올바른 순서로 호출하는지 검증합니다.
  • Response Similarity: 다양한 알고리즘(Jaccard, Levenshtein, ROUGE)을 사용하여 에이전트 응답을 비교합니다.
  • 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 평가자는 다음을 평가합니다.

  • 의미론적 동등성 (의미는 같으나 단어가 다름)
  • 사실적 정확성
  • 응답의 완전성

루브릭 기반 평가

가중치 점수화를 통해 사용자 지정 기준에 따라 평가합니다.

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 평가자에 의해 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개의 동시 평가
    .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());
}

예시

# 기본 평가
cargo run --example eval_basic

# 트랙젝토리 유효성 검사
cargo run --example eval_trajectory

# LLM으로 판단하는 의미론적 일치
cargo run --example eval_semantic

# 루브릭 기반 채점
cargo run --example eval_rubric

# 응답 유사성 알고리즘
cargo run --example eval_similarity

# 보고서 생성
cargo run --example eval_report

모범 사례

  1. 간단하게 시작: 의미론적 검사를 추가하기 전에 트랙젝토리 유효성 검사부터 시작하세요.
  2. 대표적인 케이스 사용: 테스트 파일은 엣지 케이스와 일반적인 시나리오를 모두 다뤄야 합니다.
  3. 임계값 조정: 관대한 임계값으로 시작하여 Agent가 개선됨에 따라 조여나가세요.
  4. 기준 결합: 포괄적인 평가를 위해 여러 기준을 사용하세요.
  5. 테스트 파일 버전 관리: Agent 코드와 함께 테스트 파일을 버전 관리 시스템에 유지하세요.
  6. CI/CD 통합: 회귀를 감지하기 위해 CI에서 평가를 실행하세요.

이전: ← A2A Protocol | 다음: Access Control →