1use crate::models::with_tracing::{linear, linear_no_bias, Linear, RmsNorm};
19use candle::{DType, Device, Error, IndexOp, Module, Result, Tensor, D};
20use candle_nn::{layer_norm, Activation, LayerNorm, VarBuilder};
21use std::sync::Arc;
22
23#[derive(Debug, Default, Copy, Clone, PartialEq, serde::Deserialize)]
25pub enum ModelVariant {
26 #[default]
27 Large, Small, }
30
31#[derive(Debug, Default, Clone, PartialEq, serde::Deserialize)]
34pub struct Config {
35 pub variant: ModelVariant,
36 pub vocab_size: usize,
37 pub hidden_size: usize,
38 pub intermediate_size: usize,
39 pub num_hidden_layers: usize,
40 pub num_attention_heads: usize,
41 pub max_position_embeddings: usize,
42 pub rope_theta: f64,
43 pub embed_head: EmbedHead,
44 pub norm_eps: f64, pub activation_fn: Activation, pub num_key_value_heads: usize,
48 pub type_vocab_size: usize,
50 pub scaling_factor: f64,
51}
52
53#[derive(Debug, Default, Clone, PartialEq, serde::Deserialize)]
57pub struct EmbedHead {
58 pub in_features: usize,
59 pub out_features: usize,
60}
61
62#[derive(Debug, Default, Clone, Copy)]
65pub enum EmbedDim {
66 Dim256,
67 Dim768,
68 #[default]
69 Dim1024,
70 Dim2048,
71 Dim4096,
72 Dim6144,
73 Dim8192,
74}
75
76impl EmbedDim {
77 pub fn config(&self, in_features: usize) -> EmbedHead {
78 EmbedHead {
79 in_features,
80 out_features: match &self {
81 Self::Dim256 => 256,
82 Self::Dim768 => 768,
83 Self::Dim1024 => 1024,
84 Self::Dim2048 => 2048,
85 Self::Dim4096 => 4096,
86 Self::Dim6144 => 6144,
87 Self::Dim8192 => 8192,
88 },
89 }
90 }
91}
92
93impl Config {
95 pub fn new_1_5_b_v5(embed_dim: EmbedDim) -> Self {
97 Self {
100 variant: ModelVariant::Large,
101 activation_fn: candle_nn::Activation::Silu,
102 vocab_size: 151646,
103 hidden_size: 1536,
104 intermediate_size: 8960,
105 num_hidden_layers: 28,
106 num_attention_heads: 12,
107 num_key_value_heads: 2,
108 max_position_embeddings: 131072,
109 rope_theta: 1000000.,
110 norm_eps: 1e-06,
111 embed_head: embed_dim.config(1536),
112 ..Default::default()
113 }
114 }
115
116 pub fn new_400_m_v5(embed_dim: EmbedDim) -> Self {
118 Self {
119 variant: ModelVariant::Small,
120 vocab_size: 30528,
121 hidden_size: 1024,
122 intermediate_size: 4096,
123 num_hidden_layers: 24,
124 num_attention_heads: 16,
125 max_position_embeddings: 8192,
126 type_vocab_size: 2,
127 norm_eps: 1e-12,
128 scaling_factor: 2.0,
129 rope_theta: 160000.0,
130 activation_fn: Activation::Gelu,
131 embed_head: embed_dim.config(1024),
132 ..Default::default()
133 }
134 }
135}
136
137#[derive(Debug, Clone)]
138struct RotaryEmbedding {
139 sin: Tensor,
140 cos: Tensor,
141}
142
143impl RotaryEmbedding {
144 fn new(dtype: DType, cfg: &Config, dev: &Device) -> Result<Self> {
145 let dim = cfg.hidden_size / cfg.num_attention_heads;
146 let max_seq_len = if cfg.scaling_factor == 0. {
148 cfg.max_position_embeddings
149 } else {
150 ((cfg.max_position_embeddings as f64) * cfg.scaling_factor) as usize
151 };
152
153 let inv_freq: Vec<_> = (0..dim)
155 .step_by(2)
156 .map(|i| {
157 let rope_theta = if cfg.scaling_factor == 0. {
159 cfg.rope_theta
160 } else {
161 cfg.rope_theta * cfg.scaling_factor
162 };
163 let mut freq = 1. / rope_theta.powf(i as f64 / dim as f64);
164
165 if cfg.scaling_factor != 0. {
166 freq /= cfg.scaling_factor.powf(2.0 / (dim as f64))
167 }
168
169 freq as f32
170 })
171 .collect();
172
173 let inv_freq_len = inv_freq.len();
174 let inv_freq = Tensor::from_vec(inv_freq, (1, inv_freq_len), dev)?.to_dtype(dtype)?;
175
176 let t = Tensor::arange(0u32, max_seq_len as u32, dev)?
178 .to_dtype(dtype)?
179 .reshape((max_seq_len, 1))?;
180 let freqs = t.matmul(&inv_freq)?;
181 Ok(Self {
186 sin: freqs.sin()?,
187 cos: freqs.cos()?,
188 })
189 }
190
191 fn apply_rotary_emb_qkv(&self, q: &Tensor, k: &Tensor) -> Result<(Tensor, Tensor)> {
193 let (_b_sz, _h, seq_len, _n_embd) = q.dims4()?;
194 let cos = self.cos.narrow(0, 0, seq_len)?;
195 let sin = self.sin.narrow(0, 0, seq_len)?;
196
197 let q_embed = candle_nn::rotary_emb::rope(&q.contiguous()?, &cos, &sin)?;
198 let k_embed = candle_nn::rotary_emb::rope(&k.contiguous()?, &cos, &sin)?;
199 Ok((q_embed, k_embed))
200 }
201}
202
203#[derive(Debug, Clone)]
204#[allow(clippy::upper_case_acronyms)]
205struct MLP {
206 variant: ModelVariant,
207 gate_proj: Linear,
208 up_proj: Option<Linear>, down_proj: Linear,
210 act_fn: Activation,
211}
212
213impl MLP {
214 fn new(cfg: &Config, vb: VarBuilder) -> Result<Self> {
215 let hidden_sz = cfg.hidden_size;
216 let intermediate_sz = cfg.intermediate_size;
217
218 let (gate_proj, up_proj, down_proj) = match cfg.variant {
219 ModelVariant::Large => (
220 linear_no_bias(hidden_sz, intermediate_sz, vb.pp("gate_proj"))?,
221 Some(linear_no_bias(
222 hidden_sz,
223 intermediate_sz,
224 vb.pp("up_proj"),
225 )?),
226 linear_no_bias(intermediate_sz, hidden_sz, vb.pp("down_proj"))?,
227 ),
228 ModelVariant::Small => (
229 linear_no_bias(hidden_sz, intermediate_sz * 2, vb.pp("up_gate_proj"))?,
230 None,
231 linear(intermediate_sz, hidden_sz, vb.pp("down_proj"))?,
232 ),
233 };
234
235 Ok(Self {
236 variant: cfg.variant,
237 gate_proj,
238 up_proj,
239 down_proj,
240 act_fn: cfg.activation_fn,
241 })
242 }
243}
244
245impl Module for MLP {
246 fn forward(&self, xs: &Tensor) -> Result<Tensor> {
247 let up = self.gate_proj.forward(xs)?;
248
249 let (lhs, rhs) = match self.variant {
250 ModelVariant::Large => {
251 let lhs = up.apply(&self.act_fn)?;
252 let rhs = xs.apply(self.up_proj.as_ref().unwrap())?;
253
254 (lhs, rhs)
255 }
256 ModelVariant::Small => {
257 let (_batch_size, _seq_len, hidden_dim) = up.dims3()?;
259 let split_size = hidden_dim / 2;
260
261 let up_states = up.narrow(2, 0, split_size)?;
263 let gate = up.narrow(2, split_size, split_size)?.apply(&self.act_fn)?;
264
265 (up_states, gate)
266 }
267 };
268
269 (lhs * rhs)?.apply(&self.down_proj)
270 }
271}
272
273#[derive(Debug, Clone)]
274struct Attention {
275 qkv_proj: Linear,
276 o_proj: Linear,
277 num_heads: usize,
278 num_kv_heads: usize,
279 num_kv_groups: usize,
280 head_dim: usize,
281 hidden_size: usize,
282 rotary_emb: Arc<RotaryEmbedding>,
283 variant: ModelVariant,
284}
285
286impl Attention {
287 fn new(rotary_emb: Arc<RotaryEmbedding>, cfg: &Config, vb: VarBuilder) -> Result<Self> {
288 let hidden_sz = cfg.hidden_size;
289 let num_heads = cfg.num_attention_heads;
290 let num_kv_heads = cfg.num_key_value_heads;
291 let num_kv_groups = num_heads.checked_div(num_kv_heads).unwrap_or(0);
292 let head_dim = hidden_sz / num_heads;
293
294 let (qkv_proj, o_proj) = match cfg.variant {
295 ModelVariant::Large => {
296 let q_w = vb
299 .pp("q_proj")
300 .get((num_heads * head_dim, hidden_sz), "weight")?;
301 let k_w = vb
302 .pp("k_proj")
303 .get((num_kv_heads * head_dim, hidden_sz), "weight")?;
304 let v_w = vb
305 .pp("v_proj")
306 .get((num_kv_heads * head_dim, hidden_sz), "weight")?;
307 let q_b = vb.pp("q_proj").get(num_heads * head_dim, "bias")?;
309 let k_b = vb.pp("k_proj").get(num_kv_heads * head_dim, "bias")?;
310 let v_b = vb.pp("v_proj").get(num_kv_heads * head_dim, "bias")?;
311
312 let qkv_w = Tensor::cat(&[&q_w, &k_w, &v_w], 0)?;
313 let qkv_b = Tensor::cat(&[&q_b, &k_b, &v_b], 0)?;
314
315 (
316 Linear::from_weights(qkv_w, Some(qkv_b)),
317 linear_no_bias(num_heads * head_dim, hidden_sz, vb.pp("o_proj"))?,
318 )
319 }
320 ModelVariant::Small => (
321 linear(hidden_sz, 3 * num_heads * head_dim, vb.pp("qkv_proj"))?,
322 linear(num_heads * head_dim, hidden_sz, vb.pp("o_proj"))?,
323 ),
324 };
325
326 Ok(Self {
327 qkv_proj,
328 o_proj,
329 num_heads,
330 num_kv_heads,
331 num_kv_groups,
332 head_dim,
333 hidden_size: hidden_sz,
334 rotary_emb,
335 variant: cfg.variant,
336 })
337 }
338
339 fn forward(&mut self, xs: &Tensor, attention_mask: Option<&Tensor>) -> Result<Tensor> {
340 let (b_sz, q_len, _) = xs.dims3()?;
341
342 let qkv = self.qkv_proj.forward(xs)?;
343
344 let n_kv_heads = match self.variant {
345 ModelVariant::Large => self.num_kv_heads,
346 ModelVariant::Small => self.num_heads,
347 };
348
349 let (query_states, key_states, value_states) = match self.variant {
350 ModelVariant::Large => {
351 let q_sz = self.num_heads * self.head_dim;
352 let kv_sz = n_kv_heads * self.head_dim;
353
354 let q = qkv.narrow(D::Minus1, 0, q_sz)?.reshape((
355 b_sz,
356 q_len,
357 self.num_heads,
358 self.head_dim,
359 ))?;
360 let k = qkv.narrow(D::Minus1, q_sz, kv_sz)?.reshape((
361 b_sz,
362 q_len,
363 n_kv_heads,
364 self.head_dim,
365 ))?;
366 let v = qkv.narrow(D::Minus1, q_sz + kv_sz, kv_sz)?.reshape((
367 b_sz,
368 q_len,
369 n_kv_heads,
370 self.head_dim,
371 ))?;
372
373 (q, k, v)
374 }
375 ModelVariant::Small => {
376 let qkv = qkv.reshape((b_sz, q_len, 3, self.num_heads, self.head_dim))?;
378
379 (
380 qkv.i((.., .., 0, .., ..))?,
381 qkv.i((.., .., 1, .., ..))?,
382 qkv.i((.., .., 2, .., ..))?,
383 )
384 }
385 };
386
387 let query_states = query_states.transpose(1, 2)?.contiguous()?;
388 let key_states = key_states.transpose(1, 2)?.contiguous()?;
389 let value_states = value_states.transpose(1, 2)?.contiguous()?;
390
391 let (query_states, key_states) = self
392 .rotary_emb
393 .apply_rotary_emb_qkv(&query_states, &key_states)?;
394
395 let (key_states, value_states) = if self.variant == ModelVariant::Large {
397 (
398 crate::utils::repeat_kv(key_states, self.num_kv_groups)?.contiguous()?,
399 crate::utils::repeat_kv(value_states, self.num_kv_groups)?.contiguous()?,
400 )
401 } else {
402 (key_states, value_states)
403 };
404
405 let attn_output = {
406 let scale = 1f64 / f64::sqrt(self.head_dim as f64);
407 let attn_weights = query_states.matmul(&key_states.transpose(2, 3)?)?;
408 let attn_weights = (attn_weights * scale)?;
409
410 let attn_weights = match attention_mask {
411 None => attn_weights,
412 Some(mask) => attn_weights.broadcast_add(mask)?,
413 };
414 let attn_weights = candle_nn::ops::softmax_last_dim(&attn_weights)?;
415
416 attn_weights.matmul(&value_states)?
417 };
418
419 attn_output
420 .transpose(1, 2)?
421 .reshape((b_sz, q_len, self.hidden_size))?
422 .apply(&self.o_proj)
423 }
424}
425
426#[derive(Debug, Clone)]
427enum NormType {
428 Layer(LayerNorm),
429 Rms(RmsNorm),
430}
431
432#[derive(Debug, Clone)]
433struct Layer {
434 variant: ModelVariant,
435 attention: Attention,
436 mlp: MLP,
437 layernorm: NormType,
440 post_attention_layernorm: NormType,
441}
442
443impl Layer {
444 fn new(rotary_emb: Arc<RotaryEmbedding>, cfg: &Config, vb: VarBuilder) -> Result<Self> {
445 let attention = Attention::new(
446 rotary_emb,
447 cfg,
448 vb.pp(if cfg.variant == ModelVariant::Large {
449 "self_attn"
450 } else {
451 "attention"
452 }),
453 )?;
454 let mlp = MLP::new(cfg, vb.pp("mlp"))?;
455 let (layernorm, post_attention_layernorm) = match cfg.variant {
456 ModelVariant::Large => (
457 NormType::Rms(RmsNorm::new(
458 cfg.hidden_size,
459 cfg.norm_eps,
460 vb.pp("input_layernorm"),
461 )?),
462 NormType::Rms(RmsNorm::new(
463 cfg.hidden_size,
464 cfg.norm_eps,
465 vb.pp("post_attention_layernorm"),
466 )?),
467 ),
468 ModelVariant::Small => (
469 NormType::Layer(layer_norm(
470 cfg.hidden_size,
471 candle_nn::LayerNormConfig {
472 eps: cfg.norm_eps,
473 ..Default::default()
474 },
475 vb.pp("mlp_ln"),
476 )?),
477 NormType::Layer(layer_norm(
478 cfg.hidden_size,
479 candle_nn::LayerNormConfig {
480 eps: cfg.norm_eps,
481 ..Default::default()
482 },
483 vb.pp("attn_ln"),
484 )?),
485 ),
486 };
487
488 Ok(Self {
489 variant: cfg.variant,
490 attention,
491 mlp,
492 layernorm,
493 post_attention_layernorm,
494 })
495 }
496
497 fn forward(&mut self, xs: &Tensor, attention_mask: Option<&Tensor>) -> Result<Tensor> {
498 let residual = xs;
517
518 match self.variant {
519 ModelVariant::Large => {
520 let (attn_ln, input_ln) = if let (NormType::Rms(attn_ln), NormType::Rms(input_ln)) =
521 (&self.post_attention_layernorm, &self.layernorm)
522 {
523 (attn_ln, input_ln)
524 } else {
525 return Err(candle::error::Error::Msg(
526 "Stella 1.5B expects RMSNorm".to_string(),
527 ));
528 };
529
530 let xs = input_ln.forward(xs)?;
531 let xs = (self.attention.forward(&xs, attention_mask)? + residual)?;
532
533 let residual = &xs;
534 let xs = xs.apply(attn_ln)?.apply(&self.mlp)?;
535
536 residual + xs
537 }
538 ModelVariant::Small => {
539 let (attn_ln, output_ln) =
540 if let (NormType::Layer(attn_ln), NormType::Layer(input_ln)) =
541 (&self.post_attention_layernorm, &self.layernorm)
542 {
543 (attn_ln, input_ln)
544 } else {
545 return Err(candle::error::Error::Msg(
546 "Stella 400M expects RMSNorm".to_string(),
547 ));
548 };
549
550 let xs = (self.attention.forward(xs, attention_mask)? + residual)?;
551 let xs = attn_ln.forward(&xs)?;
552
553 let residual = &xs;
554 let xs = (self.mlp.forward(&xs)? + residual)?;
555
556 output_ln.forward(&xs)
557 }
558 }
559 }
560}
561
562#[derive(Debug, Clone)]
563pub struct Embeddings {
564 variant: ModelVariant,
565 embeddings: candle_nn::Embedding,
568 token_type_embeddings: Option<candle_nn::Embedding>,
570 layer_norm: Option<LayerNorm>,
571 position_ids: Option<Tensor>,
572}
573
574impl Embeddings {
575 pub fn new(cfg: &Config, vb: VarBuilder) -> Result<Self> {
576 let (embeddings, token_type_embeddings, layer_norm, position_ids) = match cfg.variant {
577 ModelVariant::Large => (
578 candle_nn::embedding(cfg.vocab_size, cfg.hidden_size, vb.pp("embed_tokens"))?,
579 None,
580 None,
581 None,
582 ),
583 ModelVariant::Small => {
584 let vb = vb.pp("embeddings");
585 let weight = vb.pp("LayerNorm").get_with_hints(
586 cfg.hidden_size,
587 "weight",
588 candle_nn::Init::Const(1.0),
589 )?;
590 let bias = vb.pp("LayerNorm").get_with_hints(
591 cfg.hidden_size,
592 "bias",
593 candle_nn::Init::Const(0.0),
594 )?;
595 let dev = bias.device().clone();
596
597 let layer_norm = candle_nn::LayerNorm::new(weight, bias, cfg.norm_eps);
598
599 (
600 candle_nn::embedding(
601 cfg.vocab_size,
602 cfg.hidden_size,
603 vb.pp("word_embeddings"),
604 )?,
605 Some(candle_nn::embedding(
606 cfg.type_vocab_size,
607 cfg.hidden_size,
608 vb.pp("token_type_embeddings"),
609 )?),
610 Some(layer_norm),
611 Some(Tensor::arange(
612 0u32,
613 cfg.max_position_embeddings as u32,
614 &dev,
615 )?),
616 )
617 }
618 };
619
620 Ok(Self {
621 variant: cfg.variant,
622 embeddings,
623 token_type_embeddings,
624 layer_norm,
625 position_ids,
626 })
627 }
628}
629
630impl Module for Embeddings {
631 fn forward(&self, xs: &Tensor) -> Result<Tensor> {
632 let embd = self.embeddings.forward(xs)?;
633 if self.variant == ModelVariant::Large {
635 return Ok(embd);
636 }
637
638 let (token_type_embed, layer_norm, pos_ids) =
639 if let (Some(token_type_embd), Some(layer_norm), Some(position_ids)) = (
640 &self.token_type_embeddings,
641 &self.layer_norm,
642 &self.position_ids,
643 ) {
644 (token_type_embd, layer_norm, position_ids)
645 } else {
646 return Err(Error::Msg(
647 "Stella 400M requires `token_type_embeddings`, `layer_norm` and `position_ids`"
648 .to_string(),
649 ));
650 };
651
652 let (batch_size, seq_length) = xs.dims2()?;
653
654 let pos_ids = pos_ids
655 .as_ref()
656 .narrow(0, 0, seq_length)?
657 .expand((batch_size, seq_length))?;
658
659 layer_norm.forward(&embd.add(&token_type_embed.forward(&pos_ids.zeros_like()?)?)?)
660 }
661}
662
663#[derive(Debug, Clone)]
664pub struct Model {
665 embeddings: Embeddings,
666 layers: Vec<Layer>,
667 norm: Option<RmsNorm>,
668 device: Device,
669 dtype: DType,
670}
671
672impl Model {
673 pub fn new(cfg: &Config, vb: VarBuilder) -> Result<Self> {
674 let vb_m = match cfg.variant {
675 ModelVariant::Large => vb.pp("model"),
676 ModelVariant::Small => vb.pp("new"),
677 };
678 let embeddings = Embeddings::new(cfg, vb_m.clone())?;
681 let rotary_emb = Arc::new(RotaryEmbedding::new(vb.dtype(), cfg, vb_m.device())?);
682 let mut layers = Vec::with_capacity(cfg.num_hidden_layers);
683 let vb_l = match cfg.variant {
684 ModelVariant::Large => vb_m.pp("layers"),
685 ModelVariant::Small => vb_m.pp("encoder").pp("layer"),
686 };
687 for layer_idx in 0..cfg.num_hidden_layers {
688 let layer = Layer::new(rotary_emb.clone(), cfg, vb_l.pp(layer_idx))?;
689 layers.push(layer)
690 }
691 let norm = match cfg.variant {
692 ModelVariant::Large => Some(RmsNorm::new(
693 cfg.hidden_size,
694 cfg.norm_eps,
695 vb_m.pp("norm"),
696 )?),
697 ModelVariant::Small => None,
698 };
699 Ok(Self {
700 embeddings,
701 layers,
702 norm,
703 device: vb.device().clone(),
704 dtype: vb.dtype(),
705 })
706 }
707
708 fn prepare_attention_mask(&self, attn_mask: &Tensor) -> Result<Tensor> {
709 let (b_sz, sql_len) = attn_mask.dims2()?;
710 let mut mask: Vec<Tensor> = vec![];
711 for b in 0..b_sz {
712 mask.push(attn_mask.i((b, ..))?.expand((1, 1, sql_len, sql_len))?);
713 }
714 let mask = Tensor::cat(&mask, 0)?;
715 let on_true = mask.zeros_like()?.to_dtype(self.dtype)?;
716 let on_false = Tensor::new(f32::NEG_INFINITY, &self.device)?
717 .broadcast_as(mask.shape())?
718 .to_dtype(self.dtype)?;
719 mask.where_cond(&on_true, &on_false)
720 }
721
722 pub fn forward(&mut self, input_ids: &Tensor, mask: &Tensor) -> Result<Tensor> {
723 let (_, seq_len) = input_ids.dims2()?;
724 let attention_mask = if seq_len <= 1 {
725 None
726 } else {
727 Some(self.prepare_attention_mask(mask)?)
729 };
730
731 let mut xs = self.embeddings.forward(input_ids)?;
732 for layer in self.layers.iter_mut() {
733 xs = layer.forward(&xs, attention_mask.as_ref())?
734 }
735
736 if let Some(n) = &self.norm {
737 xs.apply(n)
738 } else {
739 Ok(xs)
740 }
741 }
742}
743
744#[derive(Debug)]
745pub struct EmbeddingModel {
746 base_model: Model,
747 lm_head: Linear,
748}
749
750impl EmbeddingModel {
751 pub fn new(cfg: &Config, base_vb: VarBuilder, embed_vb: VarBuilder) -> Result<Self> {
752 let base_model = Model::new(cfg, base_vb.clone())?;
753 let lm_head = linear(
754 cfg.embed_head.in_features,
755 cfg.embed_head.out_features,
756 embed_vb.pp("linear"),
757 )?;
758
759 Ok(Self {
760 base_model,
761 lm_head,
762 })
763 }
764
765 pub fn forward(&mut self, input_ids: &Tensor, mask: &Tensor) -> Result<Tensor> {
766 let x = self.base_model.forward(input_ids, mask)?;
767 let x = self.pool(&x, mask)?;
768
769 self.lm_head.forward(&x.to_dtype(DType::F32)?) }
772
773 pub fn forward_norm(&mut self, input_ids: &Tensor, mask: &Tensor) -> Result<Tensor> {
775 let x = self.forward(input_ids, mask)?;
776 x.broadcast_div(&x.sqr()?.sum_keepdim(1)?.sqrt()?)
778 }
779
780 fn pool(&self, x: &Tensor, mask: &Tensor) -> Result<Tensor> {
781 let mask = mask.to_dtype(x.dtype())?; let (batch_size, seq_len, hidden_dim) = x.dims3()?;
783 let mask_expanded = mask
785 .unsqueeze(2)?
786 .broadcast_as((batch_size, seq_len, hidden_dim))?; let x = (x * &mask_expanded)?;
789
790 let sum_mask = mask
792 .sum(1)?
793 .unsqueeze(1)?
794 .expand((batch_size, hidden_dim))?;
795 x.sum(1)? / sum_mask
796 }
797}