candding 0.1.0

Pure candle embeddings for Rust with no ONNX: dense, sparse, multi-vector and rerank models today, image models on the roadmap
Documentation
//! One post-norm block with two residuals, `h = attn_ln(h + attn(h))` then `h = mlp_ln(h + mlp(h))`.

use candle_core::Tensor;
use candle_nn::VarBuilder;

use super::attention::GteNewAttention;
use super::config::GteNewConfig;
use super::mlp::GteNewMlp;
use crate::error::Result;
use crate::layers::layer_norm::LayerNorm;
use crate::layers::mask::AttentionMask;
use crate::layers::rope::RotaryEmbedding;

pub struct GteNewLayer {
  attention: GteNewAttention,
  attn_ln: LayerNorm,
  mlp: GteNewMlp,
  mlp_ln: LayerNorm,
}

impl GteNewLayer {
  /// `vb` is `encoder.layer.{i}`; `attn_ln` and `mlp_ln` sit directly under it, not inside `attention.` or `mlp.`.
  pub fn load(config: &GteNewConfig, vb: VarBuilder) -> Result<Self> {
    let hidden = config.hidden_size;
    Ok(Self {
      attention: GteNewAttention::load(config, vb.clone())?,
      attn_ln: LayerNorm::load(vb.pp("attn_ln"), hidden, config.layer_norm_eps)?,
      mlp: GteNewMlp::load(config, vb.clone())?,
      mlp_ln: LayerNorm::load(vb.pp("mlp_ln"), hidden, config.layer_norm_eps)?,
    })
  }

  pub fn forward(
    &self,
    hidden: &Tensor,
    mask: &AttentionMask,
    rope: &RotaryEmbedding,
  ) -> Result<Tensor> {
    let attended = self.attention.forward(hidden, mask, rope)?;
    let hidden = self.attn_ln.forward(&(attended + hidden)?)?;
    let projected = self.mlp.forward(&hidden)?;
    Ok(self.mlp_ln.forward(&(projected + &hidden)?)?)
  }
}