use candle_core::Module;
use candle_core::Tensor;
use candle_nn::Linear;
use candle_nn::VarBuilder;
use candle_nn::linear;
use super::attention::XlmRobertaFlashAttention;
use super::config::XlmRobertaFlashConfig;
use crate::error::Result;
use crate::layers::activation::Activation;
use crate::layers::layer_norm::LayerNorm;
use crate::layers::mask::AttentionMask;
use crate::layers::rope::RotaryEmbedding;
pub struct XlmRobertaFlashLayer {
attention: XlmRobertaFlashAttention,
norm1: LayerNorm,
fc1: Linear,
activation: Activation,
fc2: Linear,
norm2: LayerNorm,
}
impl XlmRobertaFlashLayer {
pub fn load(config: &XlmRobertaFlashConfig, vb: VarBuilder) -> Result<Self> {
Ok(Self {
attention: XlmRobertaFlashAttention::load(config, vb.pp("mixer"))?,
norm1: LayerNorm::load(vb.pp("norm1"), config.hidden_size, config.layer_norm_eps)?,
fc1: linear(
config.hidden_size,
config.intermediate_size,
vb.pp("mlp.fc1"),
)?,
activation: config.hidden_act,
fc2: linear(
config.intermediate_size,
config.hidden_size,
vb.pp("mlp.fc2"),
)?,
norm2: LayerNorm::load(vb.pp("norm2"), config.hidden_size, config.layer_norm_eps)?,
})
}
pub fn forward(
&self,
hidden: &Tensor,
mask: &AttentionMask,
rope: Option<&RotaryEmbedding>,
) -> Result<Tensor> {
let attended = self.attention.forward(hidden, mask, rope)?;
let hidden = self.norm1.forward(&(attended + hidden)?)?;
let inner = self.activation.forward(&self.fc1.forward(&hidden)?)?;
let mlp_out = self.fc2.forward(&inner)?;
Ok(self.norm2.forward(&(mlp_out + hidden)?)?)
}
}