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