use std::sync::Arc;
use crate::types::{EvalCase, EvalMetricResult, Invocation};
pub trait Evaluator: Send + Sync {
fn name(&self) -> &'static str;
fn evaluate(&self, case: &EvalCase, invocation: &Invocation) -> Option<EvalMetricResult>;
}
impl<F> Evaluator for (&'static str, F)
where
F: Fn(&EvalCase, &Invocation) -> Option<EvalMetricResult> + Send + Sync,
{
fn name(&self) -> &'static str {
self.0
}
fn evaluate(&self, case: &EvalCase, invocation: &Invocation) -> Option<EvalMetricResult> {
(self.1)(case, invocation)
}
}
pub struct EvaluatorRegistry {
evaluators: Vec<Arc<dyn Evaluator>>,
}
impl EvaluatorRegistry {
#[must_use]
pub fn new() -> Self {
Self {
evaluators: Vec::new(),
}
}
#[must_use]
pub fn with_defaults() -> Self {
let mut registry = Self::new();
registry.register(crate::match_::TrajectoryMatcher::in_order());
registry.register(crate::budget::BudgetEvaluator);
registry.register(crate::response::ResponseMatcher);
registry.register(crate::efficiency::EfficiencyEvaluator::new());
registry
}
pub fn register(&mut self, evaluator: impl Evaluator + 'static) {
self.evaluators.push(Arc::new(evaluator));
}
#[must_use]
pub fn evaluate(&self, case: &EvalCase, invocation: &Invocation) -> Vec<EvalMetricResult> {
let filter = &case.evaluators;
self.evaluators
.iter()
.filter(|e| filter.is_empty() || filter.iter().any(|name| name == e.name()))
.filter_map(|e| e.evaluate(case, invocation))
.collect()
}
}
impl Default for EvaluatorRegistry {
fn default() -> Self {
Self::new()
}
}