main.bend
bend-ml-llama@0.2.1.0 · 1,704 lines · 213 definitions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22import Base
23import bend-ml-tensor-array@0.1.19.0/main.bend as TA
24
25
26
27
28
29law add_zero:
30 for a: Nat
31 {Nat.add(a, 0n) == a : Nat}
32
33def add_zero(a):
34 match a:
35 case 0n:
36 {==}
37 case 1n+p:
38 %add_zero(p) : {1n+Nat.add(p, 0n) == 1n+_ : Nat}
39 {==}
40
41law add_succ:
42 for a: Nat
43 for -b: Nat
44 {1n+Nat.add(a, b) == Nat.add(a, 1n+b) : Nat}
45
46def add_succ(a, b):
47 match a:
48 case 0n:
49 {==}
50 case 1n+p:
51 %add_succ(p, b) : {2n+Nat.add(p, b) == 1n+_ : Nat}
52 {==}
53
54law add_one:
55 for a: Nat
56 {Nat.add(a, 1n) == 1n+a : Nat}
57
58def add_one(a):
59 match a:
60 case 0n:
61 {==}
62 case 1n+p:
63 %add_one(p) : {1n+Nat.add(p, 1n) == 1n+_ : Nat}
64 {==}
65
66law add_assoc:
67 for a: Nat
68 for -b: Nat
69 for -c: Nat
70 {Nat.add(Nat.add(a, b), c) == Nat.add(a, Nat.add(b, c)) : Nat}
71
72def add_assoc(a, b, c):
73 match a:
74 case 0n:
75 {==}
76 case 1n+p:
77 %add_assoc(p, b, c) : {1n+Nat.add(Nat.add(p, b), c) == 1n+_ : Nat}
78 {==}
79
80
81
82
83
84
85
86
87type Cfg is Data:
88 Cfg{kv: Nat, g: Nat, half: Nat, f: Nat, layers: Nat, vocab: Nat, eps: F32, theta: F32}
89
90
91def head(+half: Nat) -> Nat:
92 Nat.add(half, half)
93
94def Cfg.half(+c: Cfg) -> Nat:
95 match c:
96 case Cfg{kv, g, half, f, l, v, e, t}:
97 half
98
99def Cfg.kv(+c: Cfg) -> Nat:
100 match c:
101 case Cfg{kv, g, half, f, l, v, e, t}:
102 kv
103
104def Cfg.g(+c: Cfg) -> Nat:
105 match c:
106 case Cfg{kv, g, half, f, l, v, e, t}:
107 g
108
109def Cfg.ffn(+c: Cfg) -> Nat:
110 match c:
111 case Cfg{kv, g, half, f, l, v, e, t}:
112 f
113
114def Cfg.layers(+c: Cfg) -> Nat:
115 match c:
116 case Cfg{kv, g, half, f, l, v, e, t}:
117 l
118
119def Cfg.vocab(+c: Cfg) -> Nat:
120 match c:
121 case Cfg{kv, g, half, f, l, v, e, t}:
122 v
123
124def Cfg.eps(+c: Cfg) -> F32:
125 match c:
126 case Cfg{kv, g, half, f, l, v, e, t}:
127 e
128
129def Cfg.theta(+c: Cfg) -> F32:
130 match c:
131 case Cfg{kv, g, half, f, l, v, e, t}:
132 t
133
134
135def Cfg.head(+c: Cfg) -> Nat:
136 head(Cfg.half(c))
137
138
139def Cfg.heads(+c: Cfg) -> Nat:
140 Nat.mul(Cfg.kv(c), Cfg.g(c))
141
142
143def Cfg.dim(+c: Cfg) -> Nat:
144 Nat.mul(Cfg.heads(c), Cfg.head(c))
145
146
147def Cfg.kvw(+c: Cfg) -> Nat:
148 Nat.mul(Cfg.kv(c), Cfg.head(c))
149
150
151def smollm2_135m() -> Cfg:
152 Cfg{3n, 3n, 32n, 1536n, 30n, 49152n, 0.00001, 100000.0}
153
154
155def smollm2_360m() -> Cfg:
156 Cfg{5n, 3n, 32n, 2560n, 32n, 49152n, 0.00001, 100000.0}
157
158
159def smollm2_1_7b() -> Cfg:
160 Cfg{32n, 1n, 32n, 8192n, 24n, 49152n, 0.00001, 130000.0}
161
162
163
164
165law smollm2_135m_sizes:
166 {Cfg.dim(smollm2_135m()) == 576n : Nat} & {Cfg.heads(smollm2_135m()) == 9n : Nat} & {Cfg.head(smollm2_135m()) == 64n : Nat} & {Cfg.kvw(smollm2_135m()) == 192n : Nat}
167
168def smollm2_135m_sizes():
169 ({==}, {==}, {==}, {==})
170
171law smollm2_360m_sizes:
172 {Cfg.dim(smollm2_360m()) == 960n : Nat} & {Cfg.heads(smollm2_360m()) == 15n : Nat} & {Cfg.head(smollm2_360m()) == 64n : Nat} & {Cfg.kvw(smollm2_360m()) == 320n : Nat}
173
174def smollm2_360m_sizes():
175 ({==}, {==}, {==}, {==})
176
177law smollm2_1_7b_sizes:
178 {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}
179
180def smollm2_1_7b_sizes():
181 ({==}, {==}, {==}, {==})
182
183
184
185def n32(+n: Nat) -> U32:
186 U32.from_nat(n)
187
188
189
190def Cfg.layer_size(+c: Cfg) -> U32:
191 ((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)
192
193
194def Cfg.size(+c: Cfg) -> U32:
195 (n32(Cfg.vocab(c)) * n32(Cfg.dim(c)) + n32(Cfg.layers(c)) * Cfg.layer_size(c) + n32(Cfg.dim(c)) : U32)
196
197
198
199
200
201law layout_135m:
202 {Cfg.size(smollm2_135m()) == (134515008 : U32) : U32}
203
204def layout_135m():
205 {==}
206
207law layout_360m:
208 {Cfg.size(smollm2_360m()) == (361821120 : U32) : U32}
209
210def layout_360m():
211 {==}
212
213law layout_1_7b:
214 {Cfg.size(smollm2_1_7b()) == (1711376384 : U32) : U32}
215
216def layout_1_7b():
217 {==}
218
219
220
221
222
223
224type Head is Data:
225 Head{lo: List<&2, F32>, hi: List<&2, F32>}
226
227def split(+half: Nat, +xs: List<&2, F32>) -> Head:
228 Head{List.take(&2, F32, xs, half), List.drop(&2, F32, xs, half)}
229
230def join(h: Head) -> List<&2, F32>:
231 match h:
232 case Head{lo, hi}:
233 List.append(&2, F32, lo, hi)
234
235
236def heads(n: Nat, +half: Nat, +xs: List<&2, F32>) -> List<&2, Head>:
237 match n:
238 case 0n:
239 Nil{}
240 case 1n+p:
241 split(half, List.take(&2, F32, xs, head(half))) <> heads(p, half, List.drop(&2, F32, xs, head(half)))
242
243
244def chunks(n: Nat, +w: Nat, +xs: List<&2, F32>) -> List<&2, List<&2, F32>>:
245 match n:
246 case 0n:
247 Nil{}
248 case 1n+p:
249 List.take(&2, F32, xs, w) <> chunks(p, w, List.drop(&2, F32, xs, w))
250
251def joins(hs: List<&2, Head>) -> List<&2, List<&2, F32>>:
252 match hs:
253 case Nil{}:
254 Nil{}
255 case Con{h, t}:
256 join(h) <> joins(t)
257
258def flat(hs: List<&2, Head>) -> List<&2, F32>:
259 List.concat(&2, F32, joins(hs))
260
261
262
263law head_split:
264 for +xs: List<&2, F32>
265 for +half: Nat
266 {join(split(half, xs)) == xs : List<&2, F32>}
267
268
269
270
271def head_split(xs, half):
272 match xs half:
273 case Nil{} _:
274 {==}
275 case Con{h, t} 0n:
276 {==}
277 case Con{h, t} 1n+p:
278 %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>}
279 {==}
280
281
282
283
284
285
286
287
288def list.add(xs: List<&2, F32>, ys: List<&2, F32>) -> List<&2, F32>:
289 match xs ys:
290 case Con{+h, t} Con{+g, u}:
291 (h + g : F32) <> list.add(t, u)
292 case _ _:
293 Nil{}
294
295
296def list.mul(xs: List<&2, F32>, ys: List<&2, F32>) -> List<&2, F32>:
297 match xs ys:
298 case Con{+h, t} Con{+g, u}:
299 (h * g : F32) <> list.mul(t, u)
300 case _ _:
301 Nil{}
302
303
304def list.scale(+k: F32, xs: List<&2, F32>) -> List<&2, F32>:
305 match xs:
306 case Nil{}:
307 Nil{}
308 case Con{+h, t}:
309 (k * h : F32) <> list.scale(k, t)
310
311
312def list.sum.go(xs: List<&2, F32>, acc: F32) -> F32:
313 match xs:
314 case Nil{}:
315 acc
316 case Con{+h, t}:
317 list.sum.go(t, (acc + h : F32))
318
319def list.max.go(xs: List<&2, F32>, cur: F32) -> F32:
320 match xs:
321 case Nil{}:
322 cur
323 case Con{+h, t}:
324 list.max.go(t, F32.max(cur, h))
325
326
327def list.max(xs: List<&2, F32>) -> F32:
328 match xs:
329 case Nil{}:
330 0.0
331 case Con{+h, t}:
332 list.max.go(t, h)
333
334
335def list.exp_shift(xs: List<&2, F32>, +m: F32) -> List<&2, F32>:
336 match xs:
337 case Nil{}:
338 Nil{}
339 case Con{+h, t}:
340 F32.exp((h - m : F32)) <> list.exp_shift(t, m)
341
342
343def list.div(xs: List<&2, F32>, +s: F32) -> List<&2, F32>:
344 match xs:
345 case Nil{}:
346 Nil{}
347 case Con{+h, t}:
348 (h / s : F32) <> list.div(t, s)
349
350def list.softmax.fin(+es: List<&2, F32>) -> List<&2, F32>:
351 list.div(es, list.sum.go(es, 0.0))
352
353
354def list.softmax(+xs: List<&2, F32>) -> List<&2, F32>:
355 list.softmax.fin(list.exp_shift(xs, list.max(xs)))
356
357
358def squares(xs: List<&2, F32>) -> List<&2, F32>:
359 match xs:
360 case Nil{}:
361 Nil{}
362 case Con{+h, t}:
363 (h * h : F32) <> squares(t)
364
365
366def pair_sums(xs: List<&2, F32>) -> List<&2, F32>:
367 match xs:
368 case Con{+a, Con{+b, t}}:
369 (a + b : F32) <> pair_sums(t)
370 case _:
371 xs
372
373
374
375def tree_sum(fuel: Nat, xs: List<&2, F32>) -> F32:
376 match fuel xs:
377 case _ Nil{}:
378 0.0
379 case _ Con{+a, Nil{}}:
380 a
381 case 0n Con{+a, t}:
382 list.sum.go(t, a)
383 case 1n+p Con{+a, t}:
384 tree_sum(p, pair_sums(Con{a, t}))
385
386
387def rmsnorm(+c: Cfg, +x: List<&2, F32>, +g: List<&2, F32>) -> List<&2, F32>:
388 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))
389
390
391def inv_freq.go(n: Nat, +i: Nat, +theta: F32, +hd: F32) -> List<&2, F32>:
392 match n:
393 case 0n:
394 Nil{}
395 case 1n+p:
396 (1.0 / F32.pow(theta, (F32.from_nat(Nat.mul(2n, i)) / hd : F32)) : F32) <> inv_freq.go(p, 1n+i, theta, hd)
397
398def inv_freq(+c: Cfg) -> List<&2, F32>:
399 inv_freq.go(Cfg.half(c), 0n, Cfg.theta(c), F32.from_nat(Cfg.head(c)))
400
401def angles(+t: F32, fs: List<&2, F32>) -> List<&2, F32>:
402 match fs:
403 case Nil{}:
404 Nil{}
405 case Con{+f, r}:
406 (t * f : F32) <> angles(t, r)
407
408def cos.l(xs: List<&2, F32>) -> List<&2, F32>:
409 match xs:
410 case Nil{}:
411 Nil{}
412 case Con{+x, r}:
413 F32.cos(x) <> cos.l(r)
414
415def sin.l(xs: List<&2, F32>) -> List<&2, F32>:
416 match xs:
417 case Nil{}:
418 Nil{}
419 case Con{+x, r}:
420 F32.sin(x) <> sin.l(r)
421
422
423type Rot is Data:
424 Rot{cs: List<&2, F32>, sn: List<&2, F32>}
425
426def rot_at(+c: Cfg, +t: Nat) -> Rot:
427 Rot{cos.l(angles(F32.from_nat(t), inv_freq(c))), sin.l(angles(F32.from_nat(t), inv_freq(c)))}
428
429
430def rot_lo(h1: List<&2, F32>, h2: List<&2, F32>, cs: List<&2, F32>, sn: List<&2, F32>) -> List<&2, F32>:
431 match h1 h2 cs sn:
432 case Con{+a, ta} Con{+b, tb} Con{+c, tc} Con{+s, ts}:
433 ((a * c : F32) + (F32.neg(b) * s : F32) : F32) <> rot_lo(ta, tb, tc, ts)
434 case _ _ _ _:
435 Nil{}
436
437def rot_hi(h1: List<&2, F32>, h2: List<&2, F32>, cs: List<&2, F32>, sn: List<&2, F32>) -> List<&2, F32>:
438 match h1 h2 cs sn:
439 case Con{+a, ta} Con{+b, tb} Con{+c, tc} Con{+s, ts}:
440 ((b * c : F32) + (a * s : F32) : F32) <> rot_hi(ta, tb, tc, ts)
441 case _ _ _ _:
442 Nil{}
443
444def rope(rt: Rot, h: Head) -> Head:
445 match rt h:
446 case Rot{+cs, +sn} Head{+lo, +hi}:
447 Head{rot_lo(lo, hi, cs, sn), rot_hi(lo, hi, cs, sn)}
448
449def ropes(+rt: Rot, hs: List<&2, Head>) -> List<&2, Head>:
450 match hs:
451 case Nil{}:
452 Nil{}
453 case Con{h, t}:
454 rope(rt, h) <> ropes(rt, t)
455
456
457def silu(+x: F32) -> F32:
458 (x / (1.0 + F32.exp(F32.neg(x)) : F32) : F32)
459
460
461def swiglu(g: List<&2, F32>, u: List<&2, F32>) -> List<&2, F32>:
462 match g u:
463 case Con{+a, ga} Con{+b, ub}:
464 (silu(a) * b : F32) <> swiglu(ga, ub)
465 case _ _:
466 Nil{}
467
468
469
470
471
472
473
474
475
476type KV<-cap: Nat, -t: Nat> is Type:
477 KV{ks: List<&1, Array<F32>>, vs: List<&1, Array<F32>>}
478
479
480def arrays(n: Nat, +d: Nat) -> List<&1, Array<F32>>:
481 match n:
482 case 0n:
483 Nil{}
484 case 1n+p:
485 Array.new(F32, d, 0.0) <> arrays(p, d)
486
487
488def KV.empty(+c: Cfg, +cap: Nat) -> KV<cap, 0n>:
489 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))))}
490
491
492def write_rows(arrs: List<&1, Array<F32>>, rs: List<&2, List<&2, F32>>, +off: U32) -> List<&1, Array<F32>>:
493 match arrs rs:
494 case Con{a, at} Con{r, rt}:
495 TA.fill_list(r, off, a) <> write_rows(at, rt, off)
496 case _ _:
497 arrs
498
499
500def 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>:
501 match kv:
502 case KV{ka, va}:
503 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))))}
504
505
506def kv_count(-cap: Nat, -t: Nat, kv: KV<cap, t>) -> Nat:
507 match kv:
508 case KV{ka, va}:
509 List.length(&1, Array<F32>, ka)
510
511
512law arrays_len:
513 for +n: Nat
514 for +d: Nat
515 {List.length(&1, Array<F32>, arrays(n, d)) == n : Nat}
516
517
518def arrays_len(n, d):
519 match n:
520 case 0n:
521 {==}
522 case 1n+p:
523 %arrays_len(p, d) : {1n+List.length(&1, Array<F32>, arrays(p, d)) == 1n+_ : Nat}
524 {==}
525
526
527
528law kv_heads:
529 for +c: Cfg
530 for +cap: Nat
531 {kv_count(cap, 0n, KV.empty(c, cap)) == Cfg.kv(c) : Nat}
532
533def kv_heads(c, cap):
534 arrays_len(Cfg.kv(c), TA.cap_depth(Nat.mul(cap, Cfg.head(c))))
535
536
537def 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}:
538 match a b c:
539 case 0n _ _:
540 {==}
541 case 1n+p 0n _:
542 %e1 : TA.BD(_, Unit, {True{} == TA.leb(1n+p, c) : Bool})
543 Unit{}
544 case 1n+p 1n+q 0n:
545 %e2 : TA.BD(_, Unit, {True{} == TA.leb(1n+p, 0n) : Bool})
546 Unit{}
547 case 1n+p 1n+q 1n+r:
548 leb_trans(p, q, r, e1, e2)
549
550
551def 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}:
552 match a b:
553 case 0n _:
554 {==}
555 case 1n+p 0n:
556 %e : TA.BD(_, Unit, {True{} == TA.leb(Nat.mul(1n+p, h), 0n) : Bool})
557 Unit{}
558 case 1n++p 1n++q:
559 TA.leb_add(h, h, Nat.mul(p, h), Nat.mul(q, h), TA.leb_refl(h), leb_mul(p, q, h, e))
560
561
562
563
564
565
566law kv_room:
567 for +cap: Nat
568 for +h: Nat
569 for +t: Nat
570 for e: {True{} == TA.leb(1n+t, cap) : Bool}
571 {True{} == TA.leb(Nat.mul(1n+t, h), TA.pow2(TA.cap_depth(Nat.mul(cap, h)))) : Bool}
572
573
574
575def step_room(+t: Nat, +p: Nat, -cap: Nat, e: {Nat.add(t, 1n+p) == cap : Nat}) -> {True{} == TA.leb(1n+t, cap) : Bool}:
576 %e : {True{} == TA.leb(1n+t, _) : Bool}
577 %add_succ(t, p) : {True{} == TA.leb(1n+t, _) : Bool}
578 TA.leb_up(t, t, p, TA.leb_refl(t))
579
580def step_inv(+t: Nat, -p: Nat, -cap: Nat, e: {Nat.add(t, 1n+p) == cap : Nat}) -> {Nat.add(1n+t, p) == cap : Nat}:
581 %e : {1n+Nat.add(t, p) == _ : Nat}
582 add_succ(t, p)
583
584
585
586def kv_room(cap, h, t, e):
587 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)))
588
589
590
591
592
593def groups(n: Nat, +g: Nat, +hs: List<&2, Head>) -> List<&2, List<&2, Head>>:
594 match n:
595 case 0n:
596 Nil{}
597 case 1n+p:
598 List.take(&2, Head, hs, g) <> groups(p, g, List.drop(&2, Head, hs, g))
599
600
601
602law groups_len:
603 for n: Nat
604 for +g: Nat
605 for +hs: List<&2, Head>
606 {List.length(&2, List<&2, Head>, groups(n, g, hs)) == n : Nat}
607
608def groups_len(n, g, hs):
609 match n:
610 case 0n:
611 {==}
612 case 1n+p:
613 %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}
614 {==}
615
616
617law div_block:
618 for +m: Nat
619 for -n: Nat
620 for -d: Nat
621 for -r: Nat
622 {Nat.divmod.go(Nat.add(1n+m, n), m, d, r) == Nat.divmod.go(n, Nat.add(m, r), 1n+d, 0n) : Nat & Nat}
623
624def div_block(m, n, d, r):
625 match m:
626 case 0n:
627 {==}
628 case 1n+p:
629 %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}
630 div_block(p, n, d, 1n+r)
631
632
633law div_blocks:
634 for +j: Nat
635 for +s: Nat
636 for +n: Nat
637 for +d: Nat
638 {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}
639
640def div_blocks(j, s, n, d):
641 match j:
642 case 0n:
643 {==}
644 case 1n+jp:
645 %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}
646 %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}
647 %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}
648 %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}
649 div_blocks(jp, s, n, 1n+d)
650
651
652law div_rest:
653 for +i: Nat
654 for -k: Nat
655 for -d: Nat
656 for -r: Nat
657 {Pair.fst(Nat, Nat, Nat.divmod.go(i, Nat.add(i, k), d, r)) == d : Nat}
658
659def div_rest(i, k, d, r):
660 match i:
661 case 0n:
662 {==}
663 case 1n+p:
664 div_rest(p, k, d, 1n+r)
665
666
667
668
669law gqa_head:
670 for +j: Nat
671 for +i: Nat
672 for +k: Nat
673 {Nat.div(Nat.add(Nat.mul(j, 1n+Nat.add(i, k)), i), 1n+Nat.add(i, k)) == j : Nat}
674
675
676
677def gqa_head(j, i, k):
678 %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}
679 %add_zero(j) : {Pair.fst(Nat, Nat, Nat.divmod.go(i, Nat.add(i, k), Nat.add(j, 0n), 0n)) == _ : Nat}
680 div_rest(i, k, Nat.add(j, 0n), 0n)
681
682
683
684
685
686
687type SR is Type:
688 SR{k: Array<F32>, s: List<&2, F32>}
689
690def sr_len(sr: SR) -> Nat:
691 match sr:
692 case SR{k, s}:
693 List.length(&2, F32, s)
694
695def sr_of(k: Array<F32>, al: TA.AL) -> SR:
696 match al:
697 case TA.AL{c, l}:
698 SR{k, l}
699
700
701
702
703
704law read_len:
705 for k: Array<F32>
706 for +m: Nat
707 for +idx: U32
708 for +acc: List<&2, F32>
709 for rc: Array<F32> & F32
710 {sr_len(sr_of(k, TA.read_l(m, idx, acc, rc))) == Nat.add(1n+m, List.length(&2, F32, acc)) : Nat}
711
712def read_len(k, m, idx, acc, rc):
713 match m rc:
714 case 0n Tuple{d, +v}:
715 {==}
716 case 1n+p Tuple{d, +v}:
717 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))))
718
719
720def sr_read(+t: Nat, g: TA.G) -> SR:
721 match g:
722 case TA.G{qa, k, s}:
723 sr_of(k, TA.read_l(t, U32.from_nat(t), Nil{}, Array.get(F32, s, U32.from_nat(t))))
724
725
726
727def scores(+hd: Nat, +t: Nat, k: Array<F32>, +q: List<&2, F32>) -> SR:
728 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)))
729
730def sr_len_g(+t: Nat, g: TA.G) -> {sr_len(sr_read(t, g)) == 1n+t : Nat}:
731 match g:
732 case TA.G{qa, k, s}:
733 TA.zero_out(sr_len(sr_of(k, TA.read_l(t, U32.from_nat(t), Nil{}, Array.get(F32, s, U32.from_nat(t))))), 1n+t, read_len(k, t, U32.from_nat(t), Nil{}, Array.get(F32, s, U32.from_nat(t))))
734
735
736
737
738
739law causal:
740 for +hd: Nat
741 for +t: Nat
742 for k: Array<F32>
743 for +q: List<&2, F32>
744 {sr_len(scores(hd, t, k, q)) == 1n+t : Nat}
745
746def causal(hd, t, k, q):
747 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)))
748
749
750type WR is Type:
751 WR{v: Array<F32>, o: List<&2, F32>}
752
753def wr_of(v: Array<F32>, al: TA.AL) -> WR:
754 match al:
755 case TA.AL{c, l}:
756 WR{v, l}
757
758def wr_read(+hd: Nat, g: TA.G) -> WR:
759 match g:
760 case TA.G{wa, v, o}:
761 wr_of(v, TA.read_l(Nat.sub(hd, 1n), U32.from_nat(Nat.sub(hd, 1n)), Nil{}, Array.get(F32, o, U32.from_nat(Nat.sub(hd, 1n)))))
762
763def weighted(+hd: Nat, +t: Nat, v: Array<F32>, +w: List<&2, F32>) -> WR:
764 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)))
765
766
767type HO is Type:
768 HO{k: Array<F32>, v: Array<F32>, o: List<&2, F32>}
769
770def HO.then(-R: Type, h: HO, then: Array<F32> -> Array<F32> -> List<&2, F32> -> R) -> R:
771 match h:
772 case HO{k, v, o}:
773 then(k, v, o)
774
775def head_wr(k: Array<F32>, wr: WR) -> HO:
776 match wr:
777 case WR{v, o}:
778 HO{k, v, o}
779
780def head_sr(+hd: Nat, +t: Nat, +scale: F32, v: Array<F32>, sr: SR) -> HO:
781 match sr:
782 case SR{k, s}:
783 head_wr(k, weighted(hd, t, v, list.softmax(list.scale(scale, s))))
784
785def head_att(+hd: Nat, +t: Nat, +scale: F32, k: Array<F32>, v: Array<F32>, +q: List<&2, F32>) -> HO:
786 head_sr(hd, t, scale, v, scores(hd, t, k, q))
787
788
789def group_att(hs: List<&2, Head>, +hd: Nat, +t: Nat, +scale: F32, k: Array<F32>, v: Array<F32>, +acc: List<&2, F32>) -> HO:
790 match hs:
791 case Nil{}:
792 HO{k, v, acc}
793 case Con{h, rest}:
794 HO.then(HO, head_att(hd, t, scale, k, v, join(h)), k2 => v2 => +o =>
795
796 group_att(rest, hd, t, scale, k2, v2, List.append(&2, F32, acc, o)))
797
798
799type AT is Type:
800 AT{ks: List<&1, Array<F32>>, vs: List<&1, Array<F32>>, o: List<&2, F32>}
801
802def at_join(p: AT, q: AT) -> AT:
803 match p q:
804 case AT{k1, v1, o1} AT{k2, v2, o2}:
805 AT{List.append(&1, Array<F32>, k1, k2), List.append(&1, Array<F32>, v1, v2), List.append(&2, F32, o1, o2)}
806
807
808type GW is Type:
809 GW{g: List<&2, Head>, k: Array<F32>, v: Array<F32>}
810
811def gws(gs: List<&2, List<&2, Head>>, ks: List<&1, Array<F32>>, vs: List<&1, Array<F32>>) -> List<&1, GW>:
812 match gs ks vs:
813 case Con{g, gt} Con{k, kt} Con{v, vt}:
814 GW{g, k, v} <> gws(gt, kt, vt)
815 case _ _ _:
816 Nil{}
817
818
819def 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:
820 match ws:
821 case Con{w, wt}:
822 match w:
823 case GW{g, k, v}:
824 HO.then(AT, group_att(g, hd, t, scale, k, v, Nil{}), k2 => v2 => +o =>
825
826 seq_att(wt, hd, t, scale, k2 <> aks, v2 <> avs, List.append(&2, F32, acc, o)))
827 case Nil{}:
828 AT{List.reverse(&1, Array<F32>, aks), List.reverse(&1, Array<F32>, avs), acc}
829
830
831type GS is Type:
832 GS{l: List<&1, GW>, r: List<&1, GW>}
833
834def cut(n: Nat, xs: List<&1, GW>, acc: List<&1, GW>) -> GS:
835 match n xs:
836 case 1n+m Con{x, xt}:
837 cut(m, xt, x <> acc)
838 case _ _:
839 GS{List.reverse(&1, GW, acc), xs}
840
841
842def halvings(fuel: Nat, +n: Nat) -> Nat:
843 match fuel:
844 case 0n:
845 0n
846 case 1n+f:
847 match n:
848 case 0n:
849 0n
850 case 1n+p:
851 match p:
852 case 0n:
853 0n
854 case 1n+q:
855 1n+halvings(f, Nat.sub(2n+q, TA.half(2n+q)))
856
857
858
859def par_att(d: Nat, gs: GS, +n: Nat, +hd: Nat, +t: Nat, +scale: F32) -> AT:
860 match d gs:
861 case 0n GS{l, r}:
862
863 p q = seq_att(l, hd, t, scale, Nil{}, Nil{}, Nil{}) seq_att(r, hd, t, scale, Nil{}, Nil{}, Nil{})
864 at_join(p, q)
865 case 1n++e GS{l, r}:
866 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)
867 at_join(p, q)
868
869
870type KA<-cap: Nat, -t: Nat> is Type:
871 KA{kv: KV<cap, t>, o: List<&2, F32>}
872
873def ka_of(-cap: Nat, -t: Nat, at: AT) -> KA<cap, t>:
874 match at:
875 case AT{ks, vs, o}:
876 KA{KV{ks, vs}, o}
877
878def KA.then(-R: Type, -cap: Nat, -t: Nat, ka: KA<cap, t>, then: KV<cap, t> -> List<&2, F32> -> R) -> R:
879 match ka:
880 case KA{kv, o}:
881 then(kv, o)
882
883
884
885
886
887def attention(+c: Cfg, +d: Nat, -cap: Nat, +t: Nat, qs: List<&2, Head>, kv: KV<cap, 1n+t>) -> KA<cap, 1n+t>:
888 match d kv:
889 case 0n KV{ks, vs}:
890 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{}))
891 case 1n+e KV{ks, vs}:
892 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)))
893
894
895
896
897
898
899type LW<-c: Cfg> is Type:
900 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)>}
901
902
903
904type Act is Data:
905 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>}
906
907
908
909type BR<-c: Cfg, -cap: Nat, -t: Nat> is Type:
910 BR{y: List<&2, F32>, kv: KV<cap, 1n+t>, lw: LW<c>, act: Act}
911
912
913
914def 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:
915 match b:
916 case BR{y, kv, lw, act}:
917 k(y, kv, lw, act)
918
919def mv.go(-B: Type, -r: Nat, -k: Nat, bl: TA.BL<r, k>, then: TA.Bands<r, k> -> List<&2, F32> -> B) -> B:
920 match bl:
921 case TA.BL{w, y}:
922 then(w, y)
923
924
925def 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:
926 mv.go(B, r, k, TA.Bands.matvec_l(r, k, w, x), then)
927
928
929
930def 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>:
931 match lw:
932 case LW{+ln1, wq, wk, wv, wo, +ln2, wg, wu, wd}:
933 +n1 = rmsnorm(c, x, ln1)
934 mv(BR<c, cap, t>, Cfg.dim(c), Cfg.dim(c), wq, n1, wq => +q =>
935 mv(BR<c, cap, t>, Cfg.kvw(c), Cfg.dim(c), wk, n1, wk => +k =>
936 mv(BR<c, cap, t>, Cfg.kvw(c), Cfg.dim(c), wv, n1, wv => +v =>
937 +qs = ropes(rt, heads(Cfg.heads(c), Cfg.half(c), q))
938 +ks = ropes(rt, heads(Cfg.kv(c), Cfg.half(c), k))
939 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 =>
940 mv(BR<c, cap, t>, Cfg.dim(c), Cfg.dim(c), wo, at, wo => +a =>
941 +x1 = list.add(x, a)
942 +n2 = rmsnorm(c, x1, ln2)
943 mv(BR<c, cap, t>, Cfg.ffn(c), Cfg.dim(c), wg, n2, wg => +g =>
944 mv(BR<c, cap, t>, Cfg.ffn(c), Cfg.dim(c), wu, n2, wu => +u =>
945 mv(BR<c, cap, t>, Cfg.dim(c), Cfg.ffn(c), wd, swiglu(g, u), wd => +m =>
946 +y = list.add(x1, m)
947 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}}))))))))
948
949
950
951
952
953def 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>:
954 match lw:
955 case LW{+ln1, wq, wk, wv, wo, +ln2, wg, wu, wd}:
956 +n1 = rmsnorm(c, x, ln1)
957 mv(BR<c, cap, t>, Cfg.dim(c), Cfg.dim(c), wq, n1, wq => +q =>
958 mv(BR<c, cap, t>, Cfg.kvw(c), Cfg.dim(c), wk, n1, wk => +k =>
959 mv(BR<c, cap, t>, Cfg.kvw(c), Cfg.dim(c), wv, n1, wv => +v =>
960 +qs = ropes(rt, heads(Cfg.heads(c), Cfg.half(c), q))
961 +ks = ropes(rt, heads(Cfg.kv(c), Cfg.half(c), k))
962 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 =>
963 mv(BR<c, cap, t>, Cfg.dim(c), Cfg.dim(c), wo, at, wo => +a =>
964 +x1 = list.add(x, a)
965 +n2 = rmsnorm(c, x1, ln2)
966 mv(BR<c, cap, t>, Cfg.ffn(c), Cfg.dim(c), wg, n2, wg => +g =>
967 mv(BR<c, cap, t>, Cfg.ffn(c), Cfg.dim(c), wu, n2, wu => +u =>
968 mv(BR<c, cap, t>, Cfg.dim(c), Cfg.ffn(c), wd, swiglu(g, u), wd => +m =>
969 +y = list.add(x1, m)
970 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{}}}))))))))
971
972
973def 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>:
974 match keep:
975 case True{}:
976 block(c, d, lw, cap, t, kv, room, rt, x)
977 case False{}:
978 block_gen(c, d, lw, cap, t, kv, room, rt, x)
979
980
981
982
983
984
985type Model<-c: Cfg> is Type:
986 Model{d: Nat, emb: TA.Bands<Cfg.vocab(c), Cfg.dim(c)>, layers: List<&1, LW<c>>, lnf: List<&2, F32>}
987
988
989type Run<-c: Cfg, -cap: Nat, -t: Nat> is Type:
990 Run{x: List<&2, F32>, layers: List<&1, LW<c>>, cs: List<&1, KV<cap, 1n+t>>, acts: List<&2, Act>}
991
992
993def 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>:
994 match ls cs pend:
995 case Con{l, lt} Con{k, kt} BR{+y, kv, l0, act}:
996 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))
997 case _ _ BR{+y, kv, l0, act}:
998 Run{y, List.reverse(&1, LW<c>, l0 <> al), List.reverse(&1, KV<cap, 1n+t>, kv <> ac), List.reverse(&2, Act, act <> aa)}
999
1000def 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>:
1001 match ls cs:
1002 case Con{l, lt} Con{k, kt}:
1003 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))
1004 case _ _:
1005 Run{x, Nil{}, Nil{}, Nil{}}
1006
1007
1008
1009type Out<-c: Cfg, -cap: Nat, -t: Nat> is Type:
1010 Out{lg: List<&2, F32>, nf: List<&2, F32>, acts: List<&2, Act>, cs: List<&1, KV<cap, 1n+t>>, m: Model<c>}
1011
1012
1013def 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:
1014 match o:
1015 case Out{lg, nf, acts, cs, m}:
1016 k(lg, nf, acts, cs, m)
1017
1018
1019def 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>:
1020 match r:
1021 case Run{+x, ls, cs, acts}:
1022 +nf = rmsnorm(c, x, lnf)
1023 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}})
1024
1025def 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>:
1026 match r:
1027 case TA.BRow{emb, row}:
1028 head_of(c, cap, t, d, emb, lnf, layers(keep, c, d, cap, t, room, rot_at(c, t), ls, cs, row))
1029
1030
1031
1032def 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>:
1033 match m:
1034 case Model{+d, emb, ls, +lnf}:
1035 forward.go(keep, c, cap, t, room, d, ls, lnf, cs, TA.Bands.read_row(Cfg.vocab(c), Cfg.dim(c), emb, tok))
1036
1037
1038def 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>:
1039 forward_k(True{}, c, cap, t, m, cs, room, tok)
1040
1041
1042
1043
1044def 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>:
1045 match m:
1046 case Model{+d, emb, ls, +lnf}:
1047 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))
1048
1049
1050
1051def 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>:
1052 match r:
1053 case Run{x, ls, cs, acts}:
1054 Out{Nil{}, Nil{}, acts, cs, Model{d, emb, ls, lnf}}
1055
1056def 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>:
1057 match r:
1058 case TA.BRow{emb, row}:
1059 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))
1060
1061def 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>:
1062 match m:
1063 case Model{+d, emb, ls, +lnf}:
1064 forward_pre.go(c, cap, t, room, d, ls, lnf, cs, TA.Bands.read_row(Cfg.vocab(c), Cfg.dim(c), emb, tok))
1065
1066
1067def caches(+c: Cfg, n: Nat, +cap: Nat) -> List<&1, KV<cap, 0n>>:
1068 match n:
1069 case 0n:
1070 Nil{}
1071 case 1n+p:
1072 KV.empty(c, cap) <> caches(c, p, cap)
1073
1074
1075type AM is Data:
1076 AM{i: Nat, v: F32}
1077
1078def AM.i(am: AM) -> Nat:
1079 match am:
1080 case AM{i, v}:
1081 i
1082
1083def AM.v(am: AM) -> F32:
1084 match am:
1085 case AM{i, v}:
1086 v
1087
1088def gt_head(xs: List<&2, F32>, +v: F32) -> Bool:
1089 match xs:
1090 case Nil{}:
1091 False{}
1092 case Con{+h, t}:
1093 F32.is_gt(h, v)
1094
1095def argmax.go(xs: List<&2, F32>, g: Bool, +i: Nat, +bi: Nat, +bv: F32) -> AM:
1096 match xs g:
1097 case Nil{} _:
1098 AM{bi, bv}
1099 case Con{+h, +t} True{}:
1100 argmax.go(t, gt_head(t, h), 1n+i, i, h)
1101 case Con{h, +t} False{}:
1102 argmax.go(t, gt_head(t, bv), 1n+i, bi, bv)
1103
1104def argmax(xs: List<&2, F32>) -> AM:
1105 match xs:
1106 case Nil{}:
1107 AM{0n, 0.0}
1108 case Con{+h, +t}:
1109 argmax.go(t, gt_head(t, h), 1n, 0n, h)
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121def hash32(+x: U32) -> U32:
1122 +a = U32.xor(x, U32.shrn(x, 16n))
1123 +b = U32.mul(a, 2146121005)
1124 +c = U32.xor(b, U32.shrn(b, 15n))
1125 +d = U32.mul(c, 2221713035)
1126 U32.xor(d, U32.shrn(d, 16n))
1127
1128
1129
1130def uniform(+seed: U32, +n: U32) -> F32:
1131 F32.mul(U32.to_f32(U32.shrn(hash32(U32.add(hash32(seed), n)), 8n)), 5.9604644775390625e-8)
1132
1133
1134type Cand is Data:
1135 Cand{v: F32, i: Nat}
1136
1137def Cand.i(c: Cand) -> Nat:
1138 match c:
1139 case Cand{v, i}:
1140 i
1141
1142def Cand.v(c: Cand) -> F32:
1143 match c:
1144 case Cand{v, i}:
1145 v
1146
1147
1148def goes_before(cs: List<&2, Cand>, +v: F32) -> Bool:
1149 match cs:
1150 case Nil{}:
1151 True{}
1152 case Con{Cand{hv, hi}, t}:
1153 F32.is_lt(hv, v)
1154
1155
1156def ins(cs: List<&2, Cand>, g: Bool, +v: F32, +i: Nat) -> List<&2, Cand>:
1157 match cs g:
1158 case Nil{} _:
1159 Cand{v, i} <> Nil{}
1160 case Con{h, t} True{}:
1161 Cand{v, i} <> (h <> t)
1162 case Con{h, +t} False{}:
1163 h <> ins(t, goes_before(t, v), v, i)
1164
1165
1166def last_v(cs: List<&2, Cand>, +lo: F32) -> F32:
1167 match cs:
1168 case Nil{}:
1169 lo
1170 case Con{Cand{v, i}, t}:
1171 last_v(t, v)
1172
1173
1174def enters(xs: List<&2, F32>, room: Bool, +lo: F32) -> Bool:
1175 match xs:
1176 case Nil{}:
1177 False{}
1178 case Con{+h, t}:
1179 Bool.or(room, F32.is_gt(h, lo))
1180
1181
1182
1183def topk.go(xs: List<&2, F32>, g: Bool, +k: Nat, +i: Nat, +m: Nat, +lo: F32, +cs: List<&2, Cand>) -> List<&2, Cand>:
1184 match xs g:
1185 case Nil{} _:
1186 cs
1187 case Con{h, +t} False{}:
1188 topk.go(t, enters(t, Nat.is_lt(m, k), lo), k, 1n+i, m, lo, cs)
1189 case Con{+h, +t} True{}:
1190 +cs2 = List.take(&2, Cand, ins(cs, goes_before(cs, h), h, i), k)
1191 +m2 = Nat.min(1n+m, k)
1192 +lo2 = last_v(cs2, h)
1193 topk.go(t, enters(t, Nat.is_lt(m2, k), lo2), k, 1n+i, m2, lo2, cs2)
1194
1195def topk(+k: Nat, +xs: List<&2, F32>) -> List<&2, Cand>:
1196 topk.go(xs, enters(xs, Nat.is_lt(0n, k), 0.0), k, 0n, 0n, 0.0, Nil{})
1197
1198
1199def weight(+v: F32, +temp: F32, +top: F32) -> F32:
1200 F32.exp(F32.sub(F32.div(v, temp), F32.div(top, temp)))
1201
1202
1203def total(cs: List<&2, Cand>, +temp: F32, +top: F32, +acc: F32) -> F32:
1204 match cs:
1205 case Nil{}:
1206 acc
1207 case Con{Cand{+v, i}, t}:
1208 total(t, temp, top, F32.add(acc, weight(v, temp, top)))
1209
1210
1211type Kept is Data:
1212 Kept{n: Nat, z: F32}
1213
1214
1215def kept.go(cs: List<&2, Cand>, g: Bool, +temp: F32, +top: F32, +lim: F32, +n: Nat, +acc: F32) -> Kept:
1216 match cs g:
1217 case Nil{} _:
1218 Kept{n, acc}
1219 case Con{h, t} False{}:
1220 Kept{n, acc}
1221 case Con{Cand{+v, i}, t} True{}:
1222 +acc2 = F32.add(acc, weight(v, temp, top))
1223 kept.go(t, F32.is_lt(acc2, lim), temp, top, lim, 1n+n, acc2)
1224
1225
1226
1227def stops(cs: List<&2, Cand>, +q: Nat, +temp: F32, +top: F32, +target: F32, +acc: F32) -> Bool:
1228 match cs:
1229 case Nil{}:
1230 True{}
1231 case Con{Cand{+v, i}, t}:
1232 Bool.or(Nat.is_eq(q, 0n), F32.is_lt(target, F32.add(acc, weight(v, temp, top))))
1233
1234
1235def pick.go(cs: List<&2, Cand>, s: Bool, +q: Nat, +temp: F32, +top: F32, +target: F32, +acc: F32) -> Cand:
1236 match cs s:
1237 case Nil{} _:
1238 Cand{0.0, 0n}
1239 case Con{h, t} True{}:
1240 h
1241 case Con{Cand{+v, i}, +t} False{}:
1242 +acc2 = F32.add(acc, weight(v, temp, top))
1243 pick.go(t, stops(t, Nat.sub(q, 1n), temp, top, target, acc2), Nat.sub(q, 1n), temp, top, target, acc2)
1244
1245def sample.pick(+cs: List<&2, Cand>, kp: Kept, +temp: F32, +top: F32, +u: F32) -> Cand:
1246 match kp:
1247 case Kept{+n, +z}:
1248 pick.go(cs, stops(cs, Nat.sub(n, 1n), temp, top, F32.mul(u, z), 0.0), Nat.sub(n, 1n), temp, top, F32.mul(u, z), 0.0)
1249
1250def sample.cs(+cs: List<&2, Cand>, +temp: F32, +top: F32, +p: F32, +u: F32) -> Cand:
1251 sample.pick(cs, kept.go(cs, True{}, temp, top, F32.mul(p, total(cs, temp, top, 0.0)), 0n, 0.0), temp, top, u)
1252
1253def top_of(cs: List<&2, Cand>) -> F32:
1254 match cs:
1255 case Nil{}:
1256 0.0
1257 case Con{Cand{v, i}, t}:
1258 v
1259
1260
1261
1262def sample(+xs: List<&2, F32>, +temp: F32, +k: Nat, +p: F32, +u: F32) -> Cand:
1263 +cs = topk(k, xs)
1264 sample.cs(cs, temp, top_of(cs), p, u)
1265
1266
1267
1268
1269def below(cs: List<&2, Cand>, +n: Nat) -> Bool:
1270 match cs:
1271 case Nil{}:
1272 True{}
1273 case Con{Cand{v, i}, t}:
1274
1275 Bool.and(TA.leb(1n+i, n), below(t, n))
1276
1277
1278def and_l(+a: Bool, -b: Bool, e: {True{} == Bool.and(a, b) : Bool}) -> {True{} == a : Bool}:
1279 match a:
1280 case True{}:
1281 {==}
1282 case False{}:
1283 e
1284
1285def and_r(+a: Bool, +b: Bool, e: {True{} == Bool.and(a, b) : Bool}) -> {True{} == b : Bool}:
1286 match a:
1287 case True{}:
1288 e
1289 case False{}:
1290 %e : TA.BD(_, Unit, {True{} == b : Bool})
1291 Unit{}
1292
1293
1294
1295law ins_below:
1296 for +cs: List<&2, Cand>
1297 for +g: Bool
1298 for +v: F32
1299 for +i: Nat
1300 for +n: Nat
1301 for +e: {True{} == below(cs, n) : Bool}
1302 for ei: {True{} == TA.leb(1n+i, n) : Bool}
1303 {True{} == below(ins(cs, g, v, i), n) : Bool}
1304
1305def ins_below(cs, g, v, i, n, e, ei):
1306 match cs g:
1307 case Nil{} _:
1308 %ei : {True{} == Bool.and(_, True{}) : Bool}
1309 {==}
1310 case Con{h, t} True{}:
1311 %ei : {True{} == Bool.and(_, below(h <> t, n)) : Bool}
1312 e
1313 case Con{Cand{hv, hi}, +t} False{}:
1314 %and_l(TA.leb(1n+hi, n), below(t, n), e) : {True{} == Bool.and(_, below(ins(t, goes_before(t, v), v, i), n)) : Bool}
1315 ins_below(t, goes_before(t, v), v, i, n, and_r(TA.leb(1n+hi, n), below(t, n), e), ei)
1316
1317
1318law take_below:
1319 for +cs: List<&2, Cand>
1320 for +k: Nat
1321 for +n: Nat
1322 for +e: {True{} == below(cs, n) : Bool}
1323 {True{} == below(List.take(&2, Cand, cs, k), n) : Bool}
1324
1325def take_below(cs, k, n, e):
1326 match cs k:
1327 case Nil{} _:
1328 {==}
1329 case Con{h, t} 0n:
1330 {==}
1331 case Con{Cand{v, i}, +t} 1n+p:
1332 %and_l(TA.leb(1n+i, n), below(t, n), e) : {True{} == Bool.and(_, below(List.take(&2, Cand, t, p), n)) : Bool}
1333 take_below(t, p, n, and_r(TA.leb(1n+i, n), below(t, n), e))
1334
1335
1336
1337law topk_below:
1338 for +xs: List<&2, F32>
1339 for +g: Bool
1340 for +k: Nat
1341 for +i: Nat
1342 for +m: Nat
1343 for +lo: F32
1344 for +cs: List<&2, Cand>
1345 for +n: Nat
1346 for +inv: {Nat.add(i, List.length(&2, F32, xs)) == n : Nat}
1347 for +e: {True{} == below(cs, n) : Bool}
1348 {True{} == below(topk.go(xs, g, k, i, m, lo, cs), n) : Bool}
1349
1350def topk_below(xs, g, k, i, m, lo, cs, n, inv, e):
1351 match xs g:
1352 case Nil{} _:
1353 e
1354 case Con{h, +t} False{}:
1355 topk_below(t, enters(t, Nat.is_lt(m, k), lo), k, 1n+i, m, lo, cs, n, step_inv(i, List.length(&2, F32, t), n, inv), e)
1356 case Con{+h, +t} True{}:
1357 +cs2 = List.take(&2, Cand, ins(cs, goes_before(cs, h), h, i), k)
1358 +m2 = Nat.min(1n+m, k)
1359 +lo2 = last_v(cs2, h)
1360 topk_below(t, enters(t, Nat.is_lt(m2, k), lo2), k, 1n+i, m2, lo2, cs2, n, step_inv(i, List.length(&2, F32, t), n, inv), take_below(ins(cs, goes_before(cs, h), h, i), k, n, ins_below(cs, goes_before(cs, h), h, i, n, e, step_room(i, List.length(&2, F32, t), n, inv))))
1361
1362
1363law pick_below:
1364 for +cs: List<&2, Cand>
1365 for +s: Bool
1366 for +q: Nat
1367 for +temp: F32
1368 for +top: F32
1369 for +target: F32
1370 for +acc: F32
1371 for +n: Nat
1372 for +e: {True{} == below(cs, n) : Bool}
1373 for pos: {True{} == TA.leb(1n, n) : Bool}
1374 {True{} == TA.leb(1n+Cand.i(pick.go(cs, s, q, temp, top, target, acc)), n) : Bool}
1375
1376def pick_below(cs, s, q, temp, top, target, acc, n, e, pos):
1377 match cs s:
1378 case Nil{} _:
1379 pos
1380 case Con{Cand{v, i}, t} True{}:
1381 and_l(TA.leb(1n+i, n), below(t, n), e)
1382 case Con{Cand{+v, +i}, +t} False{}:
1383 +acc2 = F32.add(acc, weight(v, temp, top))
1384 pick_below(t, stops(t, Nat.sub(q, 1n), temp, top, target, acc2), Nat.sub(q, 1n), temp, top, target, acc2, n, and_r(TA.leb(1n+i, n), below(t, n), e), pos)
1385
1386def sample.pick_below(+cs: List<&2, Cand>, kp: Kept, +temp: F32, +top: F32, +u: F32, +n: Nat, e: {True{} == below(cs, n) : Bool}, pos: {True{} == TA.leb(1n, n) : Bool}) -> {True{} == TA.leb(1n+Cand.i(sample.pick(cs, kp, temp, top, u)), n) : Bool}:
1387 match kp:
1388 case Kept{+c, +z}:
1389 pick_below(cs, stops(cs, Nat.sub(c, 1n), temp, top, F32.mul(u, z), 0.0), Nat.sub(c, 1n), temp, top, F32.mul(u, z), 0.0, n, e, pos)
1390
1391
1392
1393
1394
1395law sample_below:
1396 for +xs: List<&2, F32>
1397 for +temp: F32
1398 for +k: Nat
1399 for +p: F32
1400 for +u: F32
1401 for pos: {True{} == TA.leb(1n, List.length(&2, F32, xs)) : Bool}
1402 {True{} == TA.leb(1n+Cand.i(sample(xs, temp, k, p, u)), List.length(&2, F32, xs)) : Bool}
1403
1404def sample_below(xs, temp, k, p, u, pos):
1405 +cs = topk(k, xs)
1406 +n = List.length(&2, F32, xs)
1407 +top = top_of(cs)
1408 sample.pick_below(cs, kept.go(cs, True{}, temp, top, F32.mul(p, total(cs, temp, top, 0.0)), 0n, 0.0), temp, top, u, n, topk_below(xs, enters(xs, Nat.is_lt(0n, k), 0.0), k, 0n, 0n, 0.0, Nil{}, n, {==}, {==}), pos)
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419def bitcast(u: U32) -> F32:
1420 match u:
1421 case U32{w}:
1422 F32{w}
1423
1424def f32_le(+b0: U32, +b1: U32, +b2: U32, +b3: U32) -> F32:
1425 bitcast((b0 + (b1 * 256 : U32) + (b2 * 65536 : U32) + (b3 * 16777216 : U32) : U32))
1426
1427def f32s(bs: List<&2, U32>) -> List<&2, F32>:
1428 match bs:
1429 case Con{b0, Con{b1, Con{b2, Con{b3, t}}}}:
1430 f32_le(b0, b1, b2, b3) <> f32s(t)
1431 case _:
1432 Nil{}
1433
1434
1435def 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>):
1436 match k m:
1437 case 0n Tuple{f, r}:
1438 do IO<List<&2, F32>>:
1439 File.close(f)
1440 return List.concat(&2, F32, List.reverse(&2, List<&2, F32>, acc))
1441 case 1n+p Tuple{f, r}:
1442 do IO<List<&2, F32>>:
1443 bs : List<&2, U32> <- IO.pass(List<&2, U32>, r)
1444 m2 : File & Result<&1, &1, U32 & String, List<&2, U32>> <- File.read_at(f, (off + blk : U32), blk)
1445 rf_loop(p, (off + blk : U32), blk, m2, f32s(bs) <> acc)
1446
1447def blocks_of(n: Nat, +per: Nat) -> Nat:
1448 Nat.div(Nat.add(n, Nat.sub(per, 1n)), per)
1449
1450
1451def read_floats(path: String, +n: Nat) -> IO(List<&2, F32>):
1452 do IO<List<&2, F32>>:
1453 f : File <- IO.try(File, File.open(path, "r"))
1454 m : File & Result<&1, &1, U32 & String, List<&2, U32>> <- File.read_at(f, 0, 1048576)
1455 fl : List<&2, F32> <- rf_loop(blocks_of(Nat.mul(n, 4n), 1048576n), 0, 1048576, m, Nil{})
1456 return List.take(&2, F32, fl, n)
1457
1458
1459
1460
1461def depth_sel(few: Bool) -> Nat:
1462 match few:
1463 case True{}:
1464 0n
1465 case False{}:
1466 4n
1467
1468def depth_for(+threads: U32) -> Nat:
1469 depth_sel(U32.is_le(threads, 2))
1470
1471
1472
1473
1474def bf16_le(+b0: U32, +b1: U32) -> F32:
1475 bitcast(((b0 * 65536 : U32) + (b1 * 16777216 : U32) : U32))
1476
1477def bf16s(bs: List<&2, U32>) -> List<&2, F32>:
1478 match bs:
1479 case Con{b0, Con{b1, t}}:
1480 bf16_le(b0, b1) <> bf16s(t)
1481 case _:
1482 Nil{}
1483
1484
1485
1486def fill_bf16(bs: List<&2, U32>, +i: U32, a: Array<F32>) -> Array<F32>:
1487 match bs:
1488 case Con{+b0, Con{+b1, t}}:
1489 fill_bf16(t, (i + 1 : U32), Array.set(F32, a, i, bf16_le(b0, b1)))
1490 case _:
1491 a
1492
1493def fill_bf16_mat(-r: Nat, -c: Nat, +i: U32, bs: List<&2, U32>, m: TA.Mat<r, c>) -> TA.Mat<r, c>:
1494 match m:
1495 case TA.Mat{d}:
1496 TA.Mat{fill_bf16(bs, i, d)}
1497
1498
1499
1500def 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>):
1501 match k m:
1502 case 0n Tuple{f, rs}:
1503 do IO<TA.Mat<r, c>>:
1504 File.close(f)
1505 return acc
1506 case 1n+p Tuple{f, rs}:
1507 do IO<TA.Mat<r, c>>:
1508 bs : List<&2, U32> <- IO.pass(List<&2, U32>, rs)
1509 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))))
1510 stream_exact(p, r, c, Nat.sub(rem, 1048576n), (off + 1048576 : U32), (idx + 524288 : U32), m2, fill_bf16_mat(r, c, idx, bs, acc))
1511
1512
1513
1514def get_band(path: String, -r: Nat, +rr: Nat, +c: Nat, +lo: U32, +start: Nat) -> IO(TA.Mat<r, c>):
1515 do IO<TA.Mat<r, c>>:
1516 +off : U32 = (lo + U32.from_nat(Nat.mul(start, 2n)) : U32)
1517 f : File <- IO.try(File, File.open(path, "r"))
1518 m : File & Result<&1, &1, U32 & String, List<&2, U32>> <- File.read_at(f, off, U32.from_nat(Nat.min(1048576n, Nat.mul(Nat.mul(rr, c), 2n))))
1519 stream_exact(blocks_of(Nat.mul(Nat.mul(rr, c), 2n), 1048576n), r, c, Nat.mul(Nat.mul(rr, c), 2n), off, 0, m, TA.Mat{Array.new(F32, TA.cap_depth(Nat.mul(rr, c)), 0.0)})
1520
1521
1522
1523
1524def load_tree(+c: Nat, -r: Nat, +d: Nat, +rr: Nat, -e: {rr == r : Nat}, +path: String, +lo: U32, +start: Nat) -> IO(TA.Bands<r, c>):
1525 match d:
1526 case 0n:
1527 do IO<TA.Bands<r, c>>:
1528 band : TA.Mat<r, c> <- get_band(path, r, rr, c, lo, start)
1529 return TA.BLeaf{band}
1530 case 1n+q:
1531 do IO<TA.Bands<r, c>>:
1532 x2 : TA.Bands<TA.half(r), c> <- load_tree(c, TA.half(r), q, TA.half(rr), TA.eq_half(rr, r, e), path, lo, start)
1533 y2 : TA.Bands<Nat.sub(r, TA.half(r)), c> <- load_tree(c, Nat.sub(r, TA.half(r)), q, Nat.sub(rr, TA.half(rr)), TA.eq_rest(rr, r, e), path, lo, Nat.add(start, Nat.mul(TA.half(rr), c)))
1534 return TA.BNode{x2, y2}
1535
1536
1537
1538def span_cmp(ok: Bool, +path: String, +t: Nat) -> IO(Unit):
1539 match ok:
1540 case True{}:
1541 IO.pure(Unit, Unit{})
1542 case False{}:
1543 IO.die(Unit, 1, path ++ ": tensor " ++ Nat.show(t) ++ " of w/st.txt ends past the end of the file or starts beyond 4 GiB (File.read_at takes a U32 offset); run reference/prep.py --index")
1544
1545def span_ok(m: File & Result<&1, &1, U32 & String, U32>, +hi: U32, +lo: U32, +end: U32, +path: String, +t: Nat) -> IO(Unit):
1546 match m:
1547 case Tuple{f, r}:
1548 do IO<Unit>:
1549 +n : U32 <- IO.pass(U32, r)
1550 File.close(f)
1551 span_cmp(Bool.and(U32.is_eq(hi, 0), Bool.and(U32.is_le(lo, end), U32.is_le(end, n))), path, t)
1552
1553
1554def check_span(+path: String, +hi: U32, +lo: U32, +n: Nat, +t: Nat) -> IO(Unit):
1555 do IO<Unit>:
1556 f : File <- IO.try(File, File.open(path, "r"))
1557 m : File & Result<&1, &1, U32 & String, U32> <- File.size(f)
1558 span_ok(m, hi, lo, (lo + U32.from_nat(Nat.mul(n, 2n)) : U32), path, t)
1559
1560
1561
1562def rb_done(m: File & Result<&1, &1, U32 & String, List<&2, U32>>) -> IO(List<&2, U32>):
1563 (f, r) = m
1564 do IO<List<&2, U32>>:
1565 bs : List<&2, U32> <- IO.pass(List<&2, U32>, r)
1566 File.close(f)
1567 return bs
1568
1569def read_bytes(path: String) -> IO(List<&2, U32>):
1570 do IO<List<&2, U32>>:
1571 f : File <- IO.try(File, File.open(path, "r"))
1572 m : File & Result<&1, &1, U32 & String, List<&2, U32>> <- File.read_bytes(f, 1048576)
1573 rb_done(m)
1574
1575def digit_head(xs: List<&2, U32>) -> Bool:
1576 match xs:
1577 case Nil{}:
1578 False{}
1579 case Con{+b, t}:
1580 Bool.and(U32.is_le(48, b), U32.is_le(b, 57))
1581
1582
1583def u32s.go(bs: List<&2, U32>, dg: Bool, +cur: U32, have: Bool, acc: List<&2, U32>) -> List<&2, U32>:
1584 match bs dg have:
1585 case Nil{} _ True{}:
1586 List.reverse(&2, U32, cur <> acc)
1587 case Nil{} _ False{}:
1588 List.reverse(&2, U32, acc)
1589 case Con{+b, +t} True{} _:
1590 u32s.go(t, digit_head(t), ((cur * 10 : U32) + U32.sub(b, 48) : U32), True{}, acc)
1591 case Con{b, +t} False{} True{}:
1592 u32s.go(t, digit_head(t), 0, False{}, cur <> acc)
1593 case Con{b, +t} False{} False{}:
1594 u32s.go(t, digit_head(t), 0, False{}, acc)
1595
1596def u32s(+bs: List<&2, U32>) -> List<&2, U32>:
1597 u32s.go(bs, digit_head(bs), 0, False{}, Nil{})
1598
1599def cfg_of(+path: String, xs: List<&2, U32>) -> IO(Cfg):
1600 match xs:
1601 case Con{+kv, Con{+g, Con{+half, Con{+f, Con{+l, Con{+v, Con{+e, Con{+t, Nil{}}}}}}}}}:
1602 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)})
1603 case _:
1604 IO.die(Cfg, 1, path ++ ": expected 8 numbers (kv g half f layers vocab eps_bits theta_bits); run make prep again")
1605
1606
1607def read_cfg(+dir: String) -> IO(Cfg):
1608 do IO<Cfg>:
1609 bs : List<&2, U32> <- read_bytes(dir ++ "/cfg.txt")
1610 cfg_of(dir ++ "/cfg.txt", u32s(bs))
1611
1612
1613
1614def st_path(+dir: String) -> String:
1615 dir ++ "/hf/model.safetensors"
1616
1617def st_nth(xs: List<&2, U32>, k: Nat) -> U32:
1618 match xs k:
1619 case Con{+x, t} 0n:
1620 x
1621 case Con{x, t} 1n+p:
1622 st_nth(t, p)
1623 case Nil{} _:
1624 0
1625
1626
1627
1628def t_layer(+i: Nat, +j: Nat) -> Nat:
1629 Nat.add(Nat.add(1n, Nat.mul(9n, i)), j)
1630
1631def st_check(ok: Bool, +dir: String, xs: List<&2, U32>) -> IO(List<&2, U32>):
1632 match ok:
1633 case True{}:
1634 IO.pure(List<&2, U32>, xs)
1635 case False{}:
1636 IO.die(List<&2, U32>, 1, dir ++ "/w/st.txt: not two numbers for each of the model's tensors; run reference/prep.py --index")
1637
1638
1639def read_st(+dir: String, +layers: Nat) -> IO(List<&2, U32>):
1640 do IO<List<&2, U32>>:
1641 bs : List<&2, U32> <- read_bytes(dir ++ "/w/st.txt")
1642 +xs : List<&2, U32> = u32s(bs)
1643 st_check(Nat.is_eq(List.length(&2, U32, xs), Nat.mul(2n, Nat.add(2n, Nat.mul(9n, layers)))), dir, xs)
1644
1645def st_hi(+st: List<&2, U32>, +t: Nat) -> U32:
1646 st_nth(st, Nat.mul(2n, t))
1647
1648def st_lo(+st: List<&2, U32>, +t: Nat) -> U32:
1649 st_nth(st, 1n+Nat.mul(2n, t))
1650
1651
1652def get_bands(+dir: String, +st: List<&2, U32>, +t: Nat, +d: Nat, +r: Nat, +c: Nat) -> IO(TA.Bands<r, c>):
1653 do IO<TA.Bands<r, c>>:
1654 check_span(st_path(dir), st_hi(st, t), st_lo(st, t), Nat.mul(r, c), t)
1655 load_tree(c, r, d, r, {==}, st_path(dir), st_lo(st, t), 0n)
1656
1657
1658def get_norm(+dir: String, +st: List<&2, U32>, +t: Nat, +n: Nat) -> IO(List<&2, F32>):
1659 do IO<List<&2, F32>>:
1660 check_span(st_path(dir), st_hi(st, t), st_lo(st, t), n, t)
1661 f : File <- IO.try(File, File.open(st_path(dir), "r"))
1662 m : File & Result<&1, &1, U32 & String, List<&2, U32>> <- File.read_at(f, st_lo(st, t), U32.from_nat(Nat.mul(n, 2n)))
1663 bs : List<&2, U32> <- rb_done(m)
1664 return List.take(&2, F32, bf16s(bs), n)
1665
1666
1667def load_lw_st(+c: Cfg, +dir: String, +st: List<&2, U32>, +i: Nat, +d: Nat) -> IO(LW<c>):
1668 do IO<LW<c>>:
1669 ln1 : List<&2, F32> <- get_norm(dir, st, t_layer(i, 0n), Cfg.dim(c))
1670 q : TA.Bands<Cfg.dim(c), Cfg.dim(c)> <- get_bands(dir, st, t_layer(i, 1n), d, Cfg.dim(c), Cfg.dim(c))
1671 k : TA.Bands<Cfg.kvw(c), Cfg.dim(c)> <- get_bands(dir, st, t_layer(i, 2n), d, Cfg.kvw(c), Cfg.dim(c))
1672 v : TA.Bands<Cfg.kvw(c), Cfg.dim(c)> <- get_bands(dir, st, t_layer(i, 3n), d, Cfg.kvw(c), Cfg.dim(c))
1673 o : TA.Bands<Cfg.dim(c), Cfg.dim(c)> <- get_bands(dir, st, t_layer(i, 4n), d, Cfg.dim(c), Cfg.dim(c))
1674 ln2 : List<&2, F32> <- get_norm(dir, st, t_layer(i, 5n), Cfg.dim(c))
1675 gate : TA.Bands<Cfg.ffn(c), Cfg.dim(c)> <- get_bands(dir, st, t_layer(i, 6n), d, Cfg.ffn(c), Cfg.dim(c))
1676 up : TA.Bands<Cfg.ffn(c), Cfg.dim(c)> <- get_bands(dir, st, t_layer(i, 7n), d, Cfg.ffn(c), Cfg.dim(c))
1677 down : TA.Bands<Cfg.dim(c), Cfg.ffn(c)> <- get_bands(dir, st, t_layer(i, 8n), d, Cfg.dim(c), Cfg.ffn(c))
1678 return LW{ln1, q, k, v, o, ln2, gate, up, down}
1679
1680
1681def load_lw(+c: Cfg, +dir: String, +i: Nat, +d: Nat) -> IO(LW<c>):
1682 do IO<LW<c>>:
1683 +st : List<&2, U32> <- read_st(dir, Cfg.layers(c))
1684 load_lw_st(c, dir, st, i, d)
1685
1686def load_layers(k: Nat, +c: Cfg, +dir: String, +st: List<&2, U32>, +d: Nat, +i: Nat, acc: List<&1, LW<c>>) -> IO(List<&1, LW<c>>):
1687 match k:
1688 case 0n:
1689 IO.pure(List<&1, LW<c>>, List.reverse(&1, LW<c>, acc))
1690 case 1n+p:
1691 do IO<List<&1, LW<c>>>:
1692 l : LW<c> <- load_lw_st(c, dir, st, i, d)
1693 load_layers(p, c, dir, st, d, 1n+i, l <> acc)
1694
1695
1696def load_model(+c: Cfg, +dir: String) -> IO(Model<c>):
1697 do IO<Model<c>>:
1698 threads : U32 <- IO.thread_count()
1699 +d : Nat = depth_for(threads)
1700 +st : List<&2, U32> <- read_st(dir, Cfg.layers(c))
1701 emb : TA.Bands<Cfg.vocab(c), Cfg.dim(c)> <- get_bands(dir, st, 0n, Nat.add(d, Nat.min(d, 1n)), Cfg.vocab(c), Cfg.dim(c))
1702 ls : List<&1, LW<c>> <- load_layers(Cfg.layers(c), c, dir, st, d, 0n, Nil{})
1703 lnf : List<&2, F32> <- get_norm(dir, st, t_layer(Cfg.layers(c), 0n), Cfg.dim(c))
1704 return Model{d, emb, ls, lnf}