Files
esh-pfi-infrastructure/services/gen-seat-mixed-quant/bench/think-leak/mtp_delta.py
T
vh c8f128bdff feat(gen-seat): quant orcarouter — its MTP head is already Robinson-abliterated in-band
Pulled orcarouter/Qwen3.8-27B-Uncensored at rev 9878936b (55.5 GB, gated, our
token has access) and built /tank/aimodels/qwen38-27b-orcarouter-nvfp4-mixed
(23.4 GB, mixed NVFP4+FP8). Verified, not yet cut over.

The operator asked whether we could apply the Robinson path to the MTP head. We
cannot, because the author already did. compare_mtp_head.py against the verbatim
base graft: 13 of 15 tensors byte-identical, exactly 2 differ --
mtp.layers.0.self_attn.o_proj.weight and mtp.layers.0.mlp.down_proj.weight, which
are precisely the two residual writers our own abliterate.py targets
(EXPECT_MTP_WRITERS = 2).

Reverse-engineered the edit from the weights alone (mtp_delta.py, added here):

  sigma2/sigma1 = 0.0164 on BOTH tensors    rank-1, a single-direction projection
  |cos| between the two recovered dirs = 1.0000   ONE shared direction
  ||delta||/||W|| = 1.42% and 1.41%         a gentle, consistent projection
  sink energy dim 3994 = 0.0000%            sink-clean; Heretic's was 6.18%

That is the Robinson in-band MTP abliteration, already applied, with a direction
that passes our sink screen outright. Nothing to do but preserve it, and the quant
carries it byte-identically. This is the configuration the entire Cold-Fusion
experiment was designed to test and never cleanly delivered.

The new format screen paid for itself on its first real use: think_prior.py on the
bf16 BEFORE any GPU time gave P(<think>) = 1.23e-06 at rank 52, against
Cold-Fusion stock 0.1850 and h300 0.2216. Roughly 150,000x cleaner.

Two durable findings about the pipeline itself:

The quant needs ~17 GB, not a whole card. It ran entirely in GPU1's spare 16 GB
with ZERO production seats stopped -- the h300 run's "stop BOTH GPU0 seats" was
never necessary, it simply had a free card by coincidence. The first attempt OOM'd
by 2.37 GiB at layer 64 of 65 with 3.57 GiB reserved-but-unallocated, which is
fragmentation, and PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True closed it.

post_quant.py now builds a missing output index from the safetensors headers.
A sub-23 GB quant saves one bare shard with no index, and post_quant needs one;
this has broken three separate rounds and been hand-fixed every time. The header
is read by struct-unpacking the u64 length and parsing the JSON -- never
safe_open, which mmaps the whole 22 GB shard and ENOMEMs on ZFS.

Artifact verified: mixed-precision, 1968 tensors, 15 mtp, 333 visual, re:^mtp.*
present in the ignore list (llm-compressor pruned it as always), preproc restored.
Imatrix deferred per operator; the log confirms the usual uniform-MSE fallback, so
this build stays apples-to-apples with heresy's PPL 6.910.
2026-08-21 01:25:37 -07:00

45 lines
2.1 KiB
Python

#!/usr/bin/env python3
"""Is orcarouter's MTP-head edit a single-direction (Robinson-style) projection?
Robinson orthogonalizes a residual WRITER as W' = (I - d d^T) W, so
delta = W' - W = -d d^T W is EXACTLY RANK 1 with left singular vector d.
Two independent predictions follow, both checkable from the weights alone:
1. sigma_2/sigma_1 ~ 0 for each edited tensor
2. the d recovered from o_proj and from down_proj must AGREE (|cos| ~ 1),
because Robinson uses ONE shared direction
Then sink-screen the recovered d: Heretic's was 6.18% concentrated in dim 3994,
which is what made an in-band graft unsafe on that trunk. Ours want < 1%.
"""
import json, torch
from pathlib import Path
from safetensors import safe_open
CAND = Path("/tank/aimodels/qwen38-27b-orcarouter-bf16")
REF = Path("/tank/aimodels/qwen38-27b-uncensored-bf16")
KEYS = ["mtp.layers.0.self_attn.o_proj.weight", "mtp.layers.0.mlp.down_proj.weight"]
SINK_DIM = 3994
def get(d: Path, key: str):
idx = json.loads((d / "model.safetensors.index.json").read_text())["weight_map"]
with safe_open(d / idx[key], framework="pt") as f:
return f.get_tensor(key)
dirs = {}
for k in KEYS:
delta = (get(CAND, k).float() - get(REF, k).float())
U, S, Vh = torch.linalg.svd(delta, full_matrices=False)
ratio = (S[1] / S[0]).item()
d = U[:, 0] # residual-space direction (dim 5120)
dirs[k] = d
sink = (d[SINK_DIM] ** 2).item() / (d @ d).item()
print(f" {k.split('.',2)[2]:<28} shape={tuple(delta.shape)}")
print(f" sigma2/sigma1 = {ratio:.6f} <- rank-1 if ~0")
print(f" ||delta||/||W|| = {(delta.norm()/get(REF,k).float().norm()).item():.5f}")
print(f" sink energy dim {SINK_DIM} = {sink*100:.4f}% <- want <1%, Heretic's was 6.18%")
a, b = dirs[KEYS[0]], dirs[KEYS[1]]
cos = torch.abs(a @ b / (a.norm() * b.norm())).item()
print(f"\n |cos| between the two recovered directions = {cos:.4f} <- ~1 means ONE shared direction")
top = torch.topk(a.abs(), 5)
print(f" top-5 |d| coords (o_proj): {[(int(i), round(float(v),4)) for i, v in zip(top.indices, top.values)]}")