use candle_core::DType;
use candle_core::Tensor;
use candle_nn::VarBuilder;
use super::config::XlmRobertaFlashConfig;
use super::embeddings::XlmRobertaFlashEmbeddings;
use super::layer::XlmRobertaFlashLayer;
use super::position::PositionScheme;
use crate::error::Result;
use crate::layers::mask::AttentionMask;
use crate::layers::rope::RotaryEmbedding;
use crate::models::Encoder;
use crate::models::EncoderInput;
pub struct XlmRobertaFlashModel {
embeddings: XlmRobertaFlashEmbeddings,
layers: Vec<XlmRobertaFlashLayer>,
rope: Option<RotaryEmbedding>,
scheme: PositionScheme,
config: XlmRobertaFlashConfig,
}
impl std::fmt::Debug for XlmRobertaFlashModel {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("XlmRobertaFlashModel")
.finish_non_exhaustive()
}
}
impl XlmRobertaFlashModel {
pub fn load(
config: XlmRobertaFlashConfig,
vb: VarBuilder,
declared: Option<PositionScheme>,
) -> Result<Self> {
config.ensure_supported()?;
let scheme = PositionScheme::resolve(declared, config.position_embedding_type.as_deref())?;
let vb = if vb.contains_tensor("embeddings.word_embeddings.weight") {
vb
} else {
vb.pp("roberta")
};
let embeddings = XlmRobertaFlashEmbeddings::load(&config, vb.clone(), scheme)?;
let layers = (0..config.num_hidden_layers)
.map(|i| XlmRobertaFlashLayer::load(&config, vb.pp(format!("encoder.layers.{i}"))))
.collect::<Result<Vec<_>>>()?;
let rope = match scheme {
PositionScheme::Rotary => Some(RotaryEmbedding::new(
config.head_dim(),
config.max_position_embeddings,
config.rotary_emb_base,
vb.dtype(),
vb.device(),
)?),
PositionScheme::Absolute => None,
};
Ok(Self {
embeddings,
layers,
rope,
scheme,
config,
})
}
}
impl Encoder for XlmRobertaFlashModel {
fn forward(&self, input: &EncoderInput) -> Result<Tensor> {
let mut hidden = self
.embeddings
.forward(input.input_ids, input.token_type_ids)?;
let mask = AttentionMask::padding(
input.attention_mask,
input.lengths,
self.config.num_attention_heads,
self.config.head_dim(),
hidden.dtype(),
)?;
for layer in &self.layers {
hidden = layer.forward(&hidden, &mask, self.rope.as_ref())?;
}
Ok(hidden)
}
fn hidden_size(&self) -> usize {
self.config.hidden_size
}
fn max_position_embeddings(&self) -> usize {
match self.scheme {
PositionScheme::Rotary => self.config.max_position_embeddings,
PositionScheme::Absolute => self.config.sequence_limit(),
}
}
fn weights_dtype(&self) -> DType {
self.embeddings.weights_dtype()
}
}
#[cfg(test)]
mod tests;