mod-trace 0.1.0__py3-none-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
Binary file
|
|
@@ -0,0 +1,546 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mod-trace
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Classifier: Programming Language :: Rust
|
|
5
|
+
Classifier: Programming Language :: Python :: 3
|
|
6
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
7
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
8
|
+
Classifier: Environment :: Console
|
|
9
|
+
Classifier: Operating System :: OS Independent
|
|
10
|
+
Classifier: Topic :: Software Development :: Build Tools
|
|
11
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Summary: Rust CLI for inspecting ML model artifacts without loading the framework
|
|
14
|
+
Keywords: cli,ml,onnx,catboost,model,inspector,ci,diff
|
|
15
|
+
Requires-Python: >=3.9
|
|
16
|
+
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
17
|
+
|
|
18
|
+
# mod-trace
|
|
19
|
+
|
|
20
|
+
Inspect ML model artifacts without loading the framework.
|
|
21
|
+
|
|
22
|
+
mod-trace is a small Rust CLI for answering a practical question:
|
|
23
|
+
|
|
24
|
+
```text
|
|
25
|
+
What is inside this model file?
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
It can inspect real artifacts such as CatBoost `.cbm` files and ONNX `.onnx` graphs, then report structure, size, parameters, operator mix, rough inference cost, and changes between versions.
|
|
29
|
+
|
|
30
|
+
The secondary tensor lab keeps the original `EXPLAIN ANALYZE` idea for tiny neural-network plans:
|
|
31
|
+
|
|
32
|
+
```sql
|
|
33
|
+
EXPLAIN ANALYZE SELECT ...
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
becomes:
|
|
37
|
+
|
|
38
|
+
```sh
|
|
39
|
+
mod-trace trace examples/tiny_attention_plan.json
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Core Commands
|
|
43
|
+
|
|
44
|
+
```sh
|
|
45
|
+
cargo run -- doctor
|
|
46
|
+
cargo run -- doctor --json
|
|
47
|
+
cargo run -- inspect path/to/model.cbm
|
|
48
|
+
cargo run -- inspect --json path/to/model.cbm
|
|
49
|
+
cargo run -- inspect --deep path/to/model.cbm
|
|
50
|
+
cargo run -- inspect path/to/model.onnx
|
|
51
|
+
cargo run -- inspect --json path/to/model.onnx
|
|
52
|
+
cargo run -- explain path/to/model.onnx
|
|
53
|
+
cargo run -- diff path/to/old_model.cbm path/to/new_model.cbm
|
|
54
|
+
cargo run -- diff --json path/to/old_model.cbm path/to/new_model.cbm
|
|
55
|
+
cargo run -- diff --deep path/to/old_model.cbm path/to/new_model.cbm
|
|
56
|
+
cargo run -- check --max-size-growth 20% --fail-on-feature-change path/to/old_model.cbm path/to/new_model.cbm
|
|
57
|
+
cargo run -- diff path/to/old_model.onnx path/to/new_model.onnx
|
|
58
|
+
cargo run -- diff --json path/to/old_model.onnx path/to/new_model.onnx
|
|
59
|
+
cargo run -- check --max-ops-growth 25% --fail-on-new-op path/to/old_model.onnx path/to/new_model.onnx
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Installed binary form:
|
|
63
|
+
|
|
64
|
+
```sh
|
|
65
|
+
mod-trace doctor
|
|
66
|
+
mod-trace doctor --json
|
|
67
|
+
mod-trace inspect model.cbm
|
|
68
|
+
mod-trace inspect --json model.cbm
|
|
69
|
+
mod-trace inspect --deep model.cbm
|
|
70
|
+
mod-trace inspect model.onnx
|
|
71
|
+
mod-trace inspect --json model.onnx
|
|
72
|
+
mod-trace explain model.onnx
|
|
73
|
+
mod-trace diff old_model.cbm new_model.cbm
|
|
74
|
+
mod-trace diff --json old_model.cbm new_model.cbm
|
|
75
|
+
mod-trace diff --deep old_model.cbm new_model.cbm
|
|
76
|
+
mod-trace check --max-size-growth 20% --fail-on-feature-change old_model.cbm new_model.cbm
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Why This Exists
|
|
80
|
+
|
|
81
|
+
Data and ML engineers often inherit model artifacts:
|
|
82
|
+
|
|
83
|
+
- `fraud_model.cbm`
|
|
84
|
+
- `ranking_model.onnx`
|
|
85
|
+
- `model_v17.cbm`
|
|
86
|
+
- `candidate_model.onnx`
|
|
87
|
+
|
|
88
|
+
Before running them, it is useful to know:
|
|
89
|
+
|
|
90
|
+
- what type of model it is
|
|
91
|
+
- how large it is
|
|
92
|
+
- how many trees, parameters, nodes, or operators it contains
|
|
93
|
+
- what the rough per-row or per-forward-pass cost looks like
|
|
94
|
+
- what changed between two versions
|
|
95
|
+
|
|
96
|
+
mod-trace is not a model runtime. It is an artifact inspector.
|
|
97
|
+
|
|
98
|
+
## Doctor
|
|
99
|
+
|
|
100
|
+
Check which inspectors and optional helpers are available:
|
|
101
|
+
|
|
102
|
+
```sh
|
|
103
|
+
cargo run -- doctor
|
|
104
|
+
cargo run -- doctor --json
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Example output:
|
|
108
|
+
|
|
109
|
+
```text
|
|
110
|
+
mod-trace Doctor
|
|
111
|
+
----------------
|
|
112
|
+
|
|
113
|
+
Built-in inspectors:
|
|
114
|
+
CatBoost metadata: ok
|
|
115
|
+
ONNX static graph: ok
|
|
116
|
+
JSON tensor plans: ok
|
|
117
|
+
|
|
118
|
+
Optional Python helpers:
|
|
119
|
+
Python: ok (/path/to/python)
|
|
120
|
+
catboost: ok (1.2.8)
|
|
121
|
+
|
|
122
|
+
Available commands:
|
|
123
|
+
inspect .cbm/.onnx/.json: available
|
|
124
|
+
diff .cbm/.onnx: available
|
|
125
|
+
inspect --deep .cbm: available
|
|
126
|
+
diff --deep .cbm: available
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Use `--json` when a setup script or CI job needs to check optional helper availability.
|
|
130
|
+
|
|
131
|
+
## JSON Output
|
|
132
|
+
|
|
133
|
+
Use JSON when mod-trace is part of CI, release checks, or model registry automation:
|
|
134
|
+
|
|
135
|
+
```sh
|
|
136
|
+
cargo run -- inspect --json path/to/model.cbm
|
|
137
|
+
cargo run -- inspect --json path/to/model.onnx
|
|
138
|
+
cargo run -- diff --json path/to/old_model.cbm path/to/new_model.cbm
|
|
139
|
+
cargo run -- diff --json path/to/old_model.onnx path/to/new_model.onnx
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
The JSON diff is designed for checks such as:
|
|
143
|
+
|
|
144
|
+
- fail if file size, parameter memory, or estimated ops grows too much
|
|
145
|
+
- fail if CatBoost feature names, training config, or learned-state fingerprint changes unexpectedly
|
|
146
|
+
- fail if ONNX operator counts or initializer tensors change
|
|
147
|
+
|
|
148
|
+
`--deep` CatBoost reports are text-only for now because they are diagnostic dumps from CatBoost's native Python parser.
|
|
149
|
+
|
|
150
|
+
## CI Checks
|
|
151
|
+
|
|
152
|
+
Use `check` when a model artifact should fail promotion if it changes too much:
|
|
153
|
+
|
|
154
|
+
```sh
|
|
155
|
+
cargo run -- check path/to/old_model.cbm path/to/new_model.cbm \
|
|
156
|
+
--max-size-growth 20% \
|
|
157
|
+
--fail-on-feature-change \
|
|
158
|
+
--fail-on-training-config-change
|
|
159
|
+
|
|
160
|
+
cargo run -- check path/to/old_model.onnx path/to/new_model.onnx \
|
|
161
|
+
--max-size-growth 20% \
|
|
162
|
+
--max-ops-growth 25% \
|
|
163
|
+
--fail-on-new-op
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
`check` prints a short PASS/FAIL report and exits nonzero when a rule fails.
|
|
167
|
+
|
|
168
|
+
## CatBoost
|
|
169
|
+
|
|
170
|
+
Inspect a CatBoost binary model:
|
|
171
|
+
|
|
172
|
+
```sh
|
|
173
|
+
cargo run -- inspect path/to/model.cbm
|
|
174
|
+
cargo run -- inspect --json path/to/model.cbm
|
|
175
|
+
cargo run -- inspect --deep path/to/model.cbm
|
|
176
|
+
cargo run -- explain path/to/model.cbm
|
|
177
|
+
cargo run -- catboost --deep --limit 10 path/to/model.cbm
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
`--deep` is optional and requires Python CatBoost. For a single artifact, it adds exact float/categorical feature typing and float border counts decoded through CatBoost's native parser.
|
|
181
|
+
|
|
182
|
+
Example output:
|
|
183
|
+
|
|
184
|
+
```text
|
|
185
|
+
CatBoost Model Summary
|
|
186
|
+
----------------------
|
|
187
|
+
Model: model.cbm
|
|
188
|
+
Format: CatBoost binary model (CBM1)
|
|
189
|
+
File size: 4.6 MiB
|
|
190
|
+
|
|
191
|
+
Execution Plan:
|
|
192
|
+
Input row
|
|
193
|
+
|
|
|
194
|
+
v
|
|
195
|
+
Quantize numeric/categorical features
|
|
196
|
+
|
|
|
197
|
+
v
|
|
198
|
+
Traverse symmetric tree ensemble
|
|
199
|
+
|
|
|
200
|
+
v
|
|
201
|
+
Sum leaf values
|
|
202
|
+
|
|
203
|
+
Estimated Cost:
|
|
204
|
+
Trees / row: 500
|
|
205
|
+
Configured/max split checks / row: 3500
|
|
206
|
+
Max leaf slots: 64000
|
|
207
|
+
Why: 500 trees * depth 7 = 3500 split checks / row
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
Diff two CatBoost artifacts:
|
|
211
|
+
|
|
212
|
+
```sh
|
|
213
|
+
cargo run -- diff path/to/old_model.cbm path/to/new_model.cbm
|
|
214
|
+
cargo run -- diff --json path/to/old_model.cbm path/to/new_model.cbm
|
|
215
|
+
cargo run -- diff --deep path/to/old_model.cbm path/to/new_model.cbm
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
The normal diff is fast and reads embedded metadata plus artifact fingerprints. `--deep` is optional and requires Python CatBoost. It fully decodes the `.cbm` files through CatBoost's native parser and compares split changes, leaf value changes, leaf weights, feature typing, scale/bias, split type mix, and float-feature border changes keyed by CatBoost's flat/original feature index.
|
|
219
|
+
|
|
220
|
+
Example output:
|
|
221
|
+
|
|
222
|
+
```text
|
|
223
|
+
Model Diff
|
|
224
|
+
----------
|
|
225
|
+
Type: CatBoost
|
|
226
|
+
|
|
227
|
+
Structure:
|
|
228
|
+
File size:
|
|
229
|
+
4.6 MiB -> 6.2 MiB (+1677721)
|
|
230
|
+
Trees:
|
|
231
|
+
500 -> 650 (+150)
|
|
232
|
+
Depth:
|
|
233
|
+
7 -> 8 (+1)
|
|
234
|
+
Configured/max split checks / row:
|
|
235
|
+
3500 -> 5200 (+1700)
|
|
236
|
+
|
|
237
|
+
Parameter-like Internals:
|
|
238
|
+
Full artifact fingerprint:
|
|
239
|
+
0x2d2b00dd2375ee48 -> 0xb22f43a2cf612a37 (changed)
|
|
240
|
+
Metadata fingerprint:
|
|
241
|
+
0x0e9a08d227179262 -> 0x54a9bd32b5196b8f (changed)
|
|
242
|
+
Learned-state fingerprint:
|
|
243
|
+
0xf57e3eeca557d48a -> 0x1390d581269e9dca (changed)
|
|
244
|
+
Note: CatBoost does not expose PyTorch-style parameter tensors here.
|
|
245
|
+
|
|
246
|
+
Training Config:
|
|
247
|
+
Loss:
|
|
248
|
+
RMSE -> RMSE (same)
|
|
249
|
+
Learning rate:
|
|
250
|
+
0.100000 -> 0.100000 (same)
|
|
251
|
+
|
|
252
|
+
Metrics:
|
|
253
|
+
Best learn RMSE:
|
|
254
|
+
105.479737 -> 118.574709 (+13.094972)
|
|
255
|
+
Note: learn RMSE increased by 12.41%. Lower is usually better if this metric is comparable.
|
|
256
|
+
|
|
257
|
+
Features:
|
|
258
|
+
Recovered feature names:
|
|
259
|
+
82 -> 83 (+1)
|
|
260
|
+
|
|
261
|
+
Interpretation:
|
|
262
|
+
Structure changed: inference cost or ensemble shape may differ.
|
|
263
|
+
Training config changed in embedded metadata.
|
|
264
|
+
Learned-state fingerprint changed, so internal CatBoost parameters likely changed even if tree count/depth did not.
|
|
265
|
+
|
|
266
|
+
CatBoost Deep Diff
|
|
267
|
+
------------------
|
|
268
|
+
Decoded Structure:
|
|
269
|
+
Trees with split changes: 400 / 400
|
|
270
|
+
Split positions changed: 2800
|
|
271
|
+
|
|
272
|
+
Leaf Values:
|
|
273
|
+
Trees with leaf value changes: 400 / 400
|
|
274
|
+
|
|
275
|
+
Feature Processing:
|
|
276
|
+
Float features: 13 -> 15
|
|
277
|
+
Categorical features: 4 -> 2
|
|
278
|
+
Total float borders: 787 -> 874
|
|
279
|
+
Float feature list changes:
|
|
280
|
+
Added:
|
|
281
|
+
13: new_numeric_feature
|
|
282
|
+
14: another_numeric_feature
|
|
283
|
+
Categorical feature list changes:
|
|
284
|
+
Removed:
|
|
285
|
+
2: old_category_feature
|
|
286
|
+
3: another_category_feature
|
|
287
|
+
Feature type changes:
|
|
288
|
+
9: month_feature: categorical -> float
|
|
289
|
+
Float features with changed borders:
|
|
290
|
+
0: numeric_feature_a: borders 59 -> 62, changed positions 59
|
|
291
|
+
1: numeric_feature_b: borders 95 -> 93, changed positions 93
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
Create a safe synthetic CatBoost model for local testing:
|
|
295
|
+
|
|
296
|
+
```sh
|
|
297
|
+
python3 -m pip install catboost
|
|
298
|
+
python3 examples/make_sample_catboost.py
|
|
299
|
+
cargo run -- inspect examples/sample_catboost.cbm
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
The generated `.cbm` uses synthetic data only and is ignored by git.
|
|
303
|
+
|
|
304
|
+
Explain a single CatBoost artifact:
|
|
305
|
+
|
|
306
|
+
```sh
|
|
307
|
+
cargo run -- explain path/to/model.cbm
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
This describes the artifact as a tree ensemble, shows evidence from CBM metadata, estimates tree traversal cost, prints training metadata, and explains how to use `diff --deep` for exact version-to-version changes.
|
|
311
|
+
|
|
312
|
+
When Python CatBoost is available, `explain` also prints feature processing:
|
|
313
|
+
|
|
314
|
+
```text
|
|
315
|
+
Feature Processing:
|
|
316
|
+
Float features: 15
|
|
317
|
+
Categorical features: 2
|
|
318
|
+
Total float borders: 874
|
|
319
|
+
Float feature list:
|
|
320
|
+
0: numeric_feature_a (62 borders)
|
|
321
|
+
Categorical feature list:
|
|
322
|
+
1: category_feature_a
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
## ONNX
|
|
326
|
+
|
|
327
|
+
Inspect an ONNX graph:
|
|
328
|
+
|
|
329
|
+
```sh
|
|
330
|
+
cargo run -- inspect path/to/model.onnx
|
|
331
|
+
cargo run -- inspect --json path/to/model.onnx
|
|
332
|
+
cargo run -- onnx --limit 10 path/to/model.onnx
|
|
333
|
+
cargo run -- onnx --json path/to/model.onnx
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
Example output:
|
|
337
|
+
|
|
338
|
+
```text
|
|
339
|
+
ONNX Model Summary
|
|
340
|
+
------------------
|
|
341
|
+
Model: model.onnx
|
|
342
|
+
Format: ONNX ModelProto
|
|
343
|
+
File size: 197.1 KiB
|
|
344
|
+
IR version: 10
|
|
345
|
+
Producer: pytorch
|
|
346
|
+
Graph: main_graph
|
|
347
|
+
Opsets: ai.onnx=18
|
|
348
|
+
|
|
349
|
+
Graph:
|
|
350
|
+
Nodes: 89
|
|
351
|
+
Initializers: 33
|
|
352
|
+
Value info entries: 120
|
|
353
|
+
Parameters: 58646 values / 231.2 KiB
|
|
354
|
+
|
|
355
|
+
Operator Mix:
|
|
356
|
+
Add 22
|
|
357
|
+
MatMul 16
|
|
358
|
+
Reshape 12
|
|
359
|
+
Transpose 10
|
|
360
|
+
LayerNormalization 5
|
|
361
|
+
|
|
362
|
+
Estimated Cost:
|
|
363
|
+
Estimated ops: 3226
|
|
364
|
+
Most expensive:
|
|
365
|
+
node_MatMul_98 MatMul 256 ops
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
Diff two ONNX graphs:
|
|
369
|
+
|
|
370
|
+
```sh
|
|
371
|
+
cargo run -- diff path/to/old_model.onnx path/to/new_model.onnx
|
|
372
|
+
cargo run -- diff --json path/to/old_model.onnx path/to/new_model.onnx
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
ONNX diff includes a `Parameter Tensors` section. It compares initializer tensor count, names, shapes, dtypes, and raw-data fingerprints when raw tensor bytes are stored in the ONNX file.
|
|
376
|
+
|
|
377
|
+
Explain likely ONNX architecture:
|
|
378
|
+
|
|
379
|
+
```sh
|
|
380
|
+
cargo run -- explain path/to/model.onnx
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
Example output:
|
|
384
|
+
|
|
385
|
+
```text
|
|
386
|
+
ONNX Architecture Explanation
|
|
387
|
+
-----------------------------
|
|
388
|
+
Model: model.onnx
|
|
389
|
+
|
|
390
|
+
This model appears to be a transformer.
|
|
391
|
+
|
|
392
|
+
Evidence:
|
|
393
|
+
- 12 Softmax nodes
|
|
394
|
+
- 24 MatMul nodes
|
|
395
|
+
- 24 LayerNormalization operators
|
|
396
|
+
- initializer names mention embeddings
|
|
397
|
+
|
|
398
|
+
Estimated Architecture:
|
|
399
|
+
Encoder/attention layers: ~12
|
|
400
|
+
Hidden size: ~768
|
|
401
|
+
Parameters: 109482240 values
|
|
402
|
+
Estimated ops: 12345678
|
|
403
|
+
|
|
404
|
+
Why:
|
|
405
|
+
Transformers repeatedly use MatMul for projections and attention scores.
|
|
406
|
+
Softmax usually appears where attention scores become probabilities.
|
|
407
|
+
LayerNormalization is common around transformer attention/MLP blocks.
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
mod-trace performs static ONNX graph inspection. It does not execute ONNX models and does not require ONNX Runtime.
|
|
411
|
+
|
|
412
|
+
## Exporting A Small ONNX Model
|
|
413
|
+
|
|
414
|
+
If you have a Hugging Face model locally, export it with fixed input shapes for better cost estimates:
|
|
415
|
+
|
|
416
|
+
```sh
|
|
417
|
+
python3 -m pip install torch transformers onnx onnxscript
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
```python
|
|
421
|
+
import torch
|
|
422
|
+
from transformers import AutoModel, AutoTokenizer
|
|
423
|
+
|
|
424
|
+
model_dir = "models/tiny-distilbert-base-cased"
|
|
425
|
+
onnx_path = f"{model_dir}/model_fixed.onnx"
|
|
426
|
+
|
|
427
|
+
tokenizer = AutoTokenizer.from_pretrained(model_dir)
|
|
428
|
+
model = AutoModel.from_pretrained(model_dir)
|
|
429
|
+
model.eval()
|
|
430
|
+
|
|
431
|
+
inputs = tokenizer(
|
|
432
|
+
"hello mod-trace",
|
|
433
|
+
return_tensors="pt",
|
|
434
|
+
padding="max_length",
|
|
435
|
+
max_length=8,
|
|
436
|
+
truncation=True,
|
|
437
|
+
)
|
|
438
|
+
|
|
439
|
+
torch.onnx.export(
|
|
440
|
+
model,
|
|
441
|
+
(inputs["input_ids"], inputs["attention_mask"]),
|
|
442
|
+
onnx_path,
|
|
443
|
+
input_names=["input_ids", "attention_mask"],
|
|
444
|
+
output_names=["last_hidden_state", "pooler_output"],
|
|
445
|
+
opset_version=18,
|
|
446
|
+
dynamo=True,
|
|
447
|
+
)
|
|
448
|
+
|
|
449
|
+
print(onnx_path)
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
Then inspect it:
|
|
453
|
+
|
|
454
|
+
```sh
|
|
455
|
+
cargo run -- inspect models/tiny-distilbert-base-cased/model_fixed.onnx
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
Fixed shapes such as `[1, 8]` produce better numeric estimates than symbolic shapes such as `[batch, sequence]`.
|
|
459
|
+
|
|
460
|
+
## Tensor Lab
|
|
461
|
+
|
|
462
|
+
The original tensor-analysis MVP still exists as a lab for small handcrafted plans:
|
|
463
|
+
|
|
464
|
+
```sh
|
|
465
|
+
cargo run -- trace examples/tiny_attention_plan.json
|
|
466
|
+
cargo run -- compare examples/tiny_attention_plan.json
|
|
467
|
+
cargo run -- why examples/tiny_attention_plan.json
|
|
468
|
+
cargo run -- validate examples/broken_shape.json
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
Example plan:
|
|
472
|
+
|
|
473
|
+
```json
|
|
474
|
+
{
|
|
475
|
+
"layers": [
|
|
476
|
+
{
|
|
477
|
+
"type": "self_attention",
|
|
478
|
+
"tokens": 3,
|
|
479
|
+
"head_dim": 4,
|
|
480
|
+
"value_dim": 4
|
|
481
|
+
},
|
|
482
|
+
{
|
|
483
|
+
"type": "linear",
|
|
484
|
+
"in": 4,
|
|
485
|
+
"out": 2
|
|
486
|
+
},
|
|
487
|
+
{
|
|
488
|
+
"type": "softmax"
|
|
489
|
+
}
|
|
490
|
+
]
|
|
491
|
+
}
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
`why` explains the attention cost:
|
|
495
|
+
|
|
496
|
+
```text
|
|
497
|
+
Why is attention expensive?
|
|
498
|
+
---------------------------
|
|
499
|
+
Attention layer: single_head_attention
|
|
500
|
+
432 ops
|
|
501
|
+
|
|
502
|
+
Breakdown:
|
|
503
|
+
Q projection 96 ops
|
|
504
|
+
K projection 96 ops
|
|
505
|
+
V projection 96 ops
|
|
506
|
+
Q @ K^T 72 ops
|
|
507
|
+
attention @ V 72 ops
|
|
508
|
+
|
|
509
|
+
Explanation:
|
|
510
|
+
Every token must compare itself against every other token.
|
|
511
|
+
The score and value-mixing terms grow roughly with tokens^2.
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
This is useful for demos and for explaining transformer internals, but it is no longer the primary product surface.
|
|
515
|
+
|
|
516
|
+
## What It Does Not Do
|
|
517
|
+
|
|
518
|
+
mod-trace does not:
|
|
519
|
+
|
|
520
|
+
- run inference
|
|
521
|
+
- train models
|
|
522
|
+
- load PyTorch directly
|
|
523
|
+
- require CatBoost, PyTorch, or ONNX Runtime for inspection
|
|
524
|
+
- provide GPU kernels
|
|
525
|
+
- replace framework-native debugging tools
|
|
526
|
+
|
|
527
|
+
## Privacy
|
|
528
|
+
|
|
529
|
+
Do not commit real model weights or private business artifacts. The repository ignores:
|
|
530
|
+
|
|
531
|
+
- `models/`
|
|
532
|
+
- `examples/*.onnx`
|
|
533
|
+
- `examples/*.cbm`
|
|
534
|
+
|
|
535
|
+
Use `examples/make_sample_catboost.py` when you need a shareable `.cbm` demo.
|
|
536
|
+
|
|
537
|
+
## Architecture
|
|
538
|
+
|
|
539
|
+
mod-trace has three small inspection paths:
|
|
540
|
+
|
|
541
|
+
- CatBoost `.cbm` metadata scanner
|
|
542
|
+
- ONNX protobuf graph scanner
|
|
543
|
+
- JSON tensor-plan analyzer
|
|
544
|
+
|
|
545
|
+
See [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for details.
|
|
546
|
+
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
mod_trace-0.1.0.data/scripts/mod-trace.exe,sha256=0Cce6dwGDleD3r6aXSobFOw14MDbE28uwKRX9TCTsMo,1270272
|
|
2
|
+
mod_trace-0.1.0.dist-info/METADATA,sha256=Vj89Zm8DVn6nW2tMMr_Yu_NVgmSwS4AEuLw6fGCIOfw,14778
|
|
3
|
+
mod_trace-0.1.0.dist-info/WHEEL,sha256=fxUURV-tpz4EGoGaAcyzIZ0CMCngNhGnetS-bU4AaSg,94
|
|
4
|
+
mod_trace-0.1.0.dist-info/licenses/LICENSE,sha256=YaR2WFSQO3vqE0s3C5-RkCn-lvoHf6vHy-LqVS_mP4E,1091
|
|
5
|
+
mod_trace-0.1.0.dist-info/sboms/mod-trace.cyclonedx.json,sha256=15P0AWOHFNxTRUZDtd9pEhQkXpL8Jhmy768vSEvkMW0,14517
|
|
6
|
+
mod_trace-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Maria Dubyaga
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,476 @@
|
|
|
1
|
+
{
|
|
2
|
+
"bomFormat": "CycloneDX",
|
|
3
|
+
"specVersion": "1.5",
|
|
4
|
+
"version": 1,
|
|
5
|
+
"serialNumber": "urn:uuid:41d66795-2242-4b7d-bd8a-d120d11399fe",
|
|
6
|
+
"metadata": {
|
|
7
|
+
"timestamp": "2026-06-04T20:34:11.593006300Z",
|
|
8
|
+
"tools": [
|
|
9
|
+
{
|
|
10
|
+
"vendor": "CycloneDX",
|
|
11
|
+
"name": "cargo-cyclonedx",
|
|
12
|
+
"version": "0.5.9"
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"component": {
|
|
16
|
+
"type": "application",
|
|
17
|
+
"bom-ref": "path+file:///D:/a/modellens/modellens#mod-trace@0.1.0",
|
|
18
|
+
"name": "mod-trace",
|
|
19
|
+
"version": "0.1.0",
|
|
20
|
+
"description": "Rust CLI for inspecting ML model artifacts without loading the framework",
|
|
21
|
+
"scope": "required",
|
|
22
|
+
"licenses": [
|
|
23
|
+
{
|
|
24
|
+
"expression": "MIT"
|
|
25
|
+
}
|
|
26
|
+
],
|
|
27
|
+
"purl": "pkg:cargo/mod-trace@0.1.0?download_url=file://.",
|
|
28
|
+
"components": [
|
|
29
|
+
{
|
|
30
|
+
"type": "application",
|
|
31
|
+
"bom-ref": "path+file:///D:/a/modellens/modellens#mod-trace@0.1.0 bin-target-0",
|
|
32
|
+
"name": "mod-trace",
|
|
33
|
+
"version": "0.1.0",
|
|
34
|
+
"purl": "pkg:cargo/mod-trace@0.1.0?download_url=file://.#src/main.rs"
|
|
35
|
+
}
|
|
36
|
+
]
|
|
37
|
+
},
|
|
38
|
+
"properties": [
|
|
39
|
+
{
|
|
40
|
+
"name": "cdx:rustc:sbom:target:all_targets",
|
|
41
|
+
"value": "true"
|
|
42
|
+
}
|
|
43
|
+
]
|
|
44
|
+
},
|
|
45
|
+
"components": [
|
|
46
|
+
{
|
|
47
|
+
"type": "library",
|
|
48
|
+
"bom-ref": "registry+https://github.com/rust-lang/crates.io-index#itoa@1.0.18",
|
|
49
|
+
"author": "David Tolnay <dtolnay@gmail.com>",
|
|
50
|
+
"name": "itoa",
|
|
51
|
+
"version": "1.0.18",
|
|
52
|
+
"description": "Fast integer primitive to string conversion",
|
|
53
|
+
"scope": "required",
|
|
54
|
+
"hashes": [
|
|
55
|
+
{
|
|
56
|
+
"alg": "SHA-256",
|
|
57
|
+
"content": "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
|
|
58
|
+
}
|
|
59
|
+
],
|
|
60
|
+
"licenses": [
|
|
61
|
+
{
|
|
62
|
+
"expression": "MIT OR Apache-2.0"
|
|
63
|
+
}
|
|
64
|
+
],
|
|
65
|
+
"purl": "pkg:cargo/itoa@1.0.18",
|
|
66
|
+
"externalReferences": [
|
|
67
|
+
{
|
|
68
|
+
"type": "documentation",
|
|
69
|
+
"url": "https://docs.rs/itoa"
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"type": "vcs",
|
|
73
|
+
"url": "https://github.com/dtolnay/itoa"
|
|
74
|
+
}
|
|
75
|
+
]
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"type": "library",
|
|
79
|
+
"bom-ref": "registry+https://github.com/rust-lang/crates.io-index#memchr@2.8.1",
|
|
80
|
+
"author": "Andrew Gallant <jamslam@gmail.com>, bluss",
|
|
81
|
+
"name": "memchr",
|
|
82
|
+
"version": "2.8.1",
|
|
83
|
+
"description": "Provides extremely fast (uses SIMD on x86_64, aarch64 and wasm32) routines for 1, 2 or 3 byte search and single substring search. ",
|
|
84
|
+
"scope": "required",
|
|
85
|
+
"hashes": [
|
|
86
|
+
{
|
|
87
|
+
"alg": "SHA-256",
|
|
88
|
+
"content": "6b947ae49db0d222b1dbc6b113ce7248a3fc3a6ca21b696717bfc000ba4484d8"
|
|
89
|
+
}
|
|
90
|
+
],
|
|
91
|
+
"licenses": [
|
|
92
|
+
{
|
|
93
|
+
"expression": "Unlicense OR MIT"
|
|
94
|
+
}
|
|
95
|
+
],
|
|
96
|
+
"purl": "pkg:cargo/memchr@2.8.1",
|
|
97
|
+
"externalReferences": [
|
|
98
|
+
{
|
|
99
|
+
"type": "documentation",
|
|
100
|
+
"url": "https://docs.rs/memchr/"
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
"type": "website",
|
|
104
|
+
"url": "https://github.com/BurntSushi/memchr"
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
"type": "vcs",
|
|
108
|
+
"url": "https://github.com/BurntSushi/memchr"
|
|
109
|
+
}
|
|
110
|
+
]
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
"type": "library",
|
|
114
|
+
"bom-ref": "registry+https://github.com/rust-lang/crates.io-index#proc-macro2@1.0.106",
|
|
115
|
+
"author": "David Tolnay <dtolnay@gmail.com>, Alex Crichton <alex@alexcrichton.com>",
|
|
116
|
+
"name": "proc-macro2",
|
|
117
|
+
"version": "1.0.106",
|
|
118
|
+
"description": "A substitute implementation of the compiler's `proc_macro` API to decouple token-based libraries from the procedural macro use case.",
|
|
119
|
+
"scope": "required",
|
|
120
|
+
"hashes": [
|
|
121
|
+
{
|
|
122
|
+
"alg": "SHA-256",
|
|
123
|
+
"content": "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
|
|
124
|
+
}
|
|
125
|
+
],
|
|
126
|
+
"licenses": [
|
|
127
|
+
{
|
|
128
|
+
"expression": "MIT OR Apache-2.0"
|
|
129
|
+
}
|
|
130
|
+
],
|
|
131
|
+
"purl": "pkg:cargo/proc-macro2@1.0.106",
|
|
132
|
+
"externalReferences": [
|
|
133
|
+
{
|
|
134
|
+
"type": "documentation",
|
|
135
|
+
"url": "https://docs.rs/proc-macro2"
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
"type": "vcs",
|
|
139
|
+
"url": "https://github.com/dtolnay/proc-macro2"
|
|
140
|
+
}
|
|
141
|
+
]
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
"type": "library",
|
|
145
|
+
"bom-ref": "registry+https://github.com/rust-lang/crates.io-index#quote@1.0.45",
|
|
146
|
+
"author": "David Tolnay <dtolnay@gmail.com>",
|
|
147
|
+
"name": "quote",
|
|
148
|
+
"version": "1.0.45",
|
|
149
|
+
"description": "Quasi-quoting macro quote!(...)",
|
|
150
|
+
"scope": "required",
|
|
151
|
+
"hashes": [
|
|
152
|
+
{
|
|
153
|
+
"alg": "SHA-256",
|
|
154
|
+
"content": "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
|
|
155
|
+
}
|
|
156
|
+
],
|
|
157
|
+
"licenses": [
|
|
158
|
+
{
|
|
159
|
+
"expression": "MIT OR Apache-2.0"
|
|
160
|
+
}
|
|
161
|
+
],
|
|
162
|
+
"purl": "pkg:cargo/quote@1.0.45",
|
|
163
|
+
"externalReferences": [
|
|
164
|
+
{
|
|
165
|
+
"type": "documentation",
|
|
166
|
+
"url": "https://docs.rs/quote/"
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
"type": "vcs",
|
|
170
|
+
"url": "https://github.com/dtolnay/quote"
|
|
171
|
+
}
|
|
172
|
+
]
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
"type": "library",
|
|
176
|
+
"bom-ref": "registry+https://github.com/rust-lang/crates.io-index#serde@1.0.228",
|
|
177
|
+
"author": "Erick Tryzelaar <erick.tryzelaar@gmail.com>, David Tolnay <dtolnay@gmail.com>",
|
|
178
|
+
"name": "serde",
|
|
179
|
+
"version": "1.0.228",
|
|
180
|
+
"description": "A generic serialization/deserialization framework",
|
|
181
|
+
"scope": "required",
|
|
182
|
+
"hashes": [
|
|
183
|
+
{
|
|
184
|
+
"alg": "SHA-256",
|
|
185
|
+
"content": "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
|
|
186
|
+
}
|
|
187
|
+
],
|
|
188
|
+
"licenses": [
|
|
189
|
+
{
|
|
190
|
+
"expression": "MIT OR Apache-2.0"
|
|
191
|
+
}
|
|
192
|
+
],
|
|
193
|
+
"purl": "pkg:cargo/serde@1.0.228",
|
|
194
|
+
"externalReferences": [
|
|
195
|
+
{
|
|
196
|
+
"type": "documentation",
|
|
197
|
+
"url": "https://docs.rs/serde"
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
"type": "website",
|
|
201
|
+
"url": "https://serde.rs"
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
"type": "vcs",
|
|
205
|
+
"url": "https://github.com/serde-rs/serde"
|
|
206
|
+
}
|
|
207
|
+
]
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
"type": "library",
|
|
211
|
+
"bom-ref": "registry+https://github.com/rust-lang/crates.io-index#serde_core@1.0.228",
|
|
212
|
+
"author": "Erick Tryzelaar <erick.tryzelaar@gmail.com>, David Tolnay <dtolnay@gmail.com>",
|
|
213
|
+
"name": "serde_core",
|
|
214
|
+
"version": "1.0.228",
|
|
215
|
+
"description": "Serde traits only, with no support for derive -- use the `serde` crate instead",
|
|
216
|
+
"scope": "required",
|
|
217
|
+
"hashes": [
|
|
218
|
+
{
|
|
219
|
+
"alg": "SHA-256",
|
|
220
|
+
"content": "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
|
|
221
|
+
}
|
|
222
|
+
],
|
|
223
|
+
"licenses": [
|
|
224
|
+
{
|
|
225
|
+
"expression": "MIT OR Apache-2.0"
|
|
226
|
+
}
|
|
227
|
+
],
|
|
228
|
+
"purl": "pkg:cargo/serde_core@1.0.228",
|
|
229
|
+
"externalReferences": [
|
|
230
|
+
{
|
|
231
|
+
"type": "documentation",
|
|
232
|
+
"url": "https://docs.rs/serde_core"
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
"type": "website",
|
|
236
|
+
"url": "https://serde.rs"
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
"type": "vcs",
|
|
240
|
+
"url": "https://github.com/serde-rs/serde"
|
|
241
|
+
}
|
|
242
|
+
]
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
"type": "library",
|
|
246
|
+
"bom-ref": "registry+https://github.com/rust-lang/crates.io-index#serde_derive@1.0.228",
|
|
247
|
+
"author": "Erick Tryzelaar <erick.tryzelaar@gmail.com>, David Tolnay <dtolnay@gmail.com>",
|
|
248
|
+
"name": "serde_derive",
|
|
249
|
+
"version": "1.0.228",
|
|
250
|
+
"description": "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]",
|
|
251
|
+
"scope": "required",
|
|
252
|
+
"hashes": [
|
|
253
|
+
{
|
|
254
|
+
"alg": "SHA-256",
|
|
255
|
+
"content": "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
|
|
256
|
+
}
|
|
257
|
+
],
|
|
258
|
+
"licenses": [
|
|
259
|
+
{
|
|
260
|
+
"expression": "MIT OR Apache-2.0"
|
|
261
|
+
}
|
|
262
|
+
],
|
|
263
|
+
"purl": "pkg:cargo/serde_derive@1.0.228",
|
|
264
|
+
"externalReferences": [
|
|
265
|
+
{
|
|
266
|
+
"type": "documentation",
|
|
267
|
+
"url": "https://serde.rs/derive.html"
|
|
268
|
+
},
|
|
269
|
+
{
|
|
270
|
+
"type": "website",
|
|
271
|
+
"url": "https://serde.rs"
|
|
272
|
+
},
|
|
273
|
+
{
|
|
274
|
+
"type": "vcs",
|
|
275
|
+
"url": "https://github.com/serde-rs/serde"
|
|
276
|
+
}
|
|
277
|
+
]
|
|
278
|
+
},
|
|
279
|
+
{
|
|
280
|
+
"type": "library",
|
|
281
|
+
"bom-ref": "registry+https://github.com/rust-lang/crates.io-index#serde_json@1.0.150",
|
|
282
|
+
"author": "Erick Tryzelaar <erick.tryzelaar@gmail.com>, David Tolnay <dtolnay@gmail.com>",
|
|
283
|
+
"name": "serde_json",
|
|
284
|
+
"version": "1.0.150",
|
|
285
|
+
"description": "A JSON serialization file format",
|
|
286
|
+
"scope": "required",
|
|
287
|
+
"hashes": [
|
|
288
|
+
{
|
|
289
|
+
"alg": "SHA-256",
|
|
290
|
+
"content": "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9"
|
|
291
|
+
}
|
|
292
|
+
],
|
|
293
|
+
"licenses": [
|
|
294
|
+
{
|
|
295
|
+
"expression": "MIT OR Apache-2.0"
|
|
296
|
+
}
|
|
297
|
+
],
|
|
298
|
+
"purl": "pkg:cargo/serde_json@1.0.150",
|
|
299
|
+
"externalReferences": [
|
|
300
|
+
{
|
|
301
|
+
"type": "documentation",
|
|
302
|
+
"url": "https://docs.rs/serde_json"
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
"type": "vcs",
|
|
306
|
+
"url": "https://github.com/serde-rs/json"
|
|
307
|
+
}
|
|
308
|
+
]
|
|
309
|
+
},
|
|
310
|
+
{
|
|
311
|
+
"type": "library",
|
|
312
|
+
"bom-ref": "registry+https://github.com/rust-lang/crates.io-index#syn@2.0.117",
|
|
313
|
+
"author": "David Tolnay <dtolnay@gmail.com>",
|
|
314
|
+
"name": "syn",
|
|
315
|
+
"version": "2.0.117",
|
|
316
|
+
"description": "Parser for Rust source code",
|
|
317
|
+
"scope": "required",
|
|
318
|
+
"hashes": [
|
|
319
|
+
{
|
|
320
|
+
"alg": "SHA-256",
|
|
321
|
+
"content": "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
|
|
322
|
+
}
|
|
323
|
+
],
|
|
324
|
+
"licenses": [
|
|
325
|
+
{
|
|
326
|
+
"expression": "MIT OR Apache-2.0"
|
|
327
|
+
}
|
|
328
|
+
],
|
|
329
|
+
"purl": "pkg:cargo/syn@2.0.117",
|
|
330
|
+
"externalReferences": [
|
|
331
|
+
{
|
|
332
|
+
"type": "documentation",
|
|
333
|
+
"url": "https://docs.rs/syn"
|
|
334
|
+
},
|
|
335
|
+
{
|
|
336
|
+
"type": "vcs",
|
|
337
|
+
"url": "https://github.com/dtolnay/syn"
|
|
338
|
+
}
|
|
339
|
+
]
|
|
340
|
+
},
|
|
341
|
+
{
|
|
342
|
+
"type": "library",
|
|
343
|
+
"bom-ref": "registry+https://github.com/rust-lang/crates.io-index#unicode-ident@1.0.24",
|
|
344
|
+
"author": "David Tolnay <dtolnay@gmail.com>",
|
|
345
|
+
"name": "unicode-ident",
|
|
346
|
+
"version": "1.0.24",
|
|
347
|
+
"description": "Determine whether characters have the XID_Start or XID_Continue properties according to Unicode Standard Annex #31",
|
|
348
|
+
"scope": "required",
|
|
349
|
+
"hashes": [
|
|
350
|
+
{
|
|
351
|
+
"alg": "SHA-256",
|
|
352
|
+
"content": "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
|
353
|
+
}
|
|
354
|
+
],
|
|
355
|
+
"licenses": [
|
|
356
|
+
{
|
|
357
|
+
"expression": "(MIT OR Apache-2.0) AND Unicode-3.0"
|
|
358
|
+
}
|
|
359
|
+
],
|
|
360
|
+
"purl": "pkg:cargo/unicode-ident@1.0.24",
|
|
361
|
+
"externalReferences": [
|
|
362
|
+
{
|
|
363
|
+
"type": "documentation",
|
|
364
|
+
"url": "https://docs.rs/unicode-ident"
|
|
365
|
+
},
|
|
366
|
+
{
|
|
367
|
+
"type": "vcs",
|
|
368
|
+
"url": "https://github.com/dtolnay/unicode-ident"
|
|
369
|
+
}
|
|
370
|
+
]
|
|
371
|
+
},
|
|
372
|
+
{
|
|
373
|
+
"type": "library",
|
|
374
|
+
"bom-ref": "registry+https://github.com/rust-lang/crates.io-index#zmij@1.0.21",
|
|
375
|
+
"author": "David Tolnay <dtolnay@gmail.com>",
|
|
376
|
+
"name": "zmij",
|
|
377
|
+
"version": "1.0.21",
|
|
378
|
+
"description": "A double-to-string conversion algorithm based on Schubfach and yy",
|
|
379
|
+
"scope": "required",
|
|
380
|
+
"hashes": [
|
|
381
|
+
{
|
|
382
|
+
"alg": "SHA-256",
|
|
383
|
+
"content": "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
|
|
384
|
+
}
|
|
385
|
+
],
|
|
386
|
+
"licenses": [
|
|
387
|
+
{
|
|
388
|
+
"expression": "MIT"
|
|
389
|
+
}
|
|
390
|
+
],
|
|
391
|
+
"purl": "pkg:cargo/zmij@1.0.21",
|
|
392
|
+
"externalReferences": [
|
|
393
|
+
{
|
|
394
|
+
"type": "documentation",
|
|
395
|
+
"url": "https://docs.rs/zmij"
|
|
396
|
+
},
|
|
397
|
+
{
|
|
398
|
+
"type": "vcs",
|
|
399
|
+
"url": "https://github.com/dtolnay/zmij"
|
|
400
|
+
}
|
|
401
|
+
]
|
|
402
|
+
}
|
|
403
|
+
],
|
|
404
|
+
"dependencies": [
|
|
405
|
+
{
|
|
406
|
+
"ref": "path+file:///D:/a/modellens/modellens#mod-trace@0.1.0",
|
|
407
|
+
"dependsOn": [
|
|
408
|
+
"registry+https://github.com/rust-lang/crates.io-index#serde@1.0.228",
|
|
409
|
+
"registry+https://github.com/rust-lang/crates.io-index#serde_json@1.0.150"
|
|
410
|
+
]
|
|
411
|
+
},
|
|
412
|
+
{
|
|
413
|
+
"ref": "registry+https://github.com/rust-lang/crates.io-index#itoa@1.0.18"
|
|
414
|
+
},
|
|
415
|
+
{
|
|
416
|
+
"ref": "registry+https://github.com/rust-lang/crates.io-index#memchr@2.8.1"
|
|
417
|
+
},
|
|
418
|
+
{
|
|
419
|
+
"ref": "registry+https://github.com/rust-lang/crates.io-index#proc-macro2@1.0.106",
|
|
420
|
+
"dependsOn": [
|
|
421
|
+
"registry+https://github.com/rust-lang/crates.io-index#unicode-ident@1.0.24"
|
|
422
|
+
]
|
|
423
|
+
},
|
|
424
|
+
{
|
|
425
|
+
"ref": "registry+https://github.com/rust-lang/crates.io-index#quote@1.0.45",
|
|
426
|
+
"dependsOn": [
|
|
427
|
+
"registry+https://github.com/rust-lang/crates.io-index#proc-macro2@1.0.106"
|
|
428
|
+
]
|
|
429
|
+
},
|
|
430
|
+
{
|
|
431
|
+
"ref": "registry+https://github.com/rust-lang/crates.io-index#serde@1.0.228",
|
|
432
|
+
"dependsOn": [
|
|
433
|
+
"registry+https://github.com/rust-lang/crates.io-index#serde_core@1.0.228",
|
|
434
|
+
"registry+https://github.com/rust-lang/crates.io-index#serde_derive@1.0.228"
|
|
435
|
+
]
|
|
436
|
+
},
|
|
437
|
+
{
|
|
438
|
+
"ref": "registry+https://github.com/rust-lang/crates.io-index#serde_core@1.0.228",
|
|
439
|
+
"dependsOn": [
|
|
440
|
+
"registry+https://github.com/rust-lang/crates.io-index#serde_derive@1.0.228"
|
|
441
|
+
]
|
|
442
|
+
},
|
|
443
|
+
{
|
|
444
|
+
"ref": "registry+https://github.com/rust-lang/crates.io-index#serde_derive@1.0.228",
|
|
445
|
+
"dependsOn": [
|
|
446
|
+
"registry+https://github.com/rust-lang/crates.io-index#proc-macro2@1.0.106",
|
|
447
|
+
"registry+https://github.com/rust-lang/crates.io-index#quote@1.0.45",
|
|
448
|
+
"registry+https://github.com/rust-lang/crates.io-index#syn@2.0.117"
|
|
449
|
+
]
|
|
450
|
+
},
|
|
451
|
+
{
|
|
452
|
+
"ref": "registry+https://github.com/rust-lang/crates.io-index#serde_json@1.0.150",
|
|
453
|
+
"dependsOn": [
|
|
454
|
+
"registry+https://github.com/rust-lang/crates.io-index#itoa@1.0.18",
|
|
455
|
+
"registry+https://github.com/rust-lang/crates.io-index#memchr@2.8.1",
|
|
456
|
+
"registry+https://github.com/rust-lang/crates.io-index#serde@1.0.228",
|
|
457
|
+
"registry+https://github.com/rust-lang/crates.io-index#serde_core@1.0.228",
|
|
458
|
+
"registry+https://github.com/rust-lang/crates.io-index#zmij@1.0.21"
|
|
459
|
+
]
|
|
460
|
+
},
|
|
461
|
+
{
|
|
462
|
+
"ref": "registry+https://github.com/rust-lang/crates.io-index#syn@2.0.117",
|
|
463
|
+
"dependsOn": [
|
|
464
|
+
"registry+https://github.com/rust-lang/crates.io-index#proc-macro2@1.0.106",
|
|
465
|
+
"registry+https://github.com/rust-lang/crates.io-index#quote@1.0.45",
|
|
466
|
+
"registry+https://github.com/rust-lang/crates.io-index#unicode-ident@1.0.24"
|
|
467
|
+
]
|
|
468
|
+
},
|
|
469
|
+
{
|
|
470
|
+
"ref": "registry+https://github.com/rust-lang/crates.io-index#unicode-ident@1.0.24"
|
|
471
|
+
},
|
|
472
|
+
{
|
|
473
|
+
"ref": "registry+https://github.com/rust-lang/crates.io-index#zmij@1.0.21"
|
|
474
|
+
}
|
|
475
|
+
]
|
|
476
|
+
}
|