use candle_core::DType;
use candle_core::Tensor;
use candle_nn::VarBuilder;
use super::bias::RelativeAttentionBias;
use super::config::MPNetConfig;
use super::embeddings::MPNetEmbeddings;
use super::layer::MPNetLayer;
use crate::error::Result;
use crate::layers::mask::AttentionMask;
use crate::models::Encoder;
use crate::models::EncoderInput;
pub struct MPNetModel {
embeddings: MPNetEmbeddings,
bias: RelativeAttentionBias,
layers: Vec<MPNetLayer>,
config: MPNetConfig,
}
impl std::fmt::Debug for MPNetModel {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("MPNetModel").finish_non_exhaustive()
}
}
impl MPNetModel {
pub fn load(config: MPNetConfig, vb: VarBuilder) -> Result<Self> {
config.ensure_supported()?;
let embeddings = MPNetEmbeddings::load(&config, vb.pp("embeddings"))?;
let bias = RelativeAttentionBias::load(&config, vb.pp("encoder.relative_attention_bias"))?;
let layers = (0..config.num_hidden_layers)
.map(|i| MPNetLayer::load(&config, vb.pp(format!("encoder.layer.{i}"))))
.collect::<Result<Vec<_>>>()?;
Ok(Self {
embeddings,
bias,
layers,
config,
})
}
}
impl Encoder for MPNetModel {
fn forward(&self, input: &EncoderInput) -> Result<Tensor> {
let mut hidden = self.embeddings.forward(input.input_ids)?;
let seq = hidden.dim(1)?;
let bias = self.bias.forward(seq, hidden.device())?;
let mask = AttentionMask::padding_with_bias(
input.attention_mask,
input.lengths,
&bias,
self.config.num_attention_heads,
self.config.head_dim(),
hidden.dtype(),
)?;
for layer in &self.layers {
hidden = layer.forward(&hidden, &mask)?;
}
Ok(hidden)
}
fn hidden_size(&self) -> usize {
self.config.hidden_size
}
fn max_position_embeddings(&self) -> usize {
self.config.sequence_limit()
}
fn weights_dtype(&self) -> DType {
self.embeddings.weights_dtype()
}
}
#[cfg(test)]
mod tests;