Skip to main content

remem/eval/local/
display.rs

1use crate::eval::local::types::EvalReport;
2
3const MAX_GOOD_TITLE_LEN: usize = 120;
4
5impl std::fmt::Display for EvalReport {
6    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
7        writeln!(
8            f,
9            "=== remem eval-local ({} memories) ===\n",
10            self.total_memories
11        )?;
12        writeln!(
13            f,
14            "[dedup] {} duplicates in {} groups ({:.1}%)",
15            self.dedup.duplicate_count,
16            self.dedup.duplicate_groups,
17            self.dedup.duplicate_rate * 100.0
18        )?;
19        if !self.dedup.worst_groups.is_empty() {
20            writeln!(f, "  worst:")?;
21            for (preview, count) in &self.dedup.worst_groups {
22                writeln!(f, "    {}x  {}", count, preview)?;
23            }
24        }
25
26        writeln!(
27            f,
28            "\n[project_filter] tested {} entities, {} true leaks / {} hits ({:.1}%)",
29            self.project_leak.total_tested,
30            self.project_leak.leaked,
31            self.project_leak.total_hits,
32            self.project_leak.leak_rate * 100.0
33        )?;
34        writeln!(
35            f,
36            "  hits: {} project-local, {} global-overlay",
37            self.project_leak.project_hits, self.project_leak.global_overlay_hits
38        )?;
39        writeln!(
40            f,
41            "\n[title_quality] {:.1}% start with bullet, {:.1}% too long (>{} chars)",
42            self.title_quality.bullet_rate * 100.0,
43            title_too_long_rate(self),
44            MAX_GOOD_TITLE_LEN
45        )?;
46        writeln!(
47            f,
48            "\n[self_retrieval] {}/{} ({:.1}%)",
49            self.self_retrieval.found,
50            self.self_retrieval.total_tested,
51            self.self_retrieval.retrieval_rate * 100.0
52        )?;
53        writeln!(f, "\n--- overall: {:.1}/5.0 ---", self.overall_score())?;
54        Ok(())
55    }
56}
57
58impl EvalReport {
59    pub fn overall_score(&self) -> f64 {
60        let dedup_score = (1.0 - self.dedup.duplicate_rate).max(0.0) * 5.0;
61        let leak_score = (1.0 - self.project_leak.leak_rate).max(0.0) * 5.0;
62        let title_score = (1.0 - self.title_quality.bullet_rate).max(0.0) * 5.0;
63        let retrieval_score = self.self_retrieval.retrieval_rate * 5.0;
64
65        dedup_score * 0.30 + leak_score * 0.25 + title_score * 0.15 + retrieval_score * 0.30
66    }
67}
68
69fn title_too_long_rate(report: &EvalReport) -> f64 {
70    if report.title_quality.total > 0 {
71        report.title_quality.too_long as f64 / report.title_quality.total as f64 * 100.0
72    } else {
73        0.0
74    }
75}