Guard large unaligned Qwen expert gathers
This commit is contained in:
1 parent
57b8ac28a7
commit
990abb4755
22 files changed
+951
-3
No files matched your search
@@ -32,6 +32,8 @@ struct Manifest {
|
||||
#[serde(default)]
|
||||
verify_gate: bool,
|
||||
#[serde(default)]
|
||||
sorted_gather_guard: bool,
|
||||
#[serde(default)]
|
||||
images: Vec<crate::engine::qwen_vision::Identity>,
|
||||
tokens: Vec<i32>,
|
||||
lazy_kv: bool,
|
||||
@@ -119,6 +121,7 @@ impl LiveSession {
|
||||
let offset = file.stream_position().map_err(|e| e.to_string())?;
|
||||
let manifest = serde_json::to_vec(&Manifest {
|
||||
verify_gate: true,
|
||||
sorted_gather_guard: true,
|
||||
identity,
|
||||
tag,
|
||||
images: self.current_images.clone(),
|
||||
@@ -193,6 +196,14 @@ impl LiveSession {
|
||||
"Qwen checkpoint uses obsolete MTP attention-gate math; rebuild the cache".into(),
|
||||
);
|
||||
}
|
||||
// Old files do not record prefill chunk sizes or producer hardware.
|
||||
// At ten routes/token this length can contain an affected chunk;
|
||||
// shorter sessions cannot. Reject before allocating/restoring state.
|
||||
if !manifest.sorted_gather_guard && manifest.tokens.len() >= 3277 {
|
||||
return Err(
|
||||
"Qwen checkpoint predates the sorted-gather row guard; rebuild the cache".into(),
|
||||
);
|
||||
}
|
||||
if !manifest.payload["mtp_history_snapshot"].is_null() != identity.mtp {
|
||||
return Err("Qwen checkpoint MTP payload differs".into());
|
||||
}
|
||||
@@ -480,6 +491,40 @@ fn qwen_checkpoint_roundtrip_and_failed_restore_preserve_live_state() {
|
||||
.unwrap()
|
||||
);
|
||||
assert_eq!(fingerprint(&live), ar_original);
|
||||
let bytes = fs::read(&path).unwrap();
|
||||
let offset = u64::from_le_bytes(bytes[8..16].try_into().unwrap()) as usize;
|
||||
let mut manifest: serde_json::Value = serde_json::from_slice(&bytes[offset..]).unwrap();
|
||||
manifest
|
||||
.as_object_mut()
|
||||
.unwrap()
|
||||
.remove("sorted_gather_guard");
|
||||
let write_manifest = |manifest: &serde_json::Value| {
|
||||
let mut old = bytes[..offset].to_vec();
|
||||
old.extend(serde_json::to_vec(manifest).unwrap());
|
||||
fs::write(&broken, old).unwrap();
|
||||
};
|
||||
write_manifest(&manifest);
|
||||
assert!(
|
||||
live.load_checkpoint(&broken, ar_identity, &streams, stream, |_| {}, || false)
|
||||
.unwrap()
|
||||
);
|
||||
assert_eq!(fingerprint(&live), ar_original);
|
||||
manifest["tokens"] = serde_json::json!(vec![1; 3277]);
|
||||
manifest["identity"]["context"] = 4096.into();
|
||||
write_manifest(&manifest);
|
||||
let large_identity = Identity {
|
||||
context: 4096,
|
||||
..ar_identity
|
||||
};
|
||||
assert!(
|
||||
live.load_checkpoint(&broken, large_identity, &streams, stream, |_| {}, || false)
|
||||
.unwrap_err()
|
||||
.contains("sorted-gather row guard")
|
||||
);
|
||||
assert_eq!(fingerprint(&live), ar_original);
|
||||
println!(
|
||||
"Qwen sorted-gather checkpoint policy: old short state exact, possibly affected long state rejected before restore"
|
||||
);
|
||||
println!(
|
||||
"Qwen checkpoint: exact roundtrip, cancellation/corruption controls, old MTP rejected and old AR restored"
|
||||
);
|
||||
|
||||
Reference in new issue
Block a user