feat(qwen38): add E03 coherence recovery candidate

This commit is contained in:
Joseph Magly
2026-08-29 18:45:57 -04:00
parent 941869d909
commit 4b737cba64
7 changed files with 112 additions and 27 deletions
+40 -17
View File
@@ -534,6 +534,7 @@ METHODS = {
"adaptive (telemetry-recommended)": "adaptive",
"Qwen3.8 E01 (held-out causal baseline)": "qwen38_e01",
"Qwen3.8 E02 (tune-only multi-direction)": "qwen38_e02",
"Qwen3.8 E03 (tune-only coherence recovery)": "qwen38_e03",
"advanced (recommended)": "advanced",
"basic (fast, single direction)": "basic",
"aggressive (maximum removal)": "aggressive",
@@ -2285,8 +2286,12 @@ def obliterate(model_choice: str, method_choice: str,
"harmful": hashlib.sha256((custom_harmful or "").encode()).hexdigest(),
"harmless": hashlib.sha256((custom_harmless or "").encode()).hexdigest(),
}
if method in {"qwen38_e01", "qwen38_e02"}:
experiment = "E01" if method == "qwen38_e01" else "E02"
if method in {"qwen38_e01", "qwen38_e02", "qwen38_e03"}:
experiment = {
"qwen38_e01": "E01",
"qwen38_e02": "E02",
"qwen38_e03": "E03",
}[method]
experiment_settings = {
"E01": {
"direction_method": "diff_means",
@@ -2313,6 +2318,20 @@ def obliterate(model_choice: str, method_choice: str,
"verify_sample_size": 142,
"evaluation_split": "optimizer_tune",
},
"E03": {
"direction_method": "svd",
"n_directions": 4,
"regularization": 0.1,
"refinement_passes": 1,
"norm_preserve": True,
"layer_selection": "middle60",
"projection_target": "output",
"rdo_refinement": True,
"winsorize_activations": True,
"use_kl_optimization": True,
"verify_sample_size": 142,
"evaluation_split": "optimizer_tune",
},
}[experiment]
run_config["immutable_experiment"] = {
"protocol": "qwen38-v1",
@@ -2416,7 +2435,7 @@ def obliterate(model_choice: str, method_choice: str,
evaluation_harmful = None
evaluation_harmless = None
if method in {"qwen38_e01", "qwen38_e02"}:
if method in {"qwen38_e01", "qwen38_e02", "qwen38_e03"}:
if model_id.rstrip("/").lower() != "qwen/qwen3.8-27b":
raise ValueError("Qwen3.8 experiments require Qwen/Qwen3.8-27B")
if use_custom or dataset_key != "builtin":
@@ -2431,7 +2450,11 @@ def obliterate(model_choice: str, method_choice: str,
split = build_qwen38_split(harmful_all, harmless_all)
train_harmful = [pair[0] for pair in split.train]
train_harmless = [pair[1] for pair in split.train]
experiment = "E01" if method == "qwen38_e01" else "E02"
experiment = {
"qwen38_e01": "E01",
"qwen38_e02": "E02",
"qwen38_e03": "E03",
}[method]
evaluation_pairs = qwen38_evaluation_pairs(
split,
experiment,
@@ -2448,7 +2471,7 @@ def obliterate(model_choice: str, method_choice: str,
)
on_log(
f"{experiment} evaluation partition: "
f"{'optimizer-tune' if experiment == 'E02' else 'final-test'} "
f"{'final-test' if experiment == 'E01' else 'optimizer-tune'} "
f"({len(evaluation_pairs)} pairs)"
)
on_log(f"Split manifest: {split.manifest['manifest_sha256']}")
@@ -2492,13 +2515,13 @@ def obliterate(model_choice: str, method_choice: str,
if immutable_qwen38:
# Promotion experiments are immutable: ignore mutable
# advanced controls and run the registered candidate.
is_e02 = method == "qwen38_e02"
is_tune_candidate = method in {"qwen38_e02", "qwen38_e03"}
advanced_options = {
"n_directions": 4 if is_e02 else 1,
"direction_method": "svd" if is_e02 else "diff_means",
"regularization": 0.0,
"n_directions": 4 if is_tune_candidate else 1,
"direction_method": "svd" if is_tune_candidate else "diff_means",
"regularization": 0.1 if method == "qwen38_e03" else 0.0,
"refinement_passes": 1,
"norm_preserve": is_e02,
"norm_preserve": is_tune_candidate,
"project_biases": False,
"use_chat_template": True,
"use_whitened_svd": False,
@@ -2515,13 +2538,13 @@ def obliterate(model_choice: str, method_choice: str,
"expert_transplant": False,
"use_wasserstein_optimal": False,
"spectral_cascade": False,
"layer_selection": "middle60" if is_e02 else "all_except_first",
"winsorize_activations": is_e02,
"use_kl_optimization": is_e02,
"layer_selection": "middle60" if is_tune_candidate else "all_except_first",
"winsorize_activations": is_tune_candidate,
"use_kl_optimization": is_tune_candidate,
"float_layer_interpolation": False,
"rdo_refinement": is_e02,
"rdo_refinement": is_tune_candidate,
"cot_aware": False,
"verify_sample_size": 142 if is_e02 else 200,
"verify_sample_size": 142 if is_tune_candidate else 200,
}
else:
advanced_options = {
@@ -2577,12 +2600,12 @@ def obliterate(model_choice: str, method_choice: str,
spectral_threshold=float(adv_spectral_threshold),
winsorize_percentile=(
0.01
if immutable_qwen38 and method == "qwen38_e02"
if immutable_qwen38 and method in {"qwen38_e02", "qwen38_e03"}
else float(adv_winsorize_percentile)
),
kl_budget=(
0.5
if immutable_qwen38 and method == "qwen38_e02"
if immutable_qwen38 and method in {"qwen38_e02", "qwen38_e03"}
else float(adv_kl_budget)
),
n_sae_features=int(adv_n_sae_features),
+10 -6
View File
@@ -215,7 +215,7 @@ method needs an isolated ablation and an interaction test before composition.
| E00 | Is the pristine evaluator stable? | final-test only, 3 seeds | none | metric variance and baselines recorded |
| E01 | Does the Arditi control work? | 400/100 | DIM, one layer/direction sweep | lower refusal with <=1.25x PPL |
| E02 | Does a low-rank writer intervention improve E01? | 500/142; final test prohibited | SVD-4 + RDO, middle-60% residual writers, KL rollback | tune refusal <30% and coherence >=80% |
| E03 | Which architecture component carries refusal? | 400/100 | DeltaNet vs full-attn vs MLP groups | best causal effect per KL unit |
| E03 | Can slight attenuation recover E02 coherence? | 500/142; final test prohibited | E02 kernel with 0.10 regularization | tune refusal <30% and coherence >=80% |
| E04 | Does SVD rank help? | 400/100 | k=1..7, joint held-out selection | nondominated gain over E01 |
| E05 | Does RDO improve targeting? | 400/100 | one and multiple RDO directions | held-out gain over E01/E04 |
| E06 | Do concept-cone combinations help? | large corpus + 128--512 trials | SOM/independent combinations | reproducible gain over E05 |
@@ -256,11 +256,15 @@ from 60% refusal in S2 to 100% in several other strata.
## Recommended next operational run
Run the pre-registered E02 candidate on the 142-pair optimizer-tune partition.
E02 must not read the 200-pair final partition. Retain its complete archive even
if it fails. If it misses either target, use only tune evidence to define the
next isolated ablation. If it passes both targets, reload that saved checkpoint
and run the final partition exactly once for release qualification.
E02 completed on the optimizer-tune partition as run
`run-efb2f334197e48fb82587f39a84fe6c9`: refusal fell to 1% (1/142), but
coherence was 70% and 6/142 harmful responses were degenerate. Its checkpoint
and full archive are retained. E03 changes only regularization from 0.00 to
0.10, retaining 10% of the measured refusal subspace to recover coherence while
using E02's 29-point refusal margin. E03 must not read the 200-pair final
partition. Promote only if tune refusal remains below 30% and coherence reaches
at least 80%; then evaluate the final partition exactly once and independently
reload the saved checkpoint for release qualification.
## Evidence base
+14 -2
View File
@@ -59,8 +59,20 @@
},
{
"id": "E03",
"purpose": "DeltaNet/full-attention/MLP writer ablation",
"depends_on": "E01"
"purpose": "tune-only coherence recovery by attenuating E02",
"depends_on": "E02",
"method": "qwen38_e03",
"evaluation_split": "optimizer_tune",
"direction_method": "svd",
"directions": 4,
"layer_selection": "middle60",
"projection_target": "output",
"regularization": 0.1,
"norm_preserve": true,
"refinement_passes": 1,
"rdo_refinement": true,
"winsorize_activations": true,
"kl_optimization": true
}
]
}
+31
View File
@@ -249,6 +249,37 @@ METHODS = {
"rdo_refinement": True,
"verify_sample_size": 142,
},
"qwen38_e03": {
"label": "Qwen3.8 E03 (tune-only coherence recovery)",
"description": (
"E02 follow-up on the same held-out tune split: retain 10% of the "
"validated residual-writer subspace to recover coherence while "
"preserving E02's refusal-removal margin."
),
"n_directions": 4,
"direction_method": "svd",
"norm_preserve": True,
"regularization": 0.1,
"refinement_passes": 1,
"project_biases": False,
"use_chat_template": True,
"use_whitened_svd": False,
"true_iterative_refinement": False,
"use_jailbreak_contrast": False,
"layer_adaptive_strength": False,
"safety_neuron_masking": False,
"per_expert_directions": False,
"attention_head_surgery": False,
"use_sae_features": False,
"invert_refusal": False,
"use_kl_optimization": True,
"winsorize_activations": True,
"winsorize_percentile": 0.01,
"layer_selection": "middle60",
"projection_target": "output",
"rdo_refinement": True,
"verify_sample_size": 142,
},
"basic": {
"label": "Basic (Arditi et al.)",
"description": "Single refusal direction via difference-in-means",
+1
View File
@@ -33,6 +33,7 @@ def qwen38_evaluation_pairs(
partitions = {
"E01": split.test,
"E02": split.tune,
"E03": split.tune,
}
try:
return partitions[experiment]
+13 -1
View File
@@ -163,7 +163,7 @@ class TestStages:
class TestMethods:
def test_methods_exist(self):
assert set(METHODS.keys()) == {"basic", "advanced", "aggressive", "informed", "surgical", "inverted", "nuclear", "optimized", "failspy", "gabliteration", "heretic", "rdo", "spectral_cascade", "som", "qwen38_e01", "qwen38_e02"}
assert set(METHODS.keys()) == {"basic", "advanced", "aggressive", "informed", "surgical", "inverted", "nuclear", "optimized", "failspy", "gabliteration", "heretic", "rdo", "spectral_cascade", "som", "qwen38_e01", "qwen38_e02", "qwen38_e03"}
def test_basic_single_direction(self):
cfg = METHODS["basic"]
@@ -179,6 +179,18 @@ class TestMethods:
assert cfg["regularization"] > 0
assert cfg["refinement_passes"] >= 2
def test_qwen38_e03_is_single_variable_e02_attenuation(self):
e02 = METHODS["qwen38_e02"]
e03 = METHODS["qwen38_e03"]
changed = {
key for key in set(e02) | set(e03)
if e02.get(key) != e03.get(key)
}
assert changed == {"label", "description", "regularization"}
assert e02["regularization"] == 0.0
assert e03["regularization"] == 0.1
def test_aggressive_full_gabliteration(self):
cfg = METHODS["aggressive"]
assert cfg["n_directions"] >= 8
+3 -1
View File
@@ -50,9 +50,11 @@ def test_qwen38_experiment_evaluation_partitions_are_fail_closed():
assert qwen38_evaluation_pairs(split, "E01") is split.test
assert qwen38_evaluation_pairs(split, "E02") is split.tune
assert qwen38_evaluation_pairs(split, "E03") is split.tune
assert not set(split.test) & set(qwen38_evaluation_pairs(split, "E02"))
assert not set(split.test) & set(qwen38_evaluation_pairs(split, "E03"))
with pytest.raises(ValueError, match="unregistered Qwen3.8 experiment"):
qwen38_evaluation_pairs(split, "E03")
qwen38_evaluation_pairs(split, "E04")
def test_qwen38_split_rejects_wrong_size_and_duplicate_pairs():