use candle_core::DType;
use candle_core::Tensor;
use candle_nn::VarBuilder;
use super::config::NomicBertConfig;
use super::embeddings::NomicBertEmbeddings;
use super::layer::NomicBertLayer;
use super::rotary::NomicRotary;
use crate::error::Result;
use crate::layers::mask::AttentionMask;
use crate::models::Encoder;
use crate::models::EncoderInput;
pub struct NomicBertModel {
embeddings: NomicBertEmbeddings,
layers: Vec<NomicBertLayer>,
rotary: NomicRotary,
config: NomicBertConfig,
}
impl std::fmt::Debug for NomicBertModel {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("NomicBertModel").finish_non_exhaustive()
}
}
impl NomicBertModel {
pub fn load(config: NomicBertConfig, vb: VarBuilder) -> Result<Self> {
config.ensure_supported()?;
let embeddings = NomicBertEmbeddings::load(&config, vb.clone())?;
let layers = (0..config.n_layer)
.map(|i| NomicBertLayer::load(&config, vb.pp(format!("encoder.layers.{i}"))))
.collect::<Result<Vec<_>>>()?;
let rotary = NomicRotary::new(&config, vb.dtype(), vb.device())?;
Ok(Self {
embeddings,
layers,
rotary,
config,
})
}
}
impl Encoder for NomicBertModel {
fn forward(&self, input: &EncoderInput) -> Result<Tensor> {
let mut hidden = self
.embeddings
.forward(input.input_ids, input.token_type_ids)?;
let seq = hidden.dim(1)?;
let mask = AttentionMask::padding(
input.attention_mask,
input.lengths,
self.config.n_head,
self.config.head_dim(),
hidden.dtype(),
)?;
let table = self.rotary.for_length(seq)?;
let rope = table.as_rope();
for layer in &self.layers {
hidden = layer.forward(&hidden, &mask, rope)?;
}
Ok(hidden)
}
fn hidden_size(&self) -> usize {
self.config.n_embd
}
fn max_position_embeddings(&self) -> usize {
usize::MAX
}
fn weights_dtype(&self) -> DType {
self.embeddings.weights_dtype()
}
}
#[cfg(test)]
mod tests;