"""Helpers used by the CLI — storyboard rendering and hit-rate reporting.""" from __future__ import annotations from typing import Any def export_storyboard_markdown(seeds: list[dict[str, Any]]) -> str: lines: list[str] = ["# AETHER-Ad Genesis — Storyboards\n"] for i, s in enumerate(seeds, 1): seed = s.get("seed", s) score = s.get("score", {}) lines.append(f"## #{i} — `{seed['seed_id']}` (final={score.get('final', 0):.3f})\n") lines.append(f"- **product**: {seed['product_id']}") lines.append(f"- **tension**: {seed['tension_id']}") lines.append(f"- **rules**: {', '.join(seed.get('rules_applied', []))}") lines.append(f"- **persona**: {seed.get('persona_summary', '')}") lines.append(f"- **duration**: {seed.get('duration', 15)}s\n") lines.append(f"**Concept.** {seed.get('concept', '')}\n") lines.append("| t (s) | beat | purpose | content |") lines.append("|---|---|---|---|") for b in seed.get("beats", []): tr = b.get("time_range", [0, 0]) lines.append( f"| {tr[0]}–{tr[1]} | {b.get('beat', '')} | {b.get('purpose', '')} | " f"{(b.get('content') or '').replace('|', '/')} |" ) if score: lines.append("") lines.append( f"**Scores.** novelty={score.get('novelty', 0):.2f} · " f"utility={score.get('utility', 0):.2f} · " f"affect={score.get('affect', 0):.2f} · " f"humor/pathos={score.get('humor_or_pathos', 0):.2f} · " f"surprise={score.get('surprise', 0):.2f} · " f"risk={score.get('risk', 0):.2f}" ) lines.append("\n---\n") return "\n".join(lines) def hit_rate_report(seeds: list[dict[str, Any]], threshold: float = 0.5) -> str: total = len(seeds) if total == 0: return "# Hit-rate report\n\nNo seeds." finals = [s.get("score", {}).get("final", 0.0) for s in seeds] hits = sum(1 for f in finals if f >= threshold) avg = sum(finals) / total top = max(finals) lines = [ "# Hit-rate Report\n", f"- **n_seeds**: {total}", f"- **threshold**: {threshold}", f"- **hits**: {hits} ({hits / total:.1%})", f"- **avg final**: {avg:.3f}", f"- **top final**: {top:.3f}", "", "## Per-seed scores", "", "| seed_id | final | rules |", "|---|---|---|", ] for s in seeds: seed = s.get("seed", s) score = s.get("score", {}) lines.append( f"| {seed.get('seed_id', '?')} | {score.get('final', 0):.3f} | " f"{','.join(seed.get('rules_applied', []))} |" ) return "\n".join(lines)