use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EvalResult {
pub relevance: f64,
pub coherence: f64,
pub groundedness: f64,
pub harmfulness: f64,
pub details: HashMap<String, f64>,
pub overall: f64,
}
impl EvalResult {
pub fn new(relevance: f64, coherence: f64, groundedness: f64, harmfulness: f64) -> Self {
let overall = Self::compute_overall(relevance, coherence, groundedness, harmfulness);
Self {
relevance: relevance.clamp(0.0, 1.0),
coherence: coherence.clamp(0.0, 1.0),
groundedness: groundedness.clamp(0.0, 1.0),
harmfulness: harmfulness.clamp(0.0, 1.0),
details: HashMap::new(),
overall,
}
}
pub fn with_detail(mut self, name: &str, score: f64) -> Self {
self.details.insert(name.to_string(), score.clamp(0.0, 1.0));
self
}
fn compute_overall(relevance: f64, coherence: f64, groundedness: f64, harmfulness: f64) -> f64 {
let weights = [0.3, 0.2, 0.3, 0.2]; let scores = [
relevance,
coherence,
groundedness,
1.0 - harmfulness, ];
let weighted_sum: f64 = weights.iter().zip(scores.iter()).map(|(w, s)| w * s).sum();
weighted_sum.clamp(0.0, 1.0)
}
pub fn passes_threshold(&self, min_overall: f64, max_harmfulness: f64) -> bool {
self.overall >= min_overall && self.harmfulness <= max_harmfulness
}
}
impl Default for EvalResult {
fn default() -> Self {
Self::new(0.0, 0.0, 0.0, 0.0)
}
}