use crate::nn::{FeedForward, LayerNorm, Module, MultiHeadAttention};
use crate::tensor::Tensor;
use crate::error::Result;
pub struct TransformerBlock {
attention: MultiHeadAttention,
norm1: LayerNorm,
feed_forward: FeedForward,
norm2: LayerNorm,
}
impl TransformerBlock {
pub fn new(embed_dim: usize, num_heads: usize, ff_hidden_dim: usize) -> Self {
Self {
attention: MultiHeadAttention::new(embed_dim, num_heads),
norm1: LayerNorm::new(embed_dim),
feed_forward: FeedForward::new(embed_dim, ff_hidden_dim),
norm2: LayerNorm::new(embed_dim),
}
}
}
impl Module for TransformerBlock {
fn forward(&self, inputs: &Tensor) -> Result<Tensor> {
let normed_inputs1 = self.norm1.forward(inputs)?;
let attention_output = self.attention.forward(&normed_inputs1)?;
let x = inputs + &attention_output;
let normed_inputs2 = self.norm2.forward(&x)?;
let ff_output = self.feed_forward.forward(&normed_inputs2)?;
let final_output = &x + &ff_output;
Ok(final_output)
}
fn parameters(&self) -> Vec<Tensor> {
let mut params = Vec::new();
params.extend(self.attention.parameters());
params.extend(self.norm1.parameters());
params.extend(self.feed_forward.parameters());
params.extend(self.norm2.parameters());
params
}
}