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
use candle_core::Module;
use candle_core::Tensor;
use candle_nn::Linear;
use candle_nn::VarBuilder;
use candle_nn::linear;

use super::attention::MPNetAttention;
use super::config::MPNetConfig;
use crate::error::Result;
use crate::layers::activation::Activation;
use crate::layers::layer_norm::LayerNorm;
use crate::layers::mask::AttentionMask;

/// Duplicates BERT's feed-forward half on purpose; extract a shared block if a third ungated family lands.
pub struct MPNetLayer {
  attention: MPNetAttention,
  intermediate: Linear,
  activation: Activation,
  output: Linear,
  layer_norm: LayerNorm,
}

impl MPNetLayer {
  /// `vb` is `encoder.layer.{i}`.
  pub fn load(config: &MPNetConfig, vb: VarBuilder) -> Result<Self> {
    Ok(Self {
      attention: MPNetAttention::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,
      )?,
    })
  }

  pub fn forward(&self, hidden: &Tensor, mask: &AttentionMask) -> Result<Tensor> {
    let attended = self.attention.forward(hidden, mask)?;
    let inner = self
      .activation
      .forward(&self.intermediate.forward(&attended)?)?;
    let projected = self.output.forward(&inner)?;
    Ok(self.layer_norm.forward(&(projected + attended)?)?)
  }
}