use candle_core::Tensor;
use candle_nn::Linear;
use candle_nn::VarBuilder;
use candle_nn::linear_no_bias;
use super::config::ModernBertConfig;
use crate::error::Result;
use crate::layers::activation::Activation;
use crate::layers::mlp::GatedMlp;
pub struct ModernBertMlp {
gated: GatedMlp,
}
impl ModernBertMlp {
pub fn load(config: &ModernBertConfig, vb: VarBuilder) -> Result<Self> {
let hidden = config.hidden_size;
let inter = config.intermediate_size;
let wi = linear_no_bias(hidden, 2 * inter, vb.pp("mlp.Wi"))?;
let activated = wi.weight().narrow(0, 0, inter)?.contiguous()?;
let multiplier = wi.weight().narrow(0, inter, inter)?.contiguous()?;
Ok(Self {
gated: GatedMlp::new(
Linear::new(activated, None),
Linear::new(multiplier, None),
linear_no_bias(inter, hidden, vb.pp("mlp.Wo"))?,
Activation::Gelu,
),
})
}
pub fn forward(&self, xs: &Tensor) -> Result<Tensor> {
self.gated.forward(xs)
}
}
#[cfg(test)]
mod tests {
use candle_core::DType;
use candle_core::Device;
use candle_nn::VarBuilder;
use super::*;
fn one_wide_config() -> ModernBertConfig {
ModernBertConfig {
hidden_size: 1,
num_attention_heads: 1,
num_hidden_layers: 1,
intermediate_size: 1,
hidden_activation: "gelu".to_string(),
global_attn_every_n_layers: 3,
local_attention: 128,
global_rope_theta: 160_000.0,
local_rope_theta: 10_000.0,
attention_bias: false,
mlp_bias: false,
norm_bias: false,
norm_eps: 1e-5,
vocab_size: 50368,
max_position_embeddings: 8192,
}
}
#[test]
fn the_first_half_of_wi_is_activated() {
let mut tensors = std::collections::HashMap::new();
tensors.insert(
"mlp.Wi.weight".to_string(),
Tensor::new(&[[1f32], [3.0]], &Device::Cpu).unwrap(),
);
tensors.insert(
"mlp.Wo.weight".to_string(),
Tensor::new(&[[1f32]], &Device::Cpu).unwrap(),
);
let vb = VarBuilder::from_tensors(tensors, DType::F32, &Device::Cpu);
let mlp = ModernBertMlp::load(&one_wide_config(), vb).unwrap();
let out = mlp
.forward(&Tensor::new(&[[1f32]], &Device::Cpu).unwrap())
.unwrap();
let value = out.to_vec2::<f32>().unwrap()[0][0];
assert!((value - 2.524_034).abs() < 1e-5, "{value}");
}
}