use candle_core::Module;
use candle_core::Tensor;
use candle_nn::Linear;
use candle_nn::VarBuilder;
use candle_nn::linear;
use super::attention::BertAttention;
use super::config::BertConfig;
use crate::error::Result;
use crate::layers::activation::Activation;
use crate::layers::layer_norm::LayerNorm;
use crate::layers::mask::AttentionMask;
pub struct BertLayer {
attention: BertAttention,
intermediate: Linear,
activation: Activation,
output: Linear,
layer_norm: LayerNorm,
}
impl BertLayer {
pub fn load(config: &BertConfig, vb: VarBuilder) -> Result<Self> {
Ok(Self {
attention: BertAttention::load(config, vb.pp("attention"))?,
intermediate: linear(
config.hidden_size,
config.intermediate_size,
vb.pp("intermediate.dense"),
)?,
activation: config.hidden_act,
output: linear(
config.intermediate_size,
config.hidden_size,
vb.pp("output.dense"),
)?,
layer_norm: LayerNorm::load(
vb.pp("output.LayerNorm"),
config.hidden_size,
config.layer_norm_eps,
)?,
})
}
fn finish(&self, attended: Tensor) -> Result<Tensor> {
let inner = self
.activation
.forward(&self.intermediate.forward(&attended)?)?;
let projected = self.output.forward(&inner)?;
Ok(self.layer_norm.forward(&(projected + attended)?)?)
}
pub fn forward(&self, hidden: &Tensor, mask: &AttentionMask) -> Result<Tensor> {
let attended = self.attention.forward(hidden, mask)?;
self.finish(attended)
}
pub fn forward_with_weights(
&self,
hidden: &Tensor,
mask: &AttentionMask,
) -> Result<(Tensor, Tensor)> {
let (attended, weights) = self.attention.forward_with_weights(hidden, mask)?;
Ok((self.finish(attended)?, weights))
}
}