main.bend
bend-ml-llama@0.2.0.0 · 1,343 lines · 175 definitions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21import Base
22import bend-ml-tensor-array@0.1.14.0/main.bend as TA
23
24
25
26
27
28law add_zero:
29 for a: Nat
30 {Nat.add(a, 0n) == a : Nat}
31
32def add_zero(a):
33 match a:
34 case 0n:
35 {==}
36 case 1n+p:
37 %add_zero(p) : {1n+Nat.add(p, 0n) == 1n+_ : Nat}
38 {==}
39
40law add_succ:
41 for a: Nat
42 for -b: Nat
43 {1n+Nat.add(a, b) == Nat.add(a, 1n+b) : Nat}
44
45def add_succ(a, b):
46 match a:
47 case 0n:
48 {==}
49 case 1n+p:
50 %add_succ(p, b) : {2n+Nat.add(p, b) == 1n+_ : Nat}
51 {==}
52
53law add_one:
54 for a: Nat
55 {Nat.add(a, 1n) == 1n+a : Nat}
56
57def add_one(a):
58 match a:
59 case 0n:
60 {==}
61 case 1n+p:
62 %add_one(p) : {1n+Nat.add(p, 1n) == 1n+_ : Nat}
63 {==}
64
65law add_assoc:
66 for a: Nat
67 for -b: Nat
68 for -c: Nat
69 {Nat.add(Nat.add(a, b), c) == Nat.add(a, Nat.add(b, c)) : Nat}
70
71def add_assoc(a, b, c):
72 match a:
73 case 0n:
74 {==}
75 case 1n+p:
76 %add_assoc(p, b, c) : {1n+Nat.add(Nat.add(p, b), c) == 1n+_ : Nat}
77 {==}
78
79
80
81
82
83
84
85
86type Cfg is Data:
87 Cfg{kv: Nat, g: Nat, half: Nat, f: Nat, layers: Nat, vocab: Nat, eps: F32, theta: F32}
88
89
90def head(+half: Nat) -> Nat:
91 Nat.add(half, half)
92
93def Cfg.half(+c: Cfg) -> Nat:
94 match c:
95 case Cfg{kv, g, half, f, l, v, e, t}:
96 half
97
98def Cfg.kv(+c: Cfg) -> Nat:
99 match c:
100 case Cfg{kv, g, half, f, l, v, e, t}:
101 kv
102
103def Cfg.g(+c: Cfg) -> Nat:
104 match c:
105 case Cfg{kv, g, half, f, l, v, e, t}:
106 g
107
108def Cfg.ffn(+c: Cfg) -> Nat:
109 match c:
110 case Cfg{kv, g, half, f, l, v, e, t}:
111 f
112
113def Cfg.layers(+c: Cfg) -> Nat:
114 match c:
115 case Cfg{kv, g, half, f, l, v, e, t}:
116 l
117
118def Cfg.vocab(+c: Cfg) -> Nat:
119 match c:
120 case Cfg{kv, g, half, f, l, v, e, t}:
121 v
122
123def Cfg.eps(+c: Cfg) -> F32:
124 match c:
125 case Cfg{kv, g, half, f, l, v, e, t}:
126 e
127
128def Cfg.theta(+c: Cfg) -> F32:
129 match c:
130 case Cfg{kv, g, half, f, l, v, e, t}:
131 t
132
133
134def Cfg.head(+c: Cfg) -> Nat:
135 head(Cfg.half(c))
136
137
138def Cfg.heads(+c: Cfg) -> Nat:
139 Nat.mul(Cfg.kv(c), Cfg.g(c))
140
141
142def Cfg.dim(+c: Cfg) -> Nat:
143 Nat.mul(Cfg.heads(c), Cfg.head(c))
144
145
146def Cfg.kvw(+c: Cfg) -> Nat:
147 Nat.mul(Cfg.kv(c), Cfg.head(c))
148
149
150def smollm2_135m() -> Cfg:
151 Cfg{3n, 3n, 32n, 1536n, 30n, 49152n, 0.00001, 100000.0}
152
153
154def smollm2_360m() -> Cfg:
155 Cfg{5n, 3n, 32n, 2560n, 32n, 49152n, 0.00001, 100000.0}
156
157
158def smollm2_1_7b() -> Cfg:
159 Cfg{32n, 1n, 32n, 8192n, 24n, 49152n, 0.00001, 130000.0}
160
161
162
163
164law smollm2_135m_sizes:
165 {Cfg.dim(smollm2_135m()) == 576n : Nat} & {Cfg.heads(smollm2_135m()) == 9n : Nat} & {Cfg.head(smollm2_135m()) == 64n : Nat} & {Cfg.kvw(smollm2_135m()) == 192n : Nat}
166
167def smollm2_135m_sizes():
168 ({==}, {==}, {==}, {==})
169
170law smollm2_360m_sizes:
171 {Cfg.dim(smollm2_360m()) == 960n : Nat} & {Cfg.heads(smollm2_360m()) == 15n : Nat} & {Cfg.head(smollm2_360m()) == 64n : Nat} & {Cfg.kvw(smollm2_360m()) == 320n : Nat}
172
173def smollm2_360m_sizes():
174 ({==}, {==}, {==}, {==})
175
176law smollm2_1_7b_sizes:
177 {Cfg.dim(smollm2_1_7b()) == 2048n : Nat} & {Cfg.heads(smollm2_1_7b()) == 32n : Nat} & {Cfg.head(smollm2_1_7b()) == 64n : Nat} & {Cfg.kvw(smollm2_1_7b()) == 2048n : Nat}
178
179def smollm2_1_7b_sizes():
180 ({==}, {==}, {==}, {==})
181
182
183
184def n32(+n: Nat) -> U32:
185 U32.from_nat(n)
186
187
188
189def Cfg.layer_size(+c: Cfg) -> U32:
190 ((2 : U32) * n32(Cfg.dim(c)) + (2 : U32) * n32(Cfg.dim(c)) * n32(Cfg.dim(c)) + (2 : U32) * n32(Cfg.kvw(c)) * n32(Cfg.dim(c)) + (3 : U32) * n32(Cfg.ffn(c)) * n32(Cfg.dim(c)) : U32)
191
192
193def Cfg.size(+c: Cfg) -> U32:
194 (n32(Cfg.vocab(c)) * n32(Cfg.dim(c)) + n32(Cfg.layers(c)) * Cfg.layer_size(c) + n32(Cfg.dim(c)) : U32)
195
196
197
198
199
200law layout_135m:
201 {Cfg.size(smollm2_135m()) == (134515008 : U32) : U32}
202
203def layout_135m():
204 {==}
205
206law layout_360m:
207 {Cfg.size(smollm2_360m()) == (361821120 : U32) : U32}
208
209def layout_360m():
210 {==}
211
212law layout_1_7b:
213 {Cfg.size(smollm2_1_7b()) == (1711376384 : U32) : U32}
214
215def layout_1_7b():
216 {==}
217
218
219
220
221
222
223type Head is Data:
224 Head{lo: List<&2, F32>, hi: List<&2, F32>}
225
226def split(+half: Nat, +xs: List<&2, F32>) -> Head:
227 Head{List.take(&2, F32, xs, half), List.drop(&2, F32, xs, half)}
228
229def join(h: Head) -> List<&2, F32>:
230 match h:
231 case Head{lo, hi}:
232 List.append(&2, F32, lo, hi)
233
234
235def heads(n: Nat, +half: Nat, +xs: List<&2, F32>) -> List<&2, Head>:
236 match n:
237 case 0n:
238 Nil{}
239 case 1n+p:
240 split(half, List.take(&2, F32, xs, head(half))) <> heads(p, half, List.drop(&2, F32, xs, head(half)))
241
242
243def chunks(n: Nat, +w: Nat, +xs: List<&2, F32>) -> List<&2, List<&2, F32>>:
244 match n:
245 case 0n:
246 Nil{}
247 case 1n+p:
248 List.take(&2, F32, xs, w) <> chunks(p, w, List.drop(&2, F32, xs, w))
249
250def joins(hs: List<&2, Head>) -> List<&2, List<&2, F32>>:
251 match hs:
252 case Nil{}:
253 Nil{}
254 case Con{h, t}:
255 join(h) <> joins(t)
256
257def flat(hs: List<&2, Head>) -> List<&2, F32>:
258 List.concat(&2, F32, joins(hs))
259
260
261
262law head_split:
263 for +xs: List<&2, F32>
264 for +half: Nat
265 {join(split(half, xs)) == xs : List<&2, F32>}
266
267
268
269
270def head_split(xs, half):
271 match xs half:
272 case Nil{} _:
273 {==}
274 case Con{h, t} 0n:
275 {==}
276 case Con{h, t} 1n+p:
277 %head_split(t, p) : {h <> List.append(&2, F32, List.take(&2, F32, t, p), List.drop(&2, F32, t, p)) == h <> _ : List<&2, F32>}
278 {==}
279
280
281
282
283
284
285
286
287def list.add(xs: List<&2, F32>, ys: List<&2, F32>) -> List<&2, F32>:
288 match xs ys:
289 case Con{+h, t} Con{+g, u}:
290 (h + g : F32) <> list.add(t, u)
291 case _ _:
292 Nil{}
293
294
295def list.mul(xs: List<&2, F32>, ys: List<&2, F32>) -> List<&2, F32>:
296 match xs ys:
297 case Con{+h, t} Con{+g, u}:
298 (h * g : F32) <> list.mul(t, u)
299 case _ _:
300 Nil{}
301
302
303def list.scale(+k: F32, xs: List<&2, F32>) -> List<&2, F32>:
304 match xs:
305 case Nil{}:
306 Nil{}
307 case Con{+h, t}:
308 (k * h : F32) <> list.scale(k, t)
309
310
311def list.sum.go(xs: List<&2, F32>, acc: F32) -> F32:
312 match xs:
313 case Nil{}:
314 acc
315 case Con{+h, t}:
316 list.sum.go(t, (acc + h : F32))
317
318def list.max.go(xs: List<&2, F32>, cur: F32) -> F32:
319 match xs:
320 case Nil{}:
321 cur
322 case Con{+h, t}:
323 list.max.go(t, F32.max(cur, h))
324
325
326def list.max(xs: List<&2, F32>) -> F32:
327 match xs:
328 case Nil{}:
329 0.0
330 case Con{+h, t}:
331 list.max.go(t, h)
332
333
334def list.exp_shift(xs: List<&2, F32>, +m: F32) -> List<&2, F32>:
335 match xs:
336 case Nil{}:
337 Nil{}
338 case Con{+h, t}:
339 F32.exp((h - m : F32)) <> list.exp_shift(t, m)
340
341
342def list.div(xs: List<&2, F32>, +s: F32) -> List<&2, F32>:
343 match xs:
344 case Nil{}:
345 Nil{}
346 case Con{+h, t}:
347 (h / s : F32) <> list.div(t, s)
348
349def list.softmax.fin(+es: List<&2, F32>) -> List<&2, F32>:
350 list.div(es, list.sum.go(es, 0.0))
351
352
353def list.softmax(+xs: List<&2, F32>) -> List<&2, F32>:
354 list.softmax.fin(list.exp_shift(xs, list.max(xs)))
355
356
357def squares(xs: List<&2, F32>) -> List<&2, F32>:
358 match xs:
359 case Nil{}:
360 Nil{}
361 case Con{+h, t}:
362 (h * h : F32) <> squares(t)
363
364
365def pair_sums(xs: List<&2, F32>) -> List<&2, F32>:
366 match xs:
367 case Con{+a, Con{+b, t}}:
368 (a + b : F32) <> pair_sums(t)
369 case _:
370 xs
371
372
373
374def tree_sum(fuel: Nat, xs: List<&2, F32>) -> F32:
375 match fuel xs:
376 case _ Nil{}:
377 0.0
378 case _ Con{+a, Nil{}}:
379 a
380 case 0n Con{+a, t}:
381 list.sum.go(t, a)
382 case 1n+p Con{+a, t}:
383 tree_sum(p, pair_sums(Con{a, t}))
384
385
386def rmsnorm(+c: Cfg, +x: List<&2, F32>, +g: List<&2, F32>) -> List<&2, F32>:
387 list.mul(g, list.scale((1.0 / F32.sqrt(((tree_sum(Cfg.dim(c), squares(x)) / F32.from_nat(Cfg.dim(c)) : F32) + Cfg.eps(c) : F32)) : F32), x))
388
389
390def inv_freq.go(n: Nat, +i: Nat, +theta: F32, +hd: F32) -> List<&2, F32>:
391 match n:
392 case 0n:
393 Nil{}
394 case 1n+p:
395 (1.0 / F32.pow(theta, (F32.from_nat(Nat.mul(2n, i)) / hd : F32)) : F32) <> inv_freq.go(p, 1n+i, theta, hd)
396
397def inv_freq(+c: Cfg) -> List<&2, F32>:
398 inv_freq.go(Cfg.half(c), 0n, Cfg.theta(c), F32.from_nat(Cfg.head(c)))
399
400def angles(+t: F32, fs: List<&2, F32>) -> List<&2, F32>:
401 match fs:
402 case Nil{}:
403 Nil{}
404 case Con{+f, r}:
405 (t * f : F32) <> angles(t, r)
406
407def cos.l(xs: List<&2, F32>) -> List<&2, F32>:
408 match xs:
409 case Nil{}:
410 Nil{}
411 case Con{+x, r}:
412 F32.cos(x) <> cos.l(r)
413
414def sin.l(xs: List<&2, F32>) -> List<&2, F32>:
415 match xs:
416 case Nil{}:
417 Nil{}
418 case Con{+x, r}:
419 F32.sin(x) <> sin.l(r)
420
421
422type Rot is Data:
423 Rot{cs: List<&2, F32>, sn: List<&2, F32>}
424
425def rot_at(+c: Cfg, +t: Nat) -> Rot:
426 Rot{cos.l(angles(F32.from_nat(t), inv_freq(c))), sin.l(angles(F32.from_nat(t), inv_freq(c)))}
427
428
429def rot_lo(h1: List<&2, F32>, h2: List<&2, F32>, cs: List<&2, F32>, sn: List<&2, F32>) -> List<&2, F32>:
430 match h1 h2 cs sn:
431 case Con{+a, ta} Con{+b, tb} Con{+c, tc} Con{+s, ts}:
432 ((a * c : F32) + (F32.neg(b) * s : F32) : F32) <> rot_lo(ta, tb, tc, ts)
433 case _ _ _ _:
434 Nil{}
435
436def rot_hi(h1: List<&2, F32>, h2: List<&2, F32>, cs: List<&2, F32>, sn: List<&2, F32>) -> List<&2, F32>:
437 match h1 h2 cs sn:
438 case Con{+a, ta} Con{+b, tb} Con{+c, tc} Con{+s, ts}:
439 ((b * c : F32) + (a * s : F32) : F32) <> rot_hi(ta, tb, tc, ts)
440 case _ _ _ _:
441 Nil{}
442
443def rope(rt: Rot, h: Head) -> Head:
444 match rt h:
445 case Rot{+cs, +sn} Head{+lo, +hi}:
446 Head{rot_lo(lo, hi, cs, sn), rot_hi(lo, hi, cs, sn)}
447
448def ropes(+rt: Rot, hs: List<&2, Head>) -> List<&2, Head>:
449 match hs:
450 case Nil{}:
451 Nil{}
452 case Con{h, t}:
453 rope(rt, h) <> ropes(rt, t)
454
455
456def silu(+x: F32) -> F32:
457 (x / (1.0 + F32.exp(F32.neg(x)) : F32) : F32)
458
459
460def swiglu(g: List<&2, F32>, u: List<&2, F32>) -> List<&2, F32>:
461 match g u:
462 case Con{+a, ga} Con{+b, ub}:
463 (silu(a) * b : F32) <> swiglu(ga, ub)
464 case _ _:
465 Nil{}
466
467
468
469
470
471
472
473
474
475type KV<-cap: Nat, -t: Nat> is Type:
476 KV{ks: List<&1, Array<F32>>, vs: List<&1, Array<F32>>}
477
478
479def arrays(n: Nat, +d: Nat) -> List<&1, Array<F32>>:
480 match n:
481 case 0n:
482 Nil{}
483 case 1n+p:
484 Array.new(F32, d, 0.0) <> arrays(p, d)
485
486
487def KV.empty(+c: Cfg, +cap: Nat) -> KV<cap, 0n>:
488 KV{arrays(Cfg.kv(c), TA.cap_depth(Nat.mul(cap, Cfg.head(c)))), arrays(Cfg.kv(c), TA.cap_depth(Nat.mul(cap, Cfg.head(c))))}
489
490
491def write_rows(arrs: List<&1, Array<F32>>, rs: List<&2, List<&2, F32>>, +off: U32) -> List<&1, Array<F32>>:
492 match arrs rs:
493 case Con{a, at} Con{r, rt}:
494 TA.fill_list(r, off, a) <> write_rows(at, rt, off)
495 case _ _:
496 arrs
497
498
499def KV.push(+c: Cfg, -cap: Nat, +t: Nat, kv: KV<cap, t>, -room: {True{} == TA.leb(1n+t, cap) : Bool}, +ks: List<&2, List<&2, F32>>, +vs: List<&2, List<&2, F32>>) -> KV<cap, 1n+t>:
500 match kv:
501 case KV{ka, va}:
502 KV{write_rows(ka, ks, U32.from_nat(Nat.mul(t, Cfg.head(c)))), write_rows(va, vs, U32.from_nat(Nat.mul(t, Cfg.head(c))))}
503
504
505def kv_count(-cap: Nat, -t: Nat, kv: KV<cap, t>) -> Nat:
506 match kv:
507 case KV{ka, va}:
508 List.length(&1, Array<F32>, ka)
509
510
511law arrays_len:
512 for +n: Nat
513 for +d: Nat
514 {List.length(&1, Array<F32>, arrays(n, d)) == n : Nat}
515
516
517def arrays_len(n, d):
518 match n:
519 case 0n:
520 {==}
521 case 1n+p:
522 %arrays_len(p, d) : {1n+List.length(&1, Array<F32>, arrays(p, d)) == 1n+_ : Nat}
523 {==}
524
525
526
527law kv_heads:
528 for +c: Cfg
529 for +cap: Nat
530 {kv_count(cap, 0n, KV.empty(c, cap)) == Cfg.kv(c) : Nat}
531
532def kv_heads(c, cap):
533 arrays_len(Cfg.kv(c), TA.cap_depth(Nat.mul(cap, Cfg.head(c))))
534
535
536def leb_trans(a: Nat, b: Nat, c: Nat, e1: {True{} == TA.leb(a, b) : Bool}, e2: {True{} == TA.leb(b, c) : Bool}) -> {True{} == TA.leb(a, c) : Bool}:
537 match a b c:
538 case 0n _ _:
539 {==}
540 case 1n+p 0n _:
541 %e1 : TA.BD(_, Unit, {True{} == TA.leb(1n+p, c) : Bool})
542 Unit{}
543 case 1n+p 1n+q 0n:
544 %e2 : TA.BD(_, Unit, {True{} == TA.leb(1n+p, 0n) : Bool})
545 Unit{}
546 case 1n+p 1n+q 1n+r:
547 leb_trans(p, q, r, e1, e2)
548
549
550def leb_mul(a: Nat, b: Nat, +h: Nat, e: {True{} == TA.leb(a, b) : Bool}) -> {True{} == TA.leb(Nat.mul(a, h), Nat.mul(b, h)) : Bool}:
551 match a b:
552 case 0n _:
553 {==}
554 case 1n+p 0n:
555 %e : TA.BD(_, Unit, {True{} == TA.leb(Nat.mul(1n+p, h), 0n) : Bool})
556 Unit{}
557 case 1n++p 1n++q:
558 TA.leb_add(h, h, Nat.mul(p, h), Nat.mul(q, h), TA.leb_refl(h), leb_mul(p, q, h, e))
559
560
561
562
563
564
565law kv_room:
566 for +cap: Nat
567 for +h: Nat
568 for +t: Nat
569 for e: {True{} == TA.leb(1n+t, cap) : Bool}
570 {True{} == TA.leb(Nat.mul(1n+t, h), TA.pow2(TA.cap_depth(Nat.mul(cap, h)))) : Bool}
571
572
573
574def step_room(+t: Nat, +p: Nat, -cap: Nat, e: {Nat.add(t, 1n+p) == cap : Nat}) -> {True{} == TA.leb(1n+t, cap) : Bool}:
575 %e : {True{} == TA.leb(1n+t, _) : Bool}
576 %add_succ(t, p) : {True{} == TA.leb(1n+t, _) : Bool}
577 TA.leb_up(t, t, p, TA.leb_refl(t))
578
579def step_inv(+t: Nat, -p: Nat, -cap: Nat, e: {Nat.add(t, 1n+p) == cap : Nat}) -> {Nat.add(1n+t, p) == cap : Nat}:
580 %e : {1n+Nat.add(t, p) == _ : Nat}
581 add_succ(t, p)
582
583
584
585def kv_room(cap, h, t, e):
586 leb_trans(Nat.mul(1n+t, h), Nat.mul(cap, h), TA.pow2(TA.cap_depth(Nat.mul(cap, h))), leb_mul(1n+t, cap, h, e), TA.cap_ok(Nat.mul(cap, h)))
587
588
589
590
591
592def groups(n: Nat, +g: Nat, +hs: List<&2, Head>) -> List<&2, List<&2, Head>>:
593 match n:
594 case 0n:
595 Nil{}
596 case 1n+p:
597 List.take(&2, Head, hs, g) <> groups(p, g, List.drop(&2, Head, hs, g))
598
599
600
601law groups_len:
602 for n: Nat
603 for +g: Nat
604 for +hs: List<&2, Head>
605 {List.length(&2, List<&2, Head>, groups(n, g, hs)) == n : Nat}
606
607def groups_len(n, g, hs):
608 match n:
609 case 0n:
610 {==}
611 case 1n+p:
612 %groups_len(p, g, List.drop(&2, Head, hs, g)) : {1n+List.length(&2, List<&2, Head>, groups(p, g, List.drop(&2, Head, hs, g))) == 1n+_ : Nat}
613 {==}
614
615
616law div_block:
617 for +m: Nat
618 for -n: Nat
619 for -d: Nat
620 for -r: Nat
621 {Nat.divmod.go(Nat.add(1n+m, n), m, d, r) == Nat.divmod.go(n, Nat.add(m, r), 1n+d, 0n) : Nat & Nat}
622
623def div_block(m, n, d, r):
624 match m:
625 case 0n:
626 {==}
627 case 1n+p:
628 %Equal.sym(Nat, 1n+Nat.add(p, r), Nat.add(p, 1n+r), add_succ(p, r)) : {Nat.divmod.go(Nat.add(1n+p, n), p, d, 1n+r) == Nat.divmod.go(n, _, 1n+d, 0n) : Nat & Nat}
629 div_block(p, n, d, 1n+r)
630
631
632law div_blocks:
633 for +j: Nat
634 for +s: Nat
635 for +n: Nat
636 for +d: Nat
637 {Nat.divmod.go(Nat.add(Nat.mul(j, 1n+s), n), s, d, 0n) == Nat.divmod.go(n, s, Nat.add(j, d), 0n) : Nat & Nat}
638
639def div_blocks(j, s, n, d):
640 match j:
641 case 0n:
642 {==}
643 case 1n+jp:
644 %Equal.sym(Nat, Nat.add(Nat.add(1n+s, Nat.mul(jp, 1n+s)), n), Nat.add(1n+s, Nat.add(Nat.mul(jp, 1n+s), n)), add_assoc(1n+s, Nat.mul(jp, 1n+s), n)) : {Nat.divmod.go(_, s, d, 0n) == Nat.divmod.go(n, s, Nat.add(1n+jp, d), 0n) : Nat & Nat}
645 %Equal.sym(Nat & Nat, Nat.divmod.go(Nat.add(1n+s, Nat.add(Nat.mul(jp, 1n+s), n)), s, d, 0n), Nat.divmod.go(Nat.add(Nat.mul(jp, 1n+s), n), Nat.add(s, 0n), 1n+d, 0n), div_block(s, Nat.add(Nat.mul(jp, 1n+s), n), d, 0n)) : {_ == Nat.divmod.go(n, s, Nat.add(1n+jp, d), 0n) : Nat & Nat}
646 %Equal.sym(Nat, Nat.add(s, 0n), s, add_zero(s)) : {Nat.divmod.go(Nat.add(Nat.mul(jp, 1n+s), n), _, 1n+d, 0n) == Nat.divmod.go(n, s, Nat.add(1n+jp, d), 0n) : Nat & Nat}
647 %Equal.sym(Nat, 1n+Nat.add(jp, d), Nat.add(jp, 1n+d), add_succ(jp, d)) : {Nat.divmod.go(Nat.add(Nat.mul(jp, 1n+s), n), s, 1n+d, 0n) == Nat.divmod.go(n, s, _, 0n) : Nat & Nat}
648 div_blocks(jp, s, n, 1n+d)
649
650
651law div_rest:
652 for +i: Nat
653 for -k: Nat
654 for -d: Nat
655 for -r: Nat
656 {Pair.fst(Nat, Nat, Nat.divmod.go(i, Nat.add(i, k), d, r)) == d : Nat}
657
658def div_rest(i, k, d, r):
659 match i:
660 case 0n:
661 {==}
662 case 1n+p:
663 div_rest(p, k, d, 1n+r)
664
665
666
667
668law gqa_head:
669 for +j: Nat
670 for +i: Nat
671 for +k: Nat
672 {Nat.div(Nat.add(Nat.mul(j, 1n+Nat.add(i, k)), i), 1n+Nat.add(i, k)) == j : Nat}
673
674
675
676def gqa_head(j, i, k):
677 %Equal.sym(Nat & Nat, Nat.divmod.go(Nat.add(Nat.mul(j, 1n+Nat.add(i, k)), i), Nat.add(i, k), 0n, 0n), Nat.divmod.go(i, Nat.add(i, k), Nat.add(j, 0n), 0n), div_blocks(j, Nat.add(i, k), i, 0n)) : {Pair.fst(Nat, Nat, _) == j : Nat}
678 %add_zero(j) : {Pair.fst(Nat, Nat, Nat.divmod.go(i, Nat.add(i, k), Nat.add(j, 0n), 0n)) == _ : Nat}
679 div_rest(i, k, Nat.add(j, 0n), 0n)
680
681
682
683
684
685
686type SR is Type:
687 SR{k: Array<F32>, s: List<&2, F32>}
688
689def sr_len(sr: SR) -> Nat:
690 match sr:
691 case SR{k, s}:
692 List.length(&2, F32, s)
693
694def sr_of(k: Array<F32>, al: TA.AL) -> SR:
695 match al:
696 case TA.AL{c, l}:
697 SR{k, l}
698
699
700
701
702law read_len:
703 for k: Array<F32>
704 for +m: Nat
705 for +idx: U32
706 for +acc: List<&2, F32>
707 for rc: Array<F32> & F32
708 {sr_len(sr_of(k, TA.read_l(m, idx, acc, rc))) == Nat.add(1n+m, List.length(&2, F32, acc)) : Nat}
709
710def read_len(k, m, idx, acc, rc):
711 match m rc:
712 case 0n Tuple{d, +v}:
713 TA.zero_out(List.length(&2, F32, List.reverse.go(&2, F32, v <> acc, Nil{})), 1n+List.length(&2, F32, acc), TA.rev_len(v <> acc, Nil{}))
714 case 1n+p Tuple{d, +v}:
715 TA.len_step(sr_len(sr_of(k, TA.read_l(p, (idx + 1 : U32), v <> acc, Array.get(F32, d, (idx + 1 : U32))))), p, List.length(&2, F32, acc), read_len(k, p, (idx + 1 : U32), v <> acc, Array.get(F32, d, (idx + 1 : U32))))
716
717
718def sr_read(+t: Nat, g: TA.G) -> SR:
719 match g:
720 case TA.G{qa, k, s}:
721 sr_of(k, TA.read_l(t, 0, Nil{}, Array.get(F32, s, 0)))
722
723
724
725def scores(+hd: Nat, +t: Nat, k: Array<F32>, +q: List<&2, F32>) -> SR:
726 sr_read(t, TA.gemm(1n, 1n+t, hd, U32.from_nat(hd), 1, 1, U32.from_nat(hd), TA.fill_list(q, 0, Array.new(F32, TA.cap_depth(hd), 0.0)), k, Array.new(F32, TA.cap_depth(1n+t), 0.0)))
727
728def sr_len_g(+t: Nat, g: TA.G) -> {sr_len(sr_read(t, g)) == 1n+t : Nat}:
729 match g:
730 case TA.G{qa, k, s}:
731 TA.zero_out(sr_len(sr_of(k, TA.read_l(t, 0, Nil{}, Array.get(F32, s, 0)))), 1n+t, read_len(k, t, 0, Nil{}, Array.get(F32, s, 0)))
732
733
734
735
736
737law causal:
738 for +hd: Nat
739 for +t: Nat
740 for k: Array<F32>
741 for +q: List<&2, F32>
742 {sr_len(scores(hd, t, k, q)) == 1n+t : Nat}
743
744def causal(hd, t, k, q):
745 sr_len_g(t, TA.gemm(1n, 1n+t, hd, U32.from_nat(hd), 1, 1, U32.from_nat(hd), TA.fill_list(q, 0, Array.new(F32, TA.cap_depth(hd), 0.0)), k, Array.new(F32, TA.cap_depth(1n+t), 0.0)))
746
747
748type WR is Type:
749 WR{v: Array<F32>, o: List<&2, F32>}
750
751def wr_of(v: Array<F32>, al: TA.AL) -> WR:
752 match al:
753 case TA.AL{c, l}:
754 WR{v, l}
755
756def wr_read(+hd: Nat, g: TA.G) -> WR:
757 match g:
758 case TA.G{wa, v, o}:
759 wr_of(v, TA.read_l(Nat.sub(hd, 1n), 0, Nil{}, Array.get(F32, o, 0)))
760
761def weighted(+hd: Nat, +t: Nat, v: Array<F32>, +w: List<&2, F32>) -> WR:
762 wr_read(hd, TA.gemm(1n, hd, 1n+t, U32.from_nat(1n+t), 1, U32.from_nat(hd), 1, TA.fill_list(w, 0, Array.new(F32, TA.cap_depth(1n+t), 0.0)), v, Array.new(F32, TA.cap_depth(hd), 0.0)))
763
764
765type HO is Type:
766 HO{k: Array<F32>, v: Array<F32>, o: List<&2, F32>}
767
768def HO.then(-R: Type, h: HO, then: Array<F32> -> Array<F32> -> List<&2, F32> -> R) -> R:
769 match h:
770 case HO{k, v, o}:
771 then(k, v, o)
772
773def head_wr(k: Array<F32>, wr: WR) -> HO:
774 match wr:
775 case WR{v, o}:
776 HO{k, v, o}
777
778def head_sr(+hd: Nat, +t: Nat, +scale: F32, v: Array<F32>, sr: SR) -> HO:
779 match sr:
780 case SR{k, s}:
781 head_wr(k, weighted(hd, t, v, list.softmax(list.scale(scale, s))))
782
783def head_att(+hd: Nat, +t: Nat, +scale: F32, k: Array<F32>, v: Array<F32>, +q: List<&2, F32>) -> HO:
784 head_sr(hd, t, scale, v, scores(hd, t, k, q))
785
786
787def group_att(hs: List<&2, Head>, +hd: Nat, +t: Nat, +scale: F32, k: Array<F32>, v: Array<F32>, +acc: List<&2, F32>) -> HO:
788 match hs:
789 case Nil{}:
790 HO{k, v, acc}
791 case Con{h, rest}:
792 HO.then(HO, head_att(hd, t, scale, k, v, join(h)), k2 => v2 => +o =>
793
794 group_att(rest, hd, t, scale, k2, v2, List.append(&2, F32, acc, o)))
795
796
797type AT is Type:
798 AT{ks: List<&1, Array<F32>>, vs: List<&1, Array<F32>>, o: List<&2, F32>}
799
800def at_join(p: AT, q: AT) -> AT:
801 match p q:
802 case AT{k1, v1, o1} AT{k2, v2, o2}:
803 AT{List.append(&1, Array<F32>, k1, k2), List.append(&1, Array<F32>, v1, v2), List.append(&2, F32, o1, o2)}
804
805
806type GW is Type:
807 GW{g: List<&2, Head>, k: Array<F32>, v: Array<F32>}
808
809def gws(gs: List<&2, List<&2, Head>>, ks: List<&1, Array<F32>>, vs: List<&1, Array<F32>>) -> List<&1, GW>:
810 match gs ks vs:
811 case Con{g, gt} Con{k, kt} Con{v, vt}:
812 GW{g, k, v} <> gws(gt, kt, vt)
813 case _ _ _:
814 Nil{}
815
816
817def seq_att(ws: List<&1, GW>, +hd: Nat, +t: Nat, +scale: F32, aks: List<&1, Array<F32>>, avs: List<&1, Array<F32>>, +acc: List<&2, F32>) -> AT:
818 match ws:
819 case Con{w, wt}:
820 match w:
821 case GW{g, k, v}:
822 HO.then(AT, group_att(g, hd, t, scale, k, v, Nil{}), k2 => v2 => +o =>
823
824 seq_att(wt, hd, t, scale, k2 <> aks, v2 <> avs, List.append(&2, F32, acc, o)))
825 case Nil{}:
826 AT{List.reverse(&1, Array<F32>, aks), List.reverse(&1, Array<F32>, avs), acc}
827
828
829type GS is Type:
830 GS{l: List<&1, GW>, r: List<&1, GW>}
831
832def cut(n: Nat, xs: List<&1, GW>, acc: List<&1, GW>) -> GS:
833 match n xs:
834 case 1n+m Con{x, xt}:
835 cut(m, xt, x <> acc)
836 case _ _:
837 GS{List.reverse(&1, GW, acc), xs}
838
839
840def halvings(fuel: Nat, +n: Nat) -> Nat:
841 match fuel:
842 case 0n:
843 0n
844 case 1n+f:
845 match n:
846 case 0n:
847 0n
848 case 1n+p:
849 match p:
850 case 0n:
851 0n
852 case 1n+q:
853 1n+halvings(f, Nat.sub(2n+q, TA.half(2n+q)))
854
855
856
857def par_att(d: Nat, gs: GS, +n: Nat, +hd: Nat, +t: Nat, +scale: F32) -> AT:
858 match d gs:
859 case 0n GS{l, r}:
860
861 p q = seq_att(l, hd, t, scale, Nil{}, Nil{}, Nil{}) seq_att(r, hd, t, scale, Nil{}, Nil{}, Nil{})
862 at_join(p, q)
863 case 1n++e GS{l, r}:
864 p q = par_att(e, cut(TA.half(TA.half(n)), l, Nil{}), TA.half(n), hd, t, scale) par_att(e, cut(TA.half(Nat.sub(n, TA.half(n))), r, Nil{}), Nat.sub(n, TA.half(n)), hd, t, scale)
865 at_join(p, q)
866
867
868type KA<-cap: Nat, -t: Nat> is Type:
869 KA{kv: KV<cap, t>, o: List<&2, F32>}
870
871def ka_of(-cap: Nat, -t: Nat, at: AT) -> KA<cap, t>:
872 match at:
873 case AT{ks, vs, o}:
874 KA{KV{ks, vs}, o}
875
876def KA.then(-R: Type, -cap: Nat, -t: Nat, ka: KA<cap, t>, then: KV<cap, t> -> List<&2, F32> -> R) -> R:
877 match ka:
878 case KA{kv, o}:
879 then(kv, o)
880
881
882
883
884
885def attention(+c: Cfg, +d: Nat, -cap: Nat, +t: Nat, qs: List<&2, Head>, kv: KV<cap, 1n+t>) -> KA<cap, 1n+t>:
886 match d kv:
887 case 0n KV{ks, vs}:
888 ka_of(cap, 1n+t, seq_att(gws(groups(Cfg.kv(c), Cfg.g(c), qs), ks, vs), Cfg.head(c), t, (1.0 / F32.sqrt(F32.from_nat(Cfg.head(c))) : F32), Nil{}, Nil{}, Nil{}))
889 case 1n+e KV{ks, vs}:
890 ka_of(cap, 1n+t, par_att(Nat.sub(halvings(Cfg.kv(c), Cfg.kv(c)), 1n), cut(TA.half(Cfg.kv(c)), gws(groups(Cfg.kv(c), Cfg.g(c), qs), ks, vs), Nil{}), Cfg.kv(c), Cfg.head(c), t, (1.0 / F32.sqrt(F32.from_nat(Cfg.head(c))) : F32)))
891
892
893
894
895
896
897type LW<-c: Cfg> is Type:
898 LW{ln1: List<&2, F32>, q: TA.Bands<Cfg.dim(c), Cfg.dim(c)>, k: TA.Bands<Cfg.kvw(c), Cfg.dim(c)>, v: TA.Bands<Cfg.kvw(c), Cfg.dim(c)>, o: TA.Bands<Cfg.dim(c), Cfg.dim(c)>, ln2: List<&2, F32>, gate: TA.Bands<Cfg.ffn(c), Cfg.dim(c)>, up: TA.Bands<Cfg.ffn(c), Cfg.dim(c)>, down: TA.Bands<Cfg.dim(c), Cfg.ffn(c)>}
899
900
901
902type Act is Data:
903 Act{n1: List<&2, F32>, q: List<&2, F32>, k: List<&2, F32>, v: List<&2, F32>, qr: List<&2, F32>, kr: List<&2, F32>, attn: List<&2, F32>, a: List<&2, F32>, n2: List<&2, F32>, m: List<&2, F32>, y: List<&2, F32>}
904
905
906
907type BR<-c: Cfg, -cap: Nat, -t: Nat> is Type:
908 BR{y: List<&2, F32>, kv: KV<cap, 1n+t>, lw: LW<c>, act: Act}
909
910
911
912def BR.then(-R: Type, -c: Cfg, -cap: Nat, -t: Nat, b: BR<c, cap, t>, k: List<&2, F32> -> KV<cap, 1n+t> -> LW<c> -> Act -> R) -> R:
913 match b:
914 case BR{y, kv, lw, act}:
915 k(y, kv, lw, act)
916
917def mv.go(-B: Type, -r: Nat, -k: Nat, bl: TA.BL<r, k>, then: TA.Bands<r, k> -> List<&2, F32> -> B) -> B:
918 match bl:
919 case TA.BL{w, y}:
920 then(w, y)
921
922
923def mv(-B: Type, +r: Nat, +k: Nat, w: TA.Bands<r, k>, +x: List<&2, F32>, then: TA.Bands<r, k> -> List<&2, F32> -> B) -> B:
924 mv.go(B, r, k, TA.Bands.matvec_l(r, k, w, x), then)
925
926
927
928def block(+c: Cfg, +d: Nat, lw: LW<c>, -cap: Nat, +t: Nat, kv: KV<cap, t>, -room: {True{} == TA.leb(1n+t, cap) : Bool}, +rt: Rot, +x: List<&2, F32>) -> BR<c, cap, t>:
929 match lw:
930 case LW{+ln1, wq, wk, wv, wo, +ln2, wg, wu, wd}:
931 +n1 = rmsnorm(c, x, ln1)
932 mv(BR<c, cap, t>, Cfg.dim(c), Cfg.dim(c), wq, n1, wq => +q =>
933 mv(BR<c, cap, t>, Cfg.kvw(c), Cfg.dim(c), wk, n1, wk => +k =>
934 mv(BR<c, cap, t>, Cfg.kvw(c), Cfg.dim(c), wv, n1, wv => +v =>
935 +qs = ropes(rt, heads(Cfg.heads(c), Cfg.half(c), q))
936 +ks = ropes(rt, heads(Cfg.kv(c), Cfg.half(c), k))
937 KA.then(BR<c, cap, t>, cap, 1n+t, attention(c, d, cap, t, qs, KV.push(c, cap, t, kv, room, joins(ks), chunks(Cfg.kv(c), Cfg.head(c), v))), kv2 => +at =>
938 mv(BR<c, cap, t>, Cfg.dim(c), Cfg.dim(c), wo, at, wo => +a =>
939 +x1 = list.add(x, a)
940 +n2 = rmsnorm(c, x1, ln2)
941 mv(BR<c, cap, t>, Cfg.ffn(c), Cfg.dim(c), wg, n2, wg => +g =>
942 mv(BR<c, cap, t>, Cfg.ffn(c), Cfg.dim(c), wu, n2, wu => +u =>
943 mv(BR<c, cap, t>, Cfg.dim(c), Cfg.ffn(c), wd, swiglu(g, u), wd => +m =>
944 +y = list.add(x1, m)
945 BR{y, kv2, LW{ln1, wq, wk, wv, wo, ln2, wg, wu, wd}, Act{n1, q, k, v, flat(qs), flat(ks), at, a, n2, m, y}}))))))))
946
947
948
949
950
951def block_gen(+c: Cfg, +d: Nat, lw: LW<c>, -cap: Nat, +t: Nat, kv: KV<cap, t>, -room: {True{} == TA.leb(1n+t, cap) : Bool}, +rt: Rot, +x: List<&2, F32>) -> BR<c, cap, t>:
952 match lw:
953 case LW{+ln1, wq, wk, wv, wo, +ln2, wg, wu, wd}:
954 +n1 = rmsnorm(c, x, ln1)
955 mv(BR<c, cap, t>, Cfg.dim(c), Cfg.dim(c), wq, n1, wq => +q =>
956 mv(BR<c, cap, t>, Cfg.kvw(c), Cfg.dim(c), wk, n1, wk => +k =>
957 mv(BR<c, cap, t>, Cfg.kvw(c), Cfg.dim(c), wv, n1, wv => +v =>
958 +qs = ropes(rt, heads(Cfg.heads(c), Cfg.half(c), q))
959 +ks = ropes(rt, heads(Cfg.kv(c), Cfg.half(c), k))
960 KA.then(BR<c, cap, t>, cap, 1n+t, attention(c, d, cap, t, qs, KV.push(c, cap, t, kv, room, joins(ks), chunks(Cfg.kv(c), Cfg.head(c), v))), kv2 => +at =>
961 mv(BR<c, cap, t>, Cfg.dim(c), Cfg.dim(c), wo, at, wo => +a =>
962 +x1 = list.add(x, a)
963 +n2 = rmsnorm(c, x1, ln2)
964 mv(BR<c, cap, t>, Cfg.ffn(c), Cfg.dim(c), wg, n2, wg => +g =>
965 mv(BR<c, cap, t>, Cfg.ffn(c), Cfg.dim(c), wu, n2, wu => +u =>
966 mv(BR<c, cap, t>, Cfg.dim(c), Cfg.ffn(c), wd, swiglu(g, u), wd => +m =>
967 +y = list.add(x1, m)
968 BR{y, kv2, LW{ln1, wq, wk, wv, wo, ln2, wg, wu, wd}, Act{Nil{}, Nil{}, Nil{}, Nil{}, Nil{}, Nil{}, Nil{}, Nil{}, Nil{}, Nil{}, Nil{}}}))))))))
969
970
971def block_k(keep: Bool, +c: Cfg, +d: Nat, lw: LW<c>, -cap: Nat, +t: Nat, kv: KV<cap, t>, -room: {True{} == TA.leb(1n+t, cap) : Bool}, +rt: Rot, +x: List<&2, F32>) -> BR<c, cap, t>:
972 match keep:
973 case True{}:
974 block(c, d, lw, cap, t, kv, room, rt, x)
975 case False{}:
976 block_gen(c, d, lw, cap, t, kv, room, rt, x)
977
978
979
980
981
982
983type Model<-c: Cfg> is Type:
984 Model{d: Nat, emb: TA.Bands<Cfg.vocab(c), Cfg.dim(c)>, layers: List<&1, LW<c>>, lnf: List<&2, F32>}
985
986
987type Run<-c: Cfg, -cap: Nat, -t: Nat> is Type:
988 Run{x: List<&2, F32>, layers: List<&1, LW<c>>, cs: List<&1, KV<cap, 1n+t>>, acts: List<&2, Act>}
989
990
991def run(+keep: Bool, +c: Cfg, +d: Nat, -cap: Nat, +t: Nat, -room: {True{} == TA.leb(1n+t, cap) : Bool}, +rt: Rot, ls: List<&1, LW<c>>, cs: List<&1, KV<cap, t>>, al: List<&1, LW<c>>, ac: List<&1, KV<cap, 1n+t>>, aa: List<&2, Act>, pend: BR<c, cap, t>) -> Run<c, cap, t>:
992 match ls cs pend:
993 case Con{l, lt} Con{k, kt} BR{+y, kv, l0, act}:
994 run(keep, c, d, cap, t, room, rt, lt, kt, l0 <> al, kv <> ac, act <> aa, block_k(keep, c, d, l, cap, t, k, room, rt, y))
995 case _ _ BR{+y, kv, l0, act}:
996 Run{y, List.reverse(&1, LW<c>, l0 <> al), List.reverse(&1, KV<cap, 1n+t>, kv <> ac), List.reverse(&2, Act, act <> aa)}
997
998def layers(+keep: Bool, +c: Cfg, +d: Nat, -cap: Nat, +t: Nat, -room: {True{} == TA.leb(1n+t, cap) : Bool}, +rt: Rot, ls: List<&1, LW<c>>, cs: List<&1, KV<cap, t>>, +x: List<&2, F32>) -> Run<c, cap, t>:
999 match ls cs:
1000 case Con{l, lt} Con{k, kt}:
1001 run(keep, c, d, cap, t, room, rt, lt, kt, Nil{}, Nil{}, Nil{}, block_k(keep, c, d, l, cap, t, k, room, rt, x))
1002 case _ _:
1003 Run{x, Nil{}, Nil{}, Nil{}}
1004
1005
1006
1007type Out<-c: Cfg, -cap: Nat, -t: Nat> is Type:
1008 Out{lg: List<&2, F32>, nf: List<&2, F32>, acts: List<&2, Act>, cs: List<&1, KV<cap, 1n+t>>, m: Model<c>}
1009
1010
1011def Out.then(-R: Type, -c: Cfg, -cap: Nat, -t: Nat, o: Out<c, cap, t>, k: List<&2, F32> -> List<&2, F32> -> List<&2, Act> -> List<&1, KV<cap, 1n+t>> -> Model<c> -> R) -> R:
1012 match o:
1013 case Out{lg, nf, acts, cs, m}:
1014 k(lg, nf, acts, cs, m)
1015
1016
1017def head_of(+c: Cfg, -cap: Nat, -t: Nat, +d: Nat, emb: TA.Bands<Cfg.vocab(c), Cfg.dim(c)>, +lnf: List<&2, F32>, r: Run<c, cap, t>) -> Out<c, cap, t>:
1018 match r:
1019 case Run{+x, ls, cs, acts}:
1020 +nf = rmsnorm(c, x, lnf)
1021 mv(Out<c, cap, t>, Cfg.vocab(c), Cfg.dim(c), emb, nf, emb => +lg => Out{lg, nf, acts, cs, Model{d, emb, ls, lnf}})
1022
1023def forward.go(+keep: Bool, +c: Cfg, -cap: Nat, +t: Nat, -room: {True{} == TA.leb(1n+t, cap) : Bool}, +d: Nat, ls: List<&1, LW<c>>, +lnf: List<&2, F32>, cs: List<&1, KV<cap, t>>, r: TA.BRow<Cfg.vocab(c), Cfg.dim(c)>) -> Out<c, cap, t>:
1024 match r:
1025 case TA.BRow{emb, row}:
1026 head_of(c, cap, t, d, emb, lnf, layers(keep, c, d, cap, t, room, rot_at(c, t), ls, cs, row))
1027
1028
1029
1030def forward_k(+keep: Bool, +c: Cfg, -cap: Nat, +t: Nat, m: Model<c>, cs: List<&1, KV<cap, t>>, -room: {True{} == TA.leb(1n+t, cap) : Bool}, +tok: Nat) -> Out<c, cap, t>:
1031 match m:
1032 case Model{+d, emb, ls, +lnf}:
1033 forward.go(keep, c, cap, t, room, d, ls, lnf, cs, TA.Bands.read_row(Cfg.vocab(c), Cfg.dim(c), emb, tok))
1034
1035
1036def forward(+c: Cfg, -cap: Nat, +t: Nat, m: Model<c>, cs: List<&1, KV<cap, t>>, -room: {True{} == TA.leb(1n+t, cap) : Bool}, +tok: Nat) -> Out<c, cap, t>:
1037 forward_k(True{}, c, cap, t, m, cs, room, tok)
1038
1039
1040
1041
1042def forward_gen(+c: Cfg, -cap: Nat, +t: Nat, m: Model<c>, cs: List<&1, KV<cap, t>>, -room: {True{} == TA.leb(1n+t, cap) : Bool}, +tok: Nat) -> Out<c, cap, t>:
1043 match m:
1044 case Model{+d, emb, ls, +lnf}:
1045 forward.go(Nat.is_eq(d, 0n), c, cap, t, room, d, ls, lnf, cs, TA.Bands.read_row(Cfg.vocab(c), Cfg.dim(c), emb, tok))
1046
1047
1048
1049def pre_of(-c: Cfg, -cap: Nat, -t: Nat, +d: Nat, emb: TA.Bands<Cfg.vocab(c), Cfg.dim(c)>, +lnf: List<&2, F32>, r: Run<c, cap, t>) -> Out<c, cap, t>:
1050 match r:
1051 case Run{x, ls, cs, acts}:
1052 Out{Nil{}, Nil{}, acts, cs, Model{d, emb, ls, lnf}}
1053
1054def forward_pre.go(+c: Cfg, -cap: Nat, +t: Nat, -room: {True{} == TA.leb(1n+t, cap) : Bool}, +d: Nat, ls: List<&1, LW<c>>, +lnf: List<&2, F32>, cs: List<&1, KV<cap, t>>, r: TA.BRow<Cfg.vocab(c), Cfg.dim(c)>) -> Out<c, cap, t>:
1055 match r:
1056 case TA.BRow{emb, row}:
1057 pre_of(c, cap, t, d, emb, lnf, layers(Nat.is_eq(d, 0n), c, d, cap, t, room, rot_at(c, t), ls, cs, row))
1058
1059def forward_pre(+c: Cfg, -cap: Nat, +t: Nat, m: Model<c>, cs: List<&1, KV<cap, t>>, -room: {True{} == TA.leb(1n+t, cap) : Bool}, +tok: Nat) -> Out<c, cap, t>:
1060 match m:
1061 case Model{+d, emb, ls, +lnf}:
1062 forward_pre.go(c, cap, t, room, d, ls, lnf, cs, TA.Bands.read_row(Cfg.vocab(c), Cfg.dim(c), emb, tok))
1063
1064
1065def caches(+c: Cfg, n: Nat, +cap: Nat) -> List<&1, KV<cap, 0n>>:
1066 match n:
1067 case 0n:
1068 Nil{}
1069 case 1n+p:
1070 KV.empty(c, cap) <> caches(c, p, cap)
1071
1072
1073type AM is Data:
1074 AM{i: Nat, v: F32}
1075
1076def AM.i(am: AM) -> Nat:
1077 match am:
1078 case AM{i, v}:
1079 i
1080
1081def AM.v(am: AM) -> F32:
1082 match am:
1083 case AM{i, v}:
1084 v
1085
1086def gt_head(xs: List<&2, F32>, +v: F32) -> Bool:
1087 match xs:
1088 case Nil{}:
1089 False{}
1090 case Con{+h, t}:
1091 F32.is_gt(h, v)
1092
1093def argmax.go(xs: List<&2, F32>, g: Bool, +i: Nat, +bi: Nat, +bv: F32) -> AM:
1094 match xs g:
1095 case Nil{} _:
1096 AM{bi, bv}
1097 case Con{+h, +t} True{}:
1098 argmax.go(t, gt_head(t, h), 1n+i, i, h)
1099 case Con{h, +t} False{}:
1100 argmax.go(t, gt_head(t, bv), 1n+i, bi, bv)
1101
1102def argmax(xs: List<&2, F32>) -> AM:
1103 match xs:
1104 case Nil{}:
1105 AM{0n, 0.0}
1106 case Con{+h, +t}:
1107 argmax.go(t, gt_head(t, h), 1n, 0n, h)
1108
1109
1110
1111
1112
1113
1114
1115def bitcast(u: U32) -> F32:
1116 match u:
1117 case U32{w}:
1118 F32{w}
1119
1120def f32_le(+b0: U32, +b1: U32, +b2: U32, +b3: U32) -> F32:
1121 bitcast((b0 + (b1 * 256 : U32) + (b2 * 65536 : U32) + (b3 * 16777216 : U32) : U32))
1122
1123def f32s(bs: List<&2, U32>) -> List<&2, F32>:
1124 match bs:
1125 case Con{b0, Con{b1, Con{b2, Con{b3, t}}}}:
1126 f32_le(b0, b1, b2, b3) <> f32s(t)
1127 case _:
1128 Nil{}
1129
1130
1131def rf_loop(k: Nat, +off: U32, +blk: U32, m: File & Result<&1, &1, U32 & String, List<&2, U32>>, acc: List<&2, List<&2, F32>>) -> IO(List<&2, F32>):
1132 match k m:
1133 case 0n Tuple{f, r}:
1134 do IO<List<&2, F32>>:
1135 File.close(f)
1136 return List.concat(&2, F32, List.reverse(&2, List<&2, F32>, acc))
1137 case 1n+p Tuple{f, r}:
1138 do IO<List<&2, F32>>:
1139 bs : List<&2, U32> <- IO.pass(List<&2, U32>, r)
1140 m2 : File & Result<&1, &1, U32 & String, List<&2, U32>> <- File.read_at(f, (off + blk : U32), blk)
1141 rf_loop(p, (off + blk : U32), blk, m2, f32s(bs) <> acc)
1142
1143def blocks_of(n: Nat, +per: Nat) -> Nat:
1144 Nat.div(Nat.add(n, Nat.sub(per, 1n)), per)
1145
1146
1147def read_floats(path: String, +n: Nat) -> IO(List<&2, F32>):
1148 do IO<List<&2, F32>>:
1149 f : File <- IO.try(File, File.open(path, "r"))
1150 m : File & Result<&1, &1, U32 & String, List<&2, U32>> <- File.read_at(f, 0, 1048576)
1151 fl : List<&2, F32> <- rf_loop(blocks_of(Nat.mul(n, 4n), 1048576n), 0, 1048576, m, Nil{})
1152 return List.take(&2, F32, fl, n)
1153
1154
1155
1156
1157def depth_sel(few: Bool) -> Nat:
1158 match few:
1159 case True{}:
1160 0n
1161 case False{}:
1162 4n
1163
1164def depth_for(+threads: U32) -> Nat:
1165 depth_sel(U32.is_le(threads, 2))
1166
1167def nm(+i: Nat, f: String) -> String:
1168 "h" ++ Nat.show(i) ++ "." ++ f
1169
1170
1171
1172def size_cmp(ok: Bool, +path: String, +got: U32, +want: Nat) -> IO(Unit):
1173 match ok:
1174 case True{}:
1175 IO.pure(Unit, Unit{})
1176 case False{}:
1177 IO.die(Unit, 1, path ++ ": expected " ++ Nat.show(want) ++ " bytes, found " ++ U32.show(got) ++ "; run make prep again")
1178
1179def size_ok(m: File & Result<&1, &1, U32 & String, U32>, +want: Nat, +path: String) -> IO(Unit):
1180 match m:
1181 case Tuple{f, r}:
1182 do IO<Unit>:
1183 +n : U32 <- IO.pass(U32, r)
1184 File.close(f)
1185 size_cmp(U32.is_eq(n, U32.from_nat(want)), path, n, want)
1186
1187
1188def check_size(+path: String, +n: Nat) -> IO(Unit):
1189 do IO<Unit>:
1190 f : File <- IO.try(File, File.open(path, "r"))
1191 m : File & Result<&1, &1, U32 & String, U32> <- File.size(f)
1192 size_ok(m, Nat.mul(n, 4n), path)
1193
1194def wpath(dir: String, name: String) -> String:
1195 dir ++ "/w/" ++ name ++ ".bin"
1196
1197def get_list(+dir: String, +name: String, +n: Nat) -> IO(List<&2, F32>):
1198 do IO<List<&2, F32>>:
1199 check_size(wpath(dir, name), n)
1200 read_floats(wpath(dir, name), n)
1201
1202
1203
1204
1205
1206
1207
1208def fill_bytes(bs: List<&2, U32>, +i: U32, a: Array<F32>) -> Array<F32>:
1209 match bs:
1210 case Con{+b0, Con{+b1, Con{+b2, Con{+b3, t}}}}:
1211 fill_bytes(t, (i + 1 : U32), Array.set(F32, a, i, f32_le(b0, b1, b2, b3)))
1212 case _:
1213 a
1214
1215def fill_bytes_mat(-r: Nat, -c: Nat, +i: U32, bs: List<&2, U32>, m: TA.Mat<r, c>) -> TA.Mat<r, c>:
1216 match m:
1217 case TA.Mat{d}:
1218 TA.Mat{fill_bytes(bs, i, d)}
1219
1220
1221
1222def stream_exact(k: Nat, -r: Nat, -c: Nat, +rem: Nat, +off: U32, +idx: U32, m: File & Result<&1, &1, U32 & String, List<&2, U32>>, acc: TA.Mat<r, c>) -> IO(TA.Mat<r, c>):
1223 match k m:
1224 case 0n Tuple{f, rs}:
1225 do IO<TA.Mat<r, c>>:
1226 File.close(f)
1227 return acc
1228 case 1n+p Tuple{f, rs}:
1229 do IO<TA.Mat<r, c>>:
1230 bs : List<&2, U32> <- IO.pass(List<&2, U32>, rs)
1231 m2 : File & Result<&1, &1, U32 & String, List<&2, U32>> <- File.read_at(f, (off + 1048576 : U32), U32.from_nat(Nat.min(1048576n, Nat.sub(rem, 1048576n))))
1232 stream_exact(p, r, c, Nat.sub(rem, 1048576n), (off + 1048576 : U32), (idx + 262144 : U32), m2, fill_bytes_mat(r, c, idx, bs, acc))
1233
1234
1235
1236def get_band(path: String, -r: Nat, +rr: Nat, +c: Nat, +start: Nat) -> IO(TA.Mat<r, c>):
1237 do IO<TA.Mat<r, c>>:
1238 f : File <- IO.try(File, File.open(path, "r"))
1239 m : File & Result<&1, &1, U32 & String, List<&2, U32>> <- File.read_at(f, U32.from_nat(Nat.mul(start, 4n)), U32.from_nat(Nat.min(1048576n, Nat.mul(Nat.mul(rr, c), 4n))))
1240 stream_exact(blocks_of(Nat.mul(Nat.mul(rr, c), 4n), 1048576n), r, c, Nat.mul(Nat.mul(rr, c), 4n), U32.from_nat(Nat.mul(start, 4n)), 0, m, TA.Mat{Array.new(F32, TA.cap_depth(Nat.mul(rr, c)), 0.0)})
1241
1242
1243def load_tree(+c: Nat, -r: Nat, b: TA.Bands<r, c>, +rr: Nat, -e: {rr == r : Nat}, +path: String, +start: Nat) -> IO(TA.Bands<r, c>):
1244 match b:
1245 case TA.BLeaf{m}:
1246 do IO<TA.Bands<r, c>>:
1247 band : TA.Mat<r, c> <- get_band(path, r, rr, c, start)
1248 return TA.BLeaf{band}
1249 case TA.BNode{x, y}:
1250 do IO<TA.Bands<r, c>>:
1251 x2 : TA.Bands<TA.half(r), c> <- load_tree(c, TA.half(r), x, TA.half(rr), TA.eq_half(rr, r, e), path, start)
1252 y2 : TA.Bands<Nat.sub(r, TA.half(r)), c> <- load_tree(c, Nat.sub(r, TA.half(r)), y, Nat.sub(rr, TA.half(rr)), TA.eq_rest(rr, r, e), path, Nat.add(start, Nat.mul(TA.half(rr), c)))
1253 return TA.BNode{x2, y2}
1254
1255def get_bands(+dir: String, +name: String, +d: Nat, +r: Nat, +c: Nat) -> IO(TA.Bands<r, c>):
1256 do IO<TA.Bands<r, c>>:
1257 check_size(wpath(dir, name), Nat.mul(r, c))
1258 load_tree(c, r, TA.Bands.zeros(d, r, c), r, {==}, wpath(dir, name), 0n)
1259
1260
1261def load_lw(+c: Cfg, +dir: String, +i: Nat, +d: Nat) -> IO(LW<c>):
1262 do IO<LW<c>>:
1263 ln1 : List<&2, F32> <- get_list(dir, nm(i, "ln1"), Cfg.dim(c))
1264 q : TA.Bands<Cfg.dim(c), Cfg.dim(c)> <- get_bands(dir, nm(i, "q"), d, Cfg.dim(c), Cfg.dim(c))
1265 k : TA.Bands<Cfg.kvw(c), Cfg.dim(c)> <- get_bands(dir, nm(i, "k"), d, Cfg.kvw(c), Cfg.dim(c))
1266 v : TA.Bands<Cfg.kvw(c), Cfg.dim(c)> <- get_bands(dir, nm(i, "v"), d, Cfg.kvw(c), Cfg.dim(c))
1267 o : TA.Bands<Cfg.dim(c), Cfg.dim(c)> <- get_bands(dir, nm(i, "o"), d, Cfg.dim(c), Cfg.dim(c))
1268 ln2 : List<&2, F32> <- get_list(dir, nm(i, "ln2"), Cfg.dim(c))
1269 gate : TA.Bands<Cfg.ffn(c), Cfg.dim(c)> <- get_bands(dir, nm(i, "gate"), d, Cfg.ffn(c), Cfg.dim(c))
1270 up : TA.Bands<Cfg.ffn(c), Cfg.dim(c)> <- get_bands(dir, nm(i, "up"), d, Cfg.ffn(c), Cfg.dim(c))
1271 down : TA.Bands<Cfg.dim(c), Cfg.ffn(c)> <- get_bands(dir, nm(i, "down"), d, Cfg.dim(c), Cfg.ffn(c))
1272 return LW{ln1, q, k, v, o, ln2, gate, up, down}
1273
1274def load_layers(k: Nat, +c: Cfg, +dir: String, +d: Nat, +i: Nat, acc: List<&1, LW<c>>) -> IO(List<&1, LW<c>>):
1275 match k:
1276 case 0n:
1277 IO.pure(List<&1, LW<c>>, List.reverse(&1, LW<c>, acc))
1278 case 1n+p:
1279 do IO<List<&1, LW<c>>>:
1280 l : LW<c> <- load_lw(c, dir, i, d)
1281 load_layers(p, c, dir, d, 1n+i, l <> acc)
1282
1283
1284def load_model(+c: Cfg, +dir: String) -> IO(Model<c>):
1285 do IO<Model<c>>:
1286 threads : U32 <- IO.thread_count()
1287 +d : Nat = depth_for(threads)
1288 emb : TA.Bands<Cfg.vocab(c), Cfg.dim(c)> <- get_bands(dir, "emb", Nat.add(d, Nat.min(d, 1n)), Cfg.vocab(c), Cfg.dim(c))
1289 ls : List<&1, LW<c>> <- load_layers(Cfg.layers(c), c, dir, d, 0n, Nil{})
1290 lnf : List<&2, F32> <- get_list(dir, "lnf", Cfg.dim(c))
1291 return Model{d, emb, ls, lnf}
1292
1293
1294
1295def rb_done(m: File & Result<&1, &1, U32 & String, List<&2, U32>>) -> IO(List<&2, U32>):
1296 (f, r) = m
1297 do IO<List<&2, U32>>:
1298 bs : List<&2, U32> <- IO.pass(List<&2, U32>, r)
1299 File.close(f)
1300 return bs
1301
1302def read_bytes(path: String) -> IO(List<&2, U32>):
1303 do IO<List<&2, U32>>:
1304 f : File <- IO.try(File, File.open(path, "r"))
1305 m : File & Result<&1, &1, U32 & String, List<&2, U32>> <- File.read_bytes(f, 1048576)
1306 rb_done(m)
1307
1308def digit_head(xs: List<&2, U32>) -> Bool:
1309 match xs:
1310 case Nil{}:
1311 False{}
1312 case Con{+b, t}:
1313 Bool.and(U32.is_le(48, b), U32.is_le(b, 57))
1314
1315
1316def u32s.go(bs: List<&2, U32>, dg: Bool, +cur: U32, have: Bool, acc: List<&2, U32>) -> List<&2, U32>:
1317 match bs dg have:
1318 case Nil{} _ True{}:
1319 List.reverse(&2, U32, cur <> acc)
1320 case Nil{} _ False{}:
1321 List.reverse(&2, U32, acc)
1322 case Con{+b, +t} True{} _:
1323 u32s.go(t, digit_head(t), ((cur * 10 : U32) + U32.sub(b, 48) : U32), True{}, acc)
1324 case Con{b, +t} False{} True{}:
1325 u32s.go(t, digit_head(t), 0, False{}, cur <> acc)
1326 case Con{b, +t} False{} False{}:
1327 u32s.go(t, digit_head(t), 0, False{}, acc)
1328
1329def u32s(+bs: List<&2, U32>) -> List<&2, U32>:
1330 u32s.go(bs, digit_head(bs), 0, False{}, Nil{})
1331
1332def cfg_of(+path: String, xs: List<&2, U32>) -> IO(Cfg):
1333 match xs:
1334 case Con{+kv, Con{+g, Con{+half, Con{+f, Con{+l, Con{+v, Con{+e, Con{+t, Nil{}}}}}}}}}:
1335 IO.pure(Cfg, Cfg{U32.to_nat(kv), U32.to_nat(g), U32.to_nat(half), U32.to_nat(f), U32.to_nat(l), U32.to_nat(v), bitcast(e), bitcast(t)})
1336 case _:
1337 IO.die(Cfg, 1, path ++ ": expected 8 numbers (kv g half f layers vocab eps_bits theta_bits); run make prep again")
1338
1339
1340def read_cfg(+dir: String) -> IO(Cfg):
1341 do IO<Cfg>:
1342 bs : List<&2, U32> <- read_bytes(dir ++ "/cfg.txt")
1343 cfg_of(dir ++ "/cfg.txt", u32s(bs))