diff --git a/src/benchmarking/report.py b/src/benchmarking/report.py
index 53b5ba4..83985e0 100644
--- a/src/benchmarking/report.py
+++ b/src/benchmarking/report.py
@@ -633,6 +633,9 @@ def _build_strategy_cards(rankings: list, aggregate: dict) -> str:
{_metric_bar("Similarity", m.get("avg_answer_similarity", 0), "accent")}
{_metric_bar("Faithfulness", m.get("avg_faithfulness", 0), "violet")}
{_metric_bar("No Hallucination", (1 - m.get("hallucination_rate", 0)) * 10, "teal" if m.get("hallucination_rate", 0) <= 0.1 else "rose")}
+
+ Overall: {overall:.2f}
+
"""
return cards
@@ -690,7 +693,7 @@ def _generate_decision_insights(rankings: list, aggregate: dict) -> str:
def _build_technical_aggregate_rows(rankings: list, aggregate: dict) -> str:
- """Build technical aggregate table rows."""
+ """Build technical aggregate table rows with an average row at the end."""
rows = ""
for rank, (strategy, overall) in enumerate(rankings, 1):
m = aggregate.get(strategy, {})
@@ -705,6 +708,28 @@ def _build_technical_aggregate_rows(rankings: list, aggregate: dict) -> str:
{m.get('failed_questions', 0)} |
{overall:.2f} |
"""
+
+ # Average row across all strategies
+ n = len(rankings)
+ if n > 0:
+ avg_ctx = sum(aggregate.get(s, {}).get('avg_context_relevance', 0) for s, _ in rankings) / n
+ avg_sim = sum(aggregate.get(s, {}).get('avg_answer_similarity', 0) for s, _ in rankings) / n
+ avg_faith = sum(aggregate.get(s, {}).get('avg_faithfulness', 0) for s, _ in rankings) / n
+ avg_hall = sum(aggregate.get(s, {}).get('hallucination_rate', 0) for s, _ in rankings) / n
+ avg_total = sum(aggregate.get(s, {}).get('total_questions', 0) for s, _ in rankings) / n
+ avg_failed = sum(aggregate.get(s, {}).get('failed_questions', 0) for s, _ in rankings) / n
+ avg_overall = sum(overall for _, overall in rankings) / n
+ rows += f"""
+
+ | AVERAGE |
+ {_pill(avg_ctx)} |
+ {_pill(avg_sim)} |
+ {_pill(avg_faith)} |
+ {_hall_pill(avg_hall)} |
+ {avg_total:.0f} |
+ {avg_failed:.0f} |
+ {avg_overall:.2f} |
+
"""
return rows