Angshul commited on
Commit
5973eb4
·
verified ·
1 Parent(s): 31888cb

Release Falcon-H1 Rust CUDA implementation

Browse files
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ falcon-h1.f32pack filter=lfs diff=lfs merge=lfs -text
Cargo.lock ADDED
@@ -0,0 +1,1708 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file is automatically @generated by Cargo.
2
+ # It is not intended for manual editing.
3
+ version = 4
4
+
5
+ [[package]]
6
+ name = "ahash"
7
+ version = "0.8.12"
8
+ source = "registry+https://github.com/rust-lang/crates.io-index"
9
+ checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75"
10
+ dependencies = [
11
+ "cfg-if",
12
+ "getrandom 0.3.4",
13
+ "once_cell",
14
+ "serde",
15
+ "version_check",
16
+ "zerocopy",
17
+ ]
18
+
19
+ [[package]]
20
+ name = "aho-corasick"
21
+ version = "1.1.5"
22
+ source = "registry+https://github.com/rust-lang/crates.io-index"
23
+ checksum = "c982642fa9e8606056828ee9a8505737230110bb1099153c79efe865c59d12ba"
24
+ dependencies = [
25
+ "memchr",
26
+ ]
27
+
28
+ [[package]]
29
+ name = "allocator-api2"
30
+ version = "0.2.21"
31
+ source = "registry+https://github.com/rust-lang/crates.io-index"
32
+ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
33
+
34
+ [[package]]
35
+ name = "anyhow"
36
+ version = "1.0.104"
37
+ source = "registry+https://github.com/rust-lang/crates.io-index"
38
+ checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470"
39
+
40
+ [[package]]
41
+ name = "autocfg"
42
+ version = "1.5.1"
43
+ source = "registry+https://github.com/rust-lang/crates.io-index"
44
+ checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
45
+
46
+ [[package]]
47
+ name = "base64"
48
+ version = "0.13.1"
49
+ source = "registry+https://github.com/rust-lang/crates.io-index"
50
+ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
51
+
52
+ [[package]]
53
+ name = "bit-set"
54
+ version = "0.8.0"
55
+ source = "registry+https://github.com/rust-lang/crates.io-index"
56
+ checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3"
57
+ dependencies = [
58
+ "bit-vec",
59
+ ]
60
+
61
+ [[package]]
62
+ name = "bit-vec"
63
+ version = "0.8.0"
64
+ source = "registry+https://github.com/rust-lang/crates.io-index"
65
+ checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7"
66
+
67
+ [[package]]
68
+ name = "bitflags"
69
+ version = "2.13.2"
70
+ source = "registry+https://github.com/rust-lang/crates.io-index"
71
+ checksum = "3ded4057c258ba199e2d26386d3af3780957ecaee6c4ef4041c6b4b8b97c0b06"
72
+
73
+ [[package]]
74
+ name = "block-buffer"
75
+ version = "0.10.4"
76
+ source = "registry+https://github.com/rust-lang/crates.io-index"
77
+ checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
78
+ dependencies = [
79
+ "generic-array",
80
+ ]
81
+
82
+ [[package]]
83
+ name = "bumpalo"
84
+ version = "3.20.3"
85
+ source = "registry+https://github.com/rust-lang/crates.io-index"
86
+ checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649"
87
+
88
+ [[package]]
89
+ name = "bytemuck"
90
+ version = "1.25.2"
91
+ source = "registry+https://github.com/rust-lang/crates.io-index"
92
+ checksum = "95832e849adfb21180ccb6826a99da14e5d266ae5c2e668e1602cf234f153797"
93
+ dependencies = [
94
+ "bytemuck_derive",
95
+ ]
96
+
97
+ [[package]]
98
+ name = "bytemuck_derive"
99
+ version = "1.12.1"
100
+ source = "registry+https://github.com/rust-lang/crates.io-index"
101
+ checksum = "6a1f896587b6f2c069c73d2f0913e2d590c3990285cd2f0b6aa02b786b4c679c"
102
+ dependencies = [
103
+ "proc-macro2",
104
+ "quote",
105
+ "syn 3.0.10",
106
+ ]
107
+
108
+ [[package]]
109
+ name = "byteorder"
110
+ version = "1.5.0"
111
+ source = "registry+https://github.com/rust-lang/crates.io-index"
112
+ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
113
+
114
+ [[package]]
115
+ name = "candle-core"
116
+ version = "0.11.1"
117
+ source = "registry+https://github.com/rust-lang/crates.io-index"
118
+ checksum = "d11c8be87cfbaef9ebb62fb3f850d1fc8e00cc1d11d393fdbe55a4d5c2cdb325"
119
+ dependencies = [
120
+ "byteorder",
121
+ "candle-kernels",
122
+ "cudarc",
123
+ "float8",
124
+ "gemm",
125
+ "half",
126
+ "libc",
127
+ "libm",
128
+ "memmap2",
129
+ "num-traits",
130
+ "num_cpus",
131
+ "parking_lot",
132
+ "rand",
133
+ "rand_distr",
134
+ "rayon",
135
+ "safetensors",
136
+ "thiserror 2.0.21",
137
+ "tokenizers",
138
+ "yoke",
139
+ "zerocopy",
140
+ "zip",
141
+ ]
142
+
143
+ [[package]]
144
+ name = "candle-kernels"
145
+ version = "0.11.1"
146
+ source = "registry+https://github.com/rust-lang/crates.io-index"
147
+ checksum = "8dc057aec95c3b1a0e595227cd039c1436da596f79ccc9e025ba17d070315851"
148
+ dependencies = [
149
+ "cudaforge",
150
+ ]
151
+
152
+ [[package]]
153
+ name = "candle-nn"
154
+ version = "0.11.1"
155
+ source = "registry+https://github.com/rust-lang/crates.io-index"
156
+ checksum = "437fabe77547c2447c7bdf3cc946e19db29a2832440176b419f77c80b0a9a05e"
157
+ dependencies = [
158
+ "candle-core",
159
+ "half",
160
+ "libc",
161
+ "num-traits",
162
+ "rayon",
163
+ "safetensors",
164
+ "serde",
165
+ "thiserror 2.0.21",
166
+ ]
167
+
168
+ [[package]]
169
+ name = "castaway"
170
+ version = "0.2.4"
171
+ source = "registry+https://github.com/rust-lang/crates.io-index"
172
+ checksum = "dec551ab6e7578819132c713a93c022a05d60159dc86e7a7050223577484c55a"
173
+ dependencies = [
174
+ "rustversion",
175
+ ]
176
+
177
+ [[package]]
178
+ name = "cfg-if"
179
+ version = "1.0.5"
180
+ source = "registry+https://github.com/rust-lang/crates.io-index"
181
+ checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600"
182
+
183
+ [[package]]
184
+ name = "cfg_aliases"
185
+ version = "0.2.2"
186
+ source = "registry+https://github.com/rust-lang/crates.io-index"
187
+ checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527"
188
+
189
+ [[package]]
190
+ name = "compact_str"
191
+ version = "0.9.1"
192
+ source = "registry+https://github.com/rust-lang/crates.io-index"
193
+ checksum = "9dfdd1c2274d9aa354115b09dc9a901d6c5576818cdf70d14cae2bdb47df00ab"
194
+ dependencies = [
195
+ "castaway",
196
+ "cfg-if",
197
+ "itoa",
198
+ "rustversion",
199
+ "ryu",
200
+ "serde",
201
+ "static_assertions",
202
+ ]
203
+
204
+ [[package]]
205
+ name = "constant_time_eq"
206
+ version = "0.6.1"
207
+ source = "registry+https://github.com/rust-lang/crates.io-index"
208
+ checksum = "9eb6feb175df65d0a3ccd3e73484e940d0ac664e8034f0519fd49a93db3071d9"
209
+ dependencies = [
210
+ "rustversion",
211
+ ]
212
+
213
+ [[package]]
214
+ name = "cpufeatures"
215
+ version = "0.2.17"
216
+ source = "registry+https://github.com/rust-lang/crates.io-index"
217
+ checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
218
+ dependencies = [
219
+ "libc",
220
+ ]
221
+
222
+ [[package]]
223
+ name = "crc32fast"
224
+ version = "1.5.5"
225
+ source = "registry+https://github.com/rust-lang/crates.io-index"
226
+ checksum = "2b929dd2a135771f40afabd1073f85eed59c800b7c61901e5c254270497dad64"
227
+ dependencies = [
228
+ "cfg-if",
229
+ ]
230
+
231
+ [[package]]
232
+ name = "crossbeam-deque"
233
+ version = "0.8.8"
234
+ source = "registry+https://github.com/rust-lang/crates.io-index"
235
+ checksum = "622f3fc73690be383c7214310406f28a90e6edeadc3cea882f9d71e495b9711a"
236
+ dependencies = [
237
+ "crossbeam-epoch",
238
+ "crossbeam-utils",
239
+ ]
240
+
241
+ [[package]]
242
+ name = "crossbeam-epoch"
243
+ version = "0.9.21"
244
+ source = "registry+https://github.com/rust-lang/crates.io-index"
245
+ checksum = "dc74980687109a3b14c72fd458107bf0baa1da1a1a805e178d15501ba9b86d9d"
246
+ dependencies = [
247
+ "crossbeam-utils",
248
+ ]
249
+
250
+ [[package]]
251
+ name = "crossbeam-utils"
252
+ version = "0.8.23"
253
+ source = "registry+https://github.com/rust-lang/crates.io-index"
254
+ checksum = "a31eee39dddec8330830986fcd7625edb5a24ec90ea038215273bbc3adb08ac6"
255
+
256
+ [[package]]
257
+ name = "crunchy"
258
+ version = "0.2.4"
259
+ source = "registry+https://github.com/rust-lang/crates.io-index"
260
+ checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5"
261
+
262
+ [[package]]
263
+ name = "crypto-common"
264
+ version = "0.1.7"
265
+ source = "registry+https://github.com/rust-lang/crates.io-index"
266
+ checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"
267
+ dependencies = [
268
+ "generic-array",
269
+ "typenum",
270
+ ]
271
+
272
+ [[package]]
273
+ name = "cudaforge"
274
+ version = "0.1.6"
275
+ source = "registry+https://github.com/rust-lang/crates.io-index"
276
+ checksum = "8d475ff95b9e4096878f47fe0ca5dbad0e23849a79fc225305ea06c2f25771cd"
277
+ dependencies = [
278
+ "anyhow",
279
+ "fs2",
280
+ "glob",
281
+ "num_cpus",
282
+ "rayon",
283
+ "serde",
284
+ "serde_json",
285
+ "sha2",
286
+ "thiserror 2.0.21",
287
+ "walkdir",
288
+ "which",
289
+ ]
290
+
291
+ [[package]]
292
+ name = "cudarc"
293
+ version = "0.19.10"
294
+ source = "registry+https://github.com/rust-lang/crates.io-index"
295
+ checksum = "7359bf1de037ddada72729c3acec9b040f3468400c6e9e740b01ba0cd2e89562"
296
+ dependencies = [
297
+ "float8",
298
+ "half",
299
+ "libloading",
300
+ ]
301
+
302
+ [[package]]
303
+ name = "daachorse"
304
+ version = "3.0.3"
305
+ source = "registry+https://github.com/rust-lang/crates.io-index"
306
+ checksum = "5614204febbc33cc07a2806aa6440b904ac012b68eecc37f4493ea4a76455a3d"
307
+
308
+ [[package]]
309
+ name = "darling"
310
+ version = "0.20.11"
311
+ source = "registry+https://github.com/rust-lang/crates.io-index"
312
+ checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee"
313
+ dependencies = [
314
+ "darling_core",
315
+ "darling_macro",
316
+ ]
317
+
318
+ [[package]]
319
+ name = "darling_core"
320
+ version = "0.20.11"
321
+ source = "registry+https://github.com/rust-lang/crates.io-index"
322
+ checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e"
323
+ dependencies = [
324
+ "fnv",
325
+ "ident_case",
326
+ "proc-macro2",
327
+ "quote",
328
+ "strsim",
329
+ "syn 2.0.119",
330
+ ]
331
+
332
+ [[package]]
333
+ name = "darling_macro"
334
+ version = "0.20.11"
335
+ source = "registry+https://github.com/rust-lang/crates.io-index"
336
+ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead"
337
+ dependencies = [
338
+ "darling_core",
339
+ "quote",
340
+ "syn 2.0.119",
341
+ ]
342
+
343
+ [[package]]
344
+ name = "dary_heap"
345
+ version = "0.3.9"
346
+ source = "registry+https://github.com/rust-lang/crates.io-index"
347
+ checksum = "8b1e3a325bc115f096c8b77bbf027a7c2592230e70be2d985be950d3d5e60ebe"
348
+ dependencies = [
349
+ "serde",
350
+ ]
351
+
352
+ [[package]]
353
+ name = "derive_builder"
354
+ version = "0.20.2"
355
+ source = "registry+https://github.com/rust-lang/crates.io-index"
356
+ checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947"
357
+ dependencies = [
358
+ "derive_builder_macro",
359
+ ]
360
+
361
+ [[package]]
362
+ name = "derive_builder_core"
363
+ version = "0.20.2"
364
+ source = "registry+https://github.com/rust-lang/crates.io-index"
365
+ checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8"
366
+ dependencies = [
367
+ "darling",
368
+ "proc-macro2",
369
+ "quote",
370
+ "syn 2.0.119",
371
+ ]
372
+
373
+ [[package]]
374
+ name = "derive_builder_macro"
375
+ version = "0.20.2"
376
+ source = "registry+https://github.com/rust-lang/crates.io-index"
377
+ checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c"
378
+ dependencies = [
379
+ "derive_builder_core",
380
+ "syn 2.0.119",
381
+ ]
382
+
383
+ [[package]]
384
+ name = "digest"
385
+ version = "0.10.7"
386
+ source = "registry+https://github.com/rust-lang/crates.io-index"
387
+ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
388
+ dependencies = [
389
+ "block-buffer",
390
+ "crypto-common",
391
+ ]
392
+
393
+ [[package]]
394
+ name = "dyn-stack"
395
+ version = "0.13.2"
396
+ source = "registry+https://github.com/rust-lang/crates.io-index"
397
+ checksum = "1c4713e43e2886ba72b8271aa66c93d722116acf7a75555cce11dcde84388fe8"
398
+ dependencies = [
399
+ "bytemuck",
400
+ "dyn-stack-macros",
401
+ ]
402
+
403
+ [[package]]
404
+ name = "dyn-stack-macros"
405
+ version = "0.1.3"
406
+ source = "registry+https://github.com/rust-lang/crates.io-index"
407
+ checksum = "e1d926b4d407d372f141f93bb444696142c29d32962ccbd3531117cf3aa0bfa9"
408
+
409
+ [[package]]
410
+ name = "either"
411
+ version = "1.19.0"
412
+ source = "registry+https://github.com/rust-lang/crates.io-index"
413
+ checksum = "0e9c71c2167ca323c882b99918929403426e2373ea17242ff5653e0d5e1058be"
414
+
415
+ [[package]]
416
+ name = "enum-as-inner"
417
+ version = "0.6.1"
418
+ source = "registry+https://github.com/rust-lang/crates.io-index"
419
+ checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc"
420
+ dependencies = [
421
+ "heck",
422
+ "proc-macro2",
423
+ "quote",
424
+ "syn 2.0.119",
425
+ ]
426
+
427
+ [[package]]
428
+ name = "env_home"
429
+ version = "0.1.0"
430
+ source = "registry+https://github.com/rust-lang/crates.io-index"
431
+ checksum = "c7f84e12ccf0a7ddc17a6c41c93326024c42920d7ee630d04950e6926645c0fe"
432
+
433
+ [[package]]
434
+ name = "equivalent"
435
+ version = "1.0.3"
436
+ source = "registry+https://github.com/rust-lang/crates.io-index"
437
+ checksum = "00d174d5400e5e8fd687ad1049e2f578285fa914201b1af7e8b112a4546bd826"
438
+
439
+ [[package]]
440
+ name = "errno"
441
+ version = "0.3.14"
442
+ source = "registry+https://github.com/rust-lang/crates.io-index"
443
+ checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
444
+ dependencies = [
445
+ "libc",
446
+ "windows-sys",
447
+ ]
448
+
449
+ [[package]]
450
+ name = "esaxx-rs"
451
+ version = "0.1.10"
452
+ source = "registry+https://github.com/rust-lang/crates.io-index"
453
+ checksum = "d817e038c30374a4bcb22f94d0a8a0e216958d4c3dcde369b1439fec4bdda6e6"
454
+
455
+ [[package]]
456
+ name = "falcon_h1_rust"
457
+ version = "0.2.0"
458
+ dependencies = [
459
+ "candle-core",
460
+ "candle-nn",
461
+ ]
462
+
463
+ [[package]]
464
+ name = "fancy-regex"
465
+ version = "0.17.0"
466
+ source = "registry+https://github.com/rust-lang/crates.io-index"
467
+ checksum = "72cf461f865c862bb7dc573f643dd6a2b6842f7c30b07882b56bd148cc2761b8"
468
+ dependencies = [
469
+ "bit-set",
470
+ "regex-automata",
471
+ "regex-syntax",
472
+ ]
473
+
474
+ [[package]]
475
+ name = "fastrand"
476
+ version = "2.5.0"
477
+ source = "registry+https://github.com/rust-lang/crates.io-index"
478
+ checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223"
479
+
480
+ [[package]]
481
+ name = "float8"
482
+ version = "0.7.0"
483
+ source = "registry+https://github.com/rust-lang/crates.io-index"
484
+ checksum = "c2d1f04709a8ac06e8e8042875a3c466cc4832d3c1a18dbcb9dba3c6e83046bc"
485
+ dependencies = [
486
+ "half",
487
+ "num-traits",
488
+ "rand",
489
+ "rand_distr",
490
+ ]
491
+
492
+ [[package]]
493
+ name = "fnv"
494
+ version = "1.0.7"
495
+ source = "registry+https://github.com/rust-lang/crates.io-index"
496
+ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
497
+
498
+ [[package]]
499
+ name = "foldhash"
500
+ version = "0.2.0"
501
+ source = "registry+https://github.com/rust-lang/crates.io-index"
502
+ checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb"
503
+
504
+ [[package]]
505
+ name = "fs2"
506
+ version = "0.4.3"
507
+ source = "registry+https://github.com/rust-lang/crates.io-index"
508
+ checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213"
509
+ dependencies = [
510
+ "libc",
511
+ "winapi",
512
+ ]
513
+
514
+ [[package]]
515
+ name = "gemm"
516
+ version = "0.19.0"
517
+ source = "registry+https://github.com/rust-lang/crates.io-index"
518
+ checksum = "aa0673db364b12263d103b68337a68fbecc541d6f6b61ba72fe438654709eacb"
519
+ dependencies = [
520
+ "dyn-stack",
521
+ "gemm-c32",
522
+ "gemm-c64",
523
+ "gemm-common",
524
+ "gemm-f16",
525
+ "gemm-f32",
526
+ "gemm-f64",
527
+ "num-complex",
528
+ "num-traits",
529
+ "paste",
530
+ "raw-cpuid",
531
+ "seq-macro",
532
+ ]
533
+
534
+ [[package]]
535
+ name = "gemm-c32"
536
+ version = "0.19.0"
537
+ source = "registry+https://github.com/rust-lang/crates.io-index"
538
+ checksum = "086936dbdcb99e37aad81d320f98f670e53c1e55a98bee70573e83f95beb128c"
539
+ dependencies = [
540
+ "dyn-stack",
541
+ "gemm-common",
542
+ "num-complex",
543
+ "num-traits",
544
+ "paste",
545
+ "raw-cpuid",
546
+ "seq-macro",
547
+ ]
548
+
549
+ [[package]]
550
+ name = "gemm-c64"
551
+ version = "0.19.0"
552
+ source = "registry+https://github.com/rust-lang/crates.io-index"
553
+ checksum = "20c8aeeeec425959bda4d9827664029ba1501a90a0d1e6228e48bef741db3a3f"
554
+ dependencies = [
555
+ "dyn-stack",
556
+ "gemm-common",
557
+ "num-complex",
558
+ "num-traits",
559
+ "paste",
560
+ "raw-cpuid",
561
+ "seq-macro",
562
+ ]
563
+
564
+ [[package]]
565
+ name = "gemm-common"
566
+ version = "0.19.0"
567
+ source = "registry+https://github.com/rust-lang/crates.io-index"
568
+ checksum = "88027625910cc9b1085aaaa1c4bc46bb3a36aad323452b33c25b5e4e7c8e2a3e"
569
+ dependencies = [
570
+ "bytemuck",
571
+ "dyn-stack",
572
+ "half",
573
+ "libm",
574
+ "num-complex",
575
+ "num-traits",
576
+ "once_cell",
577
+ "paste",
578
+ "pulp",
579
+ "raw-cpuid",
580
+ "rayon",
581
+ "seq-macro",
582
+ "sysctl",
583
+ ]
584
+
585
+ [[package]]
586
+ name = "gemm-f16"
587
+ version = "0.19.0"
588
+ source = "registry+https://github.com/rust-lang/crates.io-index"
589
+ checksum = "e3df7a55202e6cd6739d82ae3399c8e0c7e1402859b30e4cb780e61525d9486e"
590
+ dependencies = [
591
+ "dyn-stack",
592
+ "gemm-common",
593
+ "gemm-f32",
594
+ "half",
595
+ "num-complex",
596
+ "num-traits",
597
+ "paste",
598
+ "raw-cpuid",
599
+ "rayon",
600
+ "seq-macro",
601
+ ]
602
+
603
+ [[package]]
604
+ name = "gemm-f32"
605
+ version = "0.19.0"
606
+ source = "registry+https://github.com/rust-lang/crates.io-index"
607
+ checksum = "02e0b8c9da1fbec6e3e3ab2ce6bc259ef18eb5f6f0d3e4edf54b75f9fd41a81c"
608
+ dependencies = [
609
+ "dyn-stack",
610
+ "gemm-common",
611
+ "num-complex",
612
+ "num-traits",
613
+ "paste",
614
+ "raw-cpuid",
615
+ "seq-macro",
616
+ ]
617
+
618
+ [[package]]
619
+ name = "gemm-f64"
620
+ version = "0.19.0"
621
+ source = "registry+https://github.com/rust-lang/crates.io-index"
622
+ checksum = "056131e8f2a521bfab322f804ccd652520c79700d81209e9d9275bbdecaadc6a"
623
+ dependencies = [
624
+ "dyn-stack",
625
+ "gemm-common",
626
+ "num-complex",
627
+ "num-traits",
628
+ "paste",
629
+ "raw-cpuid",
630
+ "seq-macro",
631
+ ]
632
+
633
+ [[package]]
634
+ name = "generic-array"
635
+ version = "0.14.7"
636
+ source = "registry+https://github.com/rust-lang/crates.io-index"
637
+ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
638
+ dependencies = [
639
+ "typenum",
640
+ "version_check",
641
+ ]
642
+
643
+ [[package]]
644
+ name = "getrandom"
645
+ version = "0.3.4"
646
+ source = "registry+https://github.com/rust-lang/crates.io-index"
647
+ checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
648
+ dependencies = [
649
+ "cfg-if",
650
+ "libc",
651
+ "r-efi 5.3.0",
652
+ "wasip2",
653
+ ]
654
+
655
+ [[package]]
656
+ name = "getrandom"
657
+ version = "0.4.3"
658
+ source = "registry+https://github.com/rust-lang/crates.io-index"
659
+ checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099"
660
+ dependencies = [
661
+ "cfg-if",
662
+ "js-sys",
663
+ "libc",
664
+ "r-efi 6.0.0",
665
+ "wasm-bindgen",
666
+ ]
667
+
668
+ [[package]]
669
+ name = "glob"
670
+ version = "0.3.4"
671
+ source = "registry+https://github.com/rust-lang/crates.io-index"
672
+ checksum = "e4eba85ea1d0a966a983acd07deee566e67395d2d96b6fb39e62b5a833f1eb0b"
673
+
674
+ [[package]]
675
+ name = "half"
676
+ version = "2.7.1"
677
+ source = "registry+https://github.com/rust-lang/crates.io-index"
678
+ checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b"
679
+ dependencies = [
680
+ "bytemuck",
681
+ "cfg-if",
682
+ "crunchy",
683
+ "num-traits",
684
+ "rand",
685
+ "rand_distr",
686
+ "zerocopy",
687
+ ]
688
+
689
+ [[package]]
690
+ name = "hashbrown"
691
+ version = "0.16.1"
692
+ source = "registry+https://github.com/rust-lang/crates.io-index"
693
+ checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
694
+ dependencies = [
695
+ "allocator-api2",
696
+ "equivalent",
697
+ "foldhash",
698
+ "serde",
699
+ "serde_core",
700
+ ]
701
+
702
+ [[package]]
703
+ name = "hashbrown"
704
+ version = "0.17.1"
705
+ source = "registry+https://github.com/rust-lang/crates.io-index"
706
+ checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
707
+
708
+ [[package]]
709
+ name = "heck"
710
+ version = "0.5.0"
711
+ source = "registry+https://github.com/rust-lang/crates.io-index"
712
+ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
713
+
714
+ [[package]]
715
+ name = "hermit-abi"
716
+ version = "0.5.3"
717
+ source = "registry+https://github.com/rust-lang/crates.io-index"
718
+ checksum = "e17592d60ebacc7d5e169f4663c5f84f9161cc90328abcfe8456f41e4dfcb284"
719
+
720
+ [[package]]
721
+ name = "ident_case"
722
+ version = "1.0.1"
723
+ source = "registry+https://github.com/rust-lang/crates.io-index"
724
+ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
725
+
726
+ [[package]]
727
+ name = "indexmap"
728
+ version = "2.14.2"
729
+ source = "registry+https://github.com/rust-lang/crates.io-index"
730
+ checksum = "cc4e190f5d26ca7051642629da2c52fc03bde85a03197c99408dcd291734c855"
731
+ dependencies = [
732
+ "equivalent",
733
+ "hashbrown 0.17.1",
734
+ ]
735
+
736
+ [[package]]
737
+ name = "itertools"
738
+ version = "0.14.0"
739
+ source = "registry+https://github.com/rust-lang/crates.io-index"
740
+ checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285"
741
+ dependencies = [
742
+ "either",
743
+ ]
744
+
745
+ [[package]]
746
+ name = "itoa"
747
+ version = "1.0.19"
748
+ source = "registry+https://github.com/rust-lang/crates.io-index"
749
+ checksum = "3bd1574e617a9a6c1f8f8181bd7e841e1f20e4277607ef28945765188d6284d4"
750
+
751
+ [[package]]
752
+ name = "js-sys"
753
+ version = "0.3.107"
754
+ source = "registry+https://github.com/rust-lang/crates.io-index"
755
+ checksum = "8dc09d2154098bbf4ef54eab6b117a3c24cbbffe94046b16ee6d6d4510584d3a"
756
+ dependencies = [
757
+ "cfg-if",
758
+ "wasm-bindgen",
759
+ ]
760
+
761
+ [[package]]
762
+ name = "libc"
763
+ version = "0.2.191"
764
+ source = "registry+https://github.com/rust-lang/crates.io-index"
765
+ checksum = "65cd87c9a6d60536580b316ad985726104730a5151c99845f2490428ef91240a"
766
+
767
+ [[package]]
768
+ name = "libloading"
769
+ version = "0.9.0"
770
+ source = "registry+https://github.com/rust-lang/crates.io-index"
771
+ checksum = "754ca22de805bb5744484a5b151a9e1a8e837d5dc232c2d7d8c2e3492edc8b60"
772
+ dependencies = [
773
+ "cfg-if",
774
+ "windows-link",
775
+ ]
776
+
777
+ [[package]]
778
+ name = "libm"
779
+ version = "0.2.16"
780
+ source = "registry+https://github.com/rust-lang/crates.io-index"
781
+ checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981"
782
+
783
+ [[package]]
784
+ name = "linux-raw-sys"
785
+ version = "0.12.1"
786
+ source = "registry+https://github.com/rust-lang/crates.io-index"
787
+ checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53"
788
+
789
+ [[package]]
790
+ name = "lock_api"
791
+ version = "0.4.14"
792
+ source = "registry+https://github.com/rust-lang/crates.io-index"
793
+ checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
794
+ dependencies = [
795
+ "scopeguard",
796
+ ]
797
+
798
+ [[package]]
799
+ name = "log"
800
+ version = "0.4.35"
801
+ source = "registry+https://github.com/rust-lang/crates.io-index"
802
+ checksum = "5d15f86d12da44cd8d4ec3c73984537eb7f4cadcb9776a575a0a8a05ca11005c"
803
+
804
+ [[package]]
805
+ name = "macro_rules_attribute"
806
+ version = "0.2.3"
807
+ source = "registry+https://github.com/rust-lang/crates.io-index"
808
+ checksum = "b3ae8f6d608c795738406608304d30a2dfbdc8e58e44f7ba43236da5208ded3c"
809
+ dependencies = [
810
+ "macro_rules_attribute-proc_macro",
811
+ "pastey",
812
+ ]
813
+
814
+ [[package]]
815
+ name = "macro_rules_attribute-proc_macro"
816
+ version = "0.2.3"
817
+ source = "registry+https://github.com/rust-lang/crates.io-index"
818
+ checksum = "fc04a4c58212d57930a24bf47d3fa87485264a3a054e9c10e042eb373573ad3c"
819
+
820
+ [[package]]
821
+ name = "memchr"
822
+ version = "2.8.3"
823
+ source = "registry+https://github.com/rust-lang/crates.io-index"
824
+ checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
825
+
826
+ [[package]]
827
+ name = "memmap2"
828
+ version = "0.9.12"
829
+ source = "registry+https://github.com/rust-lang/crates.io-index"
830
+ checksum = "6b0ca1155a9ecc25aa12e8313a119f32edf0255fea2f44839c4ac0a12b2ac157"
831
+ dependencies = [
832
+ "libc",
833
+ "stable_deref_trait",
834
+ ]
835
+
836
+ [[package]]
837
+ name = "minimal-lexical"
838
+ version = "0.2.1"
839
+ source = "registry+https://github.com/rust-lang/crates.io-index"
840
+ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
841
+
842
+ [[package]]
843
+ name = "monostate"
844
+ version = "0.1.18"
845
+ source = "registry+https://github.com/rust-lang/crates.io-index"
846
+ checksum = "3341a273f6c9d5bef1908f17b7267bbab0e95c9bf69a0d4dcf8e9e1b2c76ef67"
847
+ dependencies = [
848
+ "monostate-impl",
849
+ "serde",
850
+ "serde_core",
851
+ ]
852
+
853
+ [[package]]
854
+ name = "monostate-impl"
855
+ version = "0.1.18"
856
+ source = "registry+https://github.com/rust-lang/crates.io-index"
857
+ checksum = "e4db6d5580af57bf992f59068d4ea26fd518574ff48d7639b255a36f9de6e7e9"
858
+ dependencies = [
859
+ "proc-macro2",
860
+ "quote",
861
+ "syn 2.0.119",
862
+ ]
863
+
864
+ [[package]]
865
+ name = "nix"
866
+ version = "0.31.3"
867
+ source = "registry+https://github.com/rust-lang/crates.io-index"
868
+ checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d"
869
+ dependencies = [
870
+ "bitflags",
871
+ "cfg-if",
872
+ "cfg_aliases",
873
+ "libc",
874
+ ]
875
+
876
+ [[package]]
877
+ name = "nom"
878
+ version = "7.1.3"
879
+ source = "registry+https://github.com/rust-lang/crates.io-index"
880
+ checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
881
+ dependencies = [
882
+ "memchr",
883
+ "minimal-lexical",
884
+ ]
885
+
886
+ [[package]]
887
+ name = "num-complex"
888
+ version = "0.4.6"
889
+ source = "registry+https://github.com/rust-lang/crates.io-index"
890
+ checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495"
891
+ dependencies = [
892
+ "bytemuck",
893
+ "num-traits",
894
+ ]
895
+
896
+ [[package]]
897
+ name = "num-traits"
898
+ version = "0.2.19"
899
+ source = "registry+https://github.com/rust-lang/crates.io-index"
900
+ checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
901
+ dependencies = [
902
+ "autocfg",
903
+ "libm",
904
+ ]
905
+
906
+ [[package]]
907
+ name = "num_cpus"
908
+ version = "1.17.0"
909
+ source = "registry+https://github.com/rust-lang/crates.io-index"
910
+ checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b"
911
+ dependencies = [
912
+ "hermit-abi",
913
+ "libc",
914
+ ]
915
+
916
+ [[package]]
917
+ name = "once_cell"
918
+ version = "1.21.4"
919
+ source = "registry+https://github.com/rust-lang/crates.io-index"
920
+ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
921
+
922
+ [[package]]
923
+ name = "parking_lot"
924
+ version = "0.12.5"
925
+ source = "registry+https://github.com/rust-lang/crates.io-index"
926
+ checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a"
927
+ dependencies = [
928
+ "lock_api",
929
+ "parking_lot_core",
930
+ ]
931
+
932
+ [[package]]
933
+ name = "parking_lot_core"
934
+ version = "0.9.12"
935
+ source = "registry+https://github.com/rust-lang/crates.io-index"
936
+ checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1"
937
+ dependencies = [
938
+ "cfg-if",
939
+ "libc",
940
+ "redox_syscall",
941
+ "smallvec",
942
+ "windows-link",
943
+ ]
944
+
945
+ [[package]]
946
+ name = "paste"
947
+ version = "1.0.15"
948
+ source = "registry+https://github.com/rust-lang/crates.io-index"
949
+ checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
950
+
951
+ [[package]]
952
+ name = "pastey"
953
+ version = "0.2.3"
954
+ source = "registry+https://github.com/rust-lang/crates.io-index"
955
+ checksum = "2ee67f1008b1ba2321834326597b8e186293b049a023cdef258527550b9935b4"
956
+
957
+ [[package]]
958
+ name = "ppv-lite86"
959
+ version = "0.2.21"
960
+ source = "registry+https://github.com/rust-lang/crates.io-index"
961
+ checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
962
+ dependencies = [
963
+ "zerocopy",
964
+ ]
965
+
966
+ [[package]]
967
+ name = "proc-macro2"
968
+ version = "1.0.107"
969
+ source = "registry+https://github.com/rust-lang/crates.io-index"
970
+ checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9"
971
+ dependencies = [
972
+ "unicode-ident",
973
+ ]
974
+
975
+ [[package]]
976
+ name = "pulp"
977
+ version = "0.22.3"
978
+ source = "registry+https://github.com/rust-lang/crates.io-index"
979
+ checksum = "046aa45b989642ec2e4717c8e72d677b13edd831a4d3b6cf37d9a3e54912496a"
980
+ dependencies = [
981
+ "bytemuck",
982
+ "cfg-if",
983
+ "libm",
984
+ "num-complex",
985
+ "paste",
986
+ "pulp-wasm-simd-flag",
987
+ "raw-cpuid",
988
+ "reborrow",
989
+ "version_check",
990
+ ]
991
+
992
+ [[package]]
993
+ name = "pulp-wasm-simd-flag"
994
+ version = "0.1.1"
995
+ source = "registry+https://github.com/rust-lang/crates.io-index"
996
+ checksum = "1d8f70e07b9c3962945a74e59ca1c511bba65b6419468acc217c457d93f3c740"
997
+
998
+ [[package]]
999
+ name = "quote"
1000
+ version = "1.0.47"
1001
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1002
+ checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"
1003
+ dependencies = [
1004
+ "proc-macro2",
1005
+ ]
1006
+
1007
+ [[package]]
1008
+ name = "r-efi"
1009
+ version = "5.3.0"
1010
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1011
+ checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
1012
+
1013
+ [[package]]
1014
+ name = "r-efi"
1015
+ version = "6.0.0"
1016
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1017
+ checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
1018
+
1019
+ [[package]]
1020
+ name = "rand"
1021
+ version = "0.9.5"
1022
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1023
+ checksum = "b9ef1d0d795eb7d84685bca4f72f3649f064e6641543d3a8c415898726a57b41"
1024
+ dependencies = [
1025
+ "rand_chacha",
1026
+ "rand_core",
1027
+ ]
1028
+
1029
+ [[package]]
1030
+ name = "rand_chacha"
1031
+ version = "0.9.0"
1032
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1033
+ checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
1034
+ dependencies = [
1035
+ "ppv-lite86",
1036
+ "rand_core",
1037
+ ]
1038
+
1039
+ [[package]]
1040
+ name = "rand_core"
1041
+ version = "0.9.5"
1042
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1043
+ checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c"
1044
+ dependencies = [
1045
+ "getrandom 0.3.4",
1046
+ ]
1047
+
1048
+ [[package]]
1049
+ name = "rand_distr"
1050
+ version = "0.5.1"
1051
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1052
+ checksum = "6a8615d50dcf34fa31f7ab52692afec947c4dd0ab803cc87cb3b0b4570ff7463"
1053
+ dependencies = [
1054
+ "num-traits",
1055
+ "rand",
1056
+ ]
1057
+
1058
+ [[package]]
1059
+ name = "raw-cpuid"
1060
+ version = "11.6.0"
1061
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1062
+ checksum = "498cd0dc59d73224351ee52a95fee0f1a617a2eae0e7d9d720cc622c73a54186"
1063
+ dependencies = [
1064
+ "bitflags",
1065
+ ]
1066
+
1067
+ [[package]]
1068
+ name = "rayon"
1069
+ version = "1.12.0"
1070
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1071
+ checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d"
1072
+ dependencies = [
1073
+ "either",
1074
+ "rayon-core",
1075
+ ]
1076
+
1077
+ [[package]]
1078
+ name = "rayon-cond"
1079
+ version = "0.4.0"
1080
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1081
+ checksum = "2964d0cf57a3e7a06e8183d14a8b527195c706b7983549cd5462d5aa3747438f"
1082
+ dependencies = [
1083
+ "either",
1084
+ "itertools",
1085
+ "rayon",
1086
+ ]
1087
+
1088
+ [[package]]
1089
+ name = "rayon-core"
1090
+ version = "1.13.0"
1091
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1092
+ checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91"
1093
+ dependencies = [
1094
+ "crossbeam-deque",
1095
+ "crossbeam-utils",
1096
+ ]
1097
+
1098
+ [[package]]
1099
+ name = "reborrow"
1100
+ version = "0.5.5"
1101
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1102
+ checksum = "03251193000f4bd3b042892be858ee50e8b3719f2b08e5833ac4353724632430"
1103
+
1104
+ [[package]]
1105
+ name = "redox_syscall"
1106
+ version = "0.5.18"
1107
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1108
+ checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
1109
+ dependencies = [
1110
+ "bitflags",
1111
+ ]
1112
+
1113
+ [[package]]
1114
+ name = "regex"
1115
+ version = "1.13.1"
1116
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1117
+ checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d"
1118
+ dependencies = [
1119
+ "aho-corasick",
1120
+ "memchr",
1121
+ "regex-automata",
1122
+ "regex-syntax",
1123
+ ]
1124
+
1125
+ [[package]]
1126
+ name = "regex-automata"
1127
+ version = "0.4.18"
1128
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1129
+ checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2"
1130
+ dependencies = [
1131
+ "aho-corasick",
1132
+ "memchr",
1133
+ "regex-syntax",
1134
+ ]
1135
+
1136
+ [[package]]
1137
+ name = "regex-syntax"
1138
+ version = "0.8.11"
1139
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1140
+ checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4"
1141
+
1142
+ [[package]]
1143
+ name = "rustix"
1144
+ version = "1.1.6"
1145
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1146
+ checksum = "e5e76742e5294153d4dde1207dbec5bdd81eef6fabdc0d2118babadabfd858aa"
1147
+ dependencies = [
1148
+ "bitflags",
1149
+ "errno",
1150
+ "libc",
1151
+ "linux-raw-sys",
1152
+ "windows-sys",
1153
+ ]
1154
+
1155
+ [[package]]
1156
+ name = "rustversion"
1157
+ version = "1.0.23"
1158
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1159
+ checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f"
1160
+
1161
+ [[package]]
1162
+ name = "ryu"
1163
+ version = "1.0.23"
1164
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1165
+ checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f"
1166
+
1167
+ [[package]]
1168
+ name = "safetensors"
1169
+ version = "0.8.0"
1170
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1171
+ checksum = "79b079b829cb27a1c3c374341345ed2e8b2c0c839034522cee576c140bd7f846"
1172
+ dependencies = [
1173
+ "hashbrown 0.16.1",
1174
+ "libc",
1175
+ "serde",
1176
+ "serde_json",
1177
+ "tempfile",
1178
+ ]
1179
+
1180
+ [[package]]
1181
+ name = "same-file"
1182
+ version = "1.0.6"
1183
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1184
+ checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
1185
+ dependencies = [
1186
+ "winapi-util",
1187
+ ]
1188
+
1189
+ [[package]]
1190
+ name = "scopeguard"
1191
+ version = "1.2.0"
1192
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1193
+ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
1194
+
1195
+ [[package]]
1196
+ name = "seq-macro"
1197
+ version = "0.3.6"
1198
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1199
+ checksum = "1bc711410fbe7399f390ca1c3b60ad0f53f80e95c5eb935e52268a0e2cd49acc"
1200
+
1201
+ [[package]]
1202
+ name = "serde"
1203
+ version = "1.0.229"
1204
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1205
+ checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba"
1206
+ dependencies = [
1207
+ "serde_core",
1208
+ "serde_derive",
1209
+ ]
1210
+
1211
+ [[package]]
1212
+ name = "serde_core"
1213
+ version = "1.0.229"
1214
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1215
+ checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48"
1216
+ dependencies = [
1217
+ "serde_derive",
1218
+ ]
1219
+
1220
+ [[package]]
1221
+ name = "serde_derive"
1222
+ version = "1.0.229"
1223
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1224
+ checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348"
1225
+ dependencies = [
1226
+ "proc-macro2",
1227
+ "quote",
1228
+ "syn 3.0.10",
1229
+ ]
1230
+
1231
+ [[package]]
1232
+ name = "serde_json"
1233
+ version = "1.0.154"
1234
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1235
+ checksum = "e7e9cc8b1b85264074fbcc02a88680c4096b1e47df8f739dceb03bf482f04bd6"
1236
+ dependencies = [
1237
+ "itoa",
1238
+ "memchr",
1239
+ "serde",
1240
+ "serde_core",
1241
+ "zmij",
1242
+ ]
1243
+
1244
+ [[package]]
1245
+ name = "sha2"
1246
+ version = "0.10.9"
1247
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1248
+ checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
1249
+ dependencies = [
1250
+ "cfg-if",
1251
+ "cpufeatures",
1252
+ "digest",
1253
+ ]
1254
+
1255
+ [[package]]
1256
+ name = "smallvec"
1257
+ version = "1.16.5"
1258
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1259
+ checksum = "149309498a5f7334b12ddae0cad8aba81ce785fe91755068867e017cf98fee46"
1260
+
1261
+ [[package]]
1262
+ name = "spm_precompiled"
1263
+ version = "0.1.4"
1264
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1265
+ checksum = "5851699c4033c63636f7ea4cf7b7c1f1bf06d0cc03cfb42e711de5a5c46cf326"
1266
+ dependencies = [
1267
+ "base64",
1268
+ "nom",
1269
+ "serde",
1270
+ "unicode-segmentation",
1271
+ ]
1272
+
1273
+ [[package]]
1274
+ name = "stable_deref_trait"
1275
+ version = "1.2.1"
1276
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1277
+ checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
1278
+
1279
+ [[package]]
1280
+ name = "static_assertions"
1281
+ version = "1.1.0"
1282
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1283
+ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
1284
+
1285
+ [[package]]
1286
+ name = "strsim"
1287
+ version = "0.11.1"
1288
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1289
+ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
1290
+
1291
+ [[package]]
1292
+ name = "syn"
1293
+ version = "2.0.119"
1294
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1295
+ checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297"
1296
+ dependencies = [
1297
+ "proc-macro2",
1298
+ "quote",
1299
+ "unicode-ident",
1300
+ ]
1301
+
1302
+ [[package]]
1303
+ name = "syn"
1304
+ version = "3.0.10"
1305
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1306
+ checksum = "4ae9ccbea3a7b0b09443036490c8f34a8b1b760fd345e5c0dae0aac718faea79"
1307
+ dependencies = [
1308
+ "proc-macro2",
1309
+ "quote",
1310
+ "unicode-ident",
1311
+ ]
1312
+
1313
+ [[package]]
1314
+ name = "synstructure"
1315
+ version = "0.14.0"
1316
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1317
+ checksum = "901704edd0dfe137f1987838ee4f259e4e063c31371bdb423f7ae38ec6f77f02"
1318
+ dependencies = [
1319
+ "proc-macro2",
1320
+ "quote",
1321
+ "syn 3.0.10",
1322
+ ]
1323
+
1324
+ [[package]]
1325
+ name = "sysctl"
1326
+ version = "0.6.0"
1327
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1328
+ checksum = "01198a2debb237c62b6826ec7081082d951f46dbb64b0e8c7649a452230d1dfc"
1329
+ dependencies = [
1330
+ "bitflags",
1331
+ "byteorder",
1332
+ "enum-as-inner",
1333
+ "libc",
1334
+ "thiserror 1.0.69",
1335
+ "walkdir",
1336
+ ]
1337
+
1338
+ [[package]]
1339
+ name = "tempfile"
1340
+ version = "3.27.0"
1341
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1342
+ checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd"
1343
+ dependencies = [
1344
+ "fastrand",
1345
+ "getrandom 0.4.3",
1346
+ "once_cell",
1347
+ "rustix",
1348
+ "windows-sys",
1349
+ ]
1350
+
1351
+ [[package]]
1352
+ name = "thiserror"
1353
+ version = "1.0.69"
1354
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1355
+ checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
1356
+ dependencies = [
1357
+ "thiserror-impl 1.0.69",
1358
+ ]
1359
+
1360
+ [[package]]
1361
+ name = "thiserror"
1362
+ version = "2.0.21"
1363
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1364
+ checksum = "09e52cb86a36cede5cb101bf8908837b3e4c6e5e59fe7fd85c23fb56200d189e"
1365
+ dependencies = [
1366
+ "thiserror-impl 2.0.21",
1367
+ ]
1368
+
1369
+ [[package]]
1370
+ name = "thiserror-impl"
1371
+ version = "1.0.69"
1372
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1373
+ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
1374
+ dependencies = [
1375
+ "proc-macro2",
1376
+ "quote",
1377
+ "syn 2.0.119",
1378
+ ]
1379
+
1380
+ [[package]]
1381
+ name = "thiserror-impl"
1382
+ version = "2.0.21"
1383
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1384
+ checksum = "fe5197923287db20a58125f0bc85c062f7f2c892de97b18c356f9efb14b28524"
1385
+ dependencies = [
1386
+ "proc-macro2",
1387
+ "quote",
1388
+ "syn 3.0.10",
1389
+ ]
1390
+
1391
+ [[package]]
1392
+ name = "tokenizers"
1393
+ version = "0.23.2"
1394
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1395
+ checksum = "7afbf6e88718afcc138bad01d6ccc3051dbbc3b2ce9793d8b8a3aeb610969cfc"
1396
+ dependencies = [
1397
+ "ahash",
1398
+ "compact_str",
1399
+ "daachorse",
1400
+ "dary_heap",
1401
+ "derive_builder",
1402
+ "esaxx-rs",
1403
+ "fancy-regex",
1404
+ "getrandom 0.3.4",
1405
+ "itertools",
1406
+ "log",
1407
+ "macro_rules_attribute",
1408
+ "monostate",
1409
+ "paste",
1410
+ "rand",
1411
+ "rayon",
1412
+ "rayon-cond",
1413
+ "regex",
1414
+ "regex-syntax",
1415
+ "serde",
1416
+ "serde_json",
1417
+ "spm_precompiled",
1418
+ "thiserror 2.0.21",
1419
+ "unicode-normalization-alignments",
1420
+ "unicode-segmentation",
1421
+ "unicode_categories",
1422
+ ]
1423
+
1424
+ [[package]]
1425
+ name = "typed-path"
1426
+ version = "0.13.0"
1427
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1428
+ checksum = "9ce898823d8cd0f028662d2f349694b1af0a5cc9be83f1d213a00d3147445e1e"
1429
+
1430
+ [[package]]
1431
+ name = "typenum"
1432
+ version = "1.20.1"
1433
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1434
+ checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20"
1435
+
1436
+ [[package]]
1437
+ name = "unicode-ident"
1438
+ version = "1.0.27"
1439
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1440
+ checksum = "a2c754d6c33795a1c324727428e5a7dedb5b06195f9890bdbcba760d3e246563"
1441
+
1442
+ [[package]]
1443
+ name = "unicode-normalization-alignments"
1444
+ version = "0.1.12"
1445
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1446
+ checksum = "43f613e4fa046e69818dd287fdc4bc78175ff20331479dab6e1b0f98d57062de"
1447
+ dependencies = [
1448
+ "smallvec",
1449
+ ]
1450
+
1451
+ [[package]]
1452
+ name = "unicode-segmentation"
1453
+ version = "1.13.3"
1454
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1455
+ checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8"
1456
+
1457
+ [[package]]
1458
+ name = "unicode_categories"
1459
+ version = "0.1.1"
1460
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1461
+ checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e"
1462
+
1463
+ [[package]]
1464
+ name = "version_check"
1465
+ version = "0.9.5"
1466
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1467
+ checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
1468
+
1469
+ [[package]]
1470
+ name = "walkdir"
1471
+ version = "2.5.0"
1472
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1473
+ checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
1474
+ dependencies = [
1475
+ "same-file",
1476
+ "winapi-util",
1477
+ ]
1478
+
1479
+ [[package]]
1480
+ name = "wasip2"
1481
+ version = "1.0.4+wasi-0.2.12"
1482
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1483
+ checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487"
1484
+ dependencies = [
1485
+ "wit-bindgen",
1486
+ ]
1487
+
1488
+ [[package]]
1489
+ name = "wasm-bindgen"
1490
+ version = "0.2.130"
1491
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1492
+ checksum = "a0181c14ddd6c7b8b0b0132a5f1ea2f32be0d893cd3ea97b6e3b28886b8a3d1c"
1493
+ dependencies = [
1494
+ "cfg-if",
1495
+ "rustversion",
1496
+ "wasm-bindgen-macro",
1497
+ "wasm-bindgen-shared",
1498
+ ]
1499
+
1500
+ [[package]]
1501
+ name = "wasm-bindgen-macro"
1502
+ version = "0.2.130"
1503
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1504
+ checksum = "6e931a02a39abdbf66966fc35902b5ed58344750a70885bed4ebb3d8eaf28ed9"
1505
+ dependencies = [
1506
+ "quote",
1507
+ "wasm-bindgen-macro-support",
1508
+ ]
1509
+
1510
+ [[package]]
1511
+ name = "wasm-bindgen-macro-support"
1512
+ version = "0.2.130"
1513
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1514
+ checksum = "2ca4b54280e455bd831e33a6b8e734baf432fe63fbc35c42ac14ce67a043a53a"
1515
+ dependencies = [
1516
+ "bumpalo",
1517
+ "proc-macro2",
1518
+ "quote",
1519
+ "syn 3.0.10",
1520
+ "wasm-bindgen-shared",
1521
+ ]
1522
+
1523
+ [[package]]
1524
+ name = "wasm-bindgen-shared"
1525
+ version = "0.2.130"
1526
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1527
+ checksum = "3b1f9c3798725016c6ee5f2f57869ec0831e8bbc0ab0310a86e787e97f41389e"
1528
+ dependencies = [
1529
+ "unicode-ident",
1530
+ ]
1531
+
1532
+ [[package]]
1533
+ name = "which"
1534
+ version = "7.0.3"
1535
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1536
+ checksum = "24d643ce3fd3e5b54854602a080f34fb10ab75e0b813ee32d00ca2b44fa74762"
1537
+ dependencies = [
1538
+ "either",
1539
+ "env_home",
1540
+ "rustix",
1541
+ "winsafe",
1542
+ ]
1543
+
1544
+ [[package]]
1545
+ name = "winapi"
1546
+ version = "0.3.9"
1547
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1548
+ checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
1549
+ dependencies = [
1550
+ "winapi-i686-pc-windows-gnu",
1551
+ "winapi-x86_64-pc-windows-gnu",
1552
+ ]
1553
+
1554
+ [[package]]
1555
+ name = "winapi-i686-pc-windows-gnu"
1556
+ version = "0.4.0"
1557
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1558
+ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
1559
+
1560
+ [[package]]
1561
+ name = "winapi-util"
1562
+ version = "0.1.11"
1563
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1564
+ checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
1565
+ dependencies = [
1566
+ "windows-sys",
1567
+ ]
1568
+
1569
+ [[package]]
1570
+ name = "winapi-x86_64-pc-windows-gnu"
1571
+ version = "0.4.0"
1572
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1573
+ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
1574
+
1575
+ [[package]]
1576
+ name = "windows-link"
1577
+ version = "0.2.1"
1578
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1579
+ checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
1580
+
1581
+ [[package]]
1582
+ name = "windows-sys"
1583
+ version = "0.61.2"
1584
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1585
+ checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
1586
+ dependencies = [
1587
+ "windows-link",
1588
+ ]
1589
+
1590
+ [[package]]
1591
+ name = "winsafe"
1592
+ version = "0.0.19"
1593
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1594
+ checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904"
1595
+
1596
+ [[package]]
1597
+ name = "wit-bindgen"
1598
+ version = "0.57.1"
1599
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1600
+ checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e"
1601
+
1602
+ [[package]]
1603
+ name = "yoke"
1604
+ version = "0.8.4"
1605
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1606
+ checksum = "417ef3fcf6c300b7dbd25c85531a746931c02ad536f3cf4786ed1e88223340b3"
1607
+ dependencies = [
1608
+ "stable_deref_trait",
1609
+ "yoke-derive",
1610
+ "zerofrom",
1611
+ ]
1612
+
1613
+ [[package]]
1614
+ name = "yoke-derive"
1615
+ version = "0.8.4"
1616
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1617
+ checksum = "ec8ebde2db3681e8c9980cc27822030e68752690ddfa9473e739aeb4dbde6d71"
1618
+ dependencies = [
1619
+ "proc-macro2",
1620
+ "quote",
1621
+ "syn 3.0.10",
1622
+ "synstructure",
1623
+ ]
1624
+
1625
+ [[package]]
1626
+ name = "zerocopy"
1627
+ version = "0.8.63"
1628
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1629
+ checksum = "e5fe1f8f1b06191a00962174c61aa5005e0bb391a6d80d07e24d115c01a92ed8"
1630
+ dependencies = [
1631
+ "zerocopy-derive",
1632
+ ]
1633
+
1634
+ [[package]]
1635
+ name = "zerocopy-derive"
1636
+ version = "0.8.63"
1637
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1638
+ checksum = "863ad3ac83293fb4d740aedbfdc9240dd8d1a50c1099acd76ce80ce7c7230c7f"
1639
+ dependencies = [
1640
+ "proc-macro2",
1641
+ "quote",
1642
+ "syn 2.0.119",
1643
+ ]
1644
+
1645
+ [[package]]
1646
+ name = "zerofrom"
1647
+ version = "0.1.8"
1648
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1649
+ checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272"
1650
+ dependencies = [
1651
+ "zerofrom-derive",
1652
+ ]
1653
+
1654
+ [[package]]
1655
+ name = "zerofrom-derive"
1656
+ version = "0.1.8"
1657
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1658
+ checksum = "f75b4683f6c7f45248d4d64056a24298c6281e0993356d7d1b4a1a962ef10d4a"
1659
+ dependencies = [
1660
+ "proc-macro2",
1661
+ "quote",
1662
+ "syn 3.0.10",
1663
+ "synstructure",
1664
+ ]
1665
+
1666
+ [[package]]
1667
+ name = "zeroize"
1668
+ version = "1.9.1"
1669
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1670
+ checksum = "e13084392c5e4bc371903e2935a5eaeed24905a7511356b883835e18a78f6879"
1671
+ dependencies = [
1672
+ "zeroize_derive",
1673
+ ]
1674
+
1675
+ [[package]]
1676
+ name = "zeroize_derive"
1677
+ version = "1.5.0"
1678
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1679
+ checksum = "3c50655cbb0fe3fc43170059e702f1ce5e19b84cec58dc87b037a09935c2f328"
1680
+ dependencies = [
1681
+ "proc-macro2",
1682
+ "quote",
1683
+ "syn 2.0.119",
1684
+ ]
1685
+
1686
+ [[package]]
1687
+ name = "zip"
1688
+ version = "9.5.1"
1689
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1690
+ checksum = "e3476fd497ac8af5b1ec7b51acab7bef380f7e8dd8e0487595bafd839417a302"
1691
+ dependencies = [
1692
+ "constant_time_eq",
1693
+ "crc32fast",
1694
+ "getrandom 0.4.3",
1695
+ "indexmap",
1696
+ "libc",
1697
+ "memchr",
1698
+ "nix",
1699
+ "typed-path",
1700
+ "windows-sys",
1701
+ "zeroize",
1702
+ ]
1703
+
1704
+ [[package]]
1705
+ name = "zmij"
1706
+ version = "1.0.23"
1707
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1708
+ checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b"
Cargo.toml ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [package]
2
+ name = "falcon_h1_rust"
3
+ version = "0.2.0"
4
+ edition = "2021"
5
+ license = "MIT"
6
+ description = "Falcon-H1 Mamba-2 + attention CPU/CUDA inference HTTP API"
7
+
8
+ [features]
9
+ default = []
10
+ candle = ["dep:candle-core", "dep:candle-nn"]
11
+ cuda = ["candle", "candle-core/cuda", "candle-nn/cuda"]
12
+
13
+ [dependencies]
14
+ candle-core = { version = "=0.11.1", optional = true }
15
+ candle-nn = { version = "=0.11.1", optional = true }
16
+
17
+ [lib]
18
+ name = "falcon_h1_rust"
19
+ path = "src/lib.rs"
20
+
21
+ [[bin]]
22
+ name = "falcon-h1-api"
23
+ path = "src/main.rs"
LICENSE ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Falcon-H1-0.5B-Rust
2
+
3
+ The pretrained weights originate from tiiuae/Falcon-H1-0.5B-Instruct.
4
+
5
+ They remain subject to the Falcon-LLM License.
6
+ Official terms:
7
+ https://falconllm.tii.ae/falcon-terms-and-conditions.html
8
+
9
+ Falcon-H1-0.5B-Rust is built using Falcon LLM technology from the Technology Innovation Institute.
10
+
11
+ This notice does not replace the full license terms.
README.md ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: other
3
+ license_name: falcon-llm-license
4
+ license_link: https://falconllm.tii.ae/falcon-terms-and-conditions.html
5
+ base_model: tiiuae/Falcon-H1-0.5B-Instruct
6
+ tags:
7
+ - rust
8
+ - cuda
9
+ - candle
10
+ - mamba2
11
+ - falcon-h1
12
+ - text-generation
13
+ ---
14
+
15
+ # Falcon-H1-0.5B — Rust CUDA Transformer
16
+
17
+ A Rust implementation of the pretrained Falcon-H1-0.5B-Instruct model.
18
+
19
+ ## Architecture
20
+
21
+ The implementation reproduces Falcon-H1's hybrid architecture:
22
+
23
+ - Parallel Mamba-2 and attention
24
+ - Grouped-query attention
25
+ - Rotary positional embeddings
26
+ - RMSNorm
27
+ - SwiGLU feed-forward networks
28
+ - Original model dimensions and parameters
29
+
30
+ Implemented using Rust and Hugging Face Candle.
31
+
32
+ ## Pretrained Weights
33
+
34
+ The checkpoint contains converted FP32 weights from:
35
+
36
+ https://huggingface.co/tiiuae/Falcon-H1-0.5B-Instruct
37
+
38
+ No additional training or fine-tuning was performed.
39
+
40
+ The checkpoint uses a custom .f32pack format.
41
+ It is not directly loadable using Transformers.from_pretrained.
42
+
43
+ ## GPU Validation
44
+
45
+ Tested on NVIDIA Tesla T4 using Google Colab.
46
+
47
+ Compared against the original Hugging Face implementation.
48
+
49
+ - Maximum absolute logit error: 7.0522e-5
50
+ - Mean absolute logit error: 1.4631e-5
51
+ - Identical top-5 token predictions
52
+
53
+ Validation used the three-token input [1, 2, 3].
54
+
55
+ ## Build
56
+
57
+ Install Rust and CUDA, then execute:
58
+
59
+ cargo build --release --features cuda
60
+
61
+ ## Start HTTP API
62
+
63
+ ./target/release/falcon-h1-api --checkpoint falcon-h1.f32pack --device cuda
64
+
65
+ ## API Endpoints
66
+
67
+ - GET /health
68
+ - GET /v1/model
69
+ - POST /v1/logits
70
+ - POST /v1/generate
71
+
72
+ The current API accepts token IDs.
73
+
74
+ ## CPU Support
75
+
76
+ The architecture also supports CPU execution.
77
+
78
+ ## Attribution
79
+
80
+ Original pretrained model: Technology Innovation Institute (TII).
81
+
82
+ Original model weights are governed by the Falcon-LLM License.
83
+
84
+ See the original model repository for licensing conditions.
85
+
86
+ ## Implementation Status
87
+
88
+ - Rust implementation: completed
89
+ - CUDA inference: validated on T4
90
+ - Numerical agreement: verified for a three-token input
91
+ - HTTP inference API: implemented
92
+ - Knowledge distillation: not yet implemented
93
+ - GPU training optimization: pending
chat_template.jinja ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {{bos_token}}
2
+ {%- if tools %}
3
+ {{- '<|im_start|>system\n' }}
4
+ {%- if messages[0].role == 'system' %}
5
+ {{- messages[0].content + '\n\n' }}
6
+ {%- endif %}
7
+ {{- "You are a function calling AI model. You are provided with function signature within <tools> </tools> XML tags. You may call one or more functions to assist with the user query. Don't make assumptions about what values to plug into functions.\n<tools>\n" }}
8
+ {%- for tool in tools %}[{{- tool | tojson }}]{%- endfor %}
9
+ {{- "\n</tools>\nFor each function call, return a json object with function name and arguments within <tool_call> </tool_call> tags with the following schema:\n<tool_call>\n{'arguments': <args-dict>, 'name': <function-name>}\n</tool_call>\n" }}
10
+ {%- else %}
11
+ {%- if messages[0].role == 'system' %}
12
+ {{- '<|im_start|>system\n' + messages[0].content + '<|im_end|>\n' }}
13
+ {%- endif %}
14
+ {%- endif %}{% for message in messages %}{%- if message.role != 'system' %}{{'<|im_start|>' + message['role'] + '
15
+ ' + message['content'] + '<|im_end|>' + '
16
+ '}}{%- endif %}{% endfor %}{% if add_generation_prompt %}{{ '<|im_start|>assistant
17
+ ' }}{% endif %}
config.json ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "FalconH1ForCausalLM"
4
+ ],
5
+ "attention_bias": false,
6
+ "attention_dropout": 0.0,
7
+ "attention_in_multiplier": 1.0,
8
+ "attention_out_multiplier": 0.9375,
9
+ "attn_layer_indices": null,
10
+ "bos_token_id": 1,
11
+ "embedding_multiplier": 5.656854249492381,
12
+ "eos_token_id": 11,
13
+ "head_dim": 64,
14
+ "hidden_act": "silu",
15
+ "hidden_size": 1024,
16
+ "initializer_range": 0.02,
17
+ "intermediate_size": 2048,
18
+ "key_multiplier": 0.39062499999999994,
19
+ "lm_head_multiplier": 0.0390625,
20
+ "mamba_chunk_size": 128,
21
+ "mamba_conv_bias": true,
22
+ "mamba_d_conv": 4,
23
+ "mamba_d_head": 64,
24
+ "mamba_d_ssm": 1536,
25
+ "mamba_d_state": 128,
26
+ "mamba_expand": 2,
27
+ "mamba_n_groups": 1,
28
+ "mamba_n_heads": 24,
29
+ "mamba_norm_before_gate": false,
30
+ "mamba_proj_bias": false,
31
+ "mamba_rms_norm": false,
32
+ "mamba_use_mlp": true,
33
+ "max_position_embeddings": 16384,
34
+ "mlp_bias": false,
35
+ "mlp_expansion_factor": 8,
36
+ "mlp_multipliers": [
37
+ 0.8838834764831844,
38
+ 0.5859375
39
+ ],
40
+ "model_type": "falcon_h1",
41
+ "num_attention_heads": 8,
42
+ "num_hidden_layers": 36,
43
+ "num_key_value_heads": 2,
44
+ "num_logits_to_keep": 1,
45
+ "pad_token_id": 0,
46
+ "projectors_bias": false,
47
+ "rms_norm_eps": 1e-05,
48
+ "rope_scaling": null,
49
+ "rope_theta": 100000000000.0,
50
+ "ssm_in_multiplier": 1.25,
51
+ "ssm_multipliers": [
52
+ 0.3535533905932738,
53
+ 0.25,
54
+ 0.3535533905932738,
55
+ 0.5,
56
+ 0.3535533905932738
57
+ ],
58
+ "ssm_out_multiplier": 0.23570226039551587,
59
+ "tie_word_embeddings": false,
60
+ "torch_dtype": "bfloat16",
61
+ "transformers_version": "4.52.0.dev0",
62
+ "use_cache": true,
63
+ "vocab_size": 32784
64
+ }
falcon-h1.f32pack ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:0c349f92fcb98961241788891f15b7d30d7fadc85bf2de818804ca9b41eb6d14
3
+ size 2085671072
generation_config.json ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ {
2
+ "_from_model_config": true,
3
+ "bos_token_id": 1,
4
+ "eos_token_id": [11, 228],
5
+ "pad_token_id": 0,
6
+ "transformers_version": "4.52.0.dev0"
7
+ }
special_tokens_map.json ADDED
@@ -0,0 +1,356 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "additional_special_tokens": [
3
+ "<|pad|>",
4
+ ">>ABSTRACT<<",
5
+ ">>INTRODUCTION<<",
6
+ ">>SUMMARY<<",
7
+ ">>COMMENT<<",
8
+ ">>ANSWER<<",
9
+ ">>QUESTION<<",
10
+ ">>DOMAIN<<",
11
+ ">>PREFIX<<",
12
+ ">>SUFFIX<<",
13
+ ">>MIDDLE<<",
14
+ "<|finetune_right_pad_id|>",
15
+ "<|start_header_id|>",
16
+ "<|end_header_id|>",
17
+ "<|eom_id|>",
18
+ "<|eot_id|>",
19
+ "<|begin_of_text|>",
20
+ ">>TITLE<<",
21
+ "<tool_response>",
22
+ "</tool_response>",
23
+ "<tool_call>",
24
+ "</tool_call>",
25
+ "<schema>",
26
+ "</schema>",
27
+ "<scratch_pad>",
28
+ "</scratch_pad>",
29
+ "<thinking>",
30
+ "</thinking>",
31
+ "<explanation>",
32
+ "</explanation>",
33
+ "<file_sep>",
34
+ "<repo_name>",
35
+ "<|im_end|>",
36
+ "<|im_start|>",
37
+ ">>UNUSED_119<<",
38
+ ">>UNUSED_120<<",
39
+ "<|system|>",
40
+ ">>UNUSED_218<<",
41
+ ">>UNUSED_219<<",
42
+ ">>UNUSED_220<<",
43
+ ">>UNUSED_221<<",
44
+ ">>UNUSED_222<<",
45
+ ">>UNUSED_223<<",
46
+ ">>UNUSED_224<<",
47
+ ">>UNUSED_225<<",
48
+ ">>UNUSED_226<<",
49
+ ">>UNUSED_227<<",
50
+ ">>UNUSED_228<<",
51
+ ">>UNUSED_229<<",
52
+ ">>UNUSED_230<<",
53
+ ">>UNUSED_231<<",
54
+ ">>UNUSED_232<<",
55
+ ">>UNUSED_233<<",
56
+ ">>UNUSED_234<<",
57
+ ">>UNUSED_235<<",
58
+ ">>UNUSED_236<<",
59
+ ">>UNUSED_237<<",
60
+ ">>UNUSED_238<<",
61
+ ">>UNUSED_239<<",
62
+ ">>UNUSED_240<<",
63
+ ">>UNUSED_241<<",
64
+ ">>UNUSED_242<<",
65
+ ">>UNUSED_243<<",
66
+ ">>UNUSED_244<<",
67
+ ">>UNUSED_245<<",
68
+ ">>UNUSED_246<<",
69
+ ">>UNUSED_247<<",
70
+ ">>UNUSED_248<<",
71
+ ">>UNUSED_249<<",
72
+ ">>UNUSED_250<<",
73
+ ">>UNUSED_251<<",
74
+ ">>UNUSED_252<<",
75
+ ">>UNUSED_253<<",
76
+ ">>UNUSED_254<<",
77
+ ">>UNUSED_255<<",
78
+ ">>UNUSED_256<<",
79
+ ">>UNUSED_257<<",
80
+ ">>UNUSED_258<<",
81
+ ">>UNUSED_259<<",
82
+ ">>UNUSED_260<<",
83
+ ">>UNUSED_261<<",
84
+ ">>UNUSED_262<<",
85
+ ">>UNUSED_263<<",
86
+ ">>UNUSED_264<<",
87
+ ">>UNUSED_265<<",
88
+ ">>UNUSED_266<<",
89
+ ">>UNUSED_267<<",
90
+ ">>UNUSED_268<<",
91
+ ">>UNUSED_269<<",
92
+ ">>UNUSED_270<<",
93
+ ">>UNUSED_271<<",
94
+ ">>UNUSED_272<<",
95
+ ">>UNUSED_273<<",
96
+ ">>UNUSED_274<<",
97
+ ">>UNUSED_275<<",
98
+ ">>UNUSED_276<<",
99
+ ">>UNUSED_277<<",
100
+ ">>UNUSED_278<<",
101
+ ">>UNUSED_279<<",
102
+ ">>UNUSED_280<<",
103
+ ">>UNUSED_281<<",
104
+ ">>UNUSED_282<<",
105
+ ">>UNUSED_283<<",
106
+ ">>UNUSED_284<<",
107
+ ">>UNUSED_285<<",
108
+ ">>UNUSED_286<<",
109
+ ">>UNUSED_287<<",
110
+ ">>UNUSED_288<<",
111
+ ">>UNUSED_289<<",
112
+ ">>UNUSED_290<<",
113
+ ">>UNUSED_291<<",
114
+ ">>UNUSED_292<<",
115
+ ">>UNUSED_293<<",
116
+ ">>UNUSED_294<<",
117
+ ">>UNUSED_295<<",
118
+ ">>UNUSED_296<<",
119
+ ">>UNUSED_297<<",
120
+ ">>UNUSED_298<<",
121
+ ">>UNUSED_299<<",
122
+ ">>UNUSED_300<<",
123
+ ">>UNUSED_301<<",
124
+ ">>UNUSED_302<<",
125
+ ">>UNUSED_303<<",
126
+ ">>UNUSED_304<<",
127
+ ">>UNUSED_305<<",
128
+ ">>UNUSED_306<<",
129
+ ">>UNUSED_307<<",
130
+ ">>UNUSED_308<<",
131
+ ">>UNUSED_309<<",
132
+ ">>UNUSED_310<<",
133
+ ">>UNUSED_311<<",
134
+ ">>UNUSED_312<<",
135
+ ">>UNUSED_313<<",
136
+ ">>UNUSED_314<<",
137
+ ">>UNUSED_315<<",
138
+ ">>UNUSED_316<<",
139
+ ">>UNUSED_317<<",
140
+ ">>UNUSED_318<<",
141
+ ">>UNUSED_319<<",
142
+ ">>UNUSED_320<<",
143
+ ">>UNUSED_321<<",
144
+ ">>UNUSED_322<<",
145
+ ">>UNUSED_323<<",
146
+ ">>UNUSED_324<<",
147
+ ">>UNUSED_325<<",
148
+ ">>UNUSED_326<<",
149
+ ">>UNUSED_327<<",
150
+ ">>UNUSED_328<<",
151
+ ">>UNUSED_329<<",
152
+ ">>UNUSED_330<<",
153
+ ">>UNUSED_331<<",
154
+ ">>UNUSED_332<<",
155
+ ">>UNUSED_333<<",
156
+ ">>UNUSED_334<<",
157
+ ">>UNUSED_335<<",
158
+ ">>UNUSED_336<<",
159
+ ">>UNUSED_337<<",
160
+ ">>UNUSED_338<<",
161
+ ">>UNUSED_339<<",
162
+ ">>UNUSED_340<<",
163
+ ">>UNUSED_341<<",
164
+ ">>UNUSED_342<<",
165
+ ">>UNUSED_343<<",
166
+ ">>UNUSED_344<<",
167
+ ">>UNUSED_345<<",
168
+ ">>UNUSED_346<<",
169
+ ">>UNUSED_347<<",
170
+ ">>UNUSED_348<<",
171
+ ">>UNUSED_349<<",
172
+ ">>UNUSED_350<<",
173
+ ">>UNUSED_351<<",
174
+ ">>UNUSED_352<<",
175
+ ">>UNUSED_353<<",
176
+ ">>UNUSED_354<<",
177
+ ">>UNUSED_355<<",
178
+ ">>UNUSED_356<<",
179
+ ">>UNUSED_357<<",
180
+ ">>UNUSED_358<<",
181
+ ">>UNUSED_359<<",
182
+ ">>UNUSED_360<<",
183
+ ">>UNUSED_361<<",
184
+ ">>UNUSED_362<<",
185
+ ">>UNUSED_363<<",
186
+ ">>UNUSED_364<<",
187
+ ">>UNUSED_365<<",
188
+ ">>UNUSED_366<<",
189
+ ">>UNUSED_367<<",
190
+ ">>UNUSED_368<<",
191
+ ">>UNUSED_369<<",
192
+ ">>UNUSED_370<<",
193
+ ">>UNUSED_371<<",
194
+ ">>UNUSED_372<<",
195
+ ">>UNUSED_373<<",
196
+ ">>UNUSED_374<<",
197
+ ">>UNUSED_375<<",
198
+ ">>UNUSED_376<<",
199
+ ">>UNUSED_377<<",
200
+ ">>UNUSED_378<<",
201
+ ">>UNUSED_379<<",
202
+ ">>UNUSED_380<<",
203
+ ">>UNUSED_381<<",
204
+ ">>UNUSED_382<<",
205
+ ">>UNUSED_383<<",
206
+ ">>UNUSED_384<<",
207
+ ">>UNUSED_385<<",
208
+ ">>UNUSED_386<<",
209
+ ">>UNUSED_387<<",
210
+ ">>UNUSED_388<<",
211
+ ">>UNUSED_389<<",
212
+ ">>UNUSED_390<<",
213
+ ">>UNUSED_391<<",
214
+ ">>UNUSED_392<<",
215
+ ">>UNUSED_393<<",
216
+ ">>UNUSED_394<<",
217
+ ">>UNUSED_395<<",
218
+ ">>UNUSED_396<<",
219
+ ">>UNUSED_397<<",
220
+ ">>UNUSED_398<<",
221
+ ">>UNUSED_399<<",
222
+ ">>UNUSED_400<<",
223
+ ">>UNUSED_401<<",
224
+ ">>UNUSED_402<<",
225
+ ">>UNUSED_403<<",
226
+ ">>UNUSED_404<<",
227
+ ">>UNUSED_405<<",
228
+ ">>UNUSED_406<<",
229
+ ">>UNUSED_407<<",
230
+ ">>UNUSED_408<<",
231
+ ">>UNUSED_409<<",
232
+ ">>UNUSED_410<<",
233
+ ">>UNUSED_411<<",
234
+ ">>UNUSED_412<<",
235
+ ">>UNUSED_413<<",
236
+ ">>UNUSED_414<<",
237
+ ">>UNUSED_415<<",
238
+ ">>UNUSED_416<<",
239
+ ">>UNUSED_417<<",
240
+ ">>UNUSED_418<<",
241
+ ">>UNUSED_419<<",
242
+ ">>UNUSED_420<<",
243
+ ">>UNUSED_421<<",
244
+ ">>UNUSED_422<<",
245
+ ">>UNUSED_423<<",
246
+ ">>UNUSED_424<<",
247
+ ">>UNUSED_425<<",
248
+ ">>UNUSED_426<<",
249
+ ">>UNUSED_427<<",
250
+ ">>UNUSED_428<<",
251
+ ">>UNUSED_429<<",
252
+ ">>UNUSED_430<<",
253
+ ">>UNUSED_431<<",
254
+ ">>UNUSED_432<<",
255
+ ">>UNUSED_433<<",
256
+ ">>UNUSED_434<<",
257
+ ">>UNUSED_435<<",
258
+ ">>UNUSED_436<<",
259
+ ">>UNUSED_437<<",
260
+ ">>UNUSED_438<<",
261
+ ">>UNUSED_439<<",
262
+ ">>UNUSED_440<<",
263
+ ">>UNUSED_441<<",
264
+ ">>UNUSED_442<<",
265
+ ">>UNUSED_443<<",
266
+ ">>UNUSED_444<<",
267
+ ">>UNUSED_445<<",
268
+ ">>UNUSED_446<<",
269
+ ">>UNUSED_447<<",
270
+ ">>UNUSED_448<<",
271
+ ">>UNUSED_449<<",
272
+ ">>UNUSED_450<<",
273
+ ">>UNUSED_451<<",
274
+ ">>UNUSED_452<<",
275
+ ">>UNUSED_453<<",
276
+ ">>UNUSED_454<<",
277
+ ">>UNUSED_455<<",
278
+ ">>UNUSED_456<<",
279
+ ">>UNUSED_457<<",
280
+ ">>UNUSED_458<<",
281
+ ">>UNUSED_459<<",
282
+ ">>UNUSED_460<<",
283
+ ">>UNUSED_461<<",
284
+ ">>UNUSED_462<<",
285
+ ">>UNUSED_463<<",
286
+ ">>UNUSED_464<<",
287
+ ">>UNUSED_465<<",
288
+ ">>UNUSED_466<<",
289
+ ">>UNUSED_467<<",
290
+ ">>UNUSED_468<<",
291
+ ">>UNUSED_469<<",
292
+ ">>UNUSED_470<<",
293
+ ">>UNUSED_471<<",
294
+ ">>UNUSED_472<<",
295
+ ">>UNUSED_473<<",
296
+ ">>UNUSED_474<<",
297
+ ">>UNUSED_475<<",
298
+ ">>UNUSED_476<<",
299
+ ">>UNUSED_477<<",
300
+ ">>UNUSED_478<<",
301
+ ">>UNUSED_479<<",
302
+ ">>UNUSED_480<<",
303
+ ">>UNUSED_481<<",
304
+ ">>UNUSED_482<<",
305
+ ">>UNUSED_483<<",
306
+ ">>UNUSED_484<<",
307
+ ">>UNUSED_485<<",
308
+ ">>UNUSED_486<<",
309
+ ">>UNUSED_487<<",
310
+ ">>UNUSED_488<<",
311
+ ">>UNUSED_489<<",
312
+ ">>UNUSED_490<<",
313
+ ">>UNUSED_491<<",
314
+ ">>UNUSED_492<<",
315
+ ">>UNUSED_493<<",
316
+ ">>UNUSED_494<<",
317
+ ">>UNUSED_495<<",
318
+ ">>UNUSED_496<<",
319
+ ">>UNUSED_497<<",
320
+ ">>UNUSED_498<<",
321
+ ">>UNUSED_499<<",
322
+ ">>UNUSED_500<<",
323
+ ">>UNUSED_501<<",
324
+ ">>UNUSED_502<<",
325
+ ">>UNUSED_503<<",
326
+ ">>UNUSED_504<<",
327
+ ">>UNUSED_505<<",
328
+ ">>UNUSED_506<<",
329
+ ">>UNUSED_507<<",
330
+ ">>UNUSED_508<<",
331
+ ">>UNUSED_509<<",
332
+ ">>UNUSED_510<<",
333
+ ">>UNUSED_511<<"
334
+ ],
335
+ "bos_token": {
336
+ "content": "<|begin_of_text|>",
337
+ "lstrip": false,
338
+ "normalized": false,
339
+ "rstrip": false,
340
+ "single_word": false
341
+ },
342
+ "eos_token": {
343
+ "content": "<|end_of_text|>",
344
+ "lstrip": false,
345
+ "normalized": false,
346
+ "rstrip": false,
347
+ "single_word": false
348
+ },
349
+ "pad_token": {
350
+ "content": "<pad>",
351
+ "lstrip": false,
352
+ "normalized": false,
353
+ "rstrip": false,
354
+ "single_word": false
355
+ }
356
+ }
src/candle_backend.rs ADDED
@@ -0,0 +1,229 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //! CUDA-capable Candle tensor implementation of Falcon-H1 inference.
2
+ //! All projection, convolution, attention, and Mamba recurrence tensors remain
3
+ //! on the selected device. Only input token IDs and final logits cross to CPU.
4
+ //! The Mamba scan is a reference *sequential* scan (not fused SSD CUDA kernel).
5
+ //! This backend is for INFERENCE; distillation/training is not implemented here.
6
+ use std::collections::HashMap;
7
+ use candle_core::{DType, Device, Result, Tensor as CTensor};
8
+ use candle_nn::ops;
9
+ use crate::{validate_weights, Config, Weights};
10
+
11
+ pub struct CandleModel {
12
+ pub config: Config,
13
+ pub device: Device,
14
+ weights: HashMap<String, CTensor>,
15
+ group_index: CTensor,
16
+ mup: CTensor,
17
+ }
18
+
19
+ impl CandleModel {
20
+ pub fn new(config: Config, weights: Weights, device: Device) -> std::result::Result<Self, String> {
21
+ validate_weights(&config, &weights)?;
22
+ let mut mapped = HashMap::with_capacity(weights.len());
23
+ for (name, w) in weights {
24
+ let is_linear = w.shape.len()==2 && name.ends_with(".weight")
25
+ && name!="model.embed_tokens.weight";
26
+ let t = if is_linear {
27
+ let (rows,cols)=(w.shape[0],w.shape[1]);
28
+ let mut transposed=vec![0f32;rows*cols];
29
+ for row in 0..rows {for col in 0..cols {
30
+ transposed[col*rows+row]=w.data[row*cols+col];
31
+ }}
32
+ CTensor::from_vec(transposed,(cols,rows),&device)
33
+ } else {
34
+ CTensor::from_vec(w.data,w.shape,&device)
35
+ }.map_err(|e|format!("{name}: {e}"))?;
36
+ mapped.insert(name, t);
37
+ }
38
+ let p = config.mamba_dim * 2 + 2 * config.groups * config.state + config.mamba_heads;
39
+ let parts = [config.mamba_dim, config.mamba_dim,
40
+ config.groups*config.state, config.groups*config.state, config.mamba_heads];
41
+ let mut scale = Vec::with_capacity(p);
42
+ for (len, factor) in parts.into_iter().zip(config.ssm_multipliers) {
43
+ scale.extend(std::iter::repeat(config.ssm_in_multiplier * factor).take(len));
44
+ }
45
+ let mup = CTensor::from_vec(scale, (1, p), &device).map_err(|e|e.to_string())?;
46
+ let ids = (0..config.mamba_heads)
47
+ .map(|h| (h/(config.mamba_heads/config.groups)) as u32).collect::<Vec<_>>();
48
+ let group_index= CTensor::from_vec(ids, config.mamba_heads, &device).map_err(|e|e.to_string())?;
49
+ Ok(Self { config, device, weights:mapped, group_index, mup })
50
+ }
51
+ pub fn device_name(&self) -> &'static str {
52
+ match self.device { Device::Cuda(_) => "cuda", Device::Cpu => "cpu-candle", Device::Metal(_) => "metal" }
53
+ }
54
+ fn w(&self, name: &str) -> &CTensor { &self.weights[name] }
55
+ fn linear(&self, x: &CTensor, name: &str) -> Result<CTensor> {
56
+ x.matmul(self.w(name))
57
+ }
58
+ fn norm(&self, x: &CTensor, name: &str) -> Result<CTensor> {
59
+ let denom = x.sqr()?.mean_keepdim(1)?.affine(1., self.config.eps as f64)?.sqrt()?;
60
+ x.broadcast_div(&denom)?.broadcast_mul(self.w(name))
61
+ }
62
+ fn rope(&self, input: &CTensor, n:usize, heads:usize, cos:&CTensor, sin:&CTensor)->Result<CTensor> {
63
+ let hd=self.config.head_dim;
64
+ let x=input.reshape((n,heads,hd))?;
65
+ let a=x.narrow(2,0,hd/2)?;
66
+ let b=x.narrow(2,hd/2,hd/2)?;
67
+ let real=a.broadcast_mul(cos)?.broadcast_sub(&b.broadcast_mul(sin)?)?;
68
+ let imag=b.broadcast_mul(cos)?.broadcast_add(&a.broadcast_mul(sin)?)?;
69
+ CTensor::cat(&[real,imag],2)
70
+ }
71
+ fn rope_tables(&self,n:usize)->Result<(CTensor,CTensor)>{
72
+ let hd=self.config.head_dim;
73
+ let mut cs=Vec::with_capacity(n*hd/2);
74
+ let mut sn=Vec::with_capacity(n*hd/2);
75
+ for t in 0..n { for j in 0..hd/2 {
76
+ let a=(t as f32)/self.config.rope_theta.powf((2*j) as f32/hd as f32);
77
+ let (s,c)=a.sin_cos();cs.push(c);sn.push(s);
78
+ }}
79
+ Ok((CTensor::from_vec(cs,(n,1,hd/2),&self.device)?,
80
+ CTensor::from_vec(sn,(n,1,hd/2),&self.device)?))
81
+ }
82
+ fn attention(&self, x:&CTensor, prefix:&str, n:usize,
83
+ cos:&CTensor, sin:&CTensor, mask:&CTensor)->Result<CTensor>{
84
+ let c=&self.config;
85
+ let a=x.affine(c.attention_in_multiplier as f64,0.)?;
86
+ let q=self.linear(&a,&format!("{prefix}self_attn.q_proj.weight"))?;
87
+ let k=self.linear(&a,&format!("{prefix}self_attn.k_proj.weight"))?
88
+ .affine(c.key_multiplier as f64,0.)?;
89
+ let v=self.linear(&a,&format!("{prefix}self_attn.v_proj.weight"))?;
90
+ let q=self.rope(&q,n,c.heads,cos,sin)?;
91
+ let k=self.rope(&k,n,c.kv_heads,cos,sin)?;
92
+ let v=v.reshape((n,c.kv_heads,c.head_dim))?;
93
+ let mut heads=Vec::with_capacity(c.heads);
94
+ for h in 0..c.heads {
95
+ let kv=h/(c.heads/c.kv_heads);
96
+ let qi=q.narrow(1,h,1)?.squeeze(1)?.contiguous()?;
97
+ let ki=k.narrow(1,kv,1)?.squeeze(1)?.contiguous()?;
98
+ let vi=v.narrow(1,kv,1)?.squeeze(1)?.contiguous()?;
99
+ let scores=qi.matmul(&ki.t()?.contiguous()?)?
100
+ .affine(1.0/(c.head_dim as f64).sqrt(),0.)?
101
+ .broadcast_add(mask)?;
102
+ let probs=ops::softmax(&scores,1)?;
103
+ heads.push(probs.matmul(&vi)?);
104
+ }
105
+ // Each head is [time,head_dim]. Horizontal concat recovers Q projection width.
106
+ let joined=CTensor::cat(&heads,1)?;
107
+ self.linear(&joined,&format!("{prefix}self_attn.o_proj.weight"))?
108
+ .affine(c.attention_out_multiplier as f64,0.)
109
+ }
110
+ fn mamba(&self, x:&CTensor,prefix:&str,n:usize)->Result<CTensor>{
111
+ let c=&self.config;
112
+ let md=c.mamba_dim;
113
+ let cd=md+2*c.groups*c.state;
114
+ let hd=md/c.mamba_heads;
115
+ // All tokens projected at once; mup factors are applied to the correct
116
+ // [gate, X, B, C, dt] in_proj sections, as in Falcon-H1.
117
+ let proj=self.linear(x,&format!("{prefix}mamba.in_proj.weight"))?
118
+ .broadcast_mul(&self.mup)?;
119
+ let gate=proj.narrow(1,0,md)?;
120
+ let conv_in=proj.narrow(1,md,cd)?;
121
+ let dt=proj.narrow(1,md+cd,c.mamba_heads)?;
122
+ let conv_w=self.w(&format!("{prefix}mamba.conv1d.weight"))
123
+ .reshape((cd,c.conv))?;
124
+ let conv_bias=self.w(&format!("{prefix}mamba.conv1d.bias"));
125
+ // Depthwise causal Conv1d, vectorized across the entire time dimension.
126
+ let zeros=CTensor::zeros((c.conv-1,cd),DType::F32,&self.device)?;
127
+ let padded=CTensor::cat(&[zeros,conv_in],0)?;
128
+ let mut conv=CTensor::zeros((n,cd),DType::F32,&self.device)?;
129
+ for kernel in 0..c.conv {
130
+ let frame=padded.narrow(0,kernel,n)?;
131
+ let coeff=conv_w.narrow(1,kernel,1)?.transpose(0,1)?;
132
+ conv=conv.broadcast_add(&frame.broadcast_mul(&coeff)?)?;
133
+ }
134
+ let conv=ops::silu(&conv.broadcast_add(conv_bias)?)?;
135
+ let xx=conv.narrow(1,0,md)?.reshape((n,c.mamba_heads,hd))?;
136
+ let bb=conv.narrow(1,md,c.groups*c.state)?.reshape((n,c.groups,c.state))?;
137
+ let cc=conv.narrow(1,md+c.groups*c.state,c.groups*c.state)?.reshape((n,c.groups,c.state))?;
138
+ let dt_bias=self.w(&format!("{prefix}mamba.dt_bias"));
139
+ let alog=self.w(&format!("{prefix}mamba.A_log"));
140
+ let dskip=self.w(&format!("{prefix}mamba.D")).reshape((c.mamba_heads,1))?;
141
+ let neg_a=alog.exp()?.neg()?;
142
+ let mut state=CTensor::zeros((c.mamba_heads,hd,c.state),DType::F32,&self.device)?;
143
+ let mut outs=Vec::with_capacity(n);
144
+ for t in 0..n {
145
+ let u=xx.narrow(0,t,1)?.squeeze(0)?; // [heads,head_dim]
146
+ let b=bb.narrow(0,t,1)?.squeeze(0)?.index_select(&self.group_index,0)?;
147
+ let cv=cc.narrow(0,t,1)?.squeeze(0)?.index_select(&self.group_index,0)?;
148
+ let dt_t=dt.narrow(0,t,1)?.squeeze(0)?.broadcast_add(dt_bias)?;
149
+ let step=dt_t.exp()?.affine(1.,1.)?.log()?; // softplus
150
+ let decay=step.broadcast_mul(&neg_a)?.exp()?.reshape((c.mamba_heads,1,1))?;
151
+ let step3=step.reshape((c.mamba_heads,1,1))?;
152
+ let bu=b.unsqueeze(1)?.broadcast_mul(&u.unsqueeze(2)?)?;
153
+ state=state.broadcast_mul(&decay)?.broadcast_add(&bu.broadcast_mul(&step3)?)?;
154
+ let y=state.broadcast_mul(&cv.unsqueeze(1)?)?.sum(2)?
155
+ .broadcast_add(&u.broadcast_mul(&dskip)?)?;
156
+ let z=gate.narrow(0,t,1)?.reshape((c.mamba_heads,hd))?;
157
+ let y=y.broadcast_mul(&ops::silu(&z)?)?.reshape((1,md))?;
158
+ outs.push(y);
159
+ }
160
+ let scan=CTensor::cat(&outs,0)?;
161
+ self.linear(&scan,&format!("{prefix}mamba.out_proj.weight"))?
162
+ .affine(c.ssm_out_multiplier as f64,0.)
163
+ }
164
+ fn forward(&self,ids:&[usize])->Result<CTensor>{
165
+ let c=&self.config;
166
+ let n=ids.len();
167
+ let indices=CTensor::from_vec(ids.iter().map(|&i|i as u32).collect::<Vec<_>>(),n,&self.device)?;
168
+ let mut x=self.w("model.embed_tokens.weight").index_select(&indices,0)?
169
+ .affine(c.embedding_multiplier as f64,0.)?;
170
+ let (cos,sin)=self.rope_tables(n)?;
171
+ let mut triangle=vec![0f32;n*n];
172
+ for t in 0..n {for j in t+1..n {triangle[t*n+j]=-1.0e9;}}
173
+ let mask=CTensor::from_vec(triangle,(n,n),&self.device)?;
174
+ for layer in 0..c.layers {
175
+ let p=format!("model.layers.{layer}.");
176
+ let h=self.norm(&x,&format!("{p}input_layernorm.weight"))?;
177
+ let attention=self.attention(&h,&p,n,&cos,&sin,&mask)?;
178
+ let ssm=self.mamba(&h,&p,n)?;
179
+ x=x.broadcast_add(&attention)?.broadcast_add(&ssm)?;
180
+ let ff=self.norm(&x,&format!("{p}pre_ff_layernorm.weight"))?;
181
+ let up=self.linear(&ff,&format!("{p}feed_forward.up_proj.weight"))?;
182
+ let gate=self.linear(&ff,&format!("{p}feed_forward.gate_proj.weight"))?
183
+ .affine(c.mlp_multipliers[0] as f64,0.)?;
184
+ let activated=ops::silu(&gate)?.broadcast_mul(&up)?;
185
+ let projected=self.linear(&activated,&format!("{p}feed_forward.down_proj.weight"))?
186
+ .affine(c.mlp_multipliers[1] as f64,0.)?;
187
+ x=x.broadcast_add(&projected)?;
188
+ }
189
+ let last=x.narrow(0,n-1,1)?;
190
+ let h=self.norm(&last,"model.final_layernorm.weight")?;
191
+ self.linear(&h,"lm_head.weight")?.affine(c.lm_head_multiplier as f64,0.)
192
+ }
193
+ pub fn logits(&self,ids:&[usize])->std::result::Result<Vec<f32>,String>{
194
+ if ids.is_empty() || ids.len()>2048 {return Err("input length must be 1..=2048".into());}
195
+ if ids.iter().any(|&id| id>=self.config.vocab) {return Err("token id outside vocabulary".into());}
196
+ self.forward(ids).and_then(|t|t.squeeze(0)?.to_vec1::<f32>()).map_err(|e|e.to_string())
197
+ }
198
+ pub fn generate(&self,ids:&[usize],count:usize)->std::result::Result<Vec<usize>,String>{
199
+ if count>64 || ids.len()+count>2048 {return Err("generation exceeds limits".into())}
200
+ let mut result=ids.to_vec();
201
+ for _ in 0..count {
202
+ let logits=self.logits(&result)?;
203
+ let next=logits.iter().enumerate().max_by(|a,b|a.1.total_cmp(b.1))
204
+ .ok_or("empty vocabulary")?.0;
205
+ result.push(next);
206
+ }
207
+ Ok(result)
208
+ }
209
+ }
210
+
211
+ #[cfg(test)]
212
+ mod tests {
213
+ use super::*;
214
+ use crate::{synthetic_weights,Model};
215
+ #[test]
216
+ fn small_cpu_candle_matches_reference() {
217
+ let c=Config::demo();let w=synthetic_weights(&c);
218
+ let reference=Model::new(c.clone(),w.clone()).unwrap();
219
+ let candle=CandleModel::new(c,w,Device::Cpu).unwrap();
220
+ let a=reference.logits(&[1,2,3]).unwrap();
221
+ let b=candle.logits(&[1,2,3]).unwrap();
222
+ let max_diff=a.iter().zip(&b).map(|(x,y)|(x-y).abs()).fold(0f32,f32::max);
223
+ assert!(max_diff < 1e-3,"max difference {max_diff}");
224
+ }
225
+ #[test]
226
+ fn official_05b_shape_validation() {
227
+ assert!(Config::falcon_h1_05b().validate().is_ok());
228
+ }
229
+ }
src/lib.rs ADDED
@@ -0,0 +1,316 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //! CPU reference implementation of Falcon-H1 inference mathematics, not a CUDA backend.
2
+ //! Checkpoint tensors are loaded from the simple FH1W/f32 pack produced by tools/export.py.
3
+ //! Intended as a readable, testable baseline; not optimized for 0.5B CPU throughput.
4
+ use std::collections::HashMap;
5
+ use std::fs::File;
6
+ use std::io::{self, Read};
7
+
8
+ #[derive(Clone, Debug)]
9
+ pub struct Config {
10
+ pub vocab: usize, pub hidden: usize, pub layers: usize, pub heads: usize,
11
+ pub kv_heads: usize, pub head_dim: usize, pub mamba_heads: usize,
12
+ pub mamba_dim: usize, pub state: usize, pub groups: usize, pub conv: usize,
13
+ pub ff: usize, pub rope_theta: f32, pub eps: f32,
14
+ pub embedding_multiplier: f32, pub key_multiplier: f32,
15
+ pub attention_in_multiplier: f32, pub attention_out_multiplier: f32,
16
+ pub ssm_in_multiplier: f32, pub ssm_out_multiplier: f32,
17
+ pub ssm_multipliers: [f32;5], pub mlp_multipliers: [f32;2],
18
+ pub lm_head_multiplier: f32,
19
+ }
20
+ impl Config {
21
+ pub fn falcon_h1_05b() -> Self { Self {
22
+ vocab:32784, hidden:1024, layers:36, heads:8, kv_heads:2, head_dim:64,
23
+ mamba_heads:24, mamba_dim:1536, state:128, groups:1, conv:4, ff:2048,
24
+ rope_theta:1e11, eps:1e-5,
25
+ embedding_multiplier:5.656854249492381, key_multiplier:0.390625,
26
+ attention_in_multiplier:1., attention_out_multiplier:0.9375,
27
+ ssm_in_multiplier:1.25, ssm_out_multiplier:0.23570226039551587,
28
+ ssm_multipliers:[0.3535533905932738,0.25,0.3535533905932738,0.5,0.3535533905932738],
29
+ mlp_multipliers:[0.8838834764831844,0.5859375], lm_head_multiplier:0.0390625,
30
+ }}
31
+ pub fn demo() -> Self { Self {
32
+ vocab:64, hidden:32, layers:2, heads:4, kv_heads:2, head_dim:8,
33
+ mamba_heads:4, mamba_dim:32, state:8, groups:1, conv:4, ff:64,
34
+ rope_theta:1e11, eps:1e-5,
35
+ embedding_multiplier:1., key_multiplier:1., attention_in_multiplier:1.,
36
+ attention_out_multiplier:1., ssm_in_multiplier:1., ssm_out_multiplier:1.,
37
+ ssm_multipliers:[1.;5], mlp_multipliers:[1.;2], lm_head_multiplier:1.,
38
+ }}
39
+ pub fn validate(&self) -> Result<(), String> {
40
+ if self.heads==0 || self.kv_heads==0 || self.mamba_heads==0 || self.groups==0 || self.conv==0 || self.hidden==0 || self.vocab==0 || self.state==0 { return Err("zero dimension".into()) }
41
+ if self.heads % self.kv_heads != 0 || self.head_dim % 2 != 0 { return Err("invalid GQA/RoPE shape".into()) }
42
+ if self.mamba_dim % self.mamba_heads != 0 || self.mamba_heads % self.groups != 0 { return Err("invalid Mamba head/group shape".into()) }
43
+ // Falcon-H1 attention is narrower than the hidden state: 8*64 != 1024 for 0.5B.
44
+ if self.head_dim==0 || self.mamba_dim==0 || self.ff==0 { return Err("zero projection dimension".into()) }
45
+ Ok(())
46
+ }
47
+ }
48
+
49
+ #[derive(Clone, Debug)]
50
+ pub struct Tensor { pub shape: Vec<usize>, pub data: Vec<f32> }
51
+ impl Tensor {
52
+ fn len(&self) -> usize { self.data.len() }
53
+ }
54
+ pub type Weights = HashMap<String,Tensor>;
55
+ fn bad(e: &str) -> io::Error { io::Error::new(io::ErrorKind::InvalidData,e) }
56
+ fn take_u32(r:&mut impl Read) -> io::Result<u32> { let mut a=[0u8;4]; r.read_exact(&mut a)?; Ok(u32::from_le_bytes(a)) }
57
+
58
+ /// f32 pack: magic FH1W, u32 count, then each tensor: u16 name_len, name,
59
+ /// u8 ndim, u32 dims[ndim], little endian f32 values. No pickle/unsafe code.
60
+ pub fn load_pack(path:&str)->io::Result<Weights>{
61
+ let mut f=File::open(path)?; let mut magic=[0u8;4]; f.read_exact(&mut magic)?;
62
+ if &magic!=b"FH1W" { return Err(bad("not a FH1W checkpoint")) }
63
+ let count=take_u32(&mut f)? as usize;
64
+ if count>50000 { return Err(bad("unreasonable tensor count")) }
65
+ let mut weights=HashMap::new();
66
+ for _ in 0..count {
67
+ let mut two=[0u8;2]; f.read_exact(&mut two)?;let n=u16::from_le_bytes(two) as usize;
68
+ if n==0 || n>1024 { return Err(bad("invalid name length")) }
69
+ let mut name=vec![0u8;n];f.read_exact(&mut name)?;
70
+ let name=String::from_utf8(name).map_err(|_|bad("invalid utf8"))?;
71
+ let mut one=[0u8];f.read_exact(&mut one)?;let d=one[0] as usize;
72
+ if d==0 || d>4 { return Err(bad("invalid rank")) }
73
+ let mut shape=vec![];let mut len=1usize;
74
+ for _ in 0..d {let size=take_u32(&mut f)? as usize;
75
+ len=len.checked_mul(size).ok_or_else(||bad("tensor overflow"))?;
76
+ shape.push(size);
77
+ }
78
+ if len>1_000_000_000 {return Err(bad("unreasonable tensor size"))}
79
+ let mut bytes=vec![0u8;len.checked_mul(4).ok_or_else(||bad("size overflow"))?]; f.read_exact(&mut bytes)?;
80
+ let data=bytes.chunks_exact(4).map(|v|f32::from_le_bytes([v[0],v[1],v[2],v[3]])).collect();
81
+ if weights.insert(name,Tensor{shape,data}).is_some(){return Err(bad("duplicate tensor"))}
82
+ }
83
+ Ok(weights)
84
+ }
85
+
86
+ pub fn expected_shapes(c:&Config)->HashMap<String,Vec<usize>>{
87
+ let mut m=HashMap::new();
88
+ m.insert("model.embed_tokens.weight".into(),vec![c.vocab,c.hidden]);
89
+ m.insert("model.final_layernorm.weight".into(),vec![c.hidden]);
90
+ m.insert("lm_head.weight".into(),vec![c.vocab,c.hidden]);
91
+ let cd=c.mamba_dim+2*c.groups*c.state;
92
+ for l in 0..c.layers {
93
+ let p=format!("model.layers.{l}.");
94
+ for n in ["input_layernorm.weight","pre_ff_layernorm.weight"] {m.insert(format!("{p}{n}"),vec![c.hidden]);}
95
+ for (n,r,k) in [
96
+ ("self_attn.q_proj.weight",c.heads*c.head_dim,c.hidden),
97
+ ("self_attn.k_proj.weight",c.kv_heads*c.head_dim,c.hidden),
98
+ ("self_attn.v_proj.weight",c.kv_heads*c.head_dim,c.hidden),
99
+ ("self_attn.o_proj.weight",c.hidden,c.heads*c.head_dim),
100
+ ("feed_forward.gate_proj.weight",c.ff,c.hidden),
101
+ ("feed_forward.up_proj.weight",c.ff,c.hidden),
102
+ ("feed_forward.down_proj.weight",c.hidden,c.ff),
103
+ ("mamba.in_proj.weight",c.mamba_dim+cd+c.mamba_heads,c.hidden),
104
+ ("mamba.out_proj.weight",c.hidden,c.mamba_dim),
105
+ ] {m.insert(format!("{p}{n}"),vec![r,k]);}
106
+ for n in ["mamba.dt_bias","mamba.A_log","mamba.D"]{m.insert(format!("{p}{n}"),vec![c.mamba_heads]);}
107
+ m.insert(format!("{p}mamba.conv1d.weight"),vec![cd,1,c.conv]);
108
+ m.insert(format!("{p}mamba.conv1d.bias"),vec![cd]);
109
+ }
110
+ m
111
+ }
112
+ pub fn validate_weights(c:&Config,w:&Weights)->Result<(),String>{
113
+ c.validate()?;
114
+ for (k,s) in expected_shapes(c) {
115
+ let t=w.get(&k).ok_or_else(||format!("missing tensor {k}"))?;
116
+ if t.shape!=s { return Err(format!("bad shape for {k}: expected {s:?}, got {:?}",t.shape)) }
117
+ if t.shape.iter().product::<usize>()!=t.len(){return Err(format!("bad data length for {k}"))}
118
+ }
119
+ Ok(())
120
+ }
121
+ fn silu(x:f32)->f32 { x/(1.+(-x).exp()) }
122
+ fn softplus(x:f32)->f32 { if x>20. {x} else {(1.+x.exp()).ln()} }
123
+ fn linear(x:&[f32],w:&Tensor)->Vec<f32>{
124
+ let (rows,cols)=(w.shape[0],w.shape[1]);debug_assert_eq!(cols,x.len());
125
+ let mut y=vec![0.;rows];
126
+ for i in 0..rows {let mut v=0f32;for j in 0..cols{v+=w.data[i*cols+j]*x[j];}y[i]=v;}
127
+ y
128
+ }
129
+ fn norm(x:&[f32],weight:&Tensor,eps:f32)->Vec<f32>{
130
+ let rms=(x.iter().map(|v|v*v).sum::<f32>()/(x.len() as f32)+eps).sqrt();
131
+ x.iter().zip(&weight.data).map(|(a,b)|a/rms*b).collect()
132
+ }
133
+ fn rope(x:&mut [f32],pos:usize,theta:f32){
134
+ let half=x.len()/2;
135
+ for i in 0..half {
136
+ let angle=(pos as f32)/theta.powf(2.*i as f32/x.len() as f32);
137
+ let (s,c)=angle.sin_cos();let (a,b)=(x[i],x[i+half]);
138
+ x[i]=a*c-b*s; x[i+half]=b*c+a*s;
139
+ }
140
+ }
141
+ fn add_assign(x:&mut[f32],y:&[f32]) {for (a,b) in x.iter_mut().zip(y){*a+=b}}
142
+
143
+ /// Reference full-prefix forward. Each layer runs GQA and Mamba-2 from the SAME
144
+ /// RMS-normalized activations, then SwiGLU after a second RMSNorm.
145
+ /// No KV/SSM caching yet; per-request inference recomputes the prefix.
146
+ pub struct Model {pub config:Config, pub weights:Weights}
147
+ impl Model {
148
+ pub fn new(config:Config,weights:Weights)->Result<Self,String>{validate_weights(&config,&weights)?;Ok(Self{config,weights})}
149
+ fn t(&self,key:&str)->&Tensor {&self.weights[key]}
150
+ pub fn logits(&self,ids:&[usize])->Result<Vec<f32>,String>{
151
+ let c=&self.config;
152
+ if ids.is_empty(){return Err("input_ids must not be empty".into())}
153
+ if ids.len()>16384{return Err("sequence too long".into())}
154
+ for &i in ids {if i>=c.vocab{return Err(format!("token {i} outside vocabulary"))}}
155
+ let embeddings=self.t("model.embed_tokens.weight");
156
+ let mut x:Vec<Vec<f32>>=ids.iter().map(|id| embeddings.data[id*c.hidden..(id+1)*c.hidden].iter().map(|v|v*c.embedding_multiplier).collect()).collect();
157
+ let n=x.len();let s=c.state;let md=c.mamba_dim;let hd=md/c.mamba_heads;
158
+ let cd=md+2*c.groups*s;
159
+ for layer in 0..c.layers {
160
+ let p=format!("model.layers.{layer}.");
161
+ let normalized:Vec<Vec<f32>>=x.iter().map(|a|norm(a,self.t(&format!("{p}input_layernorm.weight")),c.eps)).collect();
162
+ // Mamba's causal depthwise conv and selective SSM scan.
163
+ let mut conv_history=vec![vec![0f32;c.conv];cd];
164
+ // [head, head_dim, state]
165
+ let mut recurrent=vec![0f32;c.mamba_heads*hd*s];
166
+ let mut mamba_out=vec![vec![0f32;c.hidden];n];
167
+ let in_proj=self.t(&format!("{p}mamba.in_proj.weight"));
168
+ let out_proj=self.t(&format!("{p}mamba.out_proj.weight"));
169
+ let cw=self.t(&format!("{p}mamba.conv1d.weight"));
170
+ let cb=self.t(&format!("{p}mamba.conv1d.bias"));
171
+ let a_log=self.t(&format!("{p}mamba.A_log"));
172
+ let dt_bias=self.t(&format!("{p}mamba.dt_bias"));
173
+ let d_skip=self.t(&format!("{p}mamba.D"));
174
+ let m=c.ssm_multipliers;
175
+ for time in 0..n {
176
+ let input:Vec<f32>=normalized[time].iter().map(|v|v*c.ssm_in_multiplier).collect();
177
+ let mut projected=linear(&input,in_proj);
178
+ for (i,v) in projected.iter_mut().enumerate(){
179
+ let scale=if i<md{m[0]}else if i<2*md{m[1]}else if i<2*md+c.groups*s{m[2]}
180
+ else if i<2*md+2*c.groups*s{m[3]}else{m[4]}; *v*=scale;
181
+ }
182
+ let gate=&projected[..md]; let conv_input=&projected[md..md+cd];
183
+ let dt=&projected[md+cd..];
184
+ let mut conv_output=vec![0f32;cd];
185
+ for channel in 0..cd {
186
+ conv_history[channel].rotate_left(1);
187
+ conv_history[channel][c.conv-1]=conv_input[channel];
188
+ let mut v=cb.data[channel];
189
+ // PyTorch Conv1d kernel orders oldest->newest.
190
+ for k in 0..c.conv{v+=cw.data[channel*c.conv+k]*conv_history[channel][k]}
191
+ conv_output[channel]=silu(v);
192
+ }
193
+ let xx=&conv_output[..md];
194
+ let b=&conv_output[md..md+c.groups*s];
195
+ let cc=&conv_output[md+c.groups*s..];
196
+ let mut output=vec![0f32;md];
197
+ for h in 0..c.mamba_heads {
198
+ let group=h/(c.mamba_heads/c.groups);
199
+ let step=softplus(dt[h]+dt_bias.data[h]);
200
+ let decay=(-a_log.data[h].exp()*step).exp();
201
+ for k in 0..hd {
202
+ let feature=h*hd+k;
203
+ let u=xx[feature];
204
+ let mut y=d_skip.data[h]*u;
205
+ for st in 0..s {
206
+ let i=feature*s+st;
207
+ recurrent[i]=decay*recurrent[i]+step*b[group*s+st]*u;
208
+ y+=cc[group*s+st]*recurrent[i];
209
+ }
210
+ output[feature]=y*silu(gate[feature]);
211
+ }
212
+ }
213
+ mamba_out[time]=linear(&output,out_proj).iter().map(|v|v*c.ssm_out_multiplier).collect();
214
+ }
215
+ // GQA: full-prefix causal softmax, per-query RoPE and K multiplier.
216
+ let mut q=vec![vec![0f32;c.heads*c.head_dim];n];
217
+ let mut k=vec![vec![0f32;c.kv_heads*c.head_dim];n];
218
+ let mut v=vec![vec![0f32;c.kv_heads*c.head_dim];n];
219
+ for t in 0..n {
220
+ let a:Vec<f32>=normalized[t].iter().map(|x|x*c.attention_in_multiplier).collect();
221
+ q[t]=linear(&a,self.t(&format!("{p}self_attn.q_proj.weight")));
222
+ k[t]=linear(&a,self.t(&format!("{p}self_attn.k_proj.weight")));
223
+ v[t]=linear(&a,self.t(&format!("{p}self_attn.v_proj.weight")));
224
+ for head in 0..c.heads {rope(&mut q[t][head*c.head_dim..(head+1)*c.head_dim],t,c.rope_theta)}
225
+ for head in 0..c.kv_heads {
226
+ let chunk=&mut k[t][head*c.head_dim..(head+1)*c.head_dim];
227
+ for x in chunk.iter_mut(){*x*=c.key_multiplier;}
228
+ rope(chunk,t,c.rope_theta);
229
+ }
230
+ }
231
+ for t in 0..n {
232
+ let mut y=vec![0f32;c.heads*c.head_dim];
233
+ for h in 0..c.heads {
234
+ let kv=h/(c.heads/c.kv_heads);
235
+ let qi=&q[t][h*c.head_dim..(h+1)*c.head_dim];
236
+ let mut scores=Vec::with_capacity(t+1);
237
+ for j in 0..=t {
238
+ let kj=&k[j][kv*c.head_dim..(kv+1)*c.head_dim];
239
+ scores.push(qi.iter().zip(kj).map(|(a,b)|a*b).sum::<f32>()/(c.head_dim as f32).sqrt());
240
+ }
241
+ let mx=scores.iter().copied().fold(f32::NEG_INFINITY,f32::max);
242
+ let exps:Vec<f32>=scores.iter().map(|z|(z-mx).exp()).collect();
243
+ let denom=exps.iter().sum::<f32>();
244
+ for j in 0..=t {
245
+ let vv=&v[j][kv*c.head_dim..(kv+1)*c.head_dim];
246
+ for d in 0..c.head_dim{y[h*c.head_dim+d]+=exps[j]/denom*vv[d];}
247
+ }
248
+ }
249
+ let attn=linear(&y,self.t(&format!("{p}self_attn.o_proj.weight")));
250
+ for i in 0..c.hidden {x[t][i]+=mamba_out[t][i]+c.attention_out_multiplier*attn[i];}
251
+ }
252
+ // pre-FF RMSNorm + SwiGLU with Falcon-H1 µP multipliers
253
+ for t in 0..n {
254
+ let a=norm(&x[t],self.t(&format!("{p}pre_ff_layernorm.weight")),c.eps);
255
+ let up=linear(&a,self.t(&format!("{p}feed_forward.up_proj.weight")));
256
+ let gate=linear(&a,self.t(&format!("{p}feed_forward.gate_proj.weight")));
257
+ let z:Vec<f32>=up.iter().zip(&gate).map(|(u,g)|u*silu(g*c.mlp_multipliers[0])).collect();
258
+ let ff=linear(&z,self.t(&format!("{p}feed_forward.down_proj.weight")));
259
+ for i in 0..c.hidden{x[t][i]+=ff[i]*c.mlp_multipliers[1]}
260
+ }
261
+ }
262
+ let final_h=norm(x.last().unwrap(),self.t("model.final_layernorm.weight"),c.eps);
263
+ Ok(linear(&final_h,self.t("lm_head.weight")).iter().map(|z|z*c.lm_head_multiplier).collect())
264
+ }
265
+ pub fn generate(&self,ids:&[usize],count:usize)->Result<Vec<usize>,String>{
266
+ if count>64 {return Err("max_new_tokens limited to 64 in CPU reference".into())}
267
+ let mut sequence=ids.to_vec();
268
+ for _ in 0..count {
269
+ let y=self.logits(&sequence)?;
270
+ let next=y.iter().enumerate().max_by(|a,b|a.1.total_cmp(b.1)).unwrap().0;
271
+ sequence.push(next);
272
+ }
273
+ Ok(sequence)
274
+ }
275
+ }
276
+
277
+ /// Deterministic tiny tensors for API unit tests. Not a pretrained model.
278
+ pub fn synthetic_weights(c:&Config)->Weights{
279
+ let mut w=HashMap::new();let mut seed:u64=0x9e3779b97f4a7c15;
280
+ for (name,shape) in expected_shapes(c){
281
+ let mut data=vec![0f32;shape.iter().product()];
282
+ for v in &mut data {seed ^= seed>>12;seed ^= seed<<25;seed ^= seed>>27;
283
+ let z=(seed.wrapping_mul(2685821657736338717)>>40) as f32/(1u32<<24) as f32;
284
+ *v=(z-0.5)*0.08;}
285
+ if name.ends_with("layernorm.weight") || name.ends_with("final_layernorm.weight") {
286
+ data.fill(1.);
287
+ }
288
+ if name.ends_with("mamba.D") {data.fill(1.);}
289
+ if name.ends_with("mamba.dt_bias") {data.fill(0.);}
290
+ if name.ends_with("mamba.A_log") {for (i,x) in data.iter_mut().enumerate(){*x=((i+1) as f32).ln()}}
291
+ w.insert(name,Tensor{shape,data});
292
+ }
293
+ w
294
+ }
295
+
296
+ #[cfg(test)]
297
+ mod tests {
298
+ use super::*;
299
+ #[test] fn test_falcon_dimensions(){assert!(Config::falcon_h1_05b().validate().is_ok());}
300
+ #[test] fn test_cpu_logits(){let c=Config::demo();let m=Model::new(c.clone(),synthetic_weights(&c)).unwrap();let y=m.logits(&[1,2,3]).unwrap();assert_eq!(y.len(),c.vocab);assert!(y.iter().all(|x|x.is_finite()));}
301
+ #[test] fn test_causal_prefix(){let c=Config::demo();let m=Model::new(c.clone(),synthetic_weights(&c)).unwrap();
302
+ let a=m.logits(&[1,2]).unwrap();let b=m.logits(&[0,1,2]).unwrap();
303
+ assert_eq!(a.len(),b.len()); // shifted positions legitimately alter RoPE
304
+ assert!(m.logits(&[1,2,3]).is_ok());}
305
+ #[test] fn test_determinism(){let c=Config::demo();let m=Model::new(c.clone(),synthetic_weights(&c)).unwrap();
306
+ assert_eq!(m.logits(&[3,5,7]).unwrap(),m.logits(&[3,5,7]).unwrap());}
307
+ #[test] fn test_generate(){let c=Config::demo();let m=Model::new(c.clone(),synthetic_weights(&c)).unwrap();
308
+ assert_eq!(m.generate(&[1,2],2).unwrap().len(),4);}
309
+ #[test] fn test_bad_token(){let c=Config::demo();let m=Model::new(c.clone(),synthetic_weights(&c)).unwrap();
310
+ assert!(m.logits(&[c.vocab]).is_err());}
311
+ #[test] fn test_weight_validation(){let c=Config::demo();let mut w=synthetic_weights(&c);
312
+ w.remove("model.embed_tokens.weight");assert!(Model::new(c,w).is_err());}
313
+ }
314
+
315
+ #[cfg(feature = "candle")]
316
+ pub mod candle_backend;
src/main.rs ADDED
@@ -0,0 +1,149 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //! Minimal dependency-free HTTP/1.1 API for token-ID-based Falcon-H1 inference.
2
+ //! For localhost/Colab tunnel demo only; deploy behind a reverse proxy for production.
3
+ use falcon_h1_rust::{load_pack,synthetic_weights,Config,Model};
4
+ use std::io::{Read,Write};
5
+ use std::net::{TcpListener,TcpStream};
6
+ use std::sync::Arc;
7
+ use std::time::Duration;
8
+
9
+ fn extract_array(body:&str,key:&str)->Result<Vec<usize>,String>{
10
+ let needle=format!("\"{key}\"");
11
+ let idx=body.find(&needle).ok_or_else(||format!("missing {key}"))?;
12
+ let tail=&body[idx+needle.len()..];
13
+ let colon=tail.find(':').ok_or("missing :")?;
14
+ let tail=&tail[colon+1..];
15
+ let start=tail.find('[').ok_or("missing [")?;
16
+ let tail=&tail[start+1..];
17
+ let end=tail.find(']').ok_or("missing ]")?;
18
+ let data=tail[..end].trim();
19
+ if data.is_empty(){return Err("empty input_ids".into())}
20
+ let ids=data.split(',').map(|x|x.trim().parse::<usize>().map_err(|_|"invalid token ID".to_string())).collect::<Result<Vec<_>,_>>()?;
21
+ if ids.len()>2048{return Err("sequence exceeds API limit (2048 tokens)".into())}
22
+ Ok(ids)
23
+ }
24
+ fn extract_number(body:&str,key:&str,default:usize)->Result<usize,String>{
25
+ let needle=format!("\"{key}\"");
26
+ if let Some(idx)=body.find(&needle){
27
+ let tail=&body[idx+needle.len()..];
28
+ let colon=tail.find(':').ok_or("missing :")?;
29
+ let num=tail[colon+1..].trim_start().chars().take_while(|c|c.is_ascii_digit()).collect::<String>();
30
+ if num.is_empty(){return Err(format!("invalid {key}"))}
31
+ num.parse::<usize>().map_err(|_|format!("invalid {key}"))
32
+ } else {Ok(default)}
33
+ }
34
+ fn response(mut stream:TcpStream,code:&str,payload:&str){
35
+ let msg=format!("HTTP/1.1 {code}\r\nContent-Type: application/json\r\nContent-Length: {}\r\nConnection: close\r\nAccess-Control-Allow-Origin: *\r\nAccess-Control-Allow-Methods: GET, POST, OPTIONS\r\nAccess-Control-Allow-Headers: Content-Type\r\n\r\n{}",payload.len(),payload);
36
+ let _=stream.write_all(msg.as_bytes());
37
+ }
38
+ fn json_err(e:&str)->String{format!("{{\"error\":\"{}\"}}",e.replace('\\',"\\\\").replace('"',"\\\"").replace('\n'," "))}
39
+ enum Backend {
40
+ Cpu(Model),
41
+ #[cfg(feature="candle")]
42
+ Candle(falcon_h1_rust::candle_backend::CandleModel),
43
+ }
44
+ impl Backend {
45
+ fn config(&self)->&Config { match self {
46
+ Self::Cpu(m)=>&m.config,
47
+ #[cfg(feature="candle")]
48
+ Self::Candle(m)=>&m.config,
49
+ }}
50
+ fn label(&self)->&'static str {match self {
51
+ Self::Cpu(_)=>"cpu-reference",
52
+ #[cfg(feature="candle")]
53
+ Self::Candle(m)=>m.device_name(),
54
+ }}
55
+ fn logits(&self,ids:&[usize])->Result<Vec<f32>,String>{match self {
56
+ Self::Cpu(m)=>m.logits(ids),
57
+ #[cfg(feature="candle")]
58
+ Self::Candle(m)=>m.logits(ids),
59
+ }}
60
+ fn generate(&self,ids:&[usize],n:usize)->Result<Vec<usize>,String>{match self {
61
+ Self::Cpu(m)=>m.generate(ids,n),
62
+ #[cfg(feature="candle")]
63
+ Self::Candle(m)=>m.generate(ids,n),
64
+ }}
65
+ }
66
+ fn handle(mut stream:TcpStream,model:Arc<Backend>){
67
+ let _=stream.set_read_timeout(Some(Duration::from_secs(15)));
68
+ let _=stream.set_write_timeout(Some(Duration::from_secs(15)));
69
+ let mut buf=vec![0u8;16384];let mut len=0usize;let mut expected=None;
70
+ loop {
71
+ if len==buf.len(){response(stream,"413 Payload Too Large",&json_err("request too large"));return}
72
+ match stream.read(&mut buf[len..]) {
73
+ Ok(0)=>break,
74
+ Ok(n)=>len+=n,
75
+ Err(_)=>return,
76
+ }
77
+ if let Some(hend)=buf[..len].windows(4).position(|w|w==b"\r\n\r\n") {
78
+ if expected.is_none(){
79
+ let headers=String::from_utf8_lossy(&buf[..hend]);
80
+ let size=headers.lines().filter_map(|l|l.split_once(':')).find(|(k,_)|k.eq_ignore_ascii_case("content-length"))
81
+ .and_then(|(_,v)|v.trim().parse::<usize>().ok()).unwrap_or(0);
82
+ expected=Some(hend+4+size);
83
+ }
84
+ if len>=expected.unwrap(){break}
85
+ }
86
+ }
87
+ let raw=String::from_utf8_lossy(&buf[..len]);
88
+ let first=raw.lines().next().unwrap_or("");
89
+ let (method,path) = {let mut p=first.split_whitespace();(p.next().unwrap_or(""),p.next().unwrap_or(""))};
90
+ if method=="OPTIONS" {response(stream,"204 No Content","");return}
91
+ if method=="GET" && path=="/health" {response(stream,"200 OK",&format!("{{\"status\":\"ok\",\"backend\":\"{}\"}}",model.label()));return}
92
+ if method=="GET" && path=="/v1/model" {
93
+ let c=model.config();
94
+ let msg=format!("{{\"architecture\":\"falcon_h1\",\"backend\":\"{}\",\"layers\":{},\"hidden\":{},\"attention_heads\":{},\"kv_heads\":{},\"mamba_heads\":{},\"vocab_size\":{}}}",model.label(),c.layers,c.hidden,c.heads,c.kv_heads,c.mamba_heads,c.vocab);
95
+ response(stream,"200 OK",&msg);return
96
+ }
97
+ if method!="POST" || (path!="/v1/logits" && path!="/v1/generate") {
98
+ response(stream,"404 Not Found",&json_err("unknown route"));return
99
+ }
100
+ let body=match raw.split_once("\r\n\r\n") {Some((_,v))=>v,None=>{response(stream,"400 Bad Request",&json_err("no body"));return}};
101
+ let result = (||->Result<String,String>{
102
+ let ids=extract_array(body,"input_ids")?;
103
+ if path=="/v1/logits" {
104
+ let y=model.logits(&ids)?;
105
+ let text=y.iter().map(|x|format!("{x:.7}")).collect::<Vec<_>>().join(",");
106
+ Ok(format!("{{\"logits\":[{text}],\"vocab_size\":{}}}",y.len()))
107
+ } else {
108
+ let count=extract_number(body,"max_new_tokens",1)?;
109
+ let seq=model.generate(&ids,count)?;
110
+ Ok(format!("{{\"output_ids\":[{}],\"generated_tokens\":{count}}}",seq.iter().map(|x|x.to_string()).collect::<Vec<_>>().join(",")))
111
+ }
112
+ })();
113
+ match result{Ok(msg)=>response(stream,"200 OK",&msg),Err(e)=>response(stream,"400 Bad Request",&json_err(&e))}
114
+ }
115
+ fn main()->Result<(),Box<dyn std::error::Error>>{
116
+ let args:Vec<String>=std::env::args().collect();
117
+ let demo=args.iter().any(|x|x=="--demo");
118
+ let bind=args.iter().position(|x|x=="--bind").and_then(|i|args.get(i+1)).map(|s|s.as_str()).unwrap_or("127.0.0.1:8080");
119
+ let c=if demo{Config::demo()}else{Config::falcon_h1_05b()};
120
+ let weights=if demo{synthetic_weights(&c)}else{
121
+ let path=args.iter().position(|x|x=="--checkpoint").and_then(|i|args.get(i+1)).ok_or("use --checkpoint path/to/fh1.f32pack or --demo")?;
122
+ load_pack(path)?
123
+ };
124
+ let device=args.iter().position(|x|x=="--device").and_then(|i|args.get(i+1)).map(|s|s.as_str()).unwrap_or("cpu");
125
+ let model=match device {
126
+ "cpu"=>Backend::Cpu(Model::new(c,weights)?),
127
+ #[cfg(feature="candle")]
128
+ "cpu-candle"=>Backend::Candle(falcon_h1_rust::candle_backend::CandleModel::new(c,weights,candle_core::Device::Cpu)?),
129
+ #[cfg(feature="cuda")]
130
+ "cuda"=>Backend::Candle(falcon_h1_rust::candle_backend::CandleModel::new(c,weights,candle_core::Device::new_cuda(0)?)?),
131
+ _=>return Err(format!("unsupported --device {device}; build with --features cuda for CUDA").into()),
132
+ };
133
+ let model=Arc::new(model);
134
+ let listener=TcpListener::bind(bind)?;
135
+ eprintln!("Falcon-H1 Rust API listening on http://{bind} (demo={demo}, backend={})",model.label());
136
+ for request in listener.incoming(){
137
+ if let Ok(stream)=request {let shared=Arc::clone(&model);
138
+ std::thread::spawn(move||handle(stream,shared));}
139
+ }
140
+ Ok(())
141
+ }
142
+
143
+ #[cfg(test)]
144
+ mod tests {
145
+ use super::*;
146
+ #[test] fn parse_ids(){ assert_eq!(extract_array(r#"{"input_ids":[1,2,3]}"#,"input_ids").unwrap(),vec![1,2,3]); }
147
+ #[test] fn reject_ids(){assert!(extract_array(r#"{"input_ids":[1,"x"]}"#,"input_ids").is_err());}
148
+ #[test] fn parse_count(){ assert_eq!(extract_number(r#"{"max_new_tokens":3}"#,"max_new_tokens",1).unwrap(),3); }
149
+ }
tokenizer.json ADDED
The diff for this file is too large to render. See raw diff
 
tokenizer_config.json ADDED
The diff for this file is too large to render. See raw diff
 
tools/client.py ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Call the Rust API with an ordinary text prompt (tokenizer runs in the client).
2
+
3
+ Usage:
4
+ pip install transformers requests
5
+ python tools/client.py --prompt 'Hello' --max-new-tokens 12
6
+
7
+ Synthetic --demo weights cannot produce meaningful text. Run with a real checkpoint.
8
+ """
9
+ import argparse
10
+ import requests
11
+ from transformers import AutoTokenizer
12
+
13
+
14
+ def main():
15
+ p = argparse.ArgumentParser()
16
+ p.add_argument('--api', default='http://127.0.0.1:8080')
17
+ p.add_argument('--repo', default='tiiuae/Falcon-H1-0.5B-Instruct')
18
+ p.add_argument('--prompt', default='Hello!')
19
+ p.add_argument('--max-new-tokens', type=int, default=8)
20
+ args = p.parse_args()
21
+ tok = AutoTokenizer.from_pretrained(args.repo)
22
+ ids = tok.encode(args.prompt, add_special_tokens=True)
23
+ r = requests.post(args.api+'/v1/generate', json={'input_ids': ids,
24
+ 'max_new_tokens': args.max_new_tokens}, timeout=1200)
25
+ r.raise_for_status()
26
+ answer = r.json()['output_ids']
27
+ print(tok.decode(answer, skip_special_tokens=True))
28
+
29
+ if __name__ == '__main__':
30
+ main()
tools/compare_hf.py ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Compare Rust token-ID /v1/logits with the official 0.5B Hugging Face model.
2
+
3
+ Run a Rust --checkpoint server first. This parity check is deliberately a report:
4
+ there is no unsupported numerical-parity claim until the numbers are inspected.
5
+ """
6
+ import argparse
7
+ import json
8
+ import urllib.request
9
+ import numpy as np
10
+ import torch
11
+ from transformers import AutoModelForCausalLM
12
+
13
+
14
+ def main():
15
+ p = argparse.ArgumentParser()
16
+ p.add_argument('--repo', default='tiiuae/Falcon-H1-0.5B-Instruct')
17
+ p.add_argument('--api', default='http://127.0.0.1:8080/v1/logits')
18
+ p.add_argument('--ids', nargs='+', type=int, default=[1, 452, 1223])
19
+ p.add_argument('--device', default='cuda' if torch.cuda.is_available() else 'cpu')
20
+ args = p.parse_args()
21
+ model = AutoModelForCausalLM.from_pretrained(args.repo, torch_dtype=torch.float32).eval().to(args.device)
22
+ with torch.no_grad():
23
+ y = model(input_ids=torch.tensor([args.ids], dtype=torch.long, device=args.device)).logits[0, -1, :].float().cpu().numpy()
24
+ req = urllib.request.Request(args.api, data=json.dumps({'input_ids': args.ids}).encode(), headers={'Content-Type':'application/json'})
25
+ with urllib.request.urlopen(req, timeout=600) as resp:
26
+ z = np.asarray(json.load(resp)['logits'], dtype='float32')
27
+ if y.shape != z.shape:
28
+ raise ValueError(f'vocab shape mismatch: HF {y.shape}, Rust {z.shape}')
29
+ print('reference_top1', int(np.argmax(y)))
30
+ print('rust_top1', int(np.argmax(z)))
31
+ print('max_abs_error', float(np.max(np.abs(y-z))))
32
+ print('mean_abs_error', float(np.mean(np.abs(y-z))))
33
+ print('cosine_similarity', float(np.dot(y,z) / (np.linalg.norm(y)*np.linalg.norm(z))))
34
+
35
+ if __name__ == '__main__':
36
+ main()
tools/export.py ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Export local HF Falcon-H1 safetensors into exact-name f32 FH1W tensor pack.
2
+
3
+ Dependencies: pip install safetensors torch huggingface_hub
4
+ Example:
5
+ python tools/export.py --repo tiiuae/Falcon-H1-0.5B-Instruct --output falcon-h1.f32pack
6
+
7
+ The 0.5B model is ~2 GB in float32; this is CPU reference, not a GPU converter.
8
+ """
9
+ import argparse
10
+ import struct
11
+ from pathlib import Path
12
+ from huggingface_hub import snapshot_download
13
+ from safetensors import safe_open
14
+
15
+
16
+ def convert(model_dir: Path, output: Path):
17
+ paths = sorted(model_dir.glob("*.safetensors"))
18
+ if not paths:
19
+ raise ValueError("No safetensors files in selected model directory")
20
+ # Include only model tensors; do not include unrelated training checkpoint tensors.
21
+ entries = []
22
+ for path in paths:
23
+ with safe_open(str(path), framework="pt", device="cpu") as sf:
24
+ for name in sf.keys():
25
+ if name.startswith(("model.", "lm_head.")):
26
+ entries.append((path, name))
27
+ if len(entries) > 50000:
28
+ raise ValueError("Too many checkpoint tensors")
29
+ output.parent.mkdir(parents=True, exist_ok=True)
30
+ with output.open("wb") as f:
31
+ f.write(b"FH1W")
32
+ f.write(struct.pack("<I", len(entries)))
33
+ for path, name in entries:
34
+ with safe_open(str(path), framework="pt", device="cpu") as sf:
35
+ tensor = sf.get_tensor(name).float().contiguous()
36
+ name_b = name.encode("utf-8")
37
+ shape = tuple(tensor.shape)
38
+ if not (1 <= len(shape) <= 4):
39
+ raise ValueError((name, shape))
40
+ f.write(struct.pack("<H", len(name_b)))
41
+ f.write(name_b)
42
+ f.write(struct.pack("<B", len(shape)))
43
+ for dim in shape:
44
+ f.write(struct.pack("<I", dim))
45
+ f.write(tensor.numpy().astype("<f4", copy=False).tobytes())
46
+ print(f"Wrote {len(entries)} named float32 tensors: {output}")
47
+
48
+
49
+ if __name__ == "__main__":
50
+ p = argparse.ArgumentParser()
51
+ p.add_argument("--repo", default="tiiuae/Falcon-H1-0.5B-Instruct")
52
+ p.add_argument("--local", help="Use an already downloaded model directory")
53
+ p.add_argument("--output", default="falcon-h1.f32pack")
54
+ a = p.parse_args()
55
+ root = Path(a.local) if a.local else Path(snapshot_download(repo_id=a.repo, allow_patterns=["*.safetensors", "*.json"]))
56
+ convert(root, Path(a.output))
tools/smoke_api.py ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Check actual HTTP endpoint execution, including reported device."""
2
+ import argparse
3
+ import json
4
+ import urllib.request
5
+
6
+ p = argparse.ArgumentParser()
7
+ p.add_argument('--backend', default='cpu-reference')
8
+ p.add_argument('--url', default='http://127.0.0.1:8080')
9
+ a = p.parse_args()
10
+
11
+ def request(path, data=None):
12
+ body = json.dumps(data).encode() if data is not None else None
13
+ req = urllib.request.Request(a.url+path, data=body,
14
+ headers={'Content-Type': 'application/json'} if body else {})
15
+ with urllib.request.urlopen(req, timeout=600) as resp:
16
+ assert resp.status == 200
17
+ return json.load(resp)
18
+
19
+ health = request('/health')
20
+ assert health['status'] == 'ok', health
21
+ assert health['backend'] == a.backend, health
22
+ info = request('/v1/model')
23
+ assert info['architecture'] == 'falcon_h1'
24
+ assert info['backend'] == a.backend
25
+ assert len(request('/v1/logits', {'input_ids': [1,2,3]})['logits']) == 64
26
+ assert len(request('/v1/generate', {'input_ids': [1,2], 'max_new_tokens':2})['output_ids']) == 4
27
+ print('PASS:', a.backend, 'health, model, logits, generate via HTTP')