use std::fmt::{Display, Formatter, Result as FmtResult};
use super::types::{GoldenEvalReport, MetricAverages};
impl Display for GoldenEvalReport {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
writeln!(
f,
"remem eval — deterministic retrieval layer, {} queries, k={}, rank_k={}",
self.total_queries, self.k, self.rank_k
)?;
if let Some(version) = self.version.as_deref() {
writeln!(f, "schema: {version}")?;
}
if let Some(description) = self.description.as_deref() {
writeln!(f, "{description}")?;
}
writeln!(f)?;
writeln!(f, "--- Evaluation Layers ---")?;
writeln!(
f,
" retrieval: {}",
self.evaluation_layers.retrieval.status
)?;
writeln!(
f,
" answer_generation: {}",
self.evaluation_layers.answer_generation.status
)?;
writeln!(
f,
" llm_judge: {}",
self.evaluation_layers.llm_judge.status
)?;
writeln!(f)?;
for query in &self.queries {
if let Some(metrics) = query.metrics.as_ref() {
writeln!(
f,
" [{}] {:>4} | H@{}={:.2} MRR@10={:.2} P@{}={:.2} R@{}={:.2} nDCG@10={:.2} evidence@{}={:.2} | slice={} category={} | {}",
query.id,
query.status.label(),
self.k,
metrics.hit_at_k,
metrics.mrr_at_10,
self.k,
metrics.precision_at_k,
self.k,
metrics.recall_at_k,
metrics.ndcg_at_10,
self.k,
metrics.evidence_recall_at_k,
query.slice,
query.category,
query.query
)?;
write_failure_details(
f,
query.status,
&query.retrieved_ids,
&query.expected_relevant_ids,
&query.missing_relevant_ids,
query.missing_evidence_refs.len(),
)?;
} else {
writeln!(
f,
" [{}] {:>4} | results={} expected_refs={} matched_refs={} | slice={} category={} | {}",
query.id,
query.status.label(),
query.result_count,
query.expected_refs,
query.matched_refs,
query.slice,
query.category,
query.query
)?;
write_failure_details(
f,
query.status,
&query.retrieved_ids,
&query.expected_relevant_ids,
&query.missing_relevant_ids,
query.missing_evidence_refs.len(),
)?;
}
}
writeln!(f)?;
writeln!(
f,
"--- Retrieval Overall ({} scored, {} abstention, {} skipped) ---",
self.scored_queries, self.abstention_queries, self.skipped_queries
)?;
if let Some(metrics) = self.overall.as_ref() {
write_metrics(f, "all", metrics, self.k)?;
}
if self.abstention_queries > 0 {
writeln!(
f,
" Abstention: {}/{}",
self.abstention_passed, self.abstention_queries
)?;
}
writeln!(f)?;
writeln!(f, "--- Answer/Judge Layer ---")?;
writeln!(f, " not run in deterministic golden retrieval eval")?;
if !self.by_slice.is_empty() {
writeln!(f)?;
writeln!(f, "--- By Slice ---")?;
for (slice, evaluation) in &self.by_slice {
if let Some(metrics) = evaluation.metrics.as_ref() {
write_metrics(f, slice, metrics, self.k)?;
write_observability(f, slice, evaluation)?;
} else {
writeln!(
f,
" {}: scored=0 abstention={}/{} total={}",
slice,
evaluation.abstention_passed,
evaluation.abstention_queries,
evaluation.total_queries
)?;
write_observability(f, slice, evaluation)?;
}
}
}
if !self.by_category.is_empty() {
writeln!(f)?;
writeln!(f, "--- By Category ---")?;
for (category, evaluation) in &self.by_category {
if let Some(metrics) = evaluation.metrics.as_ref() {
write_metrics(f, category, metrics, self.k)?;
write_observability(f, category, evaluation)?;
} else {
writeln!(
f,
" {}: scored=0 abstention={}/{} total={}",
category,
evaluation.abstention_passed,
evaluation.abstention_queries,
evaluation.total_queries
)?;
write_observability(f, category, evaluation)?;
}
}
}
Ok(())
}
}
fn write_failure_details(
f: &mut Formatter<'_>,
status: super::types::QueryStatus,
retrieved_ids: &[i64],
expected_relevant_ids: &[i64],
missing_relevant_ids: &[i64],
missing_evidence_ref_count: usize,
) -> FmtResult {
if !matches!(
status,
super::types::QueryStatus::Miss | super::types::QueryStatus::Fail
) {
return Ok(());
}
writeln!(
f,
" retrieved_ids={:?} expected_relevant_ids={:?} missing_relevant_ids={:?} missing_evidence_refs={}",
retrieved_ids, expected_relevant_ids, missing_relevant_ids, missing_evidence_ref_count
)
}
fn write_metrics(
f: &mut Formatter<'_>,
label: &str,
metrics: &MetricAverages,
k: usize,
) -> FmtResult {
writeln!(
f,
" {}: n={} H@{}={:.3} MRR@10={:.3} P@{}={:.3} R@{}={:.3} nDCG@10={:.3} evidence@{}={:.3}",
label,
metrics.count,
k,
metrics.hit_at_k,
metrics.mrr_at_10,
k,
metrics.precision_at_k,
k,
metrics.recall_at_k,
metrics.ndcg_at_10,
k,
metrics.evidence_recall_at_k
)?;
Ok(())
}
fn write_observability(
f: &mut Formatter<'_>,
label: &str,
evaluation: &super::types::CategoryEvaluation,
) -> FmtResult {
writeln!(
f,
" observability {}: tokens/query={:.1} p50={:.2}ms p95={:.2}ms",
label,
evaluation.query_tokens_per_query,
evaluation.retrieval_latency_p50_ms,
evaluation.retrieval_latency_p95_ms
)
}