1use crate::Tensor;
7
8pub fn linear(x: &Tensor, w: &Tensor) -> Tensor { x.matmul(w) }
10
11pub fn linear_hf(x: &Tensor, w: &Tensor) -> Tensor { x.matmul_bt(w) }
13
14pub fn linear_hf_q(x: &Tensor, w: &crate::QRow) -> Tensor { x.matmul_qweight(w) }
16
17pub fn causal_attention(q: &Tensor, k: &Tensor, v: &Tensor, n_heads: usize, n_kv_heads: usize) -> Tensor {
20 let t = q.shape[0];
21 let d = q.shape[1];
22 let dh = d / n_heads;
23 let g = n_heads / n_kv_heads;
24 let scale = 1.0 / (dh as f32).sqrt();
25 let qh = q.reshape(&[t, n_heads, dh]).permute(&[1, 0, 2]).contiguous(); let kv_heads = |x: &Tensor| {
28 let hx = x.reshape(&[t, n_kv_heads, dh]).permute(&[1, 0, 2]).contiguous(); hx.reshape(&[n_kv_heads, 1, t, dh]).broadcast_to(&[n_kv_heads, g, t, dh]).reshape(&[n_heads, t, dh])
30 };
31 let (kh, vh) = (kv_heads(k), kv_heads(v));
32 let scores = qh.matmul(&kh.transpose(2, 1)).mul(&q.scalar(scale)); let probs = scores.add(&causal_mask(q, t)).softmax(2); let ctx = probs.matmul(&vh); ctx.permute(&[1, 0, 2]).reshape(&[t, d])
36}
37
38pub fn decode_attention(q: &Tensor, k: &Tensor, v: &Tensor, n_heads: usize, n_kv_heads: usize) -> Tensor {
42 let d = q.shape[1];
43 let dh = d / n_heads;
44 let s = k.shape[0];
45 let g = n_heads / n_kv_heads;
46 let scale = 1.0 / (dh as f32).sqrt();
47 let qh = q.reshape(&[1, n_heads, dh]).permute(&[1, 0, 2]).contiguous(); let kv_heads = |x: &Tensor| {
49 let hx = x.reshape(&[s, n_kv_heads, dh]).permute(&[1, 0, 2]).contiguous(); hx.reshape(&[n_kv_heads, 1, s, dh]).broadcast_to(&[n_kv_heads, g, s, dh]).reshape(&[n_heads, s, dh])
51 };
52 let (kh, vh) = (kv_heads(k), kv_heads(v)); let probs = qh.matmul(&kh.transpose(2, 1)).mul(&q.scalar(scale)).softmax(2); probs.matmul(&vh).permute(&[1, 0, 2]).reshape(&[1, d]) }
56
57pub fn bidirectional_attention(q: &Tensor, k: &Tensor, v: &Tensor, n_heads: usize, n_kv_heads: usize) -> Tensor {
60 let (t, d) = (q.shape[0], q.shape[1]);
61 let dh = d / n_heads;
62 let g = n_heads / n_kv_heads;
63 let scale = 1.0 / (dh as f32).sqrt();
64 let qh = q.reshape(&[t, n_heads, dh]).permute(&[1, 0, 2]).contiguous();
65 let kv_heads = |x: &Tensor| {
66 let hx = x.reshape(&[t, n_kv_heads, dh]).permute(&[1, 0, 2]).contiguous();
67 hx.reshape(&[n_kv_heads, 1, t, dh]).broadcast_to(&[n_kv_heads, g, t, dh]).reshape(&[n_heads, t, dh])
68 };
69 let (kh, vh) = (kv_heads(k), kv_heads(v));
70 let probs = qh.matmul(&kh.transpose(2, 1)).mul(&q.scalar(scale)).softmax(2); probs.matmul(&vh).permute(&[1, 0, 2]).reshape(&[t, d])
72}
73
74fn causal_mask(like: &Tensor, t: usize) -> Tensor {
76 let mut m = vec![0.0f32; t * t];
77 for i in 0..t {
78 for j in (i + 1)..t {
79 m[i * t + j] = -1e30;
80 }
81 }
82 Tensor::from_vec(&like.ctx_arc(), &m, &[t, t])
83}