Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

275 changes: 239 additions & 36 deletions crates/gpu-gates/src/bin/gate_qwen4exp_nvfp4.rs

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions crates/hf/src/modelopt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1093,6 +1093,11 @@ mod tests {
);
let kept = normalize(get, &[("b.weight", &b)], Use::Matrix(Plain::Bf16)).unwrap();
assert_eq!((kept.type_id, &kept.bytes), (30, &bf16));
let f32 = placed(Format::F32, &[]);
let kept = normalize(get, &[("f.weight", &f32)], Use::Matrix(Plain::F32)).unwrap();
assert_eq!((kept.type_id, &kept.bytes), (0, &f32s));
let q = normalize(get, &[("f.weight", &f32)], m).unwrap();
assert_eq!((q.type_id, &q.bytes), (8, &want));
let rows = normalize(
get,
&[("t.weight", &placed(Format::Fp8Tensor, &["t.scale"]))],
Expand Down
13 changes: 10 additions & 3 deletions crates/levers/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ pub use registry::{
PREFILL_GROUP_DEFAULT, PREFILL_GROUP_MAX, QWEN3_KV, QWEN38_EXPERTS, R8, RESIDENCY, ROUTE_TRACE,
SCREEN, SPIN, STEP_STATS, THREADS, TIER_LINK, TIER_NODES, TP_NODES, WARM_PROFILE,
};
pub use registry::{SCHEMAJUMP, SPLIT_WALK, XSTREAM};
pub use registry::{PREPARE_Q8, SCHEMAJUMP, SPLIT_WALK, XSTREAM};

#[cfg(test)]
mod tests;
Expand Down Expand Up @@ -1183,6 +1183,13 @@ impl Levers {
self.flag(SCHEMAJUMP)
}

/// `BLOOMERY_PREPARE_Q8`: `prepare` writes the BF16 or F32 matrices its map
/// reads as Q8_0 in Q8_0, not as stored.
#[must_use]
pub fn prepare_q8(&self) -> bool {
self.flag(PREPARE_Q8)
}

/// The host tier's load settings: [`HOST_POPULATE`], [`HOST_LOCK`],
/// [`CARD_DONTNEED`], [`R8`], and whether [`ROUTE_TRACE`] is set.
#[must_use]
Expand Down Expand Up @@ -2025,7 +2032,7 @@ pub enum Draft38Off {
/// Unset, and the last window needs `need` positions of `ctx`.
Ctx { need: usize, ctx: usize },
/// Unset on the Qwen3.8 seat, and the target's `name`, a matrix the
/// draft borrows, is `ty` (or `absent`), not the Q8_0 the draft reads.
/// draft borrows, is `ty` (or `absent`), not a form the draft reads.
Borrowed { name: String, ty: String },
/// Unset, and the draft yielded to the context
/// ([`RungCost::of`]'s answer, the seats' plan-side rule).
Expand Down Expand Up @@ -2072,7 +2079,7 @@ impl fmt::Display for Draft38Off {
),
Draft38Off::Borrowed { name, ty } => write!(
f,
"unset: the target's {name} is {ty}; the MTP draft reads it as Q8_0"
"unset: the target's {name} is {ty}, not a form the MTP draft reads"
),
Draft38Off::Yield(y) => y.fmt(f),
Draft38Off::Paged { arena } => write!(
Expand Down
25 changes: 25 additions & 0 deletions crates/levers/src/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ pub const TIER_NODES: &str = "BLOOMERY_TIER_NODES";
pub const TP_NODES: &str = "BLOOMERY_TP_NODES";
pub const SCREEN: &str = "BLOOMERY_SCREEN";
pub const SCHEMAJUMP: &str = "BLOOMERY_SCHEMAJUMP";
pub const PREPARE_Q8: &str = "BLOOMERY_PREPARE_Q8";

/// The largest `BLOOMERY_PREFILL_GROUP`: the batches a V4.1 prompt group
/// holds at most, which the body's buffers are sized for.
Expand Down Expand Up @@ -1073,6 +1074,30 @@ pub(crate) static REGISTRY: &[LeverSpec] = &[
phase: Phase::Load,
},
},
LeverSpec {
name: PREPARE_Q8,
class: Class::M,
kind: Kind::Flag,
default: Unset::Is("0"),
doc: "`prepare`: `1` writes each BF16 or F32 matrix its checkpoint map reads as Q8_0 (the \
attention and linear-attention projections, the shared expert, the PLE key and \
value, the hyper-connections' down and up, the head and the token embedding) as \
ggml's reference Q8_0; `0` keeps each single BF16 matrix as stored and refuses \
F32 matrices read as Q8_0. BF16 and F32 expert stacks are refused, and the \
quantized tensors (NVFP4, MXFP8, FP8) keep their stored blocks, under both \
values. The rewrite is lossy: on \
`nvidia/Qwen3.8-Flash-Next-NVFP4` at fc694b54, the checkpoint's own f32 forward \
with its BF16 projections rounded to Q8_0 is at a KL divergence of 4.288e-02 from \
the forward with them as stored, at the last of the five positions of the \
batch set, and 4.181e-02 at position 3,000 of the D3K set (refset \
`hf-qwen4exp-nvfp4`, the `_bf16` sets against the others), so it is asked for, \
never a default. `--keep-bf16`, which asks for the stored form, is refused \
beside it.",
site: Site::Parsed {
left: &[],
phase: Phase::Load,
},
},
LeverSpec {
name: "BLOOMERY_POISON",
class: Class::D,
Expand Down
12 changes: 8 additions & 4 deletions crates/levers/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,7 @@ fn accessors_read_their_rows() {
assert_eq!(unset.host_lanes(), HOST_LANES_DEFAULT);
assert_eq!(unset.nvtier_mem(), NvTierMem::Auto);
assert_eq!(unset.gen_slots(), 1);
assert!(!unset.prepare_q8());
assert_eq!(
unset.host(),
HostCfg {
Expand Down Expand Up @@ -448,6 +449,7 @@ fn accessors_read_their_rows() {
(NVTIER_MEM, "pinned"),
(PREFILL_GROUP, "8"),
(GEN_SLOTS, "2"),
(PREPARE_Q8, "1"),
]),
Scope::Every,
)
Expand Down Expand Up @@ -498,6 +500,7 @@ fn accessors_read_their_rows() {
);
}
assert_eq!(set.gen_slots(), 2);
assert!(set.prepare_q8());
assert_eq!(
set.host(),
HostCfg {
Expand Down Expand Up @@ -553,7 +556,8 @@ fn accessors_read_their_rows() {
GEN_SLOTS,
FORCE_IDS,
SCREEN,
SCHEMAJUMP
SCHEMAJUMP,
PREPARE_Q8
]
);
}
Expand Down Expand Up @@ -1303,10 +1307,10 @@ fn draft38_unset_follows_the_place_and_the_file() {
assert_eq!(
Draft38Off::Borrowed {
name: "output.weight".to_string(),
ty: "q6_K".to_string()
ty: "f16".to_string()
}
.to_string(),
"unset: the target's output.weight is q6_K; the MTP draft reads it as Q8_0"
"unset: the target's output.weight is f16, not a form the MTP draft reads"
);
}

Expand Down Expand Up @@ -1449,7 +1453,7 @@ fn a_paged_plan_turns_only_an_unset_draft_off() {
Draft38Off::Ctx { need: 5, ctx: 4 },
Draft38Off::Borrowed {
name: "output.weight".to_string(),
ty: "q6_K".to_string(),
ty: "f16".to_string(),
},
] {
assert_eq!(
Expand Down
2 changes: 2 additions & 0 deletions crates/model-hf/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ workspace = true
[dependencies]
bloomery-gguf = { path = "../gguf" }
bloomery-hf = { path = "../hf" }
# The `prepare` bin reads its one lever, `BLOOMERY_PREPARE_Q8`.
bloomery-levers = { path = "../levers" }
bloomery-model = { path = "../model" }
bloomery-safetensors = { path = "../safetensors" }
# The `prepare` bin builds serving's tokenizer from the GGUF header it wrote and checks its split.
Expand Down
Loading
Loading