use std::collections::HashMap;
use std::io::{Seek, Write};
use half::f16;
use crate::backends::gguf::types::MetaValue;
use crate::backends::gguf::writer::{GgufWriter, WriterError};
use crate::quantize::ggml_quants::apex::{ApexError, ApexPolicy};
use crate::quantize::ggml_quants::quantizer::Quantizer;
use crate::quantize::ggml_quants::standard_policy::{
tensor_type_fallback, HParams, LlmType, QsState, StandardPolicy, TensorCategory,
};
use crate::quantize::ggml_quants::{
is_audio_tensor_pattern, is_vision_tensor_pattern, quantizer_for, ArchName,
Deepseek4AgenticQ2Policy, GgmlType, LlamaFtype, QuantizeError, SourceDtype, TensorRef,
};
#[derive(Debug)]
pub enum OrchestratorError {
Quantize(QuantizeError),
Apex(ApexError),
Writer(WriterError),
StreamProtocol(String),
Imatrix(crate::quantize::imatrix::ImatrixError),
}
impl std::fmt::Display for OrchestratorError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
OrchestratorError::Quantize(e) => write!(f, "convert/quantize: {e}"),
OrchestratorError::Apex(e) => write!(f, "convert/apex: {e}"),
OrchestratorError::Writer(e) => write!(f, "convert/writer: {e}"),
OrchestratorError::StreamProtocol(s) => write!(f, "convert/stream-protocol: {s}"),
OrchestratorError::Imatrix(e) => write!(f, "convert/imatrix: {e}"),
}
}
}
impl std::error::Error for OrchestratorError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
OrchestratorError::Quantize(e) => Some(e),
OrchestratorError::Apex(e) => Some(e),
OrchestratorError::Writer(e) => Some(e),
OrchestratorError::StreamProtocol(_) => None,
OrchestratorError::Imatrix(e) => Some(e),
}
}
}
impl From<crate::quantize::imatrix::ImatrixError> for OrchestratorError {
fn from(e: crate::quantize::imatrix::ImatrixError) -> Self {
OrchestratorError::Imatrix(e)
}
}
impl From<QuantizeError> for OrchestratorError {
fn from(e: QuantizeError) -> Self {
OrchestratorError::Quantize(e)
}
}
impl From<ApexError> for OrchestratorError {
fn from(e: ApexError) -> Self {
OrchestratorError::Apex(e)
}
}
impl From<WriterError> for OrchestratorError {
fn from(e: WriterError) -> Self {
OrchestratorError::Writer(e)
}
}
#[derive(Debug, Clone)]
pub struct PlanEntry {
pub name: String,
pub shape: Vec<usize>,
pub source_dtype: SourceDtype,
pub layer_index: Option<usize>,
}
#[derive(Debug, Clone)]
struct PlannedTensor {
name: String,
dims_gguf: Vec<u64>,
ggml_type: GgmlType,
expected_numel: usize,
n_per_row: usize,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PlannedTypeSize {
pub ggml_type: GgmlType,
pub tensor_count: usize,
pub payload_bytes: u64,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PlannedSizeSummary {
pub tensor_count: usize,
pub payload_bytes: u64,
pub aligned_payload_bytes: u64,
pub by_type: Vec<PlannedTypeSize>,
}
pub struct ConvertOrchestrator {
ftype: LlamaFtype,
arch: ArchName,
hparams: HParams,
apex_policy: Option<ApexPolicy>,
deepseek4_agentic_q2: bool,
metadata: Vec<(String, MetaValue)>,
planned: Vec<PlannedTensor>,
imatrix: Option<crate::quantize::imatrix::ImatrixData>,
}
impl ConvertOrchestrator {
pub fn new(ftype: LlamaFtype, arch: ArchName, hparams: HParams) -> Self {
Self {
ftype,
arch,
hparams,
apex_policy: None,
deepseek4_agentic_q2: false,
metadata: Vec::new(),
planned: Vec::new(),
imatrix: None,
}
}
pub fn new_with_apex(
ftype: LlamaFtype,
arch: ArchName,
hparams: HParams,
apex_policy: ApexPolicy,
) -> Self {
Self {
ftype,
arch,
hparams,
apex_policy: Some(apex_policy),
deepseek4_agentic_q2: false,
metadata: Vec::new(),
planned: Vec::new(),
imatrix: None,
}
}
pub fn new_deepseek4_agentic_q2(arch: ArchName, hparams: HParams) -> Self {
assert_eq!(
arch,
ArchName::Deepseek4,
"DeepSeek-V4 agentic quantization cannot be applied to another architecture"
);
Self {
ftype: LlamaFtype::MostlyQ2_K,
arch,
hparams,
apex_policy: None,
deepseek4_agentic_q2: true,
metadata: Vec::new(),
planned: Vec::new(),
imatrix: None,
}
}
pub fn with_imatrix(mut self, imatrix: Option<crate::quantize::imatrix::ImatrixData>) -> Self {
self.imatrix = imatrix;
self
}
pub fn add_metadata(&mut self, key: String, value: MetaValue) {
self.metadata.push((key, value));
}
pub fn plan_tensors(&mut self, entries: Vec<PlanEntry>) -> Result<(), OrchestratorError> {
if !self.planned.is_empty() {
return Err(OrchestratorError::StreamProtocol(format!(
"plan_tensors called twice (already planned {} tensors)",
self.planned.len()
)));
}
fn canonical_sort_key(name: &str) -> (u32, u32, &str) {
if let Some(rest) = name.strip_prefix("blk.") {
if let Some(dot) = rest.find('.') {
if let Ok(n) = rest[..dot].parse::<u32>() {
return (1, n, name);
}
}
}
(0, 0, name)
}
let mut canonical_order: Vec<usize> = (0..entries.len()).collect();
canonical_order.sort_by(|&a, &b| {
canonical_sort_key(&entries[a].name).cmp(&canonical_sort_key(&entries[b].name))
});
let mut n_attention_wv: i32 = 0;
for e in &entries {
if is_vision_tensor_pattern(&e.name) || is_audio_tensor_pattern(&e.name) {
continue;
}
if TensorCategory::classify(&e.name).is_attn_v() {
n_attention_wv += 1;
}
}
let mut qs = QsState::new(self.ftype, self.arch, LlmType::Other, self.hparams);
qs.n_attention_wv = n_attention_wv;
qs.n_ffn_down = self.hparams.n_layer as i32;
qs.n_ffn_gate = self.hparams.n_layer as i32;
qs.n_ffn_up = self.hparams.n_layer as i32;
if entries.iter().any(|e| e.name == "output.weight") {
qs.has_tied_embeddings = false;
}
let policy = StandardPolicy::new();
let mut planned: Vec<Option<PlannedTensor>> = (0..entries.len()).map(|_| None).collect();
for &orig_idx in &canonical_order {
let e = &entries[orig_idx];
let dims_gguf: Vec<u64> = e.shape.iter().map(|&d| d as u64).collect();
let expected_numel: usize = e.shape.iter().product();
let n_per_row = e.shape[0];
let is_mtp_layer = self.hparams.n_mtp_layers > 0
&& e.layer_index
.map(|li| li >= (self.hparams.n_layer - self.hparams.n_mtp_layers) as usize)
.unwrap_or(false);
let mtp_ffn_gate_inp_demote = is_mtp_layer
&& (e.name.contains("ffn_gate_inp.weight")
|| e.name.contains("ffn_gate_inp_shexp.weight"));
let ggml_type = if matches!(e.source_dtype, SourceDtype::I32 | SourceDtype::I64) {
GgmlType::I32
} else if is_vision_tensor_pattern(&e.name)
|| is_audio_tensor_pattern(&e.name)
|| mtp_ffn_gate_inp_demote
{
if mtp_ffn_gate_inp_demote {
GgmlType::F16
} else if is_f32_keep_tensor(&e.name, e.shape.len())
&& !e.name.contains(".patch_embd")
{
GgmlType::F32
} else {
GgmlType::F16
}
} else if is_f32_keep_tensor(&e.name, e.shape.len()) {
GgmlType::F32
} else {
let tref = TensorRef {
name: &e.name,
shape: &e.shape,
source_dtype: e.source_dtype,
arch: self.arch,
layer_index: e.layer_index,
};
let category = TensorCategory::classify(&e.name);
match &self.apex_policy {
Some(ap) => {
let picked = ap.target_for(&tref)?;
tensor_type_fallback(picked, tref.n_per_row())?
}
None => {
let picked = policy.target_for(&mut qs, &tref, category)?;
if self.deepseek4_agentic_q2 {
let promoted =
Deepseek4AgenticQ2Policy::new().target_for(&tref, picked);
tensor_type_fallback(promoted, tref.n_per_row())?
} else {
picked
}
}
}
};
planned[orig_idx] = Some(PlannedTensor {
name: e.name.clone(),
dims_gguf,
ggml_type,
expected_numel,
n_per_row,
});
}
self.planned = planned
.into_iter()
.map(|p| p.expect("permutation covers all indices"))
.collect();
Ok(())
}
pub fn planned_count(&self) -> usize {
self.planned.len()
}
pub fn planned_size_summary(&self) -> Result<PlannedSizeSummary, OrchestratorError> {
let mut payload_bytes = 0u64;
let mut aligned_payload_bytes = 0u64;
let mut by_type: HashMap<GgmlType, (usize, u64)> = HashMap::new();
for tensor in &self.planned {
if tensor.n_per_row == 0 || tensor.expected_numel % tensor.n_per_row != 0 {
return Err(OrchestratorError::StreamProtocol(format!(
"planned tensor `{}` has invalid numel/row shape {}/{}",
tensor.name, tensor.expected_numel, tensor.n_per_row
)));
}
let rows = tensor.expected_numel / tensor.n_per_row;
let bytes = rows
.checked_mul(tensor.ggml_type.row_size(tensor.n_per_row))
.and_then(|value| u64::try_from(value).ok())
.ok_or_else(|| {
OrchestratorError::StreamProtocol(format!(
"planned payload size overflow for `{}`",
tensor.name
))
})?;
payload_bytes = payload_bytes.checked_add(bytes).ok_or_else(|| {
OrchestratorError::StreamProtocol("planned payload total overflow".into())
})?;
let aligned = bytes
.checked_add(31)
.map(|value| value & !31)
.ok_or_else(|| {
OrchestratorError::StreamProtocol("planned aligned payload overflow".into())
})?;
aligned_payload_bytes =
aligned_payload_bytes.checked_add(aligned).ok_or_else(|| {
OrchestratorError::StreamProtocol("planned aligned total overflow".into())
})?;
let entry = by_type.entry(tensor.ggml_type).or_insert((0, 0));
entry.0 += 1;
entry.1 = entry.1.checked_add(bytes).ok_or_else(|| {
OrchestratorError::StreamProtocol("planned per-type total overflow".into())
})?;
}
let mut by_type: Vec<_> = by_type
.into_iter()
.map(
|(ggml_type, (tensor_count, payload_bytes))| PlannedTypeSize {
ggml_type,
tensor_count,
payload_bytes,
},
)
.collect();
by_type.sort_by_key(|entry| entry.ggml_type.name());
Ok(PlannedSizeSummary {
tensor_count: self.planned.len(),
payload_bytes,
aligned_payload_bytes,
by_type,
})
}
pub fn begin_write<W: Write + Seek>(
self,
writer: W,
) -> Result<StreamingWriter<W>, OrchestratorError> {
let Self {
metadata,
planned,
imatrix,
..
} = self;
let mut w = GgufWriter::new(writer);
w.write_header(planned.len() as u64, metadata.len() as u64)?;
for (k, v) in &metadata {
w.write_metadata_kv(k, v)?;
}
for p in &planned {
w.reserve_tensor_info(&p.name, &p.dims_gguf, p.ggml_type)?;
}
w.pad_to_alignment()?;
Ok(StreamingWriter {
writer: w,
planned,
next_idx: 0,
active_chunks: None,
imatrix,
coverage_quantized: 0,
coverage_with_imatrix: 0,
coverage_missing: Vec::new(),
})
}
}
pub struct StreamingWriter<W: Write + Seek> {
writer: GgufWriter<W>,
planned: Vec<PlannedTensor>,
next_idx: usize,
active_chunks: Option<ActiveTensorChunks>,
imatrix: Option<crate::quantize::imatrix::ImatrixData>,
coverage_quantized: usize,
coverage_with_imatrix: usize,
coverage_missing: Vec<String>,
}
#[derive(Debug)]
struct ActiveTensorChunks {
tensor_idx: usize,
total_elements: usize,
chunk_count: usize,
max_chunk_elements: usize,
max_input_f32_bytes: usize,
max_f16_roundtrip_f32_bytes: usize,
max_quantized_payload_bytes: usize,
max_working_vec_bytes: usize,
imatrix: Option<Vec<f32>>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct TensorChunkStats {
pub total_elements: usize,
pub chunk_count: usize,
pub max_chunk_elements: usize,
pub max_input_f32_bytes: usize,
pub max_f16_roundtrip_f32_bytes: usize,
pub max_quantized_payload_bytes: usize,
pub max_working_vec_bytes: usize,
}
impl<W: Write + Seek> StreamingWriter<W> {
fn tensor_imatrix(
&self,
tensor_name: &str,
n_per_row: usize,
) -> Result<Option<Vec<f32>>, crate::quantize::imatrix::ImatrixError> {
let Some(data) = self.imatrix.as_ref() else {
return Ok(None);
};
let Some(acc) = data.loaded.registry.get(tensor_name) else {
return Ok(None);
};
if acc.n_per_row != n_per_row {
return Err(crate::quantize::imatrix::ImatrixError::ApplyShapeMismatch {
tensor: tensor_name.to_string(),
imatrix_n_per_row: acc.n_per_row,
model_n_per_row: n_per_row,
});
}
if acc.n_mat == 0 || acc.values.is_empty() {
return Ok(None);
}
if acc.n_mat == 1 {
return Ok(Some(acc.values[..n_per_row].to_vec()));
}
let total_counts: i64 = acc.counts.iter().copied().sum();
if total_counts <= 0 {
return Ok(None);
}
let mut agg = vec![0.0_f32; n_per_row];
for mat in 0..acc.n_mat {
let base = mat * n_per_row;
for j in 0..n_per_row {
agg[j] += acc.values[base + j];
}
}
let inv_total = 1.0_f32 / (total_counts as f32);
for v in agg.iter_mut() {
*v *= inv_total;
}
Ok(Some(agg))
}
pub fn tensors_remaining(&self) -> usize {
self.planned.len() - self.next_idx
}
pub fn planned_count(&self) -> usize {
self.planned.len()
}
fn validate_next_tensor(
&self,
tensor_idx: usize,
caller: &str,
) -> Result<(), OrchestratorError> {
if tensor_idx >= self.planned.len() {
return Err(OrchestratorError::StreamProtocol(format!(
"{caller}: idx {tensor_idx} out of range (planned {})",
self.planned.len()
)));
}
if tensor_idx != self.next_idx {
return Err(OrchestratorError::StreamProtocol(format!(
"{caller}: out-of-order call (got idx {tensor_idx}, expected {})",
self.next_idx
)));
}
Ok(())
}
pub fn begin_tensor_chunks(&mut self, tensor_idx: usize) -> Result<(), OrchestratorError> {
self.validate_next_tensor(tensor_idx, "begin_tensor_chunks")?;
if let Some(active) = self.active_chunks.as_ref() {
return Err(OrchestratorError::StreamProtocol(format!(
"begin_tensor_chunks: tensor {} is already active",
active.tensor_idx
)));
}
let p = &self.planned[tensor_idx];
let quantized = !matches!(p.ggml_type, GgmlType::F16 | GgmlType::F32 | GgmlType::I32);
let imatrix = if quantized {
self.tensor_imatrix(&p.name, p.n_per_row)?
} else {
None
};
self.writer.begin_tensor_payload(tensor_idx)?;
if quantized {
self.coverage_quantized += 1;
if imatrix.is_some() {
self.coverage_with_imatrix += 1;
} else if self.imatrix.is_some() {
self.coverage_missing.push(p.name.clone());
}
}
self.active_chunks = Some(ActiveTensorChunks {
tensor_idx,
total_elements: 0,
chunk_count: 0,
max_chunk_elements: 0,
max_input_f32_bytes: 0,
max_f16_roundtrip_f32_bytes: 0,
max_quantized_payload_bytes: 0,
max_working_vec_bytes: 0,
imatrix,
});
Ok(())
}
pub fn stream_tensor_chunk(
&mut self,
tensor_idx: usize,
data: &[f32],
) -> Result<(), OrchestratorError> {
let active = self.active_chunks.as_ref().ok_or_else(|| {
OrchestratorError::StreamProtocol(format!(
"stream_tensor_chunk: tensor {tensor_idx} was not begun"
))
})?;
if active.tensor_idx != tensor_idx {
return Err(OrchestratorError::StreamProtocol(format!(
"stream_tensor_chunk: tensor {tensor_idx} does not match active tensor {}",
active.tensor_idx
)));
}
if data.is_empty() {
return Err(OrchestratorError::StreamProtocol(format!(
"stream_tensor_chunk: tensor `{}` received an empty chunk",
self.planned[tensor_idx].name
)));
}
let p = &self.planned[tensor_idx];
if data.len() % p.n_per_row != 0 {
return Err(OrchestratorError::StreamProtocol(format!(
"stream_tensor_chunk: tensor `{}` chunk length {} is not row-aligned to {}",
p.name,
data.len(),
p.n_per_row
)));
}
let total_elements = active
.total_elements
.checked_add(data.len())
.ok_or_else(|| {
OrchestratorError::StreamProtocol(format!(
"stream_tensor_chunk: tensor `{}` element count overflow",
p.name
))
})?;
if total_elements > p.expected_numel {
return Err(OrchestratorError::StreamProtocol(format!(
"stream_tensor_chunk: tensor `{}` cumulative length {} exceeds planned numel {}",
p.name, total_elements, p.expected_numel
)));
}
let payload: Vec<u8> = match p.ggml_type {
GgmlType::F16 => {
let mut v = Vec::with_capacity(data.len() * 2);
for &x in data {
v.extend_from_slice(&f16::from_f32(x).to_le_bytes());
}
v
}
GgmlType::F32 => {
let mut v = Vec::with_capacity(data.len() * 4);
for &x in data {
v.extend_from_slice(&x.to_le_bytes());
}
v
}
GgmlType::I32 => {
let mut v = Vec::with_capacity(data.len() * 4);
for &x in data {
if !x.is_finite()
|| x.fract() != 0.0
|| x < i32::MIN as f32
|| x > i32::MAX as f32
{
return Err(OrchestratorError::StreamProtocol(format!(
"tensor `{}` contains non-I32 routing value {x}",
p.name
)));
}
v.extend_from_slice(&(x as i32).to_le_bytes());
}
v
}
_ => {
let quantizer = quantizer_for(p.ggml_type)?;
let f16_rt: Vec<f32> = data.iter().map(|&x| f16::from_f32(x).to_f32()).collect();
quantizer.quantize(&f16_rt, p.n_per_row, active.imatrix.as_deref())?
}
};
let input_f32_bytes = data
.len()
.checked_mul(std::mem::size_of::<f32>())
.ok_or_else(|| {
OrchestratorError::StreamProtocol(format!(
"stream_tensor_chunk: tensor `{}` input byte count overflow",
p.name
))
})?;
let quantized = !matches!(p.ggml_type, GgmlType::F16 | GgmlType::F32 | GgmlType::I32);
let f16_roundtrip_f32_bytes = if quantized { input_f32_bytes } else { 0 };
let quantized_payload_bytes = if quantized { payload.len() } else { 0 };
let working_vec_bytes = input_f32_bytes
.checked_add(f16_roundtrip_f32_bytes)
.and_then(|bytes| bytes.checked_add(payload.len()))
.ok_or_else(|| {
OrchestratorError::StreamProtocol(format!(
"stream_tensor_chunk: tensor `{}` working byte count overflow",
p.name
))
})?;
self.writer
.write_tensor_payload_chunk(tensor_idx, &payload)?;
let active = self
.active_chunks
.as_mut()
.expect("active tensor validated above");
active.total_elements = total_elements;
active.chunk_count += 1;
active.max_chunk_elements = active.max_chunk_elements.max(data.len());
active.max_input_f32_bytes = active.max_input_f32_bytes.max(input_f32_bytes);
active.max_f16_roundtrip_f32_bytes = active
.max_f16_roundtrip_f32_bytes
.max(f16_roundtrip_f32_bytes);
active.max_quantized_payload_bytes = active
.max_quantized_payload_bytes
.max(quantized_payload_bytes);
active.max_working_vec_bytes = active.max_working_vec_bytes.max(working_vec_bytes);
Ok(())
}
pub fn finish_tensor_chunks(
&mut self,
tensor_idx: usize,
) -> Result<TensorChunkStats, OrchestratorError> {
let active = self.active_chunks.as_ref().ok_or_else(|| {
OrchestratorError::StreamProtocol(format!(
"finish_tensor_chunks: tensor {tensor_idx} was not begun"
))
})?;
if active.tensor_idx != tensor_idx {
return Err(OrchestratorError::StreamProtocol(format!(
"finish_tensor_chunks: tensor {tensor_idx} does not match active tensor {}",
active.tensor_idx
)));
}
let expected = self.planned[tensor_idx].expected_numel;
if active.total_elements != expected {
return Err(OrchestratorError::StreamProtocol(format!(
"finish_tensor_chunks: tensor `{}` received {} elements, expected {}",
self.planned[tensor_idx].name, active.total_elements, expected
)));
}
self.writer.finish_tensor_payload(tensor_idx)?;
let active = self.active_chunks.take().expect("validated active tensor");
self.next_idx += 1;
Ok(TensorChunkStats {
total_elements: active.total_elements,
chunk_count: active.chunk_count,
max_chunk_elements: active.max_chunk_elements,
max_input_f32_bytes: active.max_input_f32_bytes,
max_f16_roundtrip_f32_bytes: active.max_f16_roundtrip_f32_bytes,
max_quantized_payload_bytes: active.max_quantized_payload_bytes,
max_working_vec_bytes: active.max_working_vec_bytes,
})
}
pub fn stream_tensor(
&mut self,
tensor_idx: usize,
data: &[f32],
) -> Result<TensorChunkStats, OrchestratorError> {
self.validate_next_tensor(tensor_idx, "stream_tensor")?;
let p = &self.planned[tensor_idx];
if data.len() != p.expected_numel {
return Err(OrchestratorError::StreamProtocol(format!(
"stream_tensor: tensor `{}` data length {} != planned numel {}",
p.name,
data.len(),
p.expected_numel
)));
}
self.begin_tensor_chunks(tensor_idx)?;
if !data.is_empty() {
self.stream_tensor_chunk(tensor_idx, data)?;
}
self.finish_tensor_chunks(tensor_idx)
}
pub fn finalize(mut self) -> Result<(), OrchestratorError> {
if let Some(active) = self.active_chunks.as_ref() {
return Err(OrchestratorError::StreamProtocol(format!(
"finalize: tensor {} still has an active chunk stream",
active.tensor_idx
)));
}
if self.next_idx != self.planned.len() {
return Err(OrchestratorError::StreamProtocol(format!(
"finalize: only {} of {} planned tensors streamed",
self.next_idx,
self.planned.len()
)));
}
self.writer.finalize()?;
if self.imatrix.is_some() && self.coverage_quantized > 0 {
let pct = (self.coverage_with_imatrix as f64 / self.coverage_quantized as f64) * 100.0;
eprintln!(
"[hf2q imatrix coverage] {}/{} quantized tensors used imatrix calibration ({:.1}%)",
self.coverage_with_imatrix, self.coverage_quantized, pct
);
if !self.coverage_missing.is_empty() {
let preview_n = self.coverage_missing.len().min(10);
eprintln!(
"[hf2q imatrix coverage] {} quantized tensor(s) had no matching imatrix entry; first {}:",
self.coverage_missing.len(),
preview_n
);
for name in self.coverage_missing.iter().take(preview_n) {
eprintln!("[hf2q imatrix coverage] - {name}");
}
if self.coverage_missing.len() > preview_n {
eprintln!(
"[hf2q imatrix coverage] … and {} more",
self.coverage_missing.len() - preview_n
);
}
}
}
Ok(())
}
}
fn is_f32_keep_tensor(name: &str, n_dims: usize) -> bool {
if n_dims < 2 {
return true;
}
if !name.ends_with(".weight") {
return true;
}
name == "position_embd.weight" || name == "token_types.weight" || name.contains("_norm.weight") || name.contains("ffn_gate_inp.weight") || name.contains("altup") || name.contains("laurel") || name.contains("per_layer_model_proj") || name.contains("ssm_conv1d") || name.contains("shortconv.conv.weight") || name.contains("time_mix_first.weight")
|| name.contains("time_mix_w0.weight")
|| name.contains("time_mix_w1.weight")
|| name.contains("time_mix_w2.weight")
|| name.contains("time_mix_v0.weight")
|| name.contains("time_mix_v1.weight")
|| name.contains("time_mix_v2.weight")
|| name.contains("time_mix_a0.weight")
|| name.contains("time_mix_a1.weight")
|| name.contains("time_mix_a2.weight")
|| name.contains("time_mix_g1.weight")
|| name.contains("time_mix_g2.weight")
|| name.contains("time_mix_decay_w1.weight")
|| name.contains("time_mix_decay_w2.weight")
|| name.contains("time_mix_lerp_fused.weight")
|| name.contains("attn_rel_b.weight") || name.contains(".position_embd") || name.contains("sam.pos_embd") || name.contains("sam.neck.") || name.contains("sam.net_") || name.contains(".rel_pos") || name.contains(".patch_embd") || name.contains(".patch_merger") || name == "rope_freqs.weight" }
#[derive(Debug, Clone)]
pub struct StagedTensor {
pub name: String,
pub shape: Vec<usize>,
pub data: Vec<f32>,
pub source_dtype: SourceDtype,
pub layer_index: Option<usize>,
}
pub fn convert_synthetic<W: Write + Seek>(
ftype: LlamaFtype,
arch: ArchName,
hparams: HParams,
metadata: Vec<(String, MetaValue)>,
tensors: Vec<StagedTensor>,
writer: W,
) -> Result<(), OrchestratorError> {
let mut orch = ConvertOrchestrator::new(ftype, arch, hparams);
for (k, v) in metadata {
orch.add_metadata(k, v);
}
let entries: Vec<PlanEntry> = tensors
.iter()
.map(|t| PlanEntry {
name: t.name.clone(),
shape: t.shape.clone(),
source_dtype: t.source_dtype,
layer_index: t.layer_index,
})
.collect();
orch.plan_tensors(entries)?;
let mut sw = orch.begin_write(writer)?;
for (idx, t) in tensors.iter().enumerate() {
sw.stream_tensor(idx, &t.data)?;
}
sw.finalize()
}
#[cfg(test)]
mod tests {
use super::*;
use std::io::Write as IoWrite;
fn deterministic_data(n: usize, seed: u32) -> Vec<f32> {
(0..n)
.map(|i| {
let x = ((i as u32).wrapping_mul(2654435761).wrapping_add(seed)) as i32;
(x as f32) / (i32::MAX as f32)
})
.collect()
}
fn default_hparams() -> HParams {
HParams {
n_expert: 0,
n_head: 32,
n_head_kv: 8,
n_layer: 32,
n_mtp_layers: 0,
}
}
#[test]
fn smoke_q5_k_m_round_trip_via_reader() {
let mut orch = ConvertOrchestrator::new(
LlamaFtype::MostlyQ5_K_M,
ArchName::Llama3,
default_hparams(),
);
orch.add_metadata(
"general.architecture".to_string(),
MetaValue::String("llama".into()),
);
orch.add_metadata("general.alignment".to_string(), MetaValue::U32(32));
let n_per_row = 256usize;
let shape = vec![n_per_row, 1];
let entries = vec![
PlanEntry {
name: "token_embd.weight".into(),
shape: shape.clone(),
source_dtype: SourceDtype::F32,
layer_index: None,
},
PlanEntry {
name: "output.weight".into(),
shape: shape.clone(),
source_dtype: SourceDtype::F32,
layer_index: None,
},
PlanEntry {
name: "blk.0.attn_q.weight".into(),
shape: shape.clone(),
source_dtype: SourceDtype::F32,
layer_index: Some(0),
},
PlanEntry {
name: "blk.0.ffn_down.weight".into(),
shape: shape.clone(),
source_dtype: SourceDtype::F32,
layer_index: Some(0),
},
];
let datas = vec![
deterministic_data(n_per_row, 1),
deterministic_data(n_per_row, 2),
deterministic_data(n_per_row, 3),
deterministic_data(n_per_row, 4),
];
orch.plan_tensors(entries).expect("plan");
let tmp = tempfile::NamedTempFile::new().unwrap();
{
let f = std::fs::File::create(tmp.path()).unwrap();
let mut sw = orch.begin_write(f).expect("begin_write");
for (idx, d) in datas.iter().enumerate() {
sw.stream_tensor(idx, d).expect("stream");
}
sw.finalize().expect("finalize");
}
let gguf =
mlx_native::gguf::GgufFile::open(tmp.path()).expect("mlx_native parses our GGUF");
assert_eq!(gguf.metadata_count(), 2);
assert_eq!(gguf.metadata_string("general.architecture"), Some("llama"));
assert_eq!(gguf.metadata_u32("general.alignment"), Some(32));
assert_eq!(gguf.tensor_count(), 4);
let token = gguf
.tensor_info("token_embd.weight")
.expect("token_embd present");
let output = gguf.tensor_info("output.weight").expect("output present");
let attn_q = gguf
.tensor_info("blk.0.attn_q.weight")
.expect("attn_q present");
let ffn_down = gguf
.tensor_info("blk.0.ffn_down.weight")
.expect("ffn_down present");
assert_eq!(token.shape, vec![1, 256]);
assert_eq!(output.shape, vec![1, 256]);
assert_eq!(attn_q.shape, vec![1, 256]);
assert_eq!(ffn_down.shape, vec![1, 256]);
assert_eq!(
token.ggml_type,
mlx_native::GgmlType::Q5_K,
"token_embd (non-tied) → Q5_K"
);
assert_eq!(
output.ggml_type,
mlx_native::GgmlType::Q6_K,
"output → Q6_K"
);
assert_eq!(
attn_q.ggml_type,
mlx_native::GgmlType::Q5_K,
"attn_q → Q5_K"
);
assert_eq!(
ffn_down.ggml_type,
mlx_native::GgmlType::Q6_K,
"ffn_down (i=0) → Q6_K"
);
assert_eq!(token.offset % 32, 0);
assert_eq!(output.offset % 32, 0);
assert_eq!(attn_q.offset % 32, 0);
assert_eq!(ffn_down.offset % 32, 0);
}
#[test]
fn vision_pattern_emits_f16_skipping_policy() {
let mut orch = ConvertOrchestrator::new(
LlamaFtype::MostlyQ5_K_M,
ArchName::Gemma4Mmproj,
default_hparams(),
);
orch.add_metadata(
"general.architecture".to_string(),
MetaValue::String("gemma4_mmproj".into()),
);
let n_per_row = 15usize;
let shape = vec![n_per_row, 2];
let data_vis = deterministic_data(n_per_row * 2, 7);
let entries = vec![
PlanEntry {
name: "model.visual.patch_embd.weight".into(),
shape: shape.clone(),
source_dtype: SourceDtype::F32,
layer_index: None,
},
PlanEntry {
name: "blk.0.attn_q.weight".into(),
shape: vec![256, 1],
source_dtype: SourceDtype::F32,
layer_index: Some(0),
},
];
let data_attn = deterministic_data(256, 8);
orch.plan_tensors(entries).expect("plan");
let tmp = tempfile::NamedTempFile::new().unwrap();
{
let f = std::fs::File::create(tmp.path()).unwrap();
let mut sw = orch.begin_write(f).expect("begin_write");
sw.stream_tensor(0, &data_vis).expect("stream vis");
sw.stream_tensor(1, &data_attn).expect("stream attn");
sw.finalize().expect("finalize");
}
let gguf =
mlx_native::gguf::GgufFile::open(tmp.path()).expect("mlx_native parses our GGUF");
let visual = gguf
.tensor_info("model.visual.patch_embd.weight")
.expect("vision tensor present");
assert_eq!(
visual.ggml_type,
mlx_native::GgmlType::F16,
"vision tensor must emit F16, got {:?}",
visual.ggml_type
);
assert_eq!(visual.byte_len, 60);
let attn_q = gguf
.tensor_info("blk.0.attn_q.weight")
.expect("policy tensor present");
assert_eq!(
attn_q.ggml_type,
mlx_native::GgmlType::Q5_K,
"non-vision sibling must still route through policy → Q5_K"
);
}
#[test]
fn unquantizable_row_surfaces_typed_error() {
let mut orch = ConvertOrchestrator::new(
LlamaFtype::MostlyQ5_K_M,
ArchName::Llama3,
default_hparams(),
);
orch.add_metadata(
"general.architecture".to_string(),
MetaValue::String("llama".into()),
);
let n_per_row = 15usize;
let entries = vec![PlanEntry {
name: "blk.0.attn_q.weight".into(),
shape: vec![n_per_row, 1],
source_dtype: SourceDtype::F32,
layer_index: Some(0),
}];
let err = orch.plan_tensors(entries).expect_err("must error");
match err {
OrchestratorError::Quantize(QuantizeError::NotBlockAligned {
n_per_row: 15,
..
}) => {}
other => panic!(
"expected OrchestratorError::Quantize(NotBlockAligned {{ n_per_row: 15, .. }}), got {other:?}"
),
}
}
#[test]
fn stream_tensor_rejects_out_of_order() {
let mut orch = ConvertOrchestrator::new(
LlamaFtype::MostlyQ5_K_M,
ArchName::Llama3,
default_hparams(),
);
orch.add_metadata(
"general.architecture".to_string(),
MetaValue::String("llama".into()),
);
let n_per_row = 256usize;
let entries = vec![
PlanEntry {
name: "blk.0.attn_q.weight".into(),
shape: vec![n_per_row, 1],
source_dtype: SourceDtype::F32,
layer_index: Some(0),
},
PlanEntry {
name: "blk.1.attn_q.weight".into(),
shape: vec![n_per_row, 1],
source_dtype: SourceDtype::F32,
layer_index: Some(1),
},
];
orch.plan_tensors(entries).expect("plan");
let mut buf = std::io::Cursor::new(Vec::<u8>::new());
let mut sw = orch.begin_write(&mut buf).expect("begin_write");
let data = deterministic_data(n_per_row, 5);
let err = sw.stream_tensor(1, &data).expect_err("must error");
assert!(
matches!(err, OrchestratorError::StreamProtocol(_)),
"got {err:?}"
);
}
#[test]
fn stream_tensor_rejects_wrong_length() {
let mut orch = ConvertOrchestrator::new(
LlamaFtype::MostlyQ5_K_M,
ArchName::Llama3,
default_hparams(),
);
orch.add_metadata(
"general.architecture".to_string(),
MetaValue::String("llama".into()),
);
orch.plan_tensors(vec![PlanEntry {
name: "blk.0.attn_q.weight".into(),
shape: vec![256, 1],
source_dtype: SourceDtype::F32,
layer_index: Some(0),
}])
.expect("plan");
let mut buf = std::io::Cursor::new(Vec::<u8>::new());
let mut sw = orch.begin_write(&mut buf).expect("begin_write");
let bogus = deterministic_data(128, 5); let err = sw.stream_tensor(0, &bogus).expect_err("must error");
assert!(
matches!(err, OrchestratorError::StreamProtocol(_)),
"got {err:?}"
);
}
fn one_deepseek_q2_tensor(shape: Vec<usize>) -> ConvertOrchestrator {
let mut orch = ConvertOrchestrator::new(
LlamaFtype::MostlyQ2_K_S,
ArchName::Deepseek4,
HParams {
n_expert: shape.last().copied().unwrap_or(0) as u32,
n_head: 4,
n_head_kv: 1,
n_layer: 1,
n_mtp_layers: 0,
},
);
orch.plan_tensors(vec![PlanEntry {
name: "blk.0.ffn_gate_exps.weight".into(),
shape,
source_dtype: SourceDtype::Mxfp4E2M1,
layer_index: Some(0),
}])
.expect("plan DeepSeek expert tensor");
orch
}
fn one_deepseek_agentic_tensor(name: &str, shape: Vec<usize>) -> ConvertOrchestrator {
let mut orch = ConvertOrchestrator::new_deepseek4_agentic_q2(
ArchName::Deepseek4,
HParams {
n_expert: shape.last().copied().unwrap_or(0) as u32,
n_head: 4,
n_head_kv: 1,
n_layer: 1,
n_mtp_layers: 0,
},
);
orch.plan_tensors(vec![PlanEntry {
name: name.into(),
shape,
source_dtype: SourceDtype::Mxfp4E2M1,
layer_index: Some(0),
}])
.expect("plan DeepSeek agentic tensor");
orch
}
#[test]
fn deepseek4_agentic_q2_plan_pins_context_path_and_keeps_mixed_experts() {
let mut orch = ConvertOrchestrator::new_deepseek4_agentic_q2(
ArchName::Deepseek4,
HParams {
n_expert: 256,
n_head: 64,
n_head_kv: 1,
n_layer: 43,
n_mtp_layers: 0,
},
);
let entry = |name: &str| PlanEntry {
name: name.into(),
shape: vec![4096, 256],
source_dtype: SourceDtype::F32,
layer_index: name
.strip_prefix("blk.")
.and_then(|rest| rest.split('.').next())
.and_then(|layer| layer.parse().ok()),
};
orch.plan_tensors(vec![
entry("output.weight"),
entry("token_embd.weight"),
entry("blk.2.attn_compressor_gate.weight"),
entry("blk.2.attn_q_b.weight"),
entry("blk.2.hc_attn_fn.weight"),
entry("blk.2.indexer.attn_q_b.weight"),
entry("blk.2.ffn_gate_exps.weight"),
entry("blk.2.ffn_up_exps.weight"),
entry("blk.2.ffn_down_exps.weight"),
entry("blk.2.ffn_down_shexp.weight"),
])
.unwrap();
let planned: std::collections::HashMap<_, _> = orch
.planned
.iter()
.map(|tensor| (tensor.name.as_str(), tensor.ggml_type))
.collect();
for name in [
"output.weight",
"token_embd.weight",
"blk.2.attn_compressor_gate.weight",
"blk.2.attn_q_b.weight",
"blk.2.hc_attn_fn.weight",
"blk.2.indexer.attn_q_b.weight",
] {
assert_eq!(planned[name], GgmlType::Q8_0, "{name}");
}
assert_eq!(planned["blk.2.ffn_gate_exps.weight"], GgmlType::Q2_K);
assert_eq!(planned["blk.2.ffn_up_exps.weight"], GgmlType::Q2_K);
assert_eq!(planned["blk.2.ffn_down_exps.weight"], GgmlType::Q3_K);
assert_eq!(planned["blk.2.ffn_down_shexp.weight"], GgmlType::Q3_K);
}
#[test]
fn q2_k_s_chunked_rows_are_byte_identical_to_whole_tensor() {
let n_per_row = 256;
let rows_per_expert = 4;
let experts = 2;
let per_expert = n_per_row * rows_per_expert;
let data = deterministic_data(per_expert * experts, 0x5eed);
let mut whole = std::io::Cursor::new(Vec::new());
{
let mut sw = one_deepseek_q2_tensor(vec![n_per_row, rows_per_expert, experts])
.begin_write(&mut whole)
.unwrap();
sw.stream_tensor(0, &data).unwrap();
sw.finalize().unwrap();
}
let mut chunked = std::io::Cursor::new(Vec::new());
{
let mut sw = one_deepseek_q2_tensor(vec![n_per_row, rows_per_expert, experts])
.begin_write(&mut chunked)
.unwrap();
sw.begin_tensor_chunks(0).unwrap();
sw.stream_tensor_chunk(0, &data[..per_expert]).unwrap();
sw.stream_tensor_chunk(0, &data[per_expert..]).unwrap();
let stats = sw.finish_tensor_chunks(0).unwrap();
assert_eq!(stats.chunk_count, experts);
assert_eq!(stats.max_chunk_elements, per_expert);
assert_eq!(stats.max_input_f32_bytes, per_expert * 4);
assert_eq!(stats.max_f16_roundtrip_f32_bytes, per_expert * 4);
assert_eq!(
stats.max_quantized_payload_bytes,
rows_per_expert * GgmlType::Q2_K.row_size(n_per_row)
);
assert_eq!(
stats.max_working_vec_bytes,
stats.max_input_f32_bytes
+ stats.max_f16_roundtrip_f32_bytes
+ stats.max_quantized_payload_bytes
);
sw.finalize().unwrap();
}
assert_eq!(chunked.into_inner(), whole.into_inner());
}
#[test]
fn agentic_q3_k_expert_down_chunks_are_byte_identical_to_whole_tensor() {
let n_per_row = 256;
let rows_per_expert = 4;
let experts = 3;
let per_expert = n_per_row * rows_per_expert;
let shape = vec![n_per_row, rows_per_expert, experts];
let data = deterministic_data(per_expert * experts, 0x43d0_0003);
let make = || one_deepseek_agentic_tensor("blk.0.ffn_down_exps.weight", shape.clone());
let mut whole = std::io::Cursor::new(Vec::new());
{
let mut stream = make().begin_write(&mut whole).unwrap();
stream.stream_tensor(0, &data).unwrap();
stream.finalize().unwrap();
}
let mut chunked = std::io::Cursor::new(Vec::new());
{
let mut stream = make().begin_write(&mut chunked).unwrap();
stream.begin_tensor_chunks(0).unwrap();
for expert in data.chunks_exact(per_expert) {
stream.stream_tensor_chunk(0, expert).unwrap();
}
let stats = stream.finish_tensor_chunks(0).unwrap();
assert_eq!(stats.chunk_count, experts);
assert_eq!(stats.max_chunk_elements, per_expert);
assert_eq!(
stats.max_quantized_payload_bytes,
rows_per_expert * GgmlType::Q3_K.row_size(n_per_row)
);
stream.finalize().unwrap();
}
assert_eq!(chunked.into_inner(), whole.into_inner());
}
#[test]
fn chunked_stream_preserves_256_expert_order_with_one_expert_live() {
const EXPERTS: usize = 256;
const N_PER_ROW: usize = 256;
let mut orch = ConvertOrchestrator::new(
LlamaFtype::MostlyQ2_K_S,
ArchName::Deepseek4,
HParams {
n_expert: EXPERTS as u32,
n_head: 4,
n_head_kv: 1,
n_layer: 1,
n_mtp_layers: 0,
},
);
let name = "blk.0.ffn_gate_tid2eid.weight";
orch.plan_tensors(vec![PlanEntry {
name: name.into(),
shape: vec![N_PER_ROW, 1, EXPERTS],
source_dtype: SourceDtype::I64,
layer_index: Some(0),
}])
.unwrap();
let mut out = std::io::Cursor::new(Vec::new());
{
let mut sw = orch.begin_write(&mut out).unwrap();
sw.begin_tensor_chunks(0).unwrap();
for expert in 0..EXPERTS {
let one_expert = vec![expert as f32; N_PER_ROW];
sw.stream_tensor_chunk(0, &one_expert).unwrap();
}
let stats = sw.finish_tensor_chunks(0).unwrap();
assert_eq!(stats.chunk_count, EXPERTS);
assert_eq!(stats.total_elements, EXPERTS * N_PER_ROW);
assert_eq!(stats.max_chunk_elements, N_PER_ROW);
sw.finalize().unwrap();
}
let bytes = out.into_inner();
let header_bytes = 24 + 8 + name.len() + 4 + 3 * 8 + 4 + 8;
let data_start = (header_bytes + 31) / 32 * 32;
let payload = &bytes[data_start..data_start + EXPERTS * N_PER_ROW * 4];
for (index, word) in payload.chunks_exact(4).enumerate() {
assert_eq!(
i32::from_le_bytes(word.try_into().unwrap()),
(index / N_PER_ROW) as i32,
"expert-major ordering changed at element {index}"
);
}
}
#[test]
fn official_deepseek_expert_chunk_has_a_66_625_mib_working_set_bound() {
const EXPERTS: usize = 256;
const ROWS: usize = 2048;
const N_PER_ROW: usize = 4096;
let decoded_f32 = ROWS * N_PER_ROW * std::mem::size_of::<f32>();
let f16_roundtrip_f32 = decoded_f32;
let q2_payload = ROWS * GgmlType::Q2_K.row_size(N_PER_ROW);
let bounded_peak = decoded_f32 + f16_roundtrip_f32 + q2_payload;
let former_whole_tensor_peak = bounded_peak * EXPERTS;
assert_eq!(decoded_f32, 32 * 1024 * 1024);
assert_eq!(q2_payload, 2_752_512);
assert_eq!(bounded_peak, 69_861_376); assert_eq!(former_whole_tensor_peak / bounded_peak, EXPERTS);
assert_eq!(former_whole_tensor_peak, 17_884_512_256);
}
#[test]
fn chunked_stream_rejects_misaligned_and_incomplete_input() {
let mut out = std::io::Cursor::new(Vec::new());
let mut sw = one_deepseek_q2_tensor(vec![256, 2, 2])
.begin_write(&mut out)
.unwrap();
sw.begin_tensor_chunks(0).unwrap();
let err = sw.stream_tensor_chunk(0, &[0.0; 1280]).unwrap_err();
assert!(matches!(err, OrchestratorError::StreamProtocol(_)));
let err = sw.stream_tensor_chunk(0, &[0.0; 255]).unwrap_err();
assert!(matches!(err, OrchestratorError::StreamProtocol(_)));
sw.stream_tensor_chunk(0, &[0.0; 256]).unwrap();
let err = sw.finish_tensor_chunks(0).unwrap_err();
assert!(matches!(err, OrchestratorError::StreamProtocol(_)));
}
#[test]
fn finalize_rejects_incomplete_stream() {
let mut orch = ConvertOrchestrator::new(
LlamaFtype::MostlyQ5_K_M,
ArchName::Llama3,
default_hparams(),
);
orch.add_metadata(
"general.architecture".to_string(),
MetaValue::String("llama".into()),
);
orch.plan_tensors(vec![
PlanEntry {
name: "blk.0.attn_q.weight".into(),
shape: vec![256, 1],
source_dtype: SourceDtype::F32,
layer_index: Some(0),
},
PlanEntry {
name: "blk.1.attn_q.weight".into(),
shape: vec![256, 1],
source_dtype: SourceDtype::F32,
layer_index: Some(1),
},
])
.expect("plan");
let mut buf = std::io::Cursor::new(Vec::<u8>::new());
let sw = orch.begin_write(&mut buf).expect("begin_write");
let err = sw.finalize().expect_err("must error");
assert!(
matches!(err, OrchestratorError::StreamProtocol(_)),
"got {err:?}"
);
}
#[test]
fn convert_synthetic_entry_point_works() {
let metadata = vec![(
"general.architecture".to_string(),
MetaValue::String("llama".into()),
)];
let tensors = vec![StagedTensor {
name: "blk.0.attn_q.weight".into(),
shape: vec![256, 1],
data: deterministic_data(256, 11),
source_dtype: SourceDtype::F32,
layer_index: Some(0),
}];
let tmp = tempfile::NamedTempFile::new().unwrap();
{
let f = std::fs::File::create(tmp.path()).unwrap();
convert_synthetic(
LlamaFtype::MostlyQ5_K_M,
ArchName::Llama3,
default_hparams(),
metadata,
tensors,
f,
)
.expect("convert_synthetic");
}
let gguf = mlx_native::gguf::GgufFile::open(tmp.path()).expect("parse");
assert_eq!(gguf.tensor_count(), 1);
let t = gguf.tensor_info("blk.0.attn_q.weight").unwrap();
assert_eq!(t.ggml_type, mlx_native::GgmlType::Q5_K);
}
#[test]
fn moe_ffn_down_use_more_bits_uses_n_layer_not_counted_tensors() {
const N_LAYER: u32 = 30;
let hparams = HParams {
n_expert: 128,
n_head: 8,
n_head_kv: 1,
n_layer: N_LAYER,
n_mtp_layers: 0,
};
let mut orch =
ConvertOrchestrator::new(LlamaFtype::MostlyQ5_K_M, ArchName::Gemma4, hparams);
orch.add_metadata(
"general.architecture".to_string(),
MetaValue::String("gemma4".into()),
);
let n_per_row = 256usize;
let shape = vec![n_per_row, 64];
let mut entries: Vec<PlanEntry> = Vec::new();
for li in 0..N_LAYER as usize {
entries.push(PlanEntry {
name: format!("blk.{li}.ffn_down.weight"),
shape: shape.clone(),
source_dtype: SourceDtype::F32,
layer_index: Some(li),
});
entries.push(PlanEntry {
name: format!("blk.{li}.ffn_down_exps.scale"),
shape: vec![128usize, 1],
source_dtype: SourceDtype::F32,
layer_index: Some(li),
});
entries.push(PlanEntry {
name: format!("blk.{li}.ffn_down_exps.weight"),
shape: shape.clone(),
source_dtype: SourceDtype::F32,
layer_index: Some(li),
});
}
orch.plan_tensors(entries).expect("plan");
let canonical_promoted: std::collections::HashSet<usize> =
[0, 1, 2, 5, 8, 11, 14, 17, 20, 23, 26, 27, 28, 29]
.into_iter()
.collect();
let mut q6k_layers: std::collections::HashSet<usize> = std::collections::HashSet::new();
for pt in orch.planned.iter() {
if pt.name.ends_with(".ffn_down.weight") && pt.name.starts_with("blk.") {
let layer: usize = pt
.name
.strip_prefix("blk.")
.and_then(|s| s.split('.').next())
.and_then(|s| s.parse().ok())
.expect("layer parse");
if matches!(pt.ggml_type, crate::quantize::ggml_quants::GgmlType::Q6_K) {
q6k_layers.insert(layer);
}
}
}
assert_eq!(
q6k_layers, canonical_promoted,
"ffn_down Q6_K promotion must match canonical use_more_bits(i, n_layer=30); \
pre-fix bug had n_ffn_down=90 and would produce 17 layers including {{3,4,6,7,9,10,13,16,19,22,25}}."
);
}
#[test]
fn attn_v_visit_order_sorts_to_canonical_numeric_layer_order() {
const N_LAYER: u32 = 30;
let hparams = HParams {
n_expert: 128,
n_head: 8,
n_head_kv: 1,
n_layer: N_LAYER,
n_mtp_layers: 0,
};
let mut orch =
ConvertOrchestrator::new(LlamaFtype::MostlyQ5_K_M, ArchName::Gemma4, hparams);
orch.add_metadata(
"general.architecture".to_string(),
MetaValue::String("gemma4".into()),
);
let n_per_row = 256usize;
let shape = vec![n_per_row, 64];
let layers_lex: Vec<u32> = {
let mut v: Vec<u32> = (0..N_LAYER).collect();
v.sort_by_key(|n| format!("{n}"));
v
};
let mut entries: Vec<PlanEntry> = Vec::new();
for li in layers_lex {
entries.push(PlanEntry {
name: format!("blk.{li}.attn_v.weight"),
shape: shape.clone(),
source_dtype: SourceDtype::F32,
layer_index: Some(li as usize),
});
}
orch.plan_tensors(entries).expect("plan");
fn use_more_bits(i: u32, n: u32) -> bool {
i < n / 8 || i >= 7 * n / 8 || (i.saturating_sub(n / 8)) % 3 == 2
}
for pt in orch.planned.iter() {
let layer: u32 = pt
.name
.strip_prefix("blk.")
.and_then(|s| s.split('.').next())
.and_then(|s| s.parse().ok())
.expect("layer parse");
let expected = if use_more_bits(layer, N_LAYER) {
crate::quantize::ggml_quants::GgmlType::Q6_K
} else {
crate::quantize::ggml_quants::GgmlType::Q5_K
};
assert_eq!(
pt.ggml_type, expected,
"blk.{layer}.attn_v.weight: visit-order-sorted plan must produce \
the canonical use_more_bits(layer, 30) type. Pre-fix bug would \
produce Q5_K↔Q6_K swaps due to lexical iteration order."
);
}
}
#[test]
fn empty_conversion_writes_header_only_gguf() {
let mut orch = ConvertOrchestrator::new(
LlamaFtype::MostlyQ5_K_M,
ArchName::Llama3,
default_hparams(),
);
orch.plan_tensors(Vec::new()).expect("plan empty");
let tmp = tempfile::NamedTempFile::new().unwrap();
{
let mut f = std::fs::File::create(tmp.path()).unwrap();
let sw = orch.begin_write(&mut f).expect("begin_write");
sw.finalize().expect("finalize empty");
f.flush().unwrap();
}
let gguf = mlx_native::gguf::GgufFile::open(tmp.path()).expect("parse");
assert_eq!(gguf.tensor_count(), 0);
assert_eq!(gguf.metadata_count(), 0);
}
fn make_dense_imatrix(
tensor_name: &str,
n_per_row: usize,
seed: u32,
) -> crate::quantize::imatrix::ImatrixData {
let mut registry = crate::quantize::imatrix::AccumulatorRegistry::new();
let acc = registry
.register(tensor_name, n_per_row, 1)
.expect("register accumulator");
let row1 = deterministic_data(n_per_row, seed);
let row2 = deterministic_data(n_per_row, seed.wrapping_add(1));
acc.absorb_dense(&row1).expect("absorb 1");
acc.absorb_dense(&row2).expect("absorb 2");
let loaded = crate::quantize::imatrix::LoadedImatrix {
source_path: "<synthetic>".into(),
datasets: vec!["test".into()],
chunk_count: 1,
chunk_size: 512,
registry,
};
crate::quantize::imatrix::ImatrixData {
loaded,
provenance: crate::quantize::imatrix::ImatrixProvenance::Computed {
corpus_label: "test".into(),
n_ctx: 512,
},
}
}
fn make_moe_imatrix(
tensor_name: &str,
n_per_row: usize,
n_experts: usize,
seed: u32,
) -> crate::quantize::imatrix::ImatrixData {
let mut registry = crate::quantize::imatrix::AccumulatorRegistry::new();
let acc = registry
.register(tensor_name, n_per_row, n_experts)
.expect("register MoE accumulator");
for expert_id in 0..n_experts {
let row = deterministic_data(n_per_row, seed.wrapping_add(expert_id as u32));
acc.absorb_moe(expert_id, &row).expect("absorb moe");
}
let loaded = crate::quantize::imatrix::LoadedImatrix {
source_path: "<synthetic-moe>".into(),
datasets: vec!["test-moe".into()],
chunk_count: 1,
chunk_size: 512,
registry,
};
crate::quantize::imatrix::ImatrixData {
loaded,
provenance: crate::quantize::imatrix::ImatrixProvenance::Computed {
corpus_label: "test-moe".into(),
n_ctx: 512,
},
}
}
#[test]
fn p4b_q4_k_quantize_differs_with_vs_without_imatrix() {
use crate::quantize::ggml_quants::ggml_type::GgmlType;
use crate::quantize::ggml_quants::quantizer::quantizer_for;
let n_per_row = 256usize;
let weights: Vec<f32> = (0..n_per_row)
.map(|i| {
let phase = (i as f32) * 0.371;
phase.sin() * 0.1 + ((i as f32) * 1.7e-3).cos() * 0.05
})
.collect();
let imatrix: Vec<f32> = (0..n_per_row)
.map(|i| {
let bucket = i % 16;
match bucket {
0 => 100.0,
1..=3 => 10.0,
_ => 1.0,
}
})
.collect();
let q4k = quantizer_for(GgmlType::Q4_K).expect("Q4_K quantizer");
let bytes_no_imatrix = q4k
.quantize(&weights, n_per_row, None)
.expect("quantize no-imatrix");
let bytes_with_imatrix = q4k
.quantize(&weights, n_per_row, Some(&imatrix))
.expect("quantize with-imatrix");
assert_eq!(
bytes_no_imatrix.len(),
bytes_with_imatrix.len(),
"Q4_K block size invariant"
);
assert_ne!(
bytes_no_imatrix, bytes_with_imatrix,
"ADR-033 §P4b smoke: Q4_K quantizer's imatrix-aware path \
must produce different output bytes when imatrix is Some(non-trivial-values). \
If this test fails, the K-quant kernel itself isn't honoring the imatrix \
argument (independent of orchestrator wiring)."
);
}
#[test]
fn p4b_orchestrator_threads_imatrix_through_to_quantizer() {
let n_per_row = 256usize;
let tensor_name = "blk.0.ffn_down.weight";
let data: Vec<f32> = (0..n_per_row)
.map(|i| {
let phase = (i as f32) * 0.371;
phase.sin() * 0.1 + ((i as f32) * 1.7e-3).cos() * 0.05
})
.collect();
let mut registry = crate::quantize::imatrix::AccumulatorRegistry::new();
let acc = registry
.register(tensor_name, n_per_row, 1)
.expect("register");
let synthetic_row: Vec<f32> = (0..n_per_row)
.map(|i| {
let bucket = i % 16;
match bucket {
0 => 10.0,
1..=3 => 3.16,
_ => 1.0,
}
})
.collect();
acc.absorb_dense(&synthetic_row).expect("absorb");
let imatrix = crate::quantize::imatrix::ImatrixData {
loaded: crate::quantize::imatrix::LoadedImatrix {
source_path: "<synthetic>".into(),
datasets: vec!["test".into()],
chunk_count: 1,
chunk_size: 512,
registry,
},
provenance: crate::quantize::imatrix::ImatrixProvenance::Computed {
corpus_label: "test".into(),
n_ctx: 512,
},
};
let hparams = HParams {
n_expert: 0,
n_head: 32,
n_head_kv: 8,
n_layer: 32,
n_mtp_layers: 0,
};
let entries = || {
vec![PlanEntry {
name: tensor_name.into(),
shape: vec![n_per_row, 1],
source_dtype: SourceDtype::F32,
layer_index: Some(0),
}]
};
let bytes_no_imatrix = {
let mut orch =
ConvertOrchestrator::new(LlamaFtype::MostlyQ4_K_M, ArchName::Llama3, hparams);
orch.plan_tensors(entries()).expect("plan A");
let mut buf = Vec::<u8>::new();
{
let mut sw = orch
.begin_write(std::io::Cursor::new(&mut buf))
.expect("begin_write A");
sw.stream_tensor(0, &data).expect("stream A");
sw.finalize().expect("finalize A");
}
buf
};
let bytes_with_imatrix = {
let mut orch =
ConvertOrchestrator::new(LlamaFtype::MostlyQ4_K_M, ArchName::Llama3, hparams)
.with_imatrix(Some(imatrix));
orch.plan_tensors(entries()).expect("plan B");
let mut buf = Vec::<u8>::new();
{
let mut sw = orch
.begin_write(std::io::Cursor::new(&mut buf))
.expect("begin_write B");
sw.stream_tensor(0, &data).expect("stream B");
sw.finalize().expect("finalize B");
}
buf
};
assert_eq!(
bytes_no_imatrix.len(),
bytes_with_imatrix.len(),
"P4b byte lengths should match (same ftype, same shape)"
);
assert_ne!(
bytes_no_imatrix, bytes_with_imatrix,
"ADR-033 §P4b regression: orchestrator produced byte-identical \
output with and without --imatrix attached. The imatrix is \
not reaching `quantizer.quantize(..., Some(imatrix))`. Check \
`orchestrator.rs:602` and `cli_driver.rs:518` region. \
Also verify the policy routed `blk.0.ffn_down.weight` to a \
K-quant type that consumes imatrix (Q4_K/Q5_K/Q6_K/IQ4_*)."
);
}
#[test]
fn p4b_tensor_imatrix_dense_returns_raw_values() {
let n_per_row = 8usize;
let tensor_name = "blk.0.attn_q.weight";
let imatrix = make_dense_imatrix(tensor_name, n_per_row, 100);
let row1 = deterministic_data(n_per_row, 100);
let row2 = deterministic_data(n_per_row, 101);
let expected: Vec<f32> = (0..n_per_row)
.map(|j| row1[j] * row1[j] + row2[j] * row2[j])
.collect();
let mut orch = ConvertOrchestrator::new(
LlamaFtype::MostlyQ4_K_M,
ArchName::Llama3,
default_hparams(),
)
.with_imatrix(Some(imatrix));
orch.plan_tensors(Vec::new()).expect("plan empty");
let mut buf = Vec::<u8>::new();
let sw = orch
.begin_write(std::io::Cursor::new(&mut buf))
.expect("begin_write");
let got = sw
.tensor_imatrix(tensor_name, n_per_row)
.expect("Result Ok")
.expect("imatrix slice present");
assert_eq!(got.len(), n_per_row);
for j in 0..n_per_row {
assert!(
(got[j] - expected[j]).abs() < 1e-6,
"dense imatrix col {j}: got {} expected {}",
got[j],
expected[j]
);
}
}
#[test]
fn p4b_tensor_imatrix_moe_aggregates_across_experts() {
let n_per_row = 4usize;
let n_experts = 3usize;
let tensor_name = "blk.0.ffn_gate_exps.weight";
let imatrix = make_moe_imatrix(tensor_name, n_per_row, n_experts, 200);
let mut expected = vec![0.0_f32; n_per_row];
for expert_id in 0..n_experts {
let row = deterministic_data(n_per_row, 200u32.wrapping_add(expert_id as u32));
for j in 0..n_per_row {
expected[j] += row[j] * row[j];
}
}
let inv_total = 1.0_f32 / (n_experts as f32);
for v in expected.iter_mut() {
*v *= inv_total;
}
let mut orch = ConvertOrchestrator::new(
LlamaFtype::MostlyQ4_K_M,
ArchName::Llama3,
default_hparams(),
)
.with_imatrix(Some(imatrix));
orch.plan_tensors(Vec::new()).expect("plan empty");
let mut buf = Vec::<u8>::new();
let sw = orch
.begin_write(std::io::Cursor::new(&mut buf))
.expect("begin_write");
let got = sw
.tensor_imatrix(tensor_name, n_per_row)
.expect("Result Ok")
.expect("imatrix slice present");
assert_eq!(got.len(), n_per_row);
for j in 0..n_per_row {
assert!(
(got[j] - expected[j]).abs() < 1e-6,
"MoE imatrix col {j}: got {} expected {}",
got[j],
expected[j]
);
}
}
#[test]
fn p4b_tensor_imatrix_missing_returns_none_mismatch_returns_err() {
let imatrix = make_dense_imatrix("blk.0.attn_q.weight", 16, 7);
let mut orch = ConvertOrchestrator::new(
LlamaFtype::MostlyQ4_K_M,
ArchName::Llama3,
default_hparams(),
)
.with_imatrix(Some(imatrix));
orch.plan_tensors(Vec::new()).expect("plan empty");
let mut buf = Vec::<u8>::new();
let sw = orch
.begin_write(std::io::Cursor::new(&mut buf))
.expect("begin_write");
let res = sw.tensor_imatrix("blk.99.attn_q.weight", 16);
assert!(matches!(res, Ok(None)));
let res = sw.tensor_imatrix("blk.0.attn_q.weight", 32);
match res {
Err(crate::quantize::imatrix::ImatrixError::ApplyShapeMismatch {
tensor,
imatrix_n_per_row,
model_n_per_row,
}) => {
assert_eq!(tensor, "blk.0.attn_q.weight");
assert_eq!(imatrix_n_per_row, 16);
assert_eq!(model_n_per_row, 32);
}
other => panic!("expected ApplyShapeMismatch, got {other:?}"),
}
let res = sw.tensor_imatrix("blk.0.attn_q.weight", 16);
assert!(matches!(res, Ok(Some(_))));
}
#[test]
fn p4b_no_imatrix_attached_returns_none_for_everything() {
let mut orch = ConvertOrchestrator::new(
LlamaFtype::MostlyQ4_K_M,
ArchName::Llama3,
default_hparams(),
);
orch.plan_tensors(Vec::new()).expect("plan empty");
let mut buf = Vec::<u8>::new();
let sw = orch
.begin_write(std::io::Cursor::new(&mut buf))
.expect("begin_write");
assert!(matches!(
sw.tensor_imatrix("blk.0.attn_q.weight", 16),
Ok(None)
));
assert!(matches!(
sw.tensor_imatrix("blk.0.ffn_down.weight", 256),
Ok(None)
));
}
#[test]
fn p4b_stream_tensor_propagates_apply_shape_mismatch() {
let model_n_per_row = 256usize;
let imatrix_n_per_row = 128usize; let tensor_name = "blk.0.ffn_down.weight";
let mut registry = crate::quantize::imatrix::AccumulatorRegistry::new();
let acc = registry
.register(tensor_name, imatrix_n_per_row, 1)
.expect("register");
acc.absorb_dense(&vec![1.0_f32; imatrix_n_per_row])
.expect("absorb");
let imatrix = crate::quantize::imatrix::ImatrixData {
loaded: crate::quantize::imatrix::LoadedImatrix {
source_path: "<bad>".into(),
datasets: vec!["test".into()],
chunk_count: 1,
chunk_size: 512,
registry,
},
provenance: crate::quantize::imatrix::ImatrixProvenance::Computed {
corpus_label: "test".into(),
n_ctx: 512,
},
};
let mut orch = ConvertOrchestrator::new(
LlamaFtype::MostlyQ4_K_M,
ArchName::Llama3,
default_hparams(),
)
.with_imatrix(Some(imatrix));
orch.plan_tensors(vec![PlanEntry {
name: tensor_name.into(),
shape: vec![model_n_per_row, 1],
source_dtype: SourceDtype::F32,
layer_index: Some(0),
}])
.expect("plan");
let mut buf = Vec::<u8>::new();
let mut sw = orch
.begin_write(std::io::Cursor::new(&mut buf))
.expect("begin_write");
let data: Vec<f32> = (0..model_n_per_row).map(|i| (i as f32) * 1e-3).collect();
let res = sw.stream_tensor(0, &data);
match res {
Err(OrchestratorError::Imatrix(
crate::quantize::imatrix::ImatrixError::ApplyShapeMismatch {
tensor,
imatrix_n_per_row: ipr,
model_n_per_row: mpr,
},
)) => {
assert_eq!(tensor, tensor_name);
assert_eq!(ipr, imatrix_n_per_row);
assert_eq!(mpr, model_n_per_row);
}
other => {
panic!("expected OrchestratorError::Imatrix(ApplyShapeMismatch), got {other:?}")
}
}
}
#[test]
fn p4b_coverage_tracks_missing_tensors() {
let n_per_row = 256usize;
let covered = "blk.0.attn_q.weight";
let uncovered = "blk.0.ffn_down.weight";
let imatrix = make_dense_imatrix(covered, n_per_row, 123);
let mut orch = ConvertOrchestrator::new(
LlamaFtype::MostlyQ4_K_M,
ArchName::Llama3,
default_hparams(),
)
.with_imatrix(Some(imatrix));
orch.plan_tensors(vec![
PlanEntry {
name: covered.into(),
shape: vec![n_per_row, 1],
source_dtype: SourceDtype::F32,
layer_index: Some(0),
},
PlanEntry {
name: uncovered.into(),
shape: vec![n_per_row, 1],
source_dtype: SourceDtype::F32,
layer_index: Some(0),
},
])
.expect("plan");
let mut buf = Vec::<u8>::new();
let mut sw = orch
.begin_write(std::io::Cursor::new(&mut buf))
.expect("begin_write");
let data: Vec<f32> = (0..n_per_row).map(|i| (i as f32) * 1e-3).collect();
sw.stream_tensor(0, &data).expect("stream covered");
sw.stream_tensor(1, &data).expect("stream uncovered");
assert_eq!(sw.coverage_quantized, 2);
assert_eq!(sw.coverage_with_imatrix, 1);
assert_eq!(sw.coverage_missing, vec![uncovered.to_string()]);
sw.finalize().expect("finalize");
}
}