guided: case (c) pmass_allowed=0.0 instead of NaN

When the model emits </think> in natural generation but the answer-slot
window detection fails, that's coherence collapse — the model "finished
thinking" without producing JSON. pmass=0.0 is the honest measurement
(no probability mass on allowed tokens at a non-existent slot) and lets
the coherence canary see the failure as a real signal rather than
propagating NaN through np.mean to crash c_scan. nll_json stays NaN
since no JSON was emitted to score.

Triggered by qwen3.6-27b nf4 + LoRA at c=1.0: 1/4 samples hit case (c)
and the NaN aborted c_scan instead of letting it walk down further.
This commit is contained in:
wassname
2026-05-23 21:28:06 +00:00
parent 0b39d2d3f7
commit ab4fcd2932
+8 -2
View File
@@ -285,9 +285,15 @@ def _rollout_natural_or_forced(
lp_vec = forced_lp_last[i]
nll_val = float(forced_nll_json[i].item())
else:
# Case (c) emitted </think> but no natural answer: undefined
# Case (c) emitted </think> but no natural answer slot found.
# Model "finished thinking" without producing JSON — coherence
# collapse at the answer slot. pmass=0.0 is the honest measurement
# (no probability mass on allowed tokens at a non-existent slot)
# and lets c_scan see the failure as a real signal rather than
# crashing on NaN. nll_json stays NaN (genuinely undefined: no
# JSON tokens were emitted to score).
slots[i].append({
"pmass_allowed": float("nan"),
"pmass_allowed": 0.0,
"nll_json": float("nan"),
"top5_str": "",
"lp_gather": [float("nan")] * len(gather_token_ids),