use candle_core::Tensor;
use candle_nn::VarBuilder;
use super::attention::Qwen3Attention;
use super::config::Qwen3Config;
use crate::error::Result;
use crate::layers::mask::AttentionMask;
use crate::layers::mlp::GatedMlp;
use crate::layers::rms_norm::RmsNorm;
use crate::layers::rms_norm::RmsNormStyle;
use crate::layers::rope::RotaryEmbedding;
pub struct Qwen3Layer {
input_layernorm: RmsNorm,
self_attn: Qwen3Attention,
post_attention_layernorm: RmsNorm,
mlp: GatedMlp,
}
impl Qwen3Layer {
pub fn load(config: &Qwen3Config, vb: VarBuilder) -> Result<Self> {
let eps = config.rms_norm_eps;
Ok(Self {
input_layernorm: RmsNorm::load(
vb.pp("input_layernorm"),
config.hidden_size,
eps,
RmsNormStyle::Scale,
)?,
self_attn: Qwen3Attention::load(config, vb.pp("self_attn"))?,
post_attention_layernorm: RmsNorm::load(
vb.pp("post_attention_layernorm"),
config.hidden_size,
eps,
RmsNormStyle::Scale,
)?,
mlp: GatedMlp::load(
vb.pp("mlp"),
config.hidden_size,
config.intermediate_size,
config.hidden_act,
)?,
})
}
pub fn forward(
&self,
hidden: &Tensor,
rope: &RotaryEmbedding,
mask: &AttentionMask,
) -> Result<Tensor> {
let attended = (hidden
+ self
.self_attn
.forward(&self.input_layernorm.forward(hidden)?, rope, mask)?)?;
let inner = self
.mlp
.forward(&self.post_attention_layernorm.forward(&attended)?)?;
Ok((attended + inner)?)
}
}