Avaliação de Agent

A crate adk-eval fornece ferramentas abrangentes para testar e validar o comportamento de Agent. Ao contrário dos testes de software tradicionais, a avaliação de Agent deve levar em conta a natureza probabilística de LLMs, ao mesmo tempo que oferece sinais de qualidade significativos.

Visão Geral

A avaliação de Agent em ADK-Rust suporta múltiplas estratégias de avaliação:

  • Trajectory Evaluation: Valida que os Agent chamam as Tool esperadas na sequência correta
  • Response Similarity: Compara as respostas do Agent usando vários algoritmos (Jaccard, Levenshtein, ROUGE)
  • LLM-Judged Evaluation: Usa outro LLM para avaliar a similaridade e qualidade semântica
  • Rubric-Based Scoring: Avalia contra critérios personalizados com pontuação ponderada

Início Rápido

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(())
}

Formato do Arquivo de Teste

Casos de teste são definidos em arquivos JSON com a extensão .test.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"}
              }
            ]
          }
        }
      ]
    }
  ]
}

Critérios de Avaliação

Correspondência de Trajetória de Tool

Valida se os Agents chamam os Tools esperados na ordem correta:

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()
};

Opções:

  • strict_order: Exige correspondência exata da sequência
  • strict_args: Exige correspondência exata dos argumentos (nenhum argumento extra permitido)
  • Correspondência parcial com thresholds configuráveis

Similaridade de Resposta

Compara o texto da resposta usando vários algoritmos:

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()
};

Algoritmos disponíveis:

AlgorithmDescrição
ExactCorrespondência exata de string
ContainsVerificação de substring
LevenshteinDistância de edição
JaccardSobreposição de palavras (padrão)
Rouge1Sobreposição de unigram
Rouge2Sobreposição de bigram
RougeLSubsequência comum mais longa

Correspondência Semântica Avaliada por LLM

Usa um LLM para avaliar a equivalência semântica:

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);

O LLM judge avalia:

  • Equivalência semântica (mesmo significado, palavras diferentes)
  • Precisão factual
  • Completude da resposta

Avaliação Baseada em Rubrica

Avalia contra critérios personalizados com pontuação ponderada:

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),
    ]);

Cada Rubric é pontuada de 0 a 1 pelo LLM judge, e então combinada usando pesos.

Detecção de Segurança e Alucinações

Verifica as respostas quanto a problemas de segurança e alucinações:

let criteria = EvaluationCriteria {
    safety_score: Some(0.95),        // Require high safety score
    hallucination_score: Some(0.9),  // Require low hallucination rate
    ..Default::default()
};

Relatório de Resultados

O relatório de avaliação fornece resultados detalhados:

let report = evaluator.evaluate_file(agent, "tests/agent.test.json").await?;

// Summary statistics
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);

// Detailed failures
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
        );
    }
}

// Export to JSON for CI/CD
let json = report.to_json()?;
std::fs::write("eval_results.json", json)?;

Avaliação em Lote

Avaliação Paralela

Avalie múltiplos casos de teste concorrentemente:

let results = evaluator
    .evaluate_cases_parallel(agent, &cases, 4)  // 4 concurrent evaluations
    .await;

Avaliação de Diretório

Avalie todos os arquivos de teste em um diretório:

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
    );
}

Integração com cargo test

Use a avaliação em testes Rust padrão:

#[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());
}

Exemplos

# Avaliação básica
cargo run --example eval_basic

# Validação de trajetória
cargo run --example eval_trajectory

# Correspondência semântica julgada por LLM
cargo run --example eval_semantic

# Pontuação baseada em rubrica
cargo run --example eval_rubric

# Algoritmos de similaridade de resposta
cargo run --example eval_similarity

# Geração de relatório
cargo run --example eval_report

Melhores Práticas

  1. Comece Simples: Comece com a validação de trajetória antes de adicionar verificações semânticas
  2. Use Casos Representativos: Os arquivos de teste devem cobrir casos extremos e cenários comuns
  3. Calibre os Limiares: Comece com limiares flexíveis e ajuste-os conforme o agent melhora
  4. Combine Critérios: Use múltiplos critérios para uma avaliação abrangente
  5. Versionar Arquivos de Teste: Mantenha os arquivos de teste no controle de versão junto com o código do agent
  6. Integração CI/CD: Execute avaliações em CI para detectar regressões

Anterior: ← A2A Protocol | Próximo: Access Control →