feat(reports): add overall scores to strategy cards and average row in technical report
Why: - Users need to see each strategy's overall score at a glance in the report - Technical report should show average metrics across all strategies Changes: - Each strategy card now shows its overall score below the metric bars - Technical report aggregate table includes an AVERAGE row across all strategies Impact: - Managerial report: strategy cards now show overall score - Technical report: aggregate table has a new AVERAGE row at the bottom
This commit is contained in:
@@ -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("Similarity", m.get("avg_answer_similarity", 0), "accent")}
|
||||||
{_metric_bar("Faithfulness", m.get("avg_faithfulness", 0), "violet")}
|
{_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")}
|
{_metric_bar("No Hallucination", (1 - m.get("hallucination_rate", 0)) * 10, "teal" if m.get("hallucination_rate", 0) <= 0.1 else "rose")}
|
||||||
|
<div style="margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--border); font-family: {FONT_DATA}; font-size: 13px; color: var(--text-muted);">
|
||||||
|
Overall: <span style="color: var(--accent); font-weight: 600;">{overall:.2f}</span>
|
||||||
|
</div>
|
||||||
</div>"""
|
</div>"""
|
||||||
|
|
||||||
return cards
|
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:
|
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 = ""
|
rows = ""
|
||||||
for rank, (strategy, overall) in enumerate(rankings, 1):
|
for rank, (strategy, overall) in enumerate(rankings, 1):
|
||||||
m = aggregate.get(strategy, {})
|
m = aggregate.get(strategy, {})
|
||||||
@@ -705,6 +708,28 @@ def _build_technical_aggregate_rows(rankings: list, aggregate: dict) -> str:
|
|||||||
<td>{m.get('failed_questions', 0)}</td>
|
<td>{m.get('failed_questions', 0)}</td>
|
||||||
<td><strong style="font-family: {FONT_DATA};">{overall:.2f}</strong></td>
|
<td><strong style="font-family: {FONT_DATA};">{overall:.2f}</strong></td>
|
||||||
</tr>"""
|
</tr>"""
|
||||||
|
|
||||||
|
# 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"""
|
||||||
|
<tr style="background: var(--surface); border-top: 2px solid var(--border);">
|
||||||
|
<td><strong style="color: var(--accent);">AVERAGE</strong></td>
|
||||||
|
<td>{_pill(avg_ctx)}</td>
|
||||||
|
<td>{_pill(avg_sim)}</td>
|
||||||
|
<td>{_pill(avg_faith)}</td>
|
||||||
|
<td>{_hall_pill(avg_hall)}</td>
|
||||||
|
<td>{avg_total:.0f}</td>
|
||||||
|
<td>{avg_failed:.0f}</td>
|
||||||
|
<td><strong style="font-family: {FONT_DATA}; color: var(--accent);">{avg_overall:.2f}</strong></td>
|
||||||
|
</tr>"""
|
||||||
return rows
|
return rows
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user