use serde::Deserialize;
use crate::error::CanddingError;
use crate::error::Result;
#[derive(Clone, Debug, Deserialize)]
pub struct NomicBertConfig {
pub n_embd: usize,
pub n_head: usize,
pub n_layer: usize,
pub n_inner: usize,
pub activation_function: String,
pub qkv_proj_bias: bool,
pub mlp_fc1_bias: bool,
pub mlp_fc2_bias: bool,
pub prenorm: bool,
pub causal: bool,
pub rotary_emb_interleaved: bool,
#[serde(default)]
pub norm_mlp: bool,
pub type_vocab_size: usize,
pub vocab_size: usize,
#[serde(default)]
pub pad_token_id: Option<u32>,
pub layer_norm_epsilon: f64,
pub rotary_emb_fraction: f64,
pub rotary_emb_base: f64,
#[serde(default)]
pub rotary_emb_scale_base: Option<f64>,
#[serde(default)]
pub rotary_scaling_factor: Option<f64>,
#[serde(default = "default_max_trained_positions")]
pub max_trained_positions: usize,
#[serde(default)]
pub max_position_embeddings: Option<usize>,
}
fn default_max_trained_positions() -> usize {
2048
}
impl NomicBertConfig {
pub fn head_dim(&self) -> usize {
self.n_embd / self.n_head
}
pub fn scaling_factor(&self) -> Option<f64> {
self.rotary_scaling_factor
}
pub fn ensure_supported(&self) -> Result<()> {
if self.activation_function != "swiglu" {
return Err(CanddingError::UnsupportedArchitecture(format!(
"nomic_bert: activation_function {:?} is not supported; this family reads swiglu checkpoints",
self.activation_function
)));
}
if self.prenorm {
return Err(CanddingError::UnsupportedArchitecture(format!(
"nomic_bert: prenorm {} is not supported; the three catalogued checkpoints are post-norm, normalizing \
after each residual add",
self.prenorm
)));
}
if self.causal {
return Err(CanddingError::UnsupportedArchitecture(format!(
"nomic_bert: causal {} is not supported; the three catalogued checkpoints are bidirectional encoders",
self.causal
)));
}
if self.rotary_emb_fraction != 1.0 {
return Err(CanddingError::UnsupportedArchitecture(format!(
"nomic_bert: rotary_emb_fraction {} is not supported; the three catalogued checkpoints rotate the full \
head dimension",
self.rotary_emb_fraction
)));
}
if self.rotary_emb_interleaved {
return Err(CanddingError::UnsupportedArchitecture(format!(
"nomic_bert: rotary_emb_interleaved {} is not supported; the three catalogued checkpoints rotate halves \
rather than interleaved pairs",
self.rotary_emb_interleaved
)));
}
if self.qkv_proj_bias {
return Err(CanddingError::UnsupportedArchitecture(format!(
"nomic_bert: qkv_proj_bias {} is not supported; the three catalogued checkpoints carry no bias on the \
fused Wqkv projection",
self.qkv_proj_bias
)));
}
if self.mlp_fc1_bias {
return Err(CanddingError::UnsupportedArchitecture(format!(
"nomic_bert: mlp_fc1_bias {} is not supported; the three catalogued checkpoints carry no bias on fc11 or \
fc12",
self.mlp_fc1_bias
)));
}
if self.mlp_fc2_bias {
return Err(CanddingError::UnsupportedArchitecture(format!(
"nomic_bert: mlp_fc2_bias {} is not supported; the down projection is loaded without a bias",
self.mlp_fc2_bias
)));
}
if let Some(scale_base) = self.rotary_emb_scale_base {
return Err(CanddingError::UnsupportedArchitecture(format!(
"nomic_bert: rotary_emb_scale_base {scale_base} is not supported; the three catalogued checkpoints leave \
this null"
)));
}
if self.norm_mlp {
return Err(CanddingError::UnsupportedArchitecture(format!(
"nomic_bert: norm_mlp {} is not supported; the three catalogued checkpoints apply exactly one norm \
around the mlp",
self.norm_mlp
)));
}
Ok(())
}
}
#[cfg(test)]
pub(crate) mod tests;