Commit Graph
4 Commits
Author SHA1 Message Date
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
vh 37e9e1ca7f revert(gen-seat): abandon Cold-Fusion, roll back to heresy — the leak is in the base
Operator directive, given before the result was in: if it's the base, abandon
h300 and the base too. The dose-response said base (18.5% of 22.2%), so it fired.

Live gen seat is /tank/aimodels/qwen38-27b-heresy-nvfp4-mixed again, restored
from .env.bak-coldfusion-L35-20260820. The h300 env is preserved at
.env.bak-h300-abandoned-20260821.

The clincher, same probe pointed at heresy:

  Cold-Fusion stock          P(<think>) 0.1850
  Cold-Fusion L35                       0.2048
  Cold-Fusion h300                      0.2216
  heresy (restored)          not in the top 20, <0.002

A >100x gap between the families, which is why no rollback inside Cold-Fusion
would have helped -- stock and L35 leak at nearly the h300 rate.

Verified after rollback: 0/30 leaks and 0 empty on the same instrument that
scored h300 at 8/30, with the EXISTING enable_thinking:false config; KV pool
403,065 tok / 1.54x, heresy's exact documented baseline; 7/7 aliases; vision
intact. No LiteLLM change was needed, so the chat_template_kwargs fix is left
unapplied -- it worked, but it was a workaround for a base we no longer serve.

Cost, stated plainly: 8/100 refusals becomes 29/100, a 3.6x regression on the
axis the whole Heretic-300 run existed to move. Accepted deliberately.

What carries forward is the methodology, none of which lived in the Cold-Fusion
weights: direction_scope=0 beating per-layer on a merged base, aggression not
being the lever, PR #317 silently dropping the MTP head on save, the MPOA and
sink-screen reasoning, the graft/KL/catatonia/export harnesses, and the finding
that a pristine MTP graft accepts as well as an in-band edit.

New acceptance gate earned here: run think_prior.py on a candidate's STOCK
weights before committing GPU time. It is a ~10s CPU measurement and it would
have disqualified Cold-Fusion before the 300-trial study ever started. Heretic's
objective has no format-compliance term at all -- the same blindness that removed
the self-harm guardrail.

Nothing deleted. Every Cold-Fusion artifact, the 300-trial Optuna journal and
catatonia-T260.json remain on disk. Abandon means stop serving, not rm.
2026-08-21 00:40:23 -07:00
vh 5ee2325820 feat(coldfusion-abliteration): dose-response settles the <think> leak — base 83%, our abliteration 17%
Answers "how likely is it that our abliteration caused this?" with a measurement
instead of a prior. P(<think>) at the first generated token, template rendered
enable_thinking=false so the prompt already carries a CLOSED think pair -- the
exact event behind the leak. Raw softmax, bf16, CPU-only, one process per model.
Deterministic: stock reproduced to 17 significant figures across two runs.

  coldfusion-bf16                  none (stock)          0.1850   rank 3
  coldfusion-abliterated-L35-bf16  Robinson L35, mild    0.2048   rank 2
  coldfusion-h300-mtp-bf16         Heretic-300, heavy    0.2216   rank 2

The stock, untouched base already puts 18.5% of first-token mass on opening a
think block the template had closed. Abliteration adds a real, monotonic,
dose-dependent +3.7 points -- a nudge on a pre-existing base, not the cause.
Cold-Fusion is a reasoning-token-compression finetune, i.e. a model trained to
think briefly, and the leak's text shape agrees: a compact correct trace with a
trained transition marker, which is trained behavior rather than damage.

This changes the options. Rolling back to L35 or stock does NOT fix the leak --
at 18.5% under temp 0.7 / top_p 0.8 they leak at nearly the h300 rate. Only
leaving the Cold-Fusion family escapes it, at the cost of the 8/100 refusal
result. The chat_template_kwargs fix is the correct lever.

Durable methodology point: a forward-KL budget cannot catch this. Heretic
minimizes forward KL(stock||abliterated), which is near-blind to the model
putting new mass on tokens stock barely used -- that is reverse KL's job, and we
measured exactly that asymmetry on L35 (reverse 1.43 vs forward 0.70). h300's KL
of 0.0136 is not evidence of innocence. For any "did the abliteration break
behavior X" question, measure P(token) directly.

Ran CPU-only deliberately: 96 EPYC cores and 265 GB of RAM make a 27B forward
pass cheap, so this cost no GPU window and no seat downtime, where the obvious
route was stopping both GPU0 seats.

Also normalizes two more abliteration output dirs from root-owned 0600 to
llmuser 0664. The unreadable-model failure surfaces as FileNotFoundError rather
than a permission error, which is worth knowing before it wastes a run.
2026-08-21 00:22:11 -07:00
vh 91f4cf22e1 fix(gen-seat): diagnose the unterminated-<think> leak — model defect, temp-triggered
Operator reported the new Heretic-300 gen seat "sends CoT but never completes
the turn" through Lobe. Diagnosed; not yet fixed (the fix changes gen's
semantics, so it is the operator's call).

The Qwen3.8 chat template appends a pre-closed <think>\n\n</think>\n\n when
enable_thinking is false. The h300 model opens a fresh <think> anyway and never
closes it. Because the prompt already closed the block, vLLM's qwen3 reasoning
parser is not in reasoning state, so the tag passes through as ordinary text --
reasoning_content empty, reasoning_tokens 0, and the whole reasoning-plus-answer
blob lands in content. Lobe then correctly treats the unterminated tag as
still-thinking and renders no answer. The client and the serving stack are both
behaving correctly; the model is not.

The trigger is TEMPERATURE, not presence_penalty (n=12 per arm):

  temp 0.7, pp 1.5  (current gen)   4/12
  temp 0.7, pp 0.0                  4/12
  temp 0.7, pp 0.5                  3/12
  temp 0,   pp 1.5                  0/12

That falsifies the standing hypothesis, recorded in the litellm config comment
and in the operator's own 2026-08-16 note, that presence_penalty 1.5 is the
first dial to move. It is not this bug's cause.

It also explains the blast radius: only the two temp-0.7 aliases leak, `gen`
and `summarizer-large`. summarizer, classifier, image-judge and qwen-image-bench
all run at temp 0 and are clean, so nevermore's summarizer path is unaffected.

Candidate fix, validated n=30 over 4 prompt types plus a 3-turn conversation:
chat_template_kwargs {enable_thinking: true, reasoning_effort: low} takes 8/30
leaks to 0/30, at ~+27% completion tokens and a ~3% empty-content residual.

The tell appears in eval_coldfusion_h300.json and in none of the aeon, heresy,
mixed or w4a16 evals, so it is new with this build -- but L35 was never evaled,
so this does not separate a Cold-Fusion base trait from a Heretic-300
abliteration artifact.

Reproducers and the full method land in bench/think-leak/. Note in particular
that the 7/7 alias smoke test run at cutover structurally could not catch this:
trivial prompts never invite reasoning, so they never sample the leaking token.
2026-08-21 00:12:30 -07:00