Spaces:
Running on Zero
Running on Zero
| """ | |
| report.py — Leaderboards + the no-finetune labeler verdict. | |
| Aggregates per-(model, reasoning, category, mode) metrics into: | |
| * a QUALITY leaderboard ranked by labeler_score (native json_mode columns), | |
| * a FLEET leaderboard folding throughput, and | |
| * a verdict naming the best NO-FINETUNE model — or, if none is natively | |
| sufficient, the best finetune-candidate to feed the SFT/LoRA pipeline. | |
| Native columns use json_mode (no grammar crutch) because that is the signal for | |
| whether a model emits robust JSON on its own. | |
| """ | |
| from __future__ import annotations | |
| import json | |
| from pathlib import Path | |
| from typing import Optional | |
| from .metrics import labeler_score | |
| from .throughput import fleet_score | |
| # Bucketing thresholds (config-surfaceable later). | |
| ACC_FLOOR = 0.55 # below this the vision itself is too weak | |
| NATIVE_ROBUST = 0.90 # native json_mode robustness to count as "ships as-is" | |
| def _bucket(accuracy: Optional[float], native_robust: float) -> str: | |
| if accuracy is None: | |
| return "no_task_gt" | |
| if accuracy < ACC_FLOOR: | |
| return "insufficient" | |
| if native_robust >= NATIVE_ROBUST: | |
| return "native_capable" | |
| return "finetune_candidate" | |
| def _mean(xs): | |
| xs = [x for x in xs if x is not None] | |
| return sum(xs) / len(xs) if xs else None | |
| def summarize(metric_rows: list[dict]) -> list[dict]: | |
| """Collapse per-category metric rows into one summary per (model, reasoning). | |
| Native (json_mode) columns drive the no-finetune decision; the constrained | |
| rows are kept only to compute the native-vs-constrained validity gap. | |
| """ | |
| by_model: dict[tuple[str, str], dict] = {} | |
| for r in metric_rows: | |
| key = (r["model"], r["reasoning"]) | |
| by_model.setdefault(key, {"json_mode": [], "constrained": []}) | |
| bucket = r["mode"] if r["mode"] in ("json_mode", "constrained") else "json_mode" | |
| by_model[key][bucket].append(r) | |
| summaries = [] | |
| for (model, reasoning), modes in by_model.items(): | |
| jm = modes["json_mode"] or modes["constrained"] | |
| acc = _mean([r["primary_score_mean"] for r in jm if r["has_task_score"]]) | |
| valid = _mean([r["schema_valid_rate"] for r in jm]) or 0.0 | |
| robust = _mean([r["json_robustness"] for r in jm]) or 0.0 | |
| constrained_valid = _mean([r["schema_valid_rate"] for r in modes["constrained"]]) | |
| gap = (constrained_valid - valid) if constrained_valid is not None else None | |
| tok_s = _mean([r["tokens_per_sec"] for r in jm]) or 0.0 | |
| mean_out = _mean([r["mean_output_tokens"] for r in jm]) or 0.0 | |
| lab = labeler_score(acc, valid, robust) | |
| # samples/hour from tok/s + mean output tokens (prefill folded in elsewhere) | |
| sph = (3600.0 * tok_s / mean_out) if (tok_s > 0 and mean_out > 0) else 0.0 | |
| summaries.append({ | |
| "model": model, "reasoning": reasoning, | |
| "accuracy": acc, "native_valid": valid, "native_robust": robust, | |
| "constrained_valid": constrained_valid, "native_gap": gap, | |
| "labeler_score": lab, "tokens_per_sec": tok_s, "samples_per_hour": sph, | |
| "fleet_score": fleet_score(lab, sph) if lab is not None else None, | |
| "bucket": _bucket(acc, robust), | |
| }) | |
| summaries.sort(key=lambda s: (s["labeler_score"] is not None, s["labeler_score"] or -1), reverse=True) | |
| return summaries | |
| def _fmt(x, pct=False): | |
| if x is None: | |
| return "n/a" | |
| return f"{x:.1%}" if pct else f"{x:.3f}" | |
| def quality_table(summaries: list[dict]) -> str: | |
| lines = [ | |
| "| rank | model | reason | acc | native_valid | native_robust | gap | labeler | tok/s | bucket |", | |
| "|------|-------|--------|-----|--------------|---------------|-----|---------|-------|--------|", | |
| ] | |
| for i, s in enumerate(summaries, 1): | |
| lines.append( | |
| f"| {i} | {s['model']} | {s['reasoning']} | {_fmt(s['accuracy'])} | " | |
| f"{_fmt(s['native_valid'], True)} | {_fmt(s['native_robust'], True)} | " | |
| f"{_fmt(s['native_gap'], True)} | {_fmt(s['labeler_score'])} | " | |
| f"{s['tokens_per_sec']:.0f} | {s['bucket']} |" | |
| ) | |
| return "\n".join(lines) | |
| def fleet_table(summaries: list[dict]) -> str: | |
| fs = sorted([s for s in summaries if s["fleet_score"] is not None], | |
| key=lambda s: s["fleet_score"], reverse=True) | |
| lines = [ | |
| "| rank | model | reason | labeler | samples/hr | fleet |", | |
| "|------|-------|--------|---------|------------|-------|", | |
| ] | |
| for i, s in enumerate(fs, 1): | |
| lines.append( | |
| f"| {i} | {s['model']} | {s['reasoning']} | {_fmt(s['labeler_score'])} | " | |
| f"{s['samples_per_hour']:.0f} | {_fmt(s['fleet_score'])} |" | |
| ) | |
| return "\n".join(lines) | |
| def verdict(summaries: list[dict]) -> str: | |
| native = [s for s in summaries if s["bucket"] == "native_capable"] | |
| ft = [s for s in summaries if s["bucket"] == "finetune_candidate"] | |
| out = ["## Headline recommendation", ""] | |
| if native: | |
| b = native[0] | |
| out.append( | |
| f"> **Best no-finetune labeler:** `{b['model']}` ({b['reasoning']}) — " | |
| f"{_fmt(b['native_valid'], True)} native-valid, {_fmt(b['accuracy'])} accuracy, " | |
| f"{b['tokens_per_sec']:.0f} tok/s. Ships as-is." | |
| ) | |
| elif ft: | |
| b = ft[0] | |
| out.append( | |
| f"> **No natively-sufficient model.** Best **finetune-candidate:** `{b['model']}` " | |
| f"({b['reasoning']}) — robust vision ({_fmt(b['accuracy'])} acc) but native JSON gap = " | |
| f"{_fmt(b['native_gap'], True)}. Close it with the existing data-gen → SFT/LoRA pipeline." | |
| ) | |
| else: | |
| out.append("> No model cleared the accuracy floor on this run. Re-check inputs / categories.") | |
| fleet = sorted([s for s in summaries if s["fleet_score"] is not None], | |
| key=lambda s: s["fleet_score"], reverse=True) | |
| if fleet: | |
| f = fleet[0] | |
| out.append("") | |
| out.append( | |
| f"> **Best fleet labeler (1M+ images):** `{f['model']}` ({f['reasoning']}) — " | |
| f"{f['samples_per_hour']:.0f} samples/hr at labeler {_fmt(f['labeler_score'])}." | |
| ) | |
| return "\n".join(out) | |
| def write_reports(run_dir: Path, metric_rows: list[dict], config: dict) -> dict: | |
| summaries = summarize(metric_rows) | |
| md = [ | |
| f"# Qwen VLM Labeler Selection — {run_dir.name}", | |
| "", | |
| f"models={config.get('models')} categories={len(config.get('categories', []))} " | |
| f"reasoning={config.get('reasonings')} modes={config.get('modes')} " | |
| f"n={config.get('n')} dataset={config.get('dataset')} runner={config.get('runner')}", | |
| "", | |
| "## Quality leaderboard (labeler_score, native json_mode)", | |
| "", | |
| quality_table(summaries), | |
| "", | |
| "## Fleet leaderboard (accuracy × throughput)", | |
| "", | |
| fleet_table(summaries), | |
| "", | |
| verdict(summaries), | |
| "", | |
| ] | |
| (run_dir / "leaderboard.md").write_text("\n".join(md), encoding="utf-8") | |
| (run_dir / "summary.json").write_text( | |
| json.dumps({"config": config, "summaries": summaries}, indent=2), encoding="utf-8") | |
| # CSV | |
| cols = ["model", "reasoning", "accuracy", "native_valid", "native_robust", "native_gap", | |
| "labeler_score", "tokens_per_sec", "samples_per_hour", "fleet_score", "bucket"] | |
| csv_lines = [",".join(cols)] | |
| for s in summaries: | |
| csv_lines.append(",".join("" if s.get(c) is None else str(s.get(c)) for c in cols)) | |
| (run_dir / "leaderboard.csv").write_text("\n".join(csv_lines), encoding="utf-8") | |
| return {"summaries": summaries} | |