Fastwhisper / app /evidence.py
Mbonea's picture
Deploy Habit Journal backend S0-S10 to Hugging Face Space.
990895d
Raw
History Blame Contribute Delete
4.17 kB
"""Build coach evidence blocks and SERVER_PICKS from server math.
Formats precomputed probabilities for prompts; never invents numbers.
"""
from __future__ import annotations
from typing import Any
from app.stats_math import (
FORMULAS,
by_emotion,
by_remedy,
by_tag,
daily_rates,
data_thin,
scored_entries,
server_picks,
)
def strip_sensitive(text: str) -> str:
"""Best-effort strip of emails and long digit runs from prompt text."""
import re
cleaned = re.sub(
r"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b",
"[email]",
text,
)
cleaned = re.sub(r"\b\d{8,}\b", "[digits]", cleaned)
return cleaned
def format_evidence_block(
entries: list[dict[str, Any]],
daily_rows: list[dict[str, Any]],
*,
min_n: int,
shrink_k: float,
) -> str:
"""Render the EVIDENCE markdown block for coach prompts."""
scored = scored_entries(entries)
remedies = by_remedy(entries, min_n=min_n, shrink_k=shrink_k)
tags = by_tag(entries)[:8]
emotions = by_emotion(entries)[:8]
rates = daily_rates(daily_rows)
lines = [
"EVIDENCE (server-computed; do not invent numbers)",
f"n_scored: {len(scored)}",
f"min_n: {min_n}",
"TOP_REMEDIES: remedy | n | p_worked | p_helped | rank",
]
if remedies:
for row in remedies[:10]:
lines.append(
f"- {row['key']} | {row['n']} | {row['p_worked']:.3f} | "
f"{row['p_helped']:.3f} | {row['rank']:.3f}"
)
else:
lines.append("- (none above min_n)")
lines.append("WORST_TAGS: tag | n | p_fail")
if tags:
for row in tags:
lines.append(f"- {row['key']} | {row['n']} | {row['p_failed']:.3f}")
else:
lines.append("- (none)")
lines.append("EMOTION_HITS: emotion | n | p_helped")
if emotions:
for row in emotions:
lines.append(f"- {row['key']} | {row['n']} | {row['p_helped']:.3f}")
else:
lines.append("- (none)")
lines.append(
"DAILY_RATES: "
f"p_brick_done={rates['p_brick_done']:.3f} "
f"p_corn_ok={rates['p_corn_ok']:.3f} "
f"p_no_fc={rates['p_no_fc']:.3f} "
f"p_rerun_clean={rates['p_rerun_clean']:.3f} "
f"p_court_closed={rates['p_court_closed']:.3f} "
f"avg_points={rates['avg_points']:.3f}"
)
lines.append(
"FORMULAS: "
f"p_helped={FORMULAS['p_helped']}; rank={FORMULAS['rank']}"
)
lines.append(f"DATA_THIN: {str(data_thin(len(scored))).lower()}")
return "\n".join(lines)
def format_server_picks(picks: list[dict[str, Any]]) -> str:
"""Render numbered SERVER_PICKS lines for prompts and debug paste."""
if not picks:
return "SERVER_PICKS: (none)"
lines = ["SERVER_PICKS:"]
for index, pick in enumerate(picks, start=1):
lines.append(
f"{index}) {pick['remedy_key']} pick={pick['pick']:.3f} "
f"n={pick['n']} p_helped={pick['p_helped']:.3f}"
)
return "\n".join(lines)
def build_evidence(
entries: list[dict[str, Any]],
daily_rows: list[dict[str, Any]],
current_tags: list[str],
*,
min_n: int,
shrink_k: float,
match_alpha: float,
) -> dict[str, Any]:
"""Return structured evidence plus formatted blocks and picks."""
scored = scored_entries(entries)
picks = server_picks(
entries,
current_tags,
min_n=min_n,
shrink_k=shrink_k,
match_alpha=match_alpha,
)
block = format_evidence_block(
entries,
daily_rows,
min_n=min_n,
shrink_k=shrink_k,
)
picks_text = format_server_picks(picks)
return {
"n_scored": len(scored),
"min_n": min_n,
"DATA_THIN": data_thin(len(scored)),
"by_remedy": by_remedy(entries, min_n=min_n, shrink_k=shrink_k),
"by_tag": by_tag(entries),
"by_emotion": by_emotion(entries),
"daily": daily_rates(daily_rows),
"server_picks": picks,
"evidence_block": block,
"server_picks_text": picks_text,
"formulas": FORMULAS,
}