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::DType;
use candle_core::Module;
use candle_core::Tensor;
use candle_nn::Embedding;
use candle_nn::VarBuilder;
use candle_nn::embedding;

use super::config::XlmRobertaFlashConfig;
use super::position::PositionScheme;
use crate::error::Result;
use crate::layers::layer_norm::LayerNorm;
use crate::models::xlm_roberta::embeddings::position_ids;

/// Word, position and token-type lookups, summed and normalized; the position table exists only under `Absolute`.
pub struct XlmRobertaFlashEmbeddings {
  word: Embedding,
  /// `embeddings.position_embeddings`, `[max_position_embeddings, hidden]`, under the absolute scheme alone.
  position: Option<Embedding>,
  token_type: Embedding,
  layer_norm: LayerNorm,
  pad: u32,
}

impl XlmRobertaFlashEmbeddings {
  /// `vb` is the encoder root: `emb_ln` is a sibling of `embeddings`, not nested in it.
  pub fn load(
    config: &XlmRobertaFlashConfig,
    vb: VarBuilder,
    scheme: PositionScheme,
  ) -> Result<Self> {
    let position = match scheme {
      PositionScheme::Rotary => None,
      PositionScheme::Absolute => Some(embedding(
        config.max_position_embeddings,
        config.hidden_size,
        vb.pp("embeddings").pp("position_embeddings"),
      )?),
    };
    Ok(Self {
      word: embedding(
        config.vocab_size,
        config.hidden_size,
        vb.pp("embeddings").pp("word_embeddings"),
      )?,
      position,
      token_type: embedding(
        config.type_vocab_size,
        config.hidden_size,
        vb.pp("embeddings").pp("token_type_embeddings"),
      )?,
      layer_norm: LayerNorm::load(vb.pp("emb_ln"), config.hidden_size, config.layer_norm_eps)?,
      pad: config.pad_token_id as u32,
    })
  }

  pub(super) fn weights_dtype(&self) -> DType {
    self.word.embeddings().dtype()
  }

  /// Word, position (if any), token type, then `emb_ln`, in the reference's order.
  pub fn forward(&self, input_ids: &Tensor, token_type_ids: &Tensor) -> Result<Tensor> {
    let mut summed = self.word.forward(input_ids)?;
    if let Some(position) = &self.position {
      let ids = position_ids(input_ids, self.pad)?;
      summed = (summed + position.forward(&ids)?)?;
    }
    let summed = (summed + self.token_type.forward(token_type_ids)?)?;
    Ok(self.layer_norm.forward(&summed)?)
  }
}