Buckets:

Mercity/FluxDistill / scripts /build_report_pdf.py
Pranav2748's picture
download
raw
9.42 kB
"""Build the detailed W4A8 SVDQuant PDF report:
report/QUANT_REPORT.md (body, detailed)
+ inline analysis figures (outputs/quant_report_assets/*.png)
+ APPENDIX: every cell's 8-probe teacher|quant montage (all 12 cells)
-> report/QUANT_REPORT.pdf
Run: source .venv/bin/activate && PYTHONPATH=. python scripts/build_report_pdf.py
"""
import os
import markdown
from PIL import Image, ImageDraw, ImageFont
from weasyprint import HTML
AST = "outputs/quant_report_assets"
APP = f"{AST}/appendix"
os.makedirs(APP, exist_ok=True)
RANKS = [16, 32, 64]
VARIANTS = ["plain", "plain_refine", "whiten", "whiten_refine"]
VLABEL = {"plain": "plain", "plain_refine": "plain+refine",
"whiten": "whiten", "whiten_refine": "whiten+refine"}
SMALLER = {16: "3.67×", 32: "3.59×", 64: "3.43×"}
PROBES = ["storefront text", "mountain lake", "fisherman portrait", "neon street",
"chalkboard 'FRESH COFFEE'", "breakfast flat-lay (3 eggs/2 bacon)",
"hand / five fingers", "dewy spiderweb macro"]
# full metrics per cell: eval-loss, vel-relerr, wrecon, orecon('' if n/a)
M = {
(16, "plain"): (0.0620, 0.2235, 0.1269, ""), (16, "plain_refine"): (0.0655, 0.2297, 0.1251, ""),
(16, "whiten"): (0.0656, 0.2299, 0.1290, 0.0733), (16, "whiten_refine"): (0.0556, 0.2117, 0.1273, 0.0680),
(32, "plain"): (0.0586, 0.2174, 0.1224, ""), (32, "plain_refine"): (0.0574, 0.2151, 0.1193, ""),
(32, "whiten"): (0.0545, 0.2095, 0.1257, 0.0719), (32, "whiten_refine"): (0.0476, 0.1959, 0.1226, 0.0646),
(64, "plain"): (0.0487, 0.1980, 0.1163, ""), (64, "plain_refine"): (0.0446, 0.1896, 0.1110, ""),
(64, "whiten"): (0.0588, 0.2177, 0.1209, 0.0695), (64, "whiten_refine"): (0.0451, 0.1907, 0.1155, 0.0595),
}
BEST = (64, "plain_refine")
def _font(sz):
for p in ["/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",
"/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf"]:
if os.path.exists(p):
try:
return ImageFont.truetype(p, sz)
except Exception:
pass
return ImageFont.load_default()
def cell_grid_montage(rank, variant, out_path, ncols=2, cell_w=560, label_h=26):
"""8 probe pairs (teacher|quant) for one cell, arranged ncols-wide, each labeled."""
pairs = []
for i in range(8):
p = f"outputs/abl_c300_r{rank}_{variant}/eval/cmp_{i}.png"
if os.path.exists(p):
pairs.append((PROBES[i], Image.open(p)))
if not pairs:
return False
# scale each pair to cell_w
scaled = [(lab, im.resize((cell_w, int(im.height * cell_w / im.width)))) for lab, im in pairs]
row_h = max(s.height for _, s in scaled) + label_h
nrows = (len(scaled) + ncols - 1) // ncols
W = ncols * cell_w + (ncols + 1) * 8
H = nrows * row_h + (nrows + 1) * 8
canvas = Image.new("RGB", (W, H), "white")
d = ImageDraw.Draw(canvas)
f = _font(15)
for idx, (lab, s) in enumerate(scaled):
r, c = divmod(idx, ncols)
x = 8 + c * (cell_w + 8)
y = 8 + r * (row_h + 8)
d.text((x + 2, y + 4), f"{idx}. {lab} (teacher | quant)", fill="black", font=f)
canvas.paste(s, (x, y + label_h))
canvas.save(out_path)
return True
print("generating per-cell appendix montages...")
cell_imgs = {}
for r in RANKS:
for v in VARIANTS:
op = f"{APP}/cell_r{r}_{v}.png"
if cell_grid_montage(r, v, op):
cell_imgs[(r, v)] = op
# mechanism-ablation baselines (rank-0; non-grid dir tags). (dir_tag, title, eval, vel, wrecon-mean, wrecon-max)
BASELINES = [
("nosvd_nosmooth", "RTN W4A8 — no smooth (s=1), no SVD", 0.0573, 0.2149, 0.1112, 0.1504),
("nosvd", "SmoothQuant W4A8 — rank-0 (α=0.5), no SVD", 0.0729, 0.2424, 0.1356, 0.2633),
]
base_imgs = {}
for tag, *_ in BASELINES:
op = f"{APP}/cell_r0_{tag}.png"
if cell_grid_montage(0, tag, op):
base_imgs[tag] = op
print(f" wrote {len(cell_imgs)} grid + {len(base_imgs)} baseline montages")
# --------------------------------------------------------------------- assemble HTML
md_body = open("report/QUANT_REPORT.md").read()
# strip the pandoc %-title metadata lines so they don't render as a literal paragraph
md_lines = [ln for ln in md_body.splitlines() if not ln.startswith("% ")]
body_html = markdown.markdown("\n".join(md_lines), extensions=["tables", "fenced_code", "sane_lists"])
FIGS = [
("mechanism_ladder.png", "Figure 0. Mechanism ablation — RTN (no smooth, no SVD) → SmoothQuant rank-0 → +SVD plain r16/r32/r64 → grid best. ⚠️ SmoothQuant (α=0.5) HURTS at W4A8: the RTN floor (0.0573) beats it (0.0729) AND the smoothed r16/r32 SVD cells."),
("grid_4x3.png", "Figure 1. Full method×rank grid — eval velocity-loss for all 12 cells (300-img calib)."),
("deltas_vs_plain.png", "Figure 2. Each upgrade's % change vs plain SVD, by rank. Whitening alone is non-monotonic; refine reliable; combo strongest at low rank."),
("cross_track.png", "Figure 3. Cross-track context: W4A8 SVDQuant vs the shelved block-surgery frontier on the same metric."),
("byte_compute_budget.png", "Figure 4. Where the bytes/compute go: the 4-bit residual dominates size; the low-rank branch is ~free on compute (FLOPs ∝ r/in)."),
("montage_method_r64_text.png", "Figure 5. Method comparison at rank-64 on the in-image-text probe (teacher | quant), all four variants."),
("montage_best_allprompts.png", "Figure 6. Grid-best cell (r64 plain+refine, 0.0446) vs teacher across all 8 probes."),
]
figs_html = "<h1>Figures</h1>\n"
for fn, cap in FIGS:
p = f"{AST}/{fn}"
if os.path.exists(p):
figs_html += f'<figure class="fig"><img src="{p}"/><figcaption>{cap}</figcaption></figure>\n'
# appendix: every cell, one per page, with its metrics
app_html = '<h1 class="appendix">Appendix A — Per-cell visual montages (all 12 cells × 8 probes)</h1>\n'
app_html += ("<p>Each cell built one-at-a-time on the same fixed 300-image calibration set. "
"Left = teacher (bf16, 4-step), right = W4A8 quantized student, same prompt and seed. "
"Probes 0–3 are the original set; 4–7 were added for richer evaluation.</p>\n")
# baselines first (mechanism ablation)
if base_imgs:
app_html += '<h2>A.0 — Mechanism-ablation baselines (rank-0)</h2>\n'
for tag, title, el, vr, wm, wx in BASELINES:
if tag not in base_imgs:
continue
cap = (f"{title} (~3.76× smaller)<br/>eval-loss <b>{el:.4f}</b> · vel-relerr {vr:.4f} · "
f"wrecon mean {wm:.4f} / max {wx:.4f}")
app_html += (f'<div class="cell"><h2>{title}</h2><p class="metrics">{cap}</p>'
f'<img src="{base_imgs[tag]}"/></div>\n')
for r in RANKS:
for v in VARIANTS:
if (r, v) not in cell_imgs:
continue
el, vr, wr, orc = M[(r, v)]
star = " ★ grid best" if (r, v) == BEST else ""
orc_s = f" · orecon {orc:.4f}" if orc != "" else ""
cap = (f"rank {r} · {VLABEL[v]} ({SMALLER[r]} smaller){star}<br/>"
f"eval-loss <b>{el:.4f}</b> · vel-relerr {vr:.4f} · wrecon {wr:.4f}{orc_s}")
app_html += (f'<div class="cell"><h2>r{r}{VLABEL[v]}</h2>'
f'<p class="metrics">{cap}</p>'
f'<img src="{cell_imgs[(r, v)]}"/></div>\n')
CSS = """
@page { size: A4; margin: 1.6cm 1.4cm; @bottom-center { content: counter(page); font-size: 9px; color:#888; } }
body { font-family: 'DejaVu Sans', sans-serif; font-size: 10.5px; line-height: 1.45; color:#1a1a1a; }
h1 { font-size: 19px; border-bottom: 2px solid #333; padding-bottom:3px; margin-top: 18px; }
h1.appendix, h1.fightitle { page-break-before: always; }
h2 { font-size: 14px; color:#222; margin-top: 14px; }
h3 { font-size: 12px; color:#333; }
table { border-collapse: collapse; width: 100%; font-size: 9px; margin: 8px 0; }
th, td { border: 1px solid #bbb; padding: 3px 5px; text-align: left; }
th { background: #f0f0f0; }
code { background:#f4f4f4; padding:0 2px; font-family:'DejaVu Sans Mono', monospace; font-size:9px; }
pre { background:#f6f6f6; padding:6px; border-radius:3px; font-size:8.5px; overflow-wrap:anywhere; white-space:pre-wrap; }
figure.fig { page-break-inside: avoid; text-align:center; margin: 10px 0; }
figure.fig img { max-width: 100%; border:1px solid #ddd; }
figcaption { font-size: 9px; color:#555; margin-top:3px; }
.cell { page-break-before: always; page-break-inside: avoid; }
.cell img { max-width: 100%; border:1px solid #ddd; }
.metrics { font-size: 10px; color:#333; margin: 2px 0 6px; }
.title { text-align:center; margin-top: 4cm; }
.title h1 { font-size: 26px; border:0; }
.title p { color:#555; font-size: 12px; }
"""
title = """
<div class="title">
<h1>FLUX.2 [klein] 4B → W4A8 SVDQuant</h1>
<p><b>Methodology &amp; full 4×3 method×rank ablation grid</b></p>
<p>Our own fake-quant SVDQuant + activation-aware whitening + iterative refinement</p>
<p>2026-06-01 · 1× A100-80GB · 300-image calibration · held-out velocity-matching metric</p>
</div>
<div style="page-break-after: always;"></div>
"""
html = (f"<html><head><meta charset='utf-8'><style>{CSS}</style></head><body>"
f"{title}{body_html}{figs_html}{app_html}</body></html>")
HTML(string=html, base_url=".").write_pdf("report/QUANT_REPORT.pdf")
sz = os.path.getsize("report/QUANT_REPORT.pdf") / 1e6
print(f"wrote report/QUANT_REPORT.pdf ({sz:.1f} MB)")

Xet Storage Details

Size:
9.42 kB
·
Xet hash:
2729d2c8dd8f6576575b1fab29a4a80dff3840f238bc69ef09459b237b83186c

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.