Spaces:
Paused
Paused
| """Gộp latency + COMET -> bảng markdown cho báo cáo (§10). | |
| python -m benchmark.translation.aggregate --out-dir benchmark/translation/out | |
| Đọc: latency.jsonl, comet_scores.json | |
| Ghi: benchmark/translation/out/report.md | |
| """ | |
| from __future__ import annotations | |
| import argparse | |
| import json | |
| import statistics as stats | |
| from collections import defaultdict | |
| from pathlib import Path | |
| def _pct(xs, p): | |
| if not xs: | |
| return 0.0 | |
| s = sorted(xs) | |
| k = (len(s) - 1) * p / 100 | |
| lo, hi = int(k), min(int(k) + 1, len(s) - 1) | |
| return s[lo] + (s[hi] - s[lo]) * (k - lo) | |
| def load_latency(path: Path): | |
| """Return per-system aggregate over latency-measure records.""" | |
| recs = defaultdict(list) | |
| if not path.exists(): | |
| return {} | |
| for line in open(path, encoding="utf-8"): | |
| if not line.strip(): | |
| continue | |
| r = json.loads(line) | |
| if r.get("mode") == "latency-measure": | |
| recs[r["system"]].append(r) | |
| agg = {} | |
| for sys_, rs in recs.items(): | |
| walls = [r["wall_s"] for r in rs] | |
| total_w = sum(walls) | |
| tok_out = sum(r.get("tok_out", 0) or 0 for r in rs) | |
| src_words = sum(r.get("src_words", 0) or 0 for r in rs) | |
| # s / 1000 source words — chuẩn hoá latency theo độ dài, so được doc dài/ngắn. | |
| s_per_kword = [1000 * r["wall_s"] / r["src_words"] | |
| for r in rs if r.get("src_words")] | |
| # Tỉ lệ giãn ký tự dst/src (ràng buộc ±15% là theo ký tự) — theo từng doc. | |
| char_ratio = [r["dst_chars"] / r["src_chars"] | |
| for r in rs if r.get("src_chars") and r.get("dst_chars")] | |
| agg[sys_] = { | |
| "s_per_doc_median": round(stats.median(walls), 2), | |
| "s_per_doc_p25": round(_pct(walls, 25), 2), | |
| "s_per_doc_p95": round(_pct(walls, 95), 2), | |
| "src_words_per_s": round(src_words / total_w, 2) if total_w else 0, | |
| "s_per_kword_median": round(stats.median(s_per_kword), 2) if s_per_kword else 0, | |
| "char_ratio_median": round(stats.median(char_ratio), 3) if char_ratio else 0, | |
| "out_tok_per_s": round(tok_out / total_w, 1) if total_w else 0, | |
| "retries": sum(r.get("n_retry", 0) or 0 for r in rs), | |
| "n": len(rs), | |
| } | |
| return agg | |
| def md_table(headers, rows) -> str: | |
| out = ["| " + " | ".join(headers) + " |", | |
| "|" + "|".join("---" for _ in headers) + "|"] | |
| for row in rows: | |
| out.append("| " + " | ".join(str(c) for c in row) + " |") | |
| return "\n".join(out) | |
| def main() -> None: | |
| ap = argparse.ArgumentParser() | |
| ap.add_argument("--out-dir", default="benchmark/translation/out") | |
| args = ap.parse_args() | |
| d = Path(args.out_dir) | |
| comet = json.loads((d / "comet_scores.json").read_text()) if (d / "comet_scores.json").exists() else {} | |
| lat = load_latency(d / "latency.jsonl") | |
| md = ["# Kết quả đánh giá — bảng tổng hợp\n"] | |
| # (A) per-language COMET × system | |
| langs = sorted({lang for rel in comet.values() for lang in rel.get("by_language", {})}) | |
| if langs: | |
| systems = list(comet) | |
| md.append("## (A) COMET-DA theo ngôn ngữ × hệ\n") | |
| headers = ["Target"] + systems | |
| rows = [] | |
| for lang in langs: | |
| row = [lang] | |
| for s in systems: | |
| m = comet[s]["by_language"].get(lang, {}).get("comet", {}) | |
| row.append(m.get("mean", "—")) | |
| rows.append(row) | |
| md.append(md_table(headers, rows) + "\n") | |
| # (B) system × quality × latency × cost | |
| md.append("## (B) So sánh hệ — quality × latency\n") | |
| headers = ["System", "COMET-DA", "chrF++", "s/doc (median)", "p25–p95", | |
| "s/1k-words", "words/s", "len ratio (dst/src)", "len-viol%", | |
| "out tok/s", "429 retries", "fallback%"] | |
| rows = [] | |
| for s, rel in comet.items(): | |
| o = rel["overall"] | |
| L = lat.get(s, {}) | |
| rows.append([ | |
| s, o["comet"]["mean"], o["chrf"]["mean"], | |
| L.get("s_per_doc_median", "—"), | |
| f'{L.get("s_per_doc_p25","—")}–{L.get("s_per_doc_p95","—")}', | |
| L.get("s_per_kword_median", "—"), | |
| L.get("src_words_per_s", "—"), | |
| L.get("char_ratio_median", "—"), | |
| o.get("len_viol_pct", "—"), | |
| L.get("out_tok_per_s", "—"), L.get("retries", "—"), o["fallback_pct"], | |
| ]) | |
| md.append(md_table(headers, rows) + "\n") | |
| # per-domain | |
| for s, rel in comet.items(): | |
| md.append(f"### per-domain — {s}\n") | |
| rows = [[dom, m["comet"]["mean"], m["comet"]["n"]] for dom, m in rel["by_domain"].items()] | |
| md.append(md_table(["domain", "COMET-DA", "n"], rows) + "\n") | |
| report = "\n".join(md) | |
| d.mkdir(parents=True, exist_ok=True) | |
| (d / "report.md").write_text(report, encoding="utf-8") | |
| print(report) | |
| print(f"\nSaved -> {d/'report.md'}") | |
| if __name__ == "__main__": | |
| main() | |