Evaluación de Agentes
El crate adk-eval proporciona herramientas completas para probar y validar el comportamiento de los agentes. A diferencia de las pruebas de software tradicionales, la evaluación de agentes debe tener en cuenta la naturaleza probabilística de los LLMs, al mismo tiempo que proporciona señales de calidad significativas.
Resumen
La evaluación de agentes en adk-rust admite múltiples estrategias de evaluación:
- Evaluación de Trayectoria: Valida que los agentes llamen a las herramientas esperadas en la secuencia correcta
- Similitud de Respuesta: Compara las respuestas de los agentes utilizando varios algoritmos (Jaccard, Levenshtein, ROUGE)
- Evaluación Juzgada por LLM: Utiliza otro LLM para evaluar la similitud semántica y la calidad
- Puntuación Basada en Rúbricas: Evalúa según criterios personalizados con puntuación ponderada
Inicio 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 de Archivo de Prueba
Los casos de prueba se definen en archivos JSON con la extensión .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"}
}
]
}
}
]
}
]
}
Criterios de Evaluación
Coincidencia de Trayectoria de Herramientas
Valida que los agents llamen a los Tool esperados en el orden correcto:
let criteria = EvaluationCriteria {
tool_trajectory_score: Some(1.0), // Requiere una coincidencia del 100%
tool_trajectory_config: Some(ToolTrajectoryConfig {
strict_order: true, // Los Tools deben ser llamados en el orden exacto
strict_args: false, // Permite argumentos extra en las llamadas a Tool
}),
..Default::default()
};
Opciones:
strict_order: Requiere coincidencia exacta de la secuenciastrict_args: Requiere coincidencia exacta de los argumentos (no se permiten argumentos extra)- Coincidencia parcial con umbrales configurables
Similitud de Respuesta
Compara el texto de respuesta usando varios algoritmos:
let criteria = EvaluationCriteria {
response_similarity: Some(0.8), // Se requiere un 80% de similitud
response_match_config: Some(ResponseMatchConfig {
algorithm: SimilarityAlgorithm::Jaccard,
ignore_case: true,
normalize: true,
..Default::default()
}),
..Default::default()
};
Algoritmos disponibles:
| Algoritmo | Descripción |
|---|---|
Exact | Coincidencia exacta de cadena |
Contains | Verificación de subcadena |
Levenshtein | Distancia de edición |
Jaccard | Superposición de palabras (por defecto) |
Rouge1 | Superposición de unigramas |
Rouge2 | Superposición de bigramas |
RougeL | Subsecuencia común más larga |
Coincidencia Semántica Evaluada por LLM
Usa un LLM para evaluar la equivalencia semántica:
use adk_eval::{Evaluator, EvaluationConfig, EvaluationCriteria, LlmJudge};
use adk_model::GeminiModel;
// Crea un Evaluator con el 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);
El LLM judge evalúa:
- Equivalencia semántica (mismo significado, diferentes palabras)
- Precisión fáctica
- Exhaustividad de la respuesta
Evaluación Basada en Rúbricas
Evalúa contra criterios personalizados con puntuación ponderada:
use adk_eval::{Rubric, EvaluationCriteria};
let criteria = EvaluationCriteria::default()
.with_rubrics(0.7, vec![
Rubric::new("Precisión", "La respuesta es objetivamente correcta")
.with_weight(0.5),
Rubric::new("Utilidad", "La respuesta aborda las necesidades del usuario")
.with_weight(0.3),
Rubric::new("Claridad", "La respuesta es clara y bien organizada")
.with_weight(0.2),
]);
Cada rúbrica es puntuado de 0 a 1 por el LLM judge, y luego se combinan usando pesos.
Detección de Seguridad y Alucinaciones
Verifica las respuestas en busca de problemas de seguridad y alucinaciones:
let criteria = EvaluationCriteria {
safety_score: Some(0.95), // Requiere una puntuación de seguridad alta
hallucination_score: Some(0.9), // Requiere una baja tasa de alucinación
..Default::default()
};
Reporte de Resultados
El reporte de evaluación proporciona resultados detallados:
let report = evaluator.evaluate_file(agent, "tests/agent.test.json").await?;
// Estadísticas de resumen
println!("Total: {}", report.summary.total);
println!("Aprobado: {}", report.summary.passed);
println!("Falló: {}", report.summary.failed);
println!("Tasa de Aprobación: {:.1}%", report.summary.pass_rate * 100.0);
// Fallos detallados
for result in report.failures() {
println!("Falló: {}", result.eval_id);
for failure in &result.failures {
println!(" - {}: {} (esperado: {}, actual: {})",
failure.criterion,
failure.message,
failure.expected,
failure.actual
);
}
}
// Exportar a JSON para CI/CD
let json = report.to_json()?;
std::fs::write("eval_results.json", json)?;
Evaluación por lotes
Evaluación paralela
Evalúa múltiples casos de prueba concurrentemente:
let results = evaluator
.evaluate_cases_parallel(agent, &cases, 4) // 4 evaluaciones concurrentes
.await;
Evaluación de directorio
Evalúa todos los archivos de prueba en un directorio:
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
);
}
Integración con cargo test
Usa la evaluación en pruebas estándar de 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());
}
Ejemplos
# Evaluación básica
cargo run --example eval_basic
# Validación de trayectoria
cargo run --example eval_trajectory
# Coincidencia semántica juzgada por LLM
cargo run --example eval_semantic
# Puntuación basada en rúbricas
cargo run --example eval_rubric
# Algoritmos de similitud de respuesta
cargo run --example eval_similarity
# Generación de informes
cargo run --example eval_report
Mejores prácticas
- Empieza simple: Comienza con la validación de trayectoria antes de añadir comprobaciones semánticas
- Usa casos representativos: Los archivos de prueba deben cubrir casos extremos y escenarios comunes
- Calibra los umbrales: Comienza con umbrales permisivos y ajústalos a medida que el Agent mejore
- Combina criterios: Usa múltiples criterios para una evaluación completa
- Versiona los archivos de prueba: Mantén los archivos de prueba en control de versiones junto con el código del Agent
- Integración CI/CD: Ejecuta evaluaciones en CI para detectar regresiones
Anterior: ← A2A Protocol | Siguiente: Access Control →