#![allow(non_camel_case_types)]
mod format;
mod gguf;
mod weights;
pub use format::{DequantStrategy, QuantFormat};
pub use gguf::{GgufError, GgufHeader, GgufLoader, GgufResult, GgufTensorInfo, GgufValue};
pub use weights::{LayerQuantStats, QuantStats, QuantizedWeights};
use std::fmt;
#[derive(Debug, Clone)]
pub struct QuantizedBrick {
pub name: String,
pub weights: Option<QuantizedWeights>,
pub dequant_strategy: DequantStrategy,
pub budget_tok_per_sec: Option<u64>,
}
impl QuantizedBrick {
pub fn new(name: &str) -> Self {
Self {
name: name.to_string(),
weights: None,
dequant_strategy: DequantStrategy::default(),
budget_tok_per_sec: None,
}
}
pub fn with_weights(mut self, weights: QuantizedWeights) -> Self {
self.weights = Some(weights);
self
}
pub fn with_dequant_strategy(mut self, strategy: DequantStrategy) -> Self {
self.dequant_strategy = strategy;
self
}
pub fn with_budget(mut self, tok_per_sec: u64) -> Self {
self.budget_tok_per_sec = Some(tok_per_sec);
self
}
pub fn memory_bytes(&self) -> usize {
self.weights.as_ref().map_or(0, |w| w.memory_bytes())
}
pub fn bits_per_weight(&self) -> f64 {
self.weights
.as_ref()
.map_or(0.0, |w| w.actual_bits_per_weight())
}
pub fn format(&self) -> Option<QuantFormat> {
self.weights.as_ref().map(|w| w.format)
}
pub fn has_weights(&self) -> bool {
self.weights.is_some()
}
}
impl fmt::Display for QuantizedBrick {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "QuantizedBrick[{}]", self.name)?;
if let Some(weights) = &self.weights {
write!(
f,
" format={} weights={} memory={:.2}MB",
weights.format,
weights.num_weights(),
weights.memory_bytes() as f64 / 1_000_000.0
)?;
}
Ok(())
}
}
pub fn ggml_type_to_format(ggml_type: u32) -> Option<QuantFormat> {
match ggml_type {
0 => Some(QuantFormat::F32),
1 => Some(QuantFormat::F16),
2 => Some(QuantFormat::Q4_0),
3 => Some(QuantFormat::Q4_K), 8 => Some(QuantFormat::Q8_0),
12 => Some(QuantFormat::Q4_K),
13 => Some(QuantFormat::Q5_K),
14 => Some(QuantFormat::Q6_K),
_ => None,
}
}
#[cfg(test)]
mod tests;