use candle_core::DType;
use candle_core::Module;
use candle_core::Tensor;
use candle_nn::Embedding;
use candle_nn::VarBuilder;
use candle_nn::embedding;
use super::config::XlmRobertaConfig;
use crate::error::Result;
use crate::layers::layer_norm::LayerNorm;
pub struct XlmRobertaEmbeddings {
word: Embedding,
position: Embedding,
token_type: Embedding,
layer_norm: LayerNorm,
pad: u32,
}
impl XlmRobertaEmbeddings {
pub fn load(config: &XlmRobertaConfig, vb: VarBuilder) -> Result<Self> {
Ok(Self {
word: embedding(
config.bert.vocab_size,
config.bert.hidden_size,
vb.pp("word_embeddings"),
)?,
position: embedding(
config.bert.max_position_embeddings,
config.bert.hidden_size,
vb.pp("position_embeddings"),
)?,
token_type: embedding(
config.bert.type_vocab_size,
config.bert.hidden_size,
vb.pp("token_type_embeddings"),
)?,
layer_norm: LayerNorm::load(
vb.pp("LayerNorm"),
config.bert.hidden_size,
config.bert.layer_norm_eps,
)?,
pad: config.pad_token_id as u32,
})
}
pub(super) fn weights_dtype(&self) -> DType {
self.word.embeddings().dtype()
}
pub fn forward(&self, input_ids: &Tensor, token_type_ids: &Tensor) -> Result<Tensor> {
let positions = position_ids(input_ids, self.pad)?;
let summed = (self.word.forward(input_ids)? + self.token_type.forward(token_type_ids)?)?;
let summed = (summed + self.position.forward(&positions)?)?;
Ok(self.layer_norm.forward(&summed)?)
}
}
pub fn position_ids(input_ids: &Tensor, pad: u32) -> Result<Tensor> {
let rows = input_ids.to_vec2::<u32>()?;
let (batch, seq) = input_ids.dims2()?;
let mut ids = Vec::with_capacity(batch * seq);
for row in &rows {
let mut numbered = pad;
ids.extend(row.iter().map(|&id| {
if id == pad {
return pad;
}
numbered += 1;
numbered
}));
}
Ok(Tensor::from_vec(ids, (batch, seq), input_ids.device())?)
}