1use crate::models::with_tracing::{linear_no_bias, Linear};
7use candle::{DType, Device, IndexOp, Module, Result, Tensor, D};
8use candle_nn::{RmsNorm, VarBuilder};
9
10const D_CONV: usize = 4;
11
12fn segsum(x: &Tensor) -> Result<Tensor> {
15 let device = x.device();
16 let dtype = x.dtype();
17 let t = x.dim(D::Minus1)?;
18
19 let x_cumsum = x.cumsum(D::Minus1)?;
20
21 let target_shape: Vec<usize> = {
22 let mut shape = x.dims().to_vec();
23 shape.push(t);
24 shape
25 };
26
27 let x_cumsum_row = x_cumsum
28 .unsqueeze(D::Minus1)?
29 .broadcast_as(target_shape.as_slice())?;
30 let x_cumsum_col = x_cumsum
31 .unsqueeze(x.rank() - 1)?
32 .broadcast_as(target_shape.as_slice())?;
33 let x_segsum = (&x_cumsum_row - &x_cumsum_col)?;
34
35 let mask_lower = Tensor::tril2(t, DType::U8, device)?;
36 let neg_inf = Tensor::new(f32::NEG_INFINITY, device)?
37 .to_dtype(dtype)?
38 .broadcast_as(x_segsum.shape())?;
39
40 mask_lower
41 .broadcast_as(x_segsum.shape())?
42 .where_cond(&x_segsum, &neg_inf)
43}
44
45fn pad_to_chunk_size(x: &Tensor, chunk_size: usize) -> Result<(Tensor, usize)> {
46 let seq_len = x.dim(1)?;
47 let pad_len = (chunk_size - (seq_len % chunk_size)) % chunk_size;
48 if pad_len == 0 {
49 return Ok((x.clone(), 0));
50 }
51
52 let mut pad_shape = x.dims().to_vec();
53 pad_shape[1] = pad_len;
54 let padding = Tensor::zeros(pad_shape, x.dtype(), x.device())?;
55 Ok((Tensor::cat(&[x, &padding], 1)?, pad_len))
56}
57
58fn reshape_into_chunks(x: &Tensor, chunk_size: usize) -> Result<Tensor> {
59 let dims = x.dims();
60 let b = dims[0];
61 let l = dims[1];
62 let n_chunks = l / chunk_size;
63
64 let mut new_shape = vec![b, n_chunks, chunk_size];
65 new_shape.extend_from_slice(&dims[2..]);
66 x.reshape(new_shape)
67}
68
69fn reshape_from_chunks(x: &Tensor) -> Result<Tensor> {
70 let dims = x.dims();
71 let b = dims[0];
72 let n_chunks = dims[1];
73 let chunk_size = dims[2];
74
75 let mut new_shape = vec![b, n_chunks * chunk_size];
76 new_shape.extend_from_slice(&dims[3..]);
77 x.reshape(new_shape)
78}
79
80fn default_d_state() -> usize {
81 64
82}
83fn default_expand() -> usize {
84 2
85}
86fn default_headdim() -> usize {
87 64
88}
89fn default_ngroups() -> usize {
90 1
91}
92fn default_pad_vocab_size_multiple() -> usize {
93 16
94}
95
96#[derive(Debug, Clone, serde::Deserialize)]
97pub struct Config {
98 #[serde(alias = "hidden_size")]
99 pub d_model: usize,
100 #[serde(alias = "num_hidden_layers")]
101 pub n_layer: usize,
102 pub vocab_size: usize,
103 #[serde(alias = "state_size", default = "default_d_state")]
104 pub d_state: usize,
105 #[serde(default = "default_expand")]
106 pub expand: usize,
107 #[serde(alias = "head_dim", default = "default_headdim")]
108 pub headdim: usize,
109 #[serde(alias = "n_groups", default = "default_ngroups")]
110 pub ngroups: usize,
111 #[serde(default = "default_pad_vocab_size_multiple")]
112 pub pad_vocab_size_multiple: usize,
113}
114
115impl Config {
116 fn vocab_size(&self) -> usize {
117 let pad = self.pad_vocab_size_multiple;
118 self.vocab_size.div_ceil(pad) * pad
119 }
120
121 fn d_inner(&self) -> usize {
122 self.d_model * self.expand
123 }
124
125 fn d_xbc(&self) -> usize {
126 self.d_inner() + 2 * self.ngroups * self.d_state
127 }
128
129 fn nheads(&self) -> usize {
130 self.d_inner() / self.headdim
131 }
132}
133
134pub struct State {
135 pub hs: Vec<Tensor>,
136 pub conv_states: Vec<Tensor>,
137 pub pos: usize,
138}
139
140impl State {
141 pub fn new(batch_size: usize, cfg: &Config, dtype: DType, device: &Device) -> Result<Self> {
142 let d_xbc = cfg.d_xbc();
143 let nheads = cfg.nheads();
144 let mut hs = Vec::with_capacity(cfg.n_layer);
145 let mut conv_states = Vec::with_capacity(cfg.n_layer);
146 for _ in 0..cfg.n_layer {
147 let h = Tensor::zeros(
148 (batch_size, nheads, cfg.headdim, cfg.d_state),
149 dtype,
150 device,
151 )?;
152 let conv = Tensor::zeros((batch_size, d_xbc, D_CONV), dtype, device)?;
153 hs.push(h);
154 conv_states.push(conv);
155 }
156 Ok(Self {
157 hs,
158 conv_states,
159 pos: 0,
160 })
161 }
162}
163
164#[derive(Clone, Debug)]
165pub struct Mamba2Block {
166 in_proj: Linear,
167 conv1d_weight: Tensor,
168 conv1d_bias: Tensor,
169 a_log: Tensor,
170 d: Tensor,
171 dt_bias: Tensor,
172 out_proj: Linear,
173 norm: RmsNorm,
174 d_inner: usize,
175 d_state: usize,
176 d_xbc: usize,
177 headdim: usize,
178 nheads: usize,
179 ngroups: usize,
180 layer_idx: usize,
181}
182
183impl Mamba2Block {
184 pub fn new(layer_idx: usize, cfg: &Config, vb: VarBuilder) -> Result<Self> {
185 let d_inner = cfg.d_inner();
186 let nheads = cfg.nheads();
187 let ngroups = cfg.ngroups;
188 let d_state = cfg.d_state;
189 let d_xbc = cfg.d_xbc();
190
191 let proj_size = d_inner + d_xbc + nheads;
192 let in_proj = linear_no_bias(cfg.d_model, proj_size, vb.pp("in_proj"))?;
193
194 let conv1d_weight = vb.get((d_xbc, 1, D_CONV), "conv1d.weight")?;
195 let conv1d_bias = vb.get(d_xbc, "conv1d.bias")?;
196
197 let a_log = vb.get(nheads, "A_log")?;
198 let d = vb.get(nheads, "D")?;
199 let dt_bias = vb.get(nheads, "dt_bias")?;
200
201 let out_proj = linear_no_bias(d_inner, cfg.d_model, vb.pp("out_proj"))?;
202 let norm = candle_nn::rms_norm(d_inner, 1e-5, vb.pp("norm"))?;
203
204 Ok(Self {
205 in_proj,
206 conv1d_weight,
207 conv1d_bias,
208 a_log,
209 d,
210 dt_bias,
211 out_proj,
212 norm,
213 d_inner,
214 d_state,
215 d_xbc,
216 headdim: cfg.headdim,
217 nheads,
218 ngroups,
219 layer_idx,
220 })
221 }
222
223 pub fn forward(&self, xs: &Tensor, state: &mut State) -> Result<Tensor> {
224 let (b_sz, _dim) = xs.dims2()?;
225
226 let proj = self.in_proj.forward(xs)?;
227
228 let z = proj.narrow(D::Minus1, 0, self.d_inner)?;
229 let xbc = proj.narrow(D::Minus1, self.d_inner, self.d_xbc)?;
230 let dt = proj.narrow(D::Minus1, self.d_inner + self.d_xbc, self.nheads)?;
231
232 let xbc_conv = self.apply_conv1d(&xbc, &mut state.conv_states[self.layer_idx])?;
233 let xbc_conv = candle_nn::ops::silu(&xbc_conv)?;
234
235 let x_conv = xbc_conv.narrow(D::Minus1, 0, self.d_inner)?;
236 let b = xbc_conv.narrow(D::Minus1, self.d_inner, self.ngroups * self.d_state)?;
237 let c = xbc_conv.narrow(
238 D::Minus1,
239 self.d_inner + self.ngroups * self.d_state,
240 self.ngroups * self.d_state,
241 )?;
242
243 let dt_bias = self.dt_bias.broadcast_as(dt.shape())?;
244 let dt = ((&dt + &dt_bias)?.exp()? + 1.)?.log()?; let a = self.a_log.exp()?.neg()?;
247
248 let y = self.ssm_step(&x_conv, &a, &b, &c, &dt, state)?;
249
250 let d = self.d.broadcast_as((b_sz, self.nheads))?;
251 let x_skip = x_conv.reshape((b_sz, self.nheads, self.headdim))?;
252 let y = (&y + x_skip.broadcast_mul(&d.unsqueeze(D::Minus1)?)?)?;
253 let y = y.reshape((b_sz, self.d_inner))?;
254
255 let y = (y * candle_nn::ops::silu(&z)?)?;
257 let y = self.norm.forward(&y)?;
258
259 self.out_proj.forward(&y)
260 }
261
262 fn apply_conv1d(&self, xbc: &Tensor, conv_state: &mut Tensor) -> Result<Tensor> {
263 let (b_sz, d_xbc) = xbc.dims2()?;
264
265 let shifted = conv_state.narrow(D::Minus1, 1, D_CONV - 1)?;
266 let xbc_expanded = xbc.unsqueeze(D::Minus1)?;
267 *conv_state = Tensor::cat(&[shifted, xbc_expanded], D::Minus1)?;
268
269 let mut result = self.conv1d_bias.broadcast_as((b_sz, d_xbc))?;
270 for i in 0..D_CONV {
271 let w = self.conv1d_weight.i((.., 0, i))?;
272 let xbc_i = conv_state.i((.., .., i))?;
273 result = (result + w.broadcast_mul(&xbc_i)?)?;
274 }
275 Ok(result)
276 }
277
278 fn ssm_step(
279 &self,
280 x: &Tensor,
281 a: &Tensor,
282 b: &Tensor,
283 c: &Tensor,
284 dt: &Tensor,
285 state: &mut State,
286 ) -> Result<Tensor> {
287 let (b_sz, _) = x.dims2()?;
288 let h = &mut state.hs[self.layer_idx];
289
290 let x = x.reshape((b_sz, self.nheads, self.headdim))?;
291
292 let b = b.reshape((b_sz, self.ngroups, self.d_state))?;
293 let c = c.reshape((b_sz, self.ngroups, self.d_state))?;
294 let heads_per_group = self.nheads / self.ngroups;
295 let b =
296 b.unsqueeze(2)?
297 .broadcast_as((b_sz, self.ngroups, heads_per_group, self.d_state))?;
298 let b = b.reshape((b_sz, self.nheads, self.d_state))?;
299 let c =
300 c.unsqueeze(2)?
301 .broadcast_as((b_sz, self.ngroups, heads_per_group, self.d_state))?;
302 let c = c.reshape((b_sz, self.nheads, self.d_state))?;
303
304 let dt_a = dt.broadcast_mul(a)?;
305 let decay = dt_a.exp()?;
306 let decay = decay.unsqueeze(D::Minus1)?.unsqueeze(D::Minus1)?;
307 let decay = decay.broadcast_as((b_sz, self.nheads, self.headdim, self.d_state))?;
308
309 let x_unsq = x.unsqueeze(D::Minus1)?;
310 let b_unsq = b.unsqueeze(2)?;
311 let x_b = x_unsq.broadcast_mul(&b_unsq)?;
312
313 let dt_expanded = dt.unsqueeze(D::Minus1)?.unsqueeze(D::Minus1)?;
314 let dt_expanded =
315 dt_expanded.broadcast_as((b_sz, self.nheads, self.headdim, self.d_state))?;
316
317 *h = ((&*h * &decay)? + (&dt_expanded * &x_b)?)?;
319
320 let c_unsq = c.unsqueeze(2)?;
321 let c_broadcast = c_unsq.broadcast_as(h.shape())?;
322 let y = (&*h * &c_broadcast)?.sum(D::Minus1)?;
323
324 Ok(y)
325 }
326
327 fn ssd_chunked(
329 &self,
330 x: &Tensor,
331 a: &Tensor,
332 b: &Tensor,
333 c: &Tensor,
334 chunk_size: usize,
335 initial_state: Option<&Tensor>,
336 ) -> Result<(Tensor, Tensor)> {
337 let device = x.device();
338 let dtype = x.dtype();
339 let (batch, seq_len, nheads, headdim) = x.dims4()?;
340 let d_state = self.d_state;
341 let n_chunks = seq_len / chunk_size;
342
343 let x = reshape_into_chunks(x, chunk_size)?;
344 let a = reshape_into_chunks(a, chunk_size)?;
345 let b = reshape_into_chunks(b, chunk_size)?;
346 let c = reshape_into_chunks(c, chunk_size)?;
347
348 let a = a.permute((0, 3, 1, 2))?.contiguous()?;
350 let a_cumsum = a.cumsum(D::Minus1)?;
351
352 let l = segsum(&a)?.exp()?;
354
355 let c_expanded = c.unsqueeze(3)?;
356 let b_expanded = b.unsqueeze(2)?;
357 let cb_shape = (batch, n_chunks, chunk_size, chunk_size, nheads, d_state);
358 let cb = (c_expanded.broadcast_as(cb_shape)? * b_expanded.broadcast_as(cb_shape)?)?
359 .sum(D::Minus1)?;
360 let cb = cb.permute((0, 1, 4, 2, 3))?;
361
362 let l_t = l.permute((0, 2, 1, 3, 4))?;
363 let cb_l = (&cb * &l_t)?;
364
365 let x_t = x.permute((0, 1, 3, 2, 4))?;
366 let y_diag_shape = (batch, n_chunks, nheads, chunk_size, chunk_size, headdim);
367 let y_diag = (cb_l.unsqueeze(D::Minus1)?.broadcast_as(y_diag_shape)?
368 * x_t.unsqueeze(3)?.broadcast_as(y_diag_shape)?)?
369 .sum(4)?
370 .permute((0, 1, 3, 2, 4))?;
371
372 let a_last = a_cumsum.narrow(D::Minus1, chunk_size - 1, 1)?;
374 let decay_states = (a_last.broadcast_as(a_cumsum.shape())? - &a_cumsum)?.exp()?;
375
376 let decay_s = decay_states.permute((0, 2, 1, 3))?.unsqueeze(D::Minus1)?;
377 let b_t = b.permute((0, 1, 3, 2, 4))?;
378 let b_weighted = b_t.broadcast_mul(&decay_s)?;
379
380 let x_t2 = x.permute((0, 1, 3, 2, 4))?;
381 let states_shape = (batch, n_chunks, nheads, chunk_size, headdim, d_state);
382 let states = (x_t2.unsqueeze(D::Minus1)?.broadcast_as(states_shape)?
383 * b_weighted.unsqueeze(4)?.broadcast_as(states_shape)?)?
384 .sum(3)?;
385
386 let init_state = match initial_state {
388 Some(s) => s.unsqueeze(1)?,
389 None => Tensor::zeros((batch, 1, nheads, headdim, d_state), dtype, device)?,
390 };
391 let states_with_init = Tensor::cat(&[&init_state, &states], 1)?;
392
393 let a_chunk = a_cumsum
394 .narrow(D::Minus1, chunk_size - 1, 1)?
395 .squeeze(D::Minus1)?;
396 let zeros = Tensor::zeros((batch, nheads, 1), dtype, device)?;
397 let a_chunk_padded = Tensor::cat(&[&zeros, &a_chunk], D::Minus1)?;
398 let decay_chunk = segsum(&a_chunk_padded)?.exp()?;
399
400 let states_p = states_with_init.permute((0, 2, 1, 3, 4))?;
401 let inter_shape = (batch, nheads, n_chunks + 1, n_chunks + 1, headdim, d_state);
402 let new_states = (decay_chunk
403 .unsqueeze(D::Minus1)?
404 .unsqueeze(D::Minus1)?
405 .broadcast_as(inter_shape)?
406 * states_p.unsqueeze(2)?.broadcast_as(inter_shape)?)?
407 .sum(3)?
408 .permute((0, 2, 1, 3, 4))?;
409
410 let states_out = new_states.narrow(1, 0, n_chunks)?;
411 let final_state = new_states.narrow(1, n_chunks, 1)?.squeeze(1)?;
412
413 let state_decay_out = a_cumsum.exp()?;
415
416 let c_t2 = c.permute((0, 1, 3, 2, 4))?;
417 let off_shape = (batch, n_chunks, nheads, chunk_size, headdim, d_state);
418 let c_states = (c_t2.unsqueeze(4)?.broadcast_as(off_shape)?
419 * states_out.unsqueeze(3)?.broadcast_as(off_shape)?)?
420 .sum(D::Minus1)?;
421
422 let decay_out = state_decay_out
423 .permute((0, 2, 1, 3))?
424 .unsqueeze(D::Minus1)?;
425 let y_off = c_states
426 .broadcast_mul(&decay_out)?
427 .permute((0, 1, 3, 2, 4))?;
428
429 let y = (&y_diag + &y_off)?;
430 let y = reshape_from_chunks(&y)?;
431
432 Ok((y, final_state))
433 }
434
435 pub fn forward_prefill(
436 &self,
437 xs: &Tensor,
438 state: &mut State,
439 chunk_size: usize,
440 ) -> Result<Tensor> {
441 let (b_sz, seq_len, _) = xs.dims3()?;
442
443 let (xs, pad_len) = pad_to_chunk_size(xs, chunk_size)?;
444 let padded_len = xs.dim(1)?;
445
446 let proj = xs.apply(&self.in_proj)?;
447
448 let z = proj.narrow(D::Minus1, 0, self.d_inner)?;
449 let xbc = proj.narrow(D::Minus1, self.d_inner, self.d_xbc)?;
450 let dt = proj.narrow(D::Minus1, self.d_inner + self.d_xbc, self.nheads)?;
451
452 let xbc_t = xbc.transpose(1, 2)?;
453 let pad = Tensor::zeros((b_sz, self.d_xbc, D_CONV - 1), xbc.dtype(), xbc.device())?;
454 let xbc_padded = Tensor::cat(&[&pad, &xbc_t], D::Minus1)?;
455 let xbc_conv = xbc_padded.conv1d(&self.conv1d_weight, 0, 1, 1, self.d_xbc)?;
456 let xbc_conv = xbc_conv
457 .broadcast_add(&self.conv1d_bias.reshape((1, self.d_xbc, 1))?)?
458 .transpose(1, 2)?;
459 let xbc_conv = candle_nn::ops::silu(&xbc_conv)?;
460
461 let start = seq_len.saturating_sub(D_CONV);
463 let count = D_CONV.min(seq_len);
464 let last_tokens = xbc.narrow(1, start, count)?;
465 let last_tokens = last_tokens.transpose(1, 2)?;
466 if count >= D_CONV {
467 state.conv_states[self.layer_idx] = last_tokens.contiguous()?;
468 } else {
469 let existing =
470 state.conv_states[self.layer_idx].narrow(D::Minus1, count, D_CONV - count)?;
471 state.conv_states[self.layer_idx] = Tensor::cat(&[&existing, &last_tokens], D::Minus1)?;
472 }
473
474 let x_conv = xbc_conv.narrow(D::Minus1, 0, self.d_inner)?;
475 let b = xbc_conv.narrow(D::Minus1, self.d_inner, self.ngroups * self.d_state)?;
476 let c = xbc_conv.narrow(
477 D::Minus1,
478 self.d_inner + self.ngroups * self.d_state,
479 self.ngroups * self.d_state,
480 )?;
481
482 let dt_bias = self.dt_bias.broadcast_as(dt.shape())?;
483 let dt = ((&dt + &dt_bias)?.exp()? + 1.)?.log()?;
484
485 let a = self.a_log.exp()?.neg()?;
486 let mut a_dt = dt.broadcast_mul(&a)?;
487
488 let mut x_ssd = x_conv.reshape((b_sz, padded_len, self.nheads, self.headdim))?;
489
490 if pad_len > 0 {
492 let mask_ones = Tensor::ones(
493 (b_sz, seq_len, self.nheads, self.headdim),
494 x_ssd.dtype(),
495 x_ssd.device(),
496 )?;
497 let mask_zeros = Tensor::zeros(
498 (b_sz, pad_len, self.nheads, self.headdim),
499 x_ssd.dtype(),
500 x_ssd.device(),
501 )?;
502 let mask = Tensor::cat(&[&mask_ones, &mask_zeros], 1)?;
503 x_ssd = x_ssd.broadcast_mul(&mask)?;
504
505 let mask_ones_a =
506 Tensor::ones((b_sz, seq_len, self.nheads), a_dt.dtype(), a_dt.device())?;
507 let mask_zeros_a =
508 Tensor::zeros((b_sz, pad_len, self.nheads), a_dt.dtype(), a_dt.device())?;
509 let mask_a = Tensor::cat(&[&mask_ones_a, &mask_zeros_a], 1)?;
510 a_dt = a_dt.broadcast_mul(&mask_a)?;
511 }
512
513 let heads_per_group = self.nheads / self.ngroups;
514 let b = b.reshape((b_sz, padded_len, self.ngroups, self.d_state))?;
515 let b = b
516 .unsqueeze(3)?
517 .broadcast_as((
518 b_sz,
519 padded_len,
520 self.ngroups,
521 heads_per_group,
522 self.d_state,
523 ))?
524 .reshape((b_sz, padded_len, self.nheads, self.d_state))?;
525 let b = b.broadcast_mul(&dt.unsqueeze(D::Minus1)?)?;
527 let c = c.reshape((b_sz, padded_len, self.ngroups, self.d_state))?;
528 let c = c
529 .unsqueeze(3)?
530 .broadcast_as((
531 b_sz,
532 padded_len,
533 self.ngroups,
534 heads_per_group,
535 self.d_state,
536 ))?
537 .reshape((b_sz, padded_len, self.nheads, self.d_state))?;
538
539 let initial_state = Some(&state.hs[self.layer_idx]);
540 let (y, final_state) =
541 self.ssd_chunked(&x_ssd, &a_dt, &b, &c, chunk_size, initial_state)?;
542 state.hs[self.layer_idx] = final_state;
543
544 let y = y.reshape((b_sz, padded_len, self.d_inner))?;
545
546 let d = self.d.unsqueeze(0)?.unsqueeze(0)?;
547 let x_skip = x_conv.reshape((b_sz, padded_len, self.nheads, self.headdim))?;
548 let y = (&y.reshape((b_sz, padded_len, self.nheads, self.headdim))?
549 + x_skip.broadcast_mul(&d.unsqueeze(D::Minus1)?)?)?;
550 let y = y.reshape((b_sz, padded_len, self.d_inner))?;
551
552 let y = (y * candle_nn::ops::silu(&z)?)?;
553 let y = y.reshape((b_sz * padded_len, self.d_inner))?;
554 let y = self.norm.forward(&y)?;
555 let y = y.reshape((b_sz, padded_len, self.d_inner))?;
556
557 let y = y.apply(&self.out_proj)?;
558
559 if pad_len > 0 {
560 y.narrow(1, 0, seq_len)
561 } else {
562 Ok(y)
563 }
564 }
565}
566
567#[derive(Clone, Debug)]
568pub struct ResidualBlock {
569 mixer: Mamba2Block,
570 norm: RmsNorm,
571}
572
573impl ResidualBlock {
574 pub fn new(layer_idx: usize, cfg: &Config, vb: VarBuilder) -> Result<Self> {
575 let norm = candle_nn::rms_norm(cfg.d_model, 1e-5, vb.pp("norm"))?;
576 let mixer = Mamba2Block::new(layer_idx, cfg, vb.pp("mixer"))?;
577 Ok(Self { mixer, norm })
578 }
579
580 fn forward(&self, xs: &Tensor, state: &mut State) -> Result<Tensor> {
581 self.mixer.forward(&xs.apply(&self.norm)?, state)? + xs
582 }
583
584 fn forward_prefill(&self, xs: &Tensor, state: &mut State, chunk_size: usize) -> Result<Tensor> {
585 let normed = xs.apply(&self.norm)?;
586 self.mixer.forward_prefill(&normed, state, chunk_size)? + xs
587 }
588}
589
590#[derive(Clone, Debug)]
591pub struct Model {
592 embedding: candle_nn::Embedding,
593 layers: Vec<ResidualBlock>,
594 norm_f: RmsNorm,
595 lm_head: Linear,
596 dtype: DType,
597}
598
599impl Model {
600 pub fn new(cfg: &Config, vb: VarBuilder) -> Result<Self> {
601 let embedding = candle_nn::embedding(cfg.vocab_size(), cfg.d_model, vb.pp("embeddings"))?;
602 let mut layers = Vec::with_capacity(cfg.n_layer);
603 let vb_l = vb.pp("layers");
604 for layer_idx in 0..cfg.n_layer {
605 layers.push(ResidualBlock::new(layer_idx, cfg, vb_l.pp(layer_idx))?);
606 }
607 let norm_f = candle_nn::rms_norm(cfg.d_model, 1e-5, vb.pp("norm_f"))?;
608 let lm_head = Linear::from_weights(embedding.embeddings().clone(), None);
609 Ok(Self {
610 embedding,
611 layers,
612 norm_f,
613 lm_head,
614 dtype: vb.dtype(),
615 })
616 }
617
618 pub fn forward(&self, input_ids: &Tensor, state: &mut State) -> Result<Tensor> {
619 let mut xs = self.embedding.forward(input_ids)?;
620 for layer in self.layers.iter() {
621 xs = layer.forward(&xs, state)?;
622 }
623 state.pos += 1;
624 xs.apply(&self.norm_f)?.apply(&self.lm_head)
625 }
626
627 pub fn forward_prefill(
628 &self,
629 input_ids: &Tensor,
630 state: &mut State,
631 chunk_size: usize,
632 ) -> Result<Tensor> {
633 let (b_sz, seq_len) = input_ids.dims2()?;
634 let mut xs = self.embedding.forward(input_ids)?;
635 for layer in self.layers.iter() {
636 xs = layer.forward_prefill(&xs, state, chunk_size)?;
637 }
638 state.pos += seq_len;
639 let xs = xs.reshape((b_sz * seq_len, xs.dim(D::Minus1)?))?;
640 let logits = xs.apply(&self.norm_f)?.apply(&self.lm_head)?;
641 logits.reshape((b_sz, seq_len, logits.dim(D::Minus1)?))
642 }
643
644 pub fn dtype(&self) -> DType {
645 self.dtype
646 }
647}