SPB Git

spb/wp30_uqo

Public
8.1 KB · 96 lines python
1"""CSV -> LaTeX fragments for the paper (booktabs). Numbers are formatted here only; values come from results/tables CSVs."""2from __future__ import annotations3import pandas as pd, numpy as np4from pathlib import Path5from ..util import ROOT6TAB = ROOT / "results/tables"; OUT = ROOT / "paper/tables"78def esc(s):9    return str(s).replace("_", "\\_").replace("%", "\\%").replace("&", "\\&").replace("→", "$\\to$").replace("≥", "$\\ge$").replace("×", "$\\times$").replace("—", "--")1011def df_to_tex(df: pd.DataFrame, path: Path, colfmt: str | None = None, floatfmt="{:.2f}"):12    cols = list(df.columns); colfmt = colfmt or "l" * len(cols)13    lines = ["\\begin{tabular}{@{}" + colfmt + "@{}}", "\\toprule", " & ".join(esc(c) for c in cols) + " \\\\", "\\midrule"]14    for _, r in df.iterrows():15        cells = []16        for c in cols:17            v = r[c]18            if isinstance(v, float):19                cells.append("--" if np.isnan(v) else (floatfmt.format(v) if abs(v) < 1e4 else f"{v:,.0f}"))20            else:21                cells.append(esc(v))22        lines.append(" & ".join(cells) + " \\\\")23    lines += ["\\bottomrule", "\\end{tabular}"]24    OUT.mkdir(parents=True, exist_ok=True); path.write_text("\n".join(lines) + "\n")2526def main():27    t1 = pd.read_csv(TAB / "table1_taxonomy.csv"); df_to_tex(t1, OUT / "table1_taxonomy.tex", "lp{4.2cm}p{2cm}p{2.3cm}p{2.3cm}p{1.6cm}p{2.6cm}")28    t2 = pd.read_csv(TAB / "table2_models.csv")[["alias", "repo", "revision", "layers", "kv_heads", "q_heads", "head_dim", "max_pos", "cache_bytes_per_token_bf16", "prefill_ms_8k", "prefill_ms_16k"]]29    t2.columns = ["alias", "checkpoint", "rev.", "L", "H_kv", "H_q", "d_h", "max pos", "cache B/token", "prefill 8k", "prefill 16k"]; df_to_tex(t2, OUT / "table2_models.tex", "llllllllrrr")30    t3 = pd.read_csv(TAB / "table3_datasets.csv"); df_to_tex(t3, OUT / "table3_datasets.tex", "llrrr", "{:.0f}")31    pr = TAB / "E1_core_primary.csv"32    if pr.exists():33        tp = pd.read_csv(pr)34        tp["pair_s"] = tp["pair"].map({"Qwen2.5-3B-Instruct-bf16->Qwen2.5-3B-Instruct-bf16": "Qwen", "Llama-3.2-3B-Instruct-bf16->Llama-3.2-3B-Instruct-bf16": "Llama"}).fillna(tp["pair"])35        tp["fam_s"] = tp["family"].str.replace("public_", "")36        tp["cell"] = tp.apply(lambda r: f"{100*r.quality:.0f} [{100*r.q_lo:.0f},{100*r.q_hi:.0f}]", axis=1)37        tp["cond_s"] = tp["condition"].str.replace("budget_tokens=512", "512", regex=False).str.replace("keep_frac=0.25", "1/4", regex=False).str.replace("|max_fetch_bytes=2000|max_lookups=6", "", regex=False).str.replace("policy=attention", "att", regex=False).str.replace("codec=zstd", "zstd", regex=False).str.replace("|", " ", regex=False)38        piv = tp.pivot_table(index="cond_s", columns=["fam_s", "pair_s"], values="cell", aggfunc="first")39        piv = piv.reindex(columns=[(f, p) for f in ["synthetic", "exec", "qasper", "2wikimqa"] for p in ["Qwen", "Llama"]])40        piv.columns = [f"{f} {p}" for f, p in piv.columns]41        order = sorted(piv.index, key=lambda c: (c[0], c))42        piv = piv.loc[order].reset_index().rename(columns={"cond_s": "condition"}).fillna("--")43        df_to_tex(piv, OUT / "table_primary.tex", "l" + "r" * (len(piv.columns) - 1))44    hh = TAB / "E4_core_handoffs.csv"45    if hh.exists():46        th = pd.read_csv(hh)47        th["chain_s"] = th["chain"].str.replace("qwen3b-llama3b", "Qwen/Llama alt.", regex=False).str.replace("qwen3b", "Qwen", regex=False).str.replace("|", " ", regex=False)48        th["accuracy_ci"] = th.apply(lambda r: f"{100*r.accuracy:.0f} [{100*r.acc_lo:.0f},{100*r.acc_hi:.0f}]", axis=1)49        th["retention_ci"] = th.apply(lambda r: f"{100*r.retention:.0f} [{100*r.ret_lo:.0f},{100*r.ret_hi:.0f}]", axis=1)50        out = th[["chain_s", "handoffs", "accuracy_ci", "retention_ci", "unsupported_mean", "msg_bytes_mean", "fetched_bytes_mean"]].rename(columns={"chain_s": "chain", "accuracy_ci": "accuracy (\\%)", "retention_ci": "retained facts (\\%)", "unsupported_mean": "unsupported/msg", "msg_bytes_mean": "message B", "fetched_bytes_mean": "fetched B"})51        df_to_tex(out, OUT / "table_handoffs.tex", "llrrrrr", "{:,.2f}")52    ff = TAB / "E5_core_fanin.csv"53    if ff.exists():54        tf = pd.read_csv(ff)55        tf["cell"] = tf.apply(lambda r: f"{100*r.quality:.0f} [{100*r.lo:.0f},{100*r.hi:.0f}]", axis=1)56        tf["method"] = tf["condition"].str.replace("|k=", " k=", regex=False).str.replace("cache_concat_negative_control", "cache concat (neg. control)", regex=False).str.replace("_", " ", regex=False)57        piv = tf.pivot_table(index="method", columns="qtype", values="cell", aggfunc="first").reset_index().fillna("--")58        df_to_tex(piv, OUT / "table_fanin.tex", "l" + "r" * (len(piv.columns) - 1))59    h = TAB / "ED_hosted.csv"60    if h.exists():61        th = pd.read_csv(h)62        th["cond"] = th["condition"].str.replace(r"\|(anthropic|openai)\|", "|", regex=True).str.replace("|budget_tokens=512", " (512)", regex=False).str.replace("|max_fetch_bytes=2000|max_lookups=6", "", regex=False).str.replace("|provider_cache=True", " +cache", regex=False).str.rstrip("|")63        th["model"] = th["provider_model"].str.replace("-20251001", "").str.replace("-2025-08-07", "")64        th["quality_ci"] = th.apply(lambda r: f"{r.quality:.2f} [{r.lo:.2f}, {r.hi:.2f}]", axis=1)65        th["cost_musd"] = (th["cost_usd_mean"] * 1e3).round(2)66        out = th[["model", "cond", "family", "n", "quality_ci", "cost_musd", "ttft_ms_p50", "total_ms_p50"]].rename(columns={"cond": "condition", "cost_musd": "cost (m\\$)", "ttft_ms_p50": "TTFT p50 (ms)", "total_ms_p50": "total p50 (ms)"})67        out["family"] = out["family"].str.replace("public_", "")68        df_to_tex(out.sort_values(["model", "family", "condition"]), OUT / "table_hosted.tex", "llllrrrr", "{:,.0f}")69    fq = TAB / "E1_core_by_question_type.csv"70    if fq.exists():71        tq = pd.read_csv(fq); tq["cell"] = tq.apply(lambda r: f"{100*r.quality:.0f} [{100*r.lo:.0f},{100*r.hi:.0f}]", axis=1)72        tq["cond"] = tq["condition"].str.replace("budget_tokens=512", "512", regex=False).str.replace("keep_frac=0.25", "1/4", regex=False).str.replace("|max_fetch_bytes=2000|max_lookups=6", "", regex=False).str.replace("policy=attention", "att", regex=False).str.replace("codec=zstd", "zstd", regex=False).str.replace("|", " ", regex=False)73        piv = tq.pivot_table(index="cond", columns="qtype", values="cell", aggfunc="first").reset_index().rename(columns={"cond": "condition"}).fillna("--")74        df_to_tex(piv, OUT / "table_qtype_core.tex", "l" + "r" * (len(piv.columns) - 1))75    ff = TAB / "E1_core_failures.csv"76    if ff.exists():77        tf = pd.read_csv(ff); df_to_tex(tf.rename(columns={tf.columns[0]: "method"}), OUT / "table_failures.tex", "l" + "r" * (len(tf.columns) - 1), "{:.0f}")78    f7 = TAB / "E7_qtypes.csv"79    if f7.exists():80        t7 = pd.read_csv(f7); t7["cell"] = t7.apply(lambda r: f"{100*r.quality:.0f} [{100*r.lo:.0f},{100*r.hi:.0f}]", axis=1)81        t7["cond"] = t7["condition"].str.replace("budget_tokens=512", "512", regex=False).str.replace("keep_frac=0.25", "1/4", regex=False).str.replace("|", " ", regex=False) + " " + t7["pair"]82        piv = t7.pivot_table(index="cond", columns="qtype", values="cell", aggfunc="first").reset_index().rename(columns={"cond": "condition / pair"}).fillna("--")83        df_to_tex(piv, OUT / "table_qtypes_exploratory.tex", "l" + "r" * (len(piv.columns) - 1))84    f3 = TAB / "E3_core_transfer.csv"85    if f3.exists():86        t3 = pd.read_csv(f3)87        t3["quality_ci"] = t3.apply(lambda r: f"{100*r.quality:.0f} [{100*r.lo:.0f},{100*r.hi:.0f}]", axis=1)88        cols = ["family", "condition", "n", "quality_ci", "unknown_share"] + [c for c in ["q_single_fact", "q_exact_copy", "q_multi_hop", "q_negation", "q_exec"] if c in t3.columns] + ["payload_bytes_median", "warm_ms_p50"]89        out = t3[cols].rename(columns={"quality_ci": "accuracy (\\%)", "unknown_share": "`unknown' share", "payload_bytes_median": "payload B", "warm_ms_p50": "warm ms"})90        out.columns = [c.replace("q_", "") for c in out.columns]91        df_to_tex(out.sort_values(["family", "condition"]), OUT / "table_transfer.tex", "ll" + "r" * (len(out.columns) - 2), "{:,.2f}")92    print("latex tables written")9394if __name__ == "__main__":95    main()96
Files · d5e182fa7d7d5118aa92e61c47c40ed848da0ecf
Menu

Theme