mjolnir-cli 0.2.0__tar.gz → 0.4.2__tar.gz
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.
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/.gitignore +14 -0
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/NOTICE +1 -1
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/PKG-INFO +40 -14
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/README.md +32 -4
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/__init__.py +1 -1
- mjolnir_cli-0.4.2/mjolnir_cli/__main__.py +10 -0
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/accuracy.py +135 -19
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/autoresearch.py +151 -45
- mjolnir_cli-0.4.2/mjolnir_cli/availability.py +349 -0
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/benchy.py +25 -11
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/AWQ_FLASHINFER/README.md +69 -0
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/AWQ_FLASHINFER/config.yaml +77 -0
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/AWQ_FLASHINFER/platforms/orin.yaml +18 -0
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/AWQ_MJOLNIR/README.md +36 -0
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/AWQ_MJOLNIR/config.yaml +81 -0
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/AWQ_MJOLNIR/platforms/orin.yaml +18 -0
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/AWQ_MJOLNIR_E2M3/.env +4 -0
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/AWQ_MJOLNIR_E2M3/README.md +36 -0
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/AWQ_MJOLNIR_E2M3/config.yaml +82 -0
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/AWQ_MJOLNIR_E2M3/platforms/orin.yaml +18 -0
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/AWQ_MJOLNIR_E2M3_VT64K/.env +6 -0
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/AWQ_MJOLNIR_E2M3_VT64K/README.md +43 -0
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/AWQ_MJOLNIR_E2M3_VT64K/config.yaml +90 -0
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/AWQ_MJOLNIR_E2M3_VT64K/platforms/orin.yaml +18 -0
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/AWQ_MJOLNIR_VT64K/.env +4 -0
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/AWQ_MJOLNIR_VT64K/README.md +84 -0
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/AWQ_MJOLNIR_VT64K/config.yaml +83 -0
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/AWQ_MJOLNIR_VT64K/platforms/orin.yaml +18 -0
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/NVFP4/README.md +114 -0
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/NVFP4/platforms/orin.yaml +5 -0
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/NVFP4/platforms/spark.yaml +5 -0
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/NVFP4/platforms/thor.yaml +4 -0
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/NVFP4_DFLASH2/README.md +36 -0
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/NVFP4_DSPARK/README.md +36 -0
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/NVFP4_FA2/README.md +36 -0
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/NVFP4_FA4hd256/README.md +36 -0
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/NVFP4_MJOLNIR/README.md +82 -0
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/NVFP4_MJOLNIR_E2M3/README.md +82 -0
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/NVFP4_MJOLNIR_E2M3_DFLASH2/README.md +36 -0
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/NVFP4_MJOLNIR_E2M3_DSPARK/README.md +36 -0
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/NVFP4_MJOLNIR_E2M3_LMH8_VT64K/README.md +102 -0
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/README.md +87 -0
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/kv_scales/draft_vocab-awq.json +1 -0
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/kv_scales/e2m3-awq.json +35197 -0
- mjolnir_cli-0.2.0/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/kv_scales.json → mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/kv_scales/e2m3.json +18842 -18842
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/nvidia/Qwen3.6-35B-A3B/NVFP4_DFLASH/.env +4 -0
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/nvidia/Qwen3.6-35B-A3B/NVFP4_DFLASH/README.md +72 -0
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/nvidia/Qwen3.6-35B-A3B/NVFP4_DFLASH/config.yaml +42 -0
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/nvidia/Qwen3.6-35B-A3B/NVFP4_MJOLNIR/README.md +65 -0
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/nvidia/Qwen3.6-35B-A3B/NVFP4_MJOLNIR/config.yaml +55 -0
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/nvidia/Qwen3.6-35B-A3B/NVFP4_MJOLNIR_E2M3/.env +3 -0
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/nvidia/Qwen3.6-35B-A3B/NVFP4_MJOLNIR_E2M3/README.md +102 -0
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/nvidia/Qwen3.6-35B-A3B/NVFP4_MJOLNIR_E2M3/config.yaml +48 -0
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/nvidia/Qwen3.6-35B-A3B/NVFP4_MJOLNIR_E2M3_LMH8_VT64K/.env +3 -0
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/nvidia/Qwen3.6-35B-A3B/NVFP4_MJOLNIR_E2M3_LMH8_VT64K/README.md +82 -0
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/nvidia/Qwen3.6-35B-A3B/NVFP4_MJOLNIR_E2M3_LMH8_VT64K/config.yaml +41 -0
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/nvidia/Qwen3.6-35B-A3B/NVFP4_MJOLNIR_E2M3_VT64K/.env +2 -0
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/nvidia/Qwen3.6-35B-A3B/NVFP4_MJOLNIR_E2M3_VT64K/README.md +36 -0
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/nvidia/Qwen3.6-35B-A3B/NVFP4_MJOLNIR_E2M3_VT64K/config.yaml +38 -0
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/nvidia/Qwen3.6-35B-A3B/README.md +62 -0
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/nvidia/Qwen3.6-35B-A3B/draft_vocab.json +1 -0
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/configs/nvidia/Qwen3.6-35B-A3B/kv_scales/e2m3.json +11425 -0
- mjolnir_cli-0.2.0/mjolnir_cli/bundled/scripts/hw/setup-thor.sh → mjolnir_cli-0.4.2/mjolnir_cli/bundled/scripts/hw/setup-jetson-steps.sh +128 -421
- mjolnir_cli-0.4.2/mjolnir_cli/bundled/scripts/hw/setup-jetson.sh +413 -0
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/cachectl.py +2 -3
- mjolnir_cli-0.4.2/mjolnir_cli/charts.py +633 -0
- mjolnir_cli-0.4.2/mjolnir_cli/charts_base.py +358 -0
- mjolnir_cli-0.4.2/mjolnir_cli/charts_e2e.py +529 -0
- mjolnir_cli-0.4.2/mjolnir_cli/charts_serving.py +587 -0
- mjolnir_cli-0.4.2/mjolnir_cli/cli.py +125 -0
- mjolnir_cli-0.4.2/mjolnir_cli/cli_shared.py +38 -0
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/clidoc.py +14 -1
- mjolnir_cli-0.4.2/mjolnir_cli/commands/__init__.py +11 -0
- mjolnir_cli-0.4.2/mjolnir_cli/commands/_common.py +58 -0
- mjolnir_cli-0.4.2/mjolnir_cli/commands/bench.py +490 -0
- mjolnir_cli-0.4.2/mjolnir_cli/commands/bench_report.py +104 -0
- mjolnir_cli-0.4.2/mjolnir_cli/commands/calibrate.py +94 -0
- mjolnir_cli-0.4.2/mjolnir_cli/commands/hw.py +102 -0
- mjolnir_cli-0.4.2/mjolnir_cli/commands/image.py +162 -0
- mjolnir_cli-0.4.2/mjolnir_cli/commands/litellm.py +91 -0
- mjolnir_cli-0.4.2/mjolnir_cli/commands/model.py +163 -0
- mjolnir_cli-0.4.2/mjolnir_cli/commands/perses.py +72 -0
- mjolnir_cli-0.4.2/mjolnir_cli/commands/platform.py +46 -0
- mjolnir_cli-0.4.2/mjolnir_cli/commands/results.py +153 -0
- mjolnir_cli-0.4.2/mjolnir_cli/commands/retention.py +35 -0
- mjolnir_cli-0.4.2/mjolnir_cli/commands/serve.py +94 -0
- mjolnir_cli-0.4.2/mjolnir_cli/commands/version.py +12 -0
- mjolnir_cli-0.4.2/mjolnir_cli/commands/window.py +54 -0
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/config.py +140 -24
- mjolnir_cli-0.4.2/mjolnir_cli/config_bench.py +254 -0
- mjolnir_cli-0.4.2/mjolnir_cli/config_profile.py +127 -0
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/dockerctl.py +237 -45
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/drivers/fa2_driver.py +16 -16
- mjolnir_cli-0.4.2/mjolnir_cli/drivers/fa4_driver.py +105 -0
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/drivers/fi_driver.py +11 -1
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/e2e.py +81 -48
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/gate.py +21 -4
- mjolnir_cli-0.4.2/mjolnir_cli/history.py +276 -0
- mjolnir_cli-0.4.2/mjolnir_cli/interactive.py +25 -0
- mjolnir_cli-0.4.2/mjolnir_cli/legs.py +235 -0
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/litellm.py +4 -4
- mjolnir_cli-0.4.2/mjolnir_cli/overlays.py +145 -0
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/perses.py +6 -6
- mjolnir_cli-0.4.2/mjolnir_cli/platforms.py +542 -0
- mjolnir_cli-0.4.2/mjolnir_cli/py.typed +0 -0
- mjolnir_cli-0.4.2/mjolnir_cli/rawprune.py +111 -0
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/readme.py +394 -506
- mjolnir_cli-0.4.2/mjolnir_cli/readme_tables.py +406 -0
- mjolnir_cli-0.4.2/mjolnir_cli/readme_targets.py +702 -0
- mjolnir_cli-0.4.2/mjolnir_cli/retention.py +167 -0
- mjolnir_cli-0.4.2/mjolnir_cli/site/__init__.py +9 -0
- mjolnir_cli-0.4.2/mjolnir_cli/site/app.css +136 -0
- mjolnir_cli-0.4.2/mjolnir_cli/site/app.js +662 -0
- mjolnir_cli-0.4.2/mjolnir_cli/site/data.py +161 -0
- mjolnir_cli-0.4.2/mjolnir_cli/site/page.py +123 -0
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/stack.py +10 -8
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/tasks.py +31 -13
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/theme.py +52 -25
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/thor.py +44 -5
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/verify/cli.py +136 -61
- mjolnir_cli-0.4.2/mjolnir_cli/verify/correctness.py +263 -0
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/verify/docker.py +134 -21
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/verify/kvcache.py +1 -1
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/verify/legs.py +77 -9
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/verify/ncu.py +45 -15
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/verify/profile.py +7 -5
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/verify/report.py +1 -2
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/verify/results.py +99 -11
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/verify/stages.py +197 -256
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/pyproject.toml +11 -11
- mjolnir_cli-0.2.0/mjolnir_cli/__main__.py +0 -4
- mjolnir_cli-0.2.0/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/NVFP4_MJOLNIR_E2M3_LMH8/.env +0 -2
- mjolnir_cli-0.2.0/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/NVFP4_MJOLNIR_E2M3_LMH8/config.yaml +0 -98
- mjolnir_cli-0.2.0/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/NVFP4_MJOLNIR_E2M3_LMH8_VT32K/.env +0 -4
- mjolnir_cli-0.2.0/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/NVFP4_MJOLNIR_E2M3_LMH8_VT32K/config.yaml +0 -98
- mjolnir_cli-0.2.0/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/NVFP4_MJOLNIR_E2M3_VT32K/.env +0 -3
- mjolnir_cli-0.2.0/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/NVFP4_MJOLNIR_E2M3_VT32K/config.yaml +0 -98
- mjolnir_cli-0.2.0/mjolnir_cli/charts.py +0 -1687
- mjolnir_cli-0.2.0/mjolnir_cli/cli.py +0 -1480
- mjolnir_cli-0.2.0/mjolnir_cli/history.py +0 -159
- mjolnir_cli-0.2.0/mjolnir_cli/interactive.py +0 -383
- mjolnir_cli-0.2.0/mjolnir_cli/legs.py +0 -109
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/LICENSE +0 -0
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/hatch_build.py +0 -0
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/NVFP4/config.yaml +0 -0
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/NVFP4_DFLASH2/config.yaml +0 -0
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/NVFP4_DSPARK/config.yaml +0 -0
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/NVFP4_FA2/config.yaml +0 -0
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/NVFP4_FA4hd256/config.yaml +0 -0
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/NVFP4_MJOLNIR/config.yaml +0 -0
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/NVFP4_MJOLNIR_E2M3/config.yaml +0 -0
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/NVFP4_MJOLNIR_E2M3_DFLASH2/config.yaml +0 -0
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/NVFP4_MJOLNIR_E2M3_DSPARK/config.yaml +0 -0
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/NVFP4_MJOLNIR_E2M3_LMH8_VT64K/.env +0 -0
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/NVFP4_MJOLNIR_E2M3_LMH8_VT64K/config.yaml +0 -0
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/draft_vocab.json +0 -0
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/bundled/configs/Qwen/Qwen3.8_chat_template.jinja +0 -0
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/bundled/docker/litellm/docker-compose.yaml +0 -0
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/bundled/docker/litellm/litellm.env.example +0 -0
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/bundled/docker/litellm/litellm_config.template.example.yaml +0 -0
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/bundled/docker/perses/README.md +0 -0
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/bundled/docker/perses/dashboards/global-datasource.yaml +0 -0
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/bundled/docker/perses/dashboards/performance_statistics.yaml +0 -0
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/bundled/docker/perses/dashboards/project.yaml +0 -0
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/bundled/docker/perses/dashboards/query_statistics.yaml +0 -0
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/bundled/docker/perses/docker-compose.yaml +0 -0
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/bundled/docker/perses/perses.yml +0 -0
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/bundled/docker/perses/prometheus.template.yaml +0 -0
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/fonts/InterDisplay-Bold.ttf +0 -0
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/fonts/InterDisplay-Medium.ttf +0 -0
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/fonts/InterDisplay-Regular.ttf +0 -0
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/fonts/InterDisplay-SemiBold.ttf +0 -0
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/fonts/OFL.txt +0 -0
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/picker.py +0 -0
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/verify/__init__.py +0 -0
- {mjolnir_cli-0.2.0 → mjolnir_cli-0.4.2}/mjolnir_cli/verify/spec.py +0 -0
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
__pycache__/
|
|
2
2
|
*.py[cod]
|
|
3
3
|
.venv/
|
|
4
|
+
.playwright-mcp/
|
|
4
5
|
.pytest_cache/
|
|
5
6
|
.ruff_cache/
|
|
7
|
+
.env
|
|
8
|
+
# the configs' env sidecars are plain mjolnir knobs (calibration paths, feature
|
|
9
|
+
# flags) and ride with the configs; real secrets stay out
|
|
10
|
+
!configs/**/.env
|
|
11
|
+
# coverage artifacts (the CI test stage writes these; they regenerate)
|
|
12
|
+
.coverage
|
|
13
|
+
.coverage.*
|
|
14
|
+
coverage.xml
|
|
15
|
+
.coverage_html/
|
|
6
16
|
dist/
|
|
7
17
|
build/
|
|
8
18
|
*.egg-info/
|
|
@@ -18,6 +28,7 @@ benchmarks/raw/*
|
|
|
18
28
|
!benchmarks/raw/accuracy/
|
|
19
29
|
benchmarks/raw/accuracy/*/*/
|
|
20
30
|
benchmarks/logs/
|
|
31
|
+
benchmarks/staging/
|
|
21
32
|
task/
|
|
22
33
|
|
|
23
34
|
# autoresearch: the live ledger is untracked (discards are `git reset --hard`);
|
|
@@ -26,3 +37,6 @@ research/ledger.jsonl
|
|
|
26
37
|
research/ledger.tsv
|
|
27
38
|
# …and the exported runs ARE committed (the generic runs/ rule above would hide them)
|
|
28
39
|
!research/runs/
|
|
40
|
+
/cutlass/
|
|
41
|
+
/fa2/
|
|
42
|
+
/llamacpp/
|
|
@@ -8,7 +8,7 @@ works listed below; each keeps its own license and copyright notice.
|
|
|
8
8
|
-------------------------------------------------------------------------------
|
|
9
9
|
1. NVIDIA CUTLASS — CuTe DSL examples BSD-3-Clause
|
|
10
10
|
-------------------------------------------------------------------------------
|
|
11
|
-
src/mjolnir/mjolnir/
|
|
11
|
+
src/mjolnir/mjolnir/arch/thor/decode.py (the Mjolnir decode-attention kernel) is
|
|
12
12
|
derived from
|
|
13
13
|
|
|
14
14
|
examples/python/CuTeDSL/cute/blackwell/kernel/attention/mixed_input_fmha/
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: mjolnir-cli
|
|
3
|
-
Version: 0.2
|
|
3
|
+
Version: 0.4.2
|
|
4
4
|
Summary: Serve, benchmark and document LLMs on NVIDIA Jetson AGX Thor: YAML model configs, the Mjolnir vLLM image, KV-cache calibration, kernel / serving / accuracy benchmarks and auto-rendered reports.
|
|
5
|
-
Project-URL: Homepage, https://github.com/
|
|
6
|
-
Project-URL: Documentation, https://github.com/
|
|
7
|
-
Project-URL: Repository, https://github.com/
|
|
8
|
-
Project-URL: Issues, https://github.com/
|
|
9
|
-
Project-URL: Changelog, https://github.com/
|
|
10
|
-
Project-URL: CLI reference, https://github.com/
|
|
5
|
+
Project-URL: Homepage, https://github.com/GoBrrr-ai/mjolnir
|
|
6
|
+
Project-URL: Documentation, https://github.com/GoBrrr-ai/mjolnir/tree/main/docs
|
|
7
|
+
Project-URL: Repository, https://github.com/GoBrrr-ai/mjolnir.git
|
|
8
|
+
Project-URL: Issues, https://github.com/GoBrrr-ai/mjolnir/issues
|
|
9
|
+
Project-URL: Changelog, https://github.com/GoBrrr-ai/mjolnir/releases
|
|
10
|
+
Project-URL: CLI reference, https://github.com/GoBrrr-ai/mjolnir/blob/main/docs/cli.md
|
|
11
11
|
Author-email: Mieszko Syty <mieszko@ms1design.pl>
|
|
12
12
|
License-Expression: Apache-2.0
|
|
13
13
|
License-File: LICENSE
|
|
@@ -18,13 +18,11 @@ Classifier: Environment :: Console
|
|
|
18
18
|
Classifier: Intended Audience :: Developers
|
|
19
19
|
Classifier: Operating System :: POSIX :: Linux
|
|
20
20
|
Classifier: Programming Language :: Python :: 3
|
|
21
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
22
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
23
21
|
Classifier: Programming Language :: Python :: 3.12
|
|
24
22
|
Classifier: Programming Language :: Python :: 3.13
|
|
25
23
|
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
26
24
|
Classifier: Topic :: System :: Benchmark
|
|
27
|
-
Requires-Python: >=3.
|
|
25
|
+
Requires-Python: >=3.12
|
|
28
26
|
Requires-Dist: jinja2>=3.1.6
|
|
29
27
|
Requires-Dist: pyyaml>=6.0.3
|
|
30
28
|
Requires-Dist: rich>=15.0.0
|
|
@@ -36,7 +34,7 @@ Description-Content-Type: text/markdown
|
|
|
36
34
|
# mjolnir-cli
|
|
37
35
|
|
|
38
36
|
**Serve, benchmark and document LLMs on the NVIDIA Jetson AGX Thor** with
|
|
39
|
-
[Mjolnir](https://github.com/
|
|
37
|
+
[Mjolnir](https://github.com/GoBrrr-ai/mjolnir) — a decode-attention kernel
|
|
40
38
|
built for Thor (`sm_110`), a 6-bit KV-cache format for vLLM and a patched vLLM
|
|
41
39
|
image that runs them. This package is the `mjolnir` command that drives all of
|
|
42
40
|
it; the kernel itself ships separately as
|
|
@@ -71,17 +69,45 @@ mjolnir serve up # serve the default model on the Mjolnir image,
|
|
|
71
69
|
tests and logs kernel experiments.
|
|
72
70
|
|
|
73
71
|
Every command, with options and defaults:
|
|
74
|
-
**[the CLI reference](https://github.com/
|
|
72
|
+
**[the CLI reference](https://github.com/GoBrrr-ai/mjolnir/blob/main/docs/cli.md)**
|
|
75
73
|
(generated from the commands; `mjolnir <command> --help` prints the same).
|
|
76
74
|
|
|
75
|
+
## Library use
|
|
76
|
+
|
|
77
|
+
Two modules are declared a public, stable API — reuse them instead of
|
|
78
|
+
re-implementing the clean-window gate or the bench-history substrate:
|
|
79
|
+
|
|
80
|
+
- **`mjolnir_cli.gate`** — `wait_for_idle`, `server_load`, `server_counters`,
|
|
81
|
+
`spec_delta`, the `CleanWindow` context manager, `PreflightError` and the
|
|
82
|
+
`DEFAULT_*` tuning constants.
|
|
83
|
+
- **`mjolnir_cli.history`** — `append_record`, `load_records` and
|
|
84
|
+
`SCHEMA_VERSION`; the history-row schema is documented in the module
|
|
85
|
+
docstring. Rows carry `schema_version` — absence means the legacy (pre-0.3)
|
|
86
|
+
format — and `load_records` returns rows raw, never normalized.
|
|
87
|
+
`append_record` files one record per serving key (platform, model, image,
|
|
88
|
+
config): a re-run merges its cells into the stored record instead of
|
|
89
|
+
appending a line; records without a serving key are appended verbatim.
|
|
90
|
+
|
|
91
|
+
Anything else can change without notice; the module docstrings are the API
|
|
92
|
+
reference: [`gate.py`](https://github.com/GoBrrr-ai/mjolnir/blob/main/src/mjolnir-cli/mjolnir_cli/gate.py),
|
|
93
|
+
[`history.py`](https://github.com/GoBrrr-ai/mjolnir/blob/main/src/mjolnir-cli/mjolnir_cli/history.py).
|
|
94
|
+
|
|
95
|
+
`uv tool install mjolnir-cli` is an isolated CLI install — *not* importable
|
|
96
|
+
from another project. Library use means adding `mjolnir-cli` as a dependency
|
|
97
|
+
of your project (`uv add mjolnir-cli` / `pip install mjolnir-cli`). The
|
|
98
|
+
gate/history import chain is stdlib-only: the CLI dependency stack (typer,
|
|
99
|
+
rich, pyyaml, jinja2) is paid at install time, not import time. Python ≥ 3.12
|
|
100
|
+
is required (pip refuses older interpreters — relevant on JetPack 6-era
|
|
101
|
+
images), and type annotations ship (`py.typed`).
|
|
102
|
+
|
|
77
103
|
## Requirements
|
|
78
104
|
|
|
79
105
|
A Jetson AGX Thor (JetPack 7.x) with Docker and the NVIDIA Container Toolkit
|
|
80
|
-
for anything that touches the GPU; Python ≥ 3.
|
|
106
|
+
for anything that touches the GPU; Python ≥ 3.12. Charts need the `plot` extra
|
|
81
107
|
(`uv tool install 'mjolnir-cli[plot]'`).
|
|
82
108
|
|
|
83
109
|
## Versions
|
|
84
110
|
|
|
85
111
|
`mjolnir-cli` and `mjolnir-kernel` version independently; the Docker image is
|
|
86
112
|
tagged after the upstream vLLM it is built on (`v0.31.0`). Release notes:
|
|
87
|
-
[GitHub Releases](https://github.com/
|
|
113
|
+
[GitHub Releases](https://github.com/GoBrrr-ai/mjolnir/releases).
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# mjolnir-cli
|
|
2
2
|
|
|
3
3
|
**Serve, benchmark and document LLMs on the NVIDIA Jetson AGX Thor** with
|
|
4
|
-
[Mjolnir](https://github.com/
|
|
4
|
+
[Mjolnir](https://github.com/GoBrrr-ai/mjolnir) — a decode-attention kernel
|
|
5
5
|
built for Thor (`sm_110`), a 6-bit KV-cache format for vLLM and a patched vLLM
|
|
6
6
|
image that runs them. This package is the `mjolnir` command that drives all of
|
|
7
7
|
it; the kernel itself ships separately as
|
|
@@ -36,17 +36,45 @@ mjolnir serve up # serve the default model on the Mjolnir image,
|
|
|
36
36
|
tests and logs kernel experiments.
|
|
37
37
|
|
|
38
38
|
Every command, with options and defaults:
|
|
39
|
-
**[the CLI reference](https://github.com/
|
|
39
|
+
**[the CLI reference](https://github.com/GoBrrr-ai/mjolnir/blob/main/docs/cli.md)**
|
|
40
40
|
(generated from the commands; `mjolnir <command> --help` prints the same).
|
|
41
41
|
|
|
42
|
+
## Library use
|
|
43
|
+
|
|
44
|
+
Two modules are declared a public, stable API — reuse them instead of
|
|
45
|
+
re-implementing the clean-window gate or the bench-history substrate:
|
|
46
|
+
|
|
47
|
+
- **`mjolnir_cli.gate`** — `wait_for_idle`, `server_load`, `server_counters`,
|
|
48
|
+
`spec_delta`, the `CleanWindow` context manager, `PreflightError` and the
|
|
49
|
+
`DEFAULT_*` tuning constants.
|
|
50
|
+
- **`mjolnir_cli.history`** — `append_record`, `load_records` and
|
|
51
|
+
`SCHEMA_VERSION`; the history-row schema is documented in the module
|
|
52
|
+
docstring. Rows carry `schema_version` — absence means the legacy (pre-0.3)
|
|
53
|
+
format — and `load_records` returns rows raw, never normalized.
|
|
54
|
+
`append_record` files one record per serving key (platform, model, image,
|
|
55
|
+
config): a re-run merges its cells into the stored record instead of
|
|
56
|
+
appending a line; records without a serving key are appended verbatim.
|
|
57
|
+
|
|
58
|
+
Anything else can change without notice; the module docstrings are the API
|
|
59
|
+
reference: [`gate.py`](https://github.com/GoBrrr-ai/mjolnir/blob/main/src/mjolnir-cli/mjolnir_cli/gate.py),
|
|
60
|
+
[`history.py`](https://github.com/GoBrrr-ai/mjolnir/blob/main/src/mjolnir-cli/mjolnir_cli/history.py).
|
|
61
|
+
|
|
62
|
+
`uv tool install mjolnir-cli` is an isolated CLI install — *not* importable
|
|
63
|
+
from another project. Library use means adding `mjolnir-cli` as a dependency
|
|
64
|
+
of your project (`uv add mjolnir-cli` / `pip install mjolnir-cli`). The
|
|
65
|
+
gate/history import chain is stdlib-only: the CLI dependency stack (typer,
|
|
66
|
+
rich, pyyaml, jinja2) is paid at install time, not import time. Python ≥ 3.12
|
|
67
|
+
is required (pip refuses older interpreters — relevant on JetPack 6-era
|
|
68
|
+
images), and type annotations ship (`py.typed`).
|
|
69
|
+
|
|
42
70
|
## Requirements
|
|
43
71
|
|
|
44
72
|
A Jetson AGX Thor (JetPack 7.x) with Docker and the NVIDIA Container Toolkit
|
|
45
|
-
for anything that touches the GPU; Python ≥ 3.
|
|
73
|
+
for anything that touches the GPU; Python ≥ 3.12. Charts need the `plot` extra
|
|
46
74
|
(`uv tool install 'mjolnir-cli[plot]'`).
|
|
47
75
|
|
|
48
76
|
## Versions
|
|
49
77
|
|
|
50
78
|
`mjolnir-cli` and `mjolnir-kernel` version independently; the Docker image is
|
|
51
79
|
tagged after the upstream vLLM it is built on (`v0.31.0`). Release notes:
|
|
52
|
-
[GitHub Releases](https://github.com/
|
|
80
|
+
[GitHub Releases](https://github.com/GoBrrr-ai/mjolnir/releases).
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"""Run the ``mjolnir`` CLI via ``python -m mjolnir_cli`` — the same entry
|
|
2
|
+
point as the console script (``mjolnir_cli.cli:main``), UnknownPlatform
|
|
3
|
+
handler included."""
|
|
4
|
+
|
|
5
|
+
import sys
|
|
6
|
+
|
|
7
|
+
from mjolnir_cli.cli import main
|
|
8
|
+
|
|
9
|
+
if __name__ == "__main__":
|
|
10
|
+
sys.exit(main())
|
|
@@ -14,8 +14,9 @@ tool-eval-bench keeps its results in ``./data/benchmarks.sqlite`` and
|
|
|
14
14
|
under ``benchmarks/raw/accuracy/<run>/<leg>/``, so the database holds exactly
|
|
15
15
|
that leg's runs. :func:`summarize_db` reads it back into the committed
|
|
16
16
|
``accuracy.json`` (``mjolnir.accuracy/1``): per suite the score, per
|
|
17
|
-
tool-call category the share of points, per scenario the points
|
|
18
|
-
|
|
17
|
+
tool-call category the share of points, per scenario the points, and the ids
|
|
18
|
+
tool-eval-bench excluded from scoring (``excluded``) — what the docs table
|
|
19
|
+
and charts are rendered from.
|
|
19
20
|
"""
|
|
20
21
|
|
|
21
22
|
from __future__ import annotations
|
|
@@ -24,6 +25,7 @@ import json
|
|
|
24
25
|
import os
|
|
25
26
|
import shlex
|
|
26
27
|
import shutil
|
|
28
|
+
import platform as host_platform # the record's host field names the machine (platform.node)
|
|
27
29
|
import sqlite3
|
|
28
30
|
import subprocess
|
|
29
31
|
import sys
|
|
@@ -31,6 +33,9 @@ import time
|
|
|
31
33
|
from pathlib import Path
|
|
32
34
|
from statistics import mean
|
|
33
35
|
|
|
36
|
+
from mjolnir_cli.config import by_model, model_of, model_short
|
|
37
|
+
from mjolnir_cli.platforms import platform_of
|
|
38
|
+
|
|
34
39
|
FORMAT = "mjolnir.accuracy/1"
|
|
35
40
|
TOOL_REPO = "https://github.com/SeraphimSerapis/tool-eval-bench"
|
|
36
41
|
# pinned: a score is only comparable to one produced by the same scenario set
|
|
@@ -94,7 +99,9 @@ def _pct(earned: float, mx: float) -> float | None:
|
|
|
94
99
|
def summarize_db(db: Path) -> dict:
|
|
95
100
|
"""tool-eval-bench's SQLite → ``{"suites": {suite: {...}}, "categories":
|
|
96
101
|
{...}, "scenarios": {...}}``. Several completed runs of a kind (``--trials``)
|
|
97
|
-
are averaged; each suite keeps its per-run scores.
|
|
102
|
+
are averaged; each suite keeps its per-run scores. A scenario the tool
|
|
103
|
+
excluded from scoring (an infrastructure failure: the probe failed, a
|
|
104
|
+
timeout) comes back as ``excluded``."""
|
|
98
105
|
if not db.exists():
|
|
99
106
|
return {"suites": {}, "categories": {}, "scenarios": {}, "runs": []}
|
|
100
107
|
con = sqlite3.connect(f"file:{db}?mode=ro", uri=True)
|
|
@@ -108,13 +115,15 @@ def summarize_db(db: Path) -> dict:
|
|
|
108
115
|
per_suite: dict[str, list[dict]] = {}
|
|
109
116
|
cats: dict[str, dict] = {}
|
|
110
117
|
scen: dict[str, list[float]] = {}
|
|
118
|
+
excluded: set[str] = set()
|
|
111
119
|
runs = []
|
|
112
|
-
for run_id, created, status, run_type, scores_json,
|
|
120
|
+
for run_id, created, status, run_type, scores_json, _config_json in rows:
|
|
113
121
|
runs.append({"run_id": run_id, "created_at": created, "status": status, "run_type": run_type})
|
|
114
122
|
if status != "completed":
|
|
115
123
|
continue
|
|
116
124
|
sc = _loads(scores_json)
|
|
117
125
|
if run_type == "tool_eval":
|
|
126
|
+
excluded |= set(sc.get("excluded_scenarios") or ()) # upstream lists them only when non-empty
|
|
118
127
|
cs = sc.get("category_scores") or []
|
|
119
128
|
std = [c for c in cs if c.get("category") != HARD_CATEGORY]
|
|
120
129
|
hard = [c for c in cs if c.get("category") == HARD_CATEGORY]
|
|
@@ -160,8 +169,13 @@ def summarize_db(db: Path) -> dict:
|
|
|
160
169
|
continue
|
|
161
170
|
last = dict(items[-1])
|
|
162
171
|
last.pop("score", None)
|
|
172
|
+
if all("max" in i for i in items): # every trial's points: deltas rescale each trial exactly
|
|
173
|
+
last["earneds"], last["maxes"] = [i["earned"] for i in items], [i["max"] for i in items]
|
|
174
|
+
comps = [i["completion_rate"] for i in items if i.get("completion_rate") is not None]
|
|
175
|
+
if comps:
|
|
176
|
+
last["completion_rate"] = min(comps) # the worst trial: an exclusion in any trial shows
|
|
163
177
|
suites[name] = {"score": round(mean(scores), 2), "scores": scores, "n": len(scores), **last}
|
|
164
|
-
|
|
178
|
+
out = {
|
|
165
179
|
"suites": suites,
|
|
166
180
|
"categories": {
|
|
167
181
|
k: {"label": v["label"], "percent": round(mean(v["percent"]), 2)}
|
|
@@ -171,6 +185,9 @@ def summarize_db(db: Path) -> dict:
|
|
|
171
185
|
"scenarios": {k: round(mean(v), 3) for k, v in sorted(scen.items())},
|
|
172
186
|
"runs": runs,
|
|
173
187
|
}
|
|
188
|
+
if excluded: # e.g. TC-45: the tool_choice=required probe failed — scored as zero on the full max
|
|
189
|
+
out["excluded"] = sorted(excluded)
|
|
190
|
+
return out
|
|
174
191
|
|
|
175
192
|
|
|
176
193
|
# ── the run ─────────────────────────────────────────────────────────────────
|
|
@@ -204,9 +221,7 @@ def leg_label(rec: dict) -> str:
|
|
|
204
221
|
if "MJOLNIR" not in cfg:
|
|
205
222
|
return f"Mjolnir image · {BACKEND_LABELS.get(cfg, cfg)} · {kv}"
|
|
206
223
|
extra = "".join(
|
|
207
|
-
f" + {name}"
|
|
208
|
-
for tag, name in (("LMH8", "fp8 lm_head"), ("VT32K", "32K draft vocab"), ("VT64K", "64K draft vocab"))
|
|
209
|
-
if tag in cfg.split("_")
|
|
224
|
+
f" + {name}" for tag, name in (("LMH8", "fp8 lm_head"), ("VT64K", "64K draft vocab")) if tag in cfg.split("_")
|
|
210
225
|
)
|
|
211
226
|
return f"Mjolnir · {kv}{extra}"
|
|
212
227
|
|
|
@@ -223,6 +238,7 @@ def run_accuracy(
|
|
|
223
238
|
tool-eval-bench against it, and write ``accuracy.json``. Returns its path."""
|
|
224
239
|
from mjolnir_cli import dockerctl
|
|
225
240
|
from mjolnir_cli.config import config_field
|
|
241
|
+
from mjolnir_cli.platforms import detect, gpu_name
|
|
226
242
|
|
|
227
243
|
tool = find_tool()
|
|
228
244
|
run_id = time.strftime("%Y%m%d-%H%M%S")
|
|
@@ -232,6 +248,10 @@ def run_accuracy(
|
|
|
232
248
|
"format": FORMAT,
|
|
233
249
|
"run_id": run_id,
|
|
234
250
|
"created": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()),
|
|
251
|
+
"host": host_platform.node() or "unknown",
|
|
252
|
+
"gpu": gpu_name(),
|
|
253
|
+
# the detection-first rule: the record names the *detected* platform
|
|
254
|
+
"platform": detect().platform,
|
|
235
255
|
"tool": {"repo": TOOL_REPO, "commit": TOOL_COMMIT, "command": tool},
|
|
236
256
|
"args": list(passthrough) or list(DEFAULT_ARGS),
|
|
237
257
|
"legs": [],
|
|
@@ -292,36 +312,132 @@ def load_runs(layout) -> list[dict]:
|
|
|
292
312
|
|
|
293
313
|
|
|
294
314
|
def latest_legs(docs: list[dict]) -> list[dict]:
|
|
295
|
-
"""One row per (model, image, config): every suite from the
|
|
296
|
-
that measured it (an A/B run and a later GSM8K run merge into
|
|
297
|
-
Order: first appearance.
|
|
315
|
+
"""One row per (platform, model, image side, config): every suite from the
|
|
316
|
+
newest run that measured it (an A/B run and a later GSM8K run merge into
|
|
317
|
+
one row). Order: first appearance. The platform comes from the run doc
|
|
318
|
+
(platform-less records are the repo's Thor history); a leg measured on
|
|
319
|
+
two platforms is two rows — its charts are per (platform, model). The
|
|
320
|
+
side (official image vs Mjolnir) keys the row, not the image tag, so a
|
|
321
|
+
re-measure on a newer image of the same side supersedes the older scores
|
|
322
|
+
in place (the row keeps its position and the newest image) instead of
|
|
323
|
+
duplicating a row the labels cannot tell apart."""
|
|
298
324
|
rows: dict[tuple, dict] = {}
|
|
299
325
|
for d in docs:
|
|
326
|
+
plat = platform_of(d)
|
|
300
327
|
for leg in d.get("legs", []):
|
|
301
|
-
key = (leg
|
|
328
|
+
key = (plat, model_of(leg), _is_mjolnir(str(leg.get("image", ""))), leg.get("config"))
|
|
302
329
|
row = rows.setdefault(
|
|
303
330
|
key,
|
|
304
331
|
{k: leg.get(k) for k in ("id", "model", "image", "config", "label", "kv_cache_dtype", "env")}
|
|
305
|
-
| {"suites": {}, "categories": {}, "scenarios": {}, "runs": {}},
|
|
332
|
+
| {"platform": plat, "suites": {}, "categories": {}, "scenarios": {}, "runs": {}},
|
|
306
333
|
)
|
|
334
|
+
row["image"] = leg.get("image") or row.get("image")
|
|
307
335
|
row["kv_cache_dtype"] = leg.get("kv_cache_dtype") or row.get("kv_cache_dtype")
|
|
308
336
|
row["label"] = leg_label(row) # recomputed: labels improve after a run is stored
|
|
309
337
|
for name, suite in (leg.get("suites") or {}).items():
|
|
310
338
|
row["suites"][name] = suite
|
|
311
339
|
row["runs"][name] = {"run_id": d.get("run_id"), "args": d.get("args")}
|
|
340
|
+
if leg.get("excluded"): # an exclusion in any run of the leg shows
|
|
341
|
+
row["excluded"] = sorted({*(row.get("excluded") or ()), *leg["excluded"]})
|
|
312
342
|
if (leg.get("suites") or {}).keys() & {"tools", "hardmode"}:
|
|
313
343
|
row["categories"] = leg.get("categories") or row["categories"]
|
|
314
344
|
row["scenarios"] = leg.get("scenarios") or row["scenarios"]
|
|
315
|
-
|
|
345
|
+
groups = by_model(r for r in rows.values() if r["suites"])
|
|
346
|
+
if len(groups) > 1: # rows of several models: each model's rows together, labels say which
|
|
347
|
+
for r in (r for g in groups.values() for r in g):
|
|
348
|
+
r["label"] = f"{model_short(r)} · {r['label']}"
|
|
349
|
+
return [r for g in groups.values() for r in g]
|
|
316
350
|
|
|
317
351
|
|
|
318
352
|
def baseline(rows: list[dict]) -> dict | None:
|
|
319
|
-
"""The reference row for deltas
|
|
320
|
-
when measured, else the first row
|
|
321
|
-
|
|
322
|
-
|
|
353
|
+
"""The reference row for deltas among ONE model's rows: native FlashInfer
|
|
354
|
+
on the official image when measured, else the first official-image row,
|
|
355
|
+
else the first row. For mixed rows use :func:`baselines`."""
|
|
356
|
+
official = [r for r in rows if not _is_mjolnir(str(r.get("image", "")))]
|
|
357
|
+
for r in official:
|
|
358
|
+
if r.get("config") == "NVFP4":
|
|
323
359
|
return r
|
|
324
|
-
return
|
|
360
|
+
return (official or rows or [None])[0]
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
def baselines(rows: list[dict]) -> list[dict | None]:
|
|
364
|
+
"""Each row's baseline, in row order: its own model's :func:`baseline`.
|
|
365
|
+
Rows of another model are never a baseline — their scores are not comparable."""
|
|
366
|
+
per_model = {m: baseline(group) for m, group in by_model(rows).items()}
|
|
367
|
+
return [per_model[model_of(r)] for r in rows]
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
def _maxes(s: dict) -> list:
|
|
371
|
+
"""Every trial's max for a suite (older records keep only the last trial's)."""
|
|
372
|
+
return list(s.get("maxes") or ([s["max"]] if s.get("max") else []))
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
def _on_max(s: dict, m: float) -> float:
|
|
376
|
+
"""The suite's score with every trial's points over ``m``: exact from the
|
|
377
|
+
per-trial points when recorded, else from the one run's points, else from
|
|
378
|
+
the mean % (an older averaged record, which keeps only the last max)."""
|
|
379
|
+
if s.get("earneds"):
|
|
380
|
+
return mean(e / m * 100 for e in s["earneds"])
|
|
381
|
+
if s.get("n", 1) == 1 and "earned" in s:
|
|
382
|
+
return s["earned"] / m * 100
|
|
383
|
+
return s["score"] * s["max"] / m
|
|
384
|
+
|
|
385
|
+
|
|
386
|
+
def delta(r: dict, base: dict | None, name: str) -> tuple[float, bool] | None:
|
|
387
|
+
"""Points ``r`` scored over ``base`` on suite ``name``, and whether an
|
|
388
|
+
excluded scenario was scored as zero (None when ``r`` is the baseline,
|
|
389
|
+
either lacks the suite, or the two measured different scenario sets).
|
|
390
|
+
|
|
391
|
+
tool-eval-bench drops a scenario it judged the endpoint unable to serve
|
|
392
|
+
(TC-45 when its ``tool_choice=required`` probe fails, a timeout, an error),
|
|
393
|
+
which shrinks that trial's max and lowers its completion rate, so its %
|
|
394
|
+
divides by less. Then every trial of both legs is scored on the largest
|
|
395
|
+
max, the excluded points counting as zero: an exclusion never raises a
|
|
396
|
+
delta. Different maxes at full completion mean different scenario sets
|
|
397
|
+
(another run's arguments), which no rescaling makes comparable."""
|
|
398
|
+
if base is None or r is base:
|
|
399
|
+
return None
|
|
400
|
+
v, b = r.get("suites", {}).get(name) or {}, base.get("suites", {}).get(name) or {}
|
|
401
|
+
if v.get("score") is None or b.get("score") is None:
|
|
402
|
+
return None
|
|
403
|
+
maxes = _maxes(v) + _maxes(b)
|
|
404
|
+
if len(set(maxes)) > 1:
|
|
405
|
+
if all(x.get("completion_rate", 100.0) >= 100.0 for x in (v, b)):
|
|
406
|
+
return None
|
|
407
|
+
m = max(maxes)
|
|
408
|
+
return _on_max(v, m) - _on_max(b, m), True
|
|
409
|
+
return v["score"] - b["score"], False
|
|
410
|
+
|
|
411
|
+
|
|
412
|
+
def fmt_delta(d: tuple[float, bool] | None) -> str:
|
|
413
|
+
"""' (+1.2)', ' (-1.4‡)' when an excluded scenario was scored as zero, '' for no delta."""
|
|
414
|
+
return f" ({d[0]:+.1f}{'‡' if d[1] else ''})" if d else ""
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
def leg_excluded(r: dict, base: dict | None, names: list[str]) -> bool:
|
|
418
|
+
"""Whether any of ``r``'s suite deltas scored an excluded scenario as zero."""
|
|
419
|
+
return any((d := delta(r, base, n)) and d[1] for n in names)
|
|
420
|
+
|
|
421
|
+
|
|
422
|
+
def any_excluded(rows: list[dict], bases: list[dict | None], names: list[str]) -> bool:
|
|
423
|
+
return any(leg_excluded(r, b, names) for r, b in zip(rows, bases, strict=True))
|
|
424
|
+
|
|
425
|
+
|
|
426
|
+
EXCLUDED_NOTE = (
|
|
427
|
+
"‡ = tool-eval-bench excluded a scenario on one of the two legs; the delta scores both on the full max, "
|
|
428
|
+
"the excluded points counting as zero"
|
|
429
|
+
)
|
|
430
|
+
EXCLUDED_NOTE_SHORT = "‡ = a scenario was excluded on one side, scored as zero"
|
|
431
|
+
CATEGORY_EXCLUDED_NOTE = (
|
|
432
|
+
"‡ = this leg had a scenario excluded: its category % divides by the smaller max, so one category reads high"
|
|
433
|
+
)
|
|
434
|
+
|
|
435
|
+
|
|
436
|
+
def baseline_caption(bases: list[dict | None], item_sep: str = " · ") -> str:
|
|
437
|
+
"""The distinct baseline labels, first-seen order, ' / '-joined ('' if none);
|
|
438
|
+
``item_sep`` replaces the label's own ' · ' separator."""
|
|
439
|
+
labels = dict.fromkeys(b["label"].replace(" · ", item_sep) for b in bases if b is not None)
|
|
440
|
+
return " / ".join(labels)
|
|
325
441
|
|
|
326
442
|
|
|
327
443
|
def suites_in(rows: list[dict]) -> list[str]:
|