mjolnir-cli 0.2.0__py3-none-any.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.
Files changed (80) hide show
  1. mjolnir_cli/__init__.py +8 -0
  2. mjolnir_cli/__main__.py +4 -0
  3. mjolnir_cli/accuracy.py +333 -0
  4. mjolnir_cli/autoresearch.py +539 -0
  5. mjolnir_cli/benchy.py +475 -0
  6. mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/NVFP4/config.yaml +78 -0
  7. mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/NVFP4_DFLASH2/config.yaml +103 -0
  8. mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/NVFP4_DSPARK/config.yaml +102 -0
  9. mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/NVFP4_FA2/config.yaml +84 -0
  10. mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/NVFP4_FA4hd256/config.yaml +104 -0
  11. mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/NVFP4_MJOLNIR/config.yaml +86 -0
  12. mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/NVFP4_MJOLNIR_E2M3/config.yaml +93 -0
  13. mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/NVFP4_MJOLNIR_E2M3_DFLASH2/config.yaml +123 -0
  14. mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/NVFP4_MJOLNIR_E2M3_DSPARK/config.yaml +124 -0
  15. mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/NVFP4_MJOLNIR_E2M3_LMH8/.env +2 -0
  16. mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/NVFP4_MJOLNIR_E2M3_LMH8/config.yaml +98 -0
  17. mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/NVFP4_MJOLNIR_E2M3_LMH8_VT32K/.env +4 -0
  18. mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/NVFP4_MJOLNIR_E2M3_LMH8_VT32K/config.yaml +98 -0
  19. mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/NVFP4_MJOLNIR_E2M3_LMH8_VT64K/.env +4 -0
  20. mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/NVFP4_MJOLNIR_E2M3_LMH8_VT64K/config.yaml +102 -0
  21. mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/NVFP4_MJOLNIR_E2M3_VT32K/.env +3 -0
  22. mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/NVFP4_MJOLNIR_E2M3_VT32K/config.yaml +98 -0
  23. mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/draft_vocab.json +1 -0
  24. mjolnir_cli/bundled/configs/Qwen/Qwen3.8-27B/kv_scales.json +35197 -0
  25. mjolnir_cli/bundled/configs/Qwen/Qwen3.8_chat_template.jinja +456 -0
  26. mjolnir_cli/bundled/docker/litellm/docker-compose.yaml +113 -0
  27. mjolnir_cli/bundled/docker/litellm/litellm.env.example +51 -0
  28. mjolnir_cli/bundled/docker/litellm/litellm_config.template.example.yaml +192 -0
  29. mjolnir_cli/bundled/docker/perses/README.md +89 -0
  30. mjolnir_cli/bundled/docker/perses/dashboards/global-datasource.yaml +17 -0
  31. mjolnir_cli/bundled/docker/perses/dashboards/performance_statistics.yaml +771 -0
  32. mjolnir_cli/bundled/docker/perses/dashboards/project.yaml +13 -0
  33. mjolnir_cli/bundled/docker/perses/dashboards/query_statistics.yaml +399 -0
  34. mjolnir_cli/bundled/docker/perses/docker-compose.yaml +51 -0
  35. mjolnir_cli/bundled/docker/perses/perses.yml +16 -0
  36. mjolnir_cli/bundled/docker/perses/prometheus.template.yaml +20 -0
  37. mjolnir_cli/bundled/scripts/hw/setup-thor.sh +1287 -0
  38. mjolnir_cli/cachectl.py +146 -0
  39. mjolnir_cli/charts.py +1687 -0
  40. mjolnir_cli/cli.py +1480 -0
  41. mjolnir_cli/clidoc.py +170 -0
  42. mjolnir_cli/config.py +346 -0
  43. mjolnir_cli/dockerctl.py +533 -0
  44. mjolnir_cli/drivers/fa2_driver.py +89 -0
  45. mjolnir_cli/drivers/fi_driver.py +134 -0
  46. mjolnir_cli/e2e.py +302 -0
  47. mjolnir_cli/fonts/InterDisplay-Bold.ttf +0 -0
  48. mjolnir_cli/fonts/InterDisplay-Medium.ttf +0 -0
  49. mjolnir_cli/fonts/InterDisplay-Regular.ttf +0 -0
  50. mjolnir_cli/fonts/InterDisplay-SemiBold.ttf +0 -0
  51. mjolnir_cli/fonts/OFL.txt +92 -0
  52. mjolnir_cli/gate.py +233 -0
  53. mjolnir_cli/history.py +159 -0
  54. mjolnir_cli/interactive.py +383 -0
  55. mjolnir_cli/legs.py +109 -0
  56. mjolnir_cli/litellm.py +254 -0
  57. mjolnir_cli/perses.py +214 -0
  58. mjolnir_cli/picker.py +70 -0
  59. mjolnir_cli/readme.py +1020 -0
  60. mjolnir_cli/stack.py +340 -0
  61. mjolnir_cli/tasks.py +122 -0
  62. mjolnir_cli/theme.py +281 -0
  63. mjolnir_cli/thor.py +108 -0
  64. mjolnir_cli/verify/__init__.py +2 -0
  65. mjolnir_cli/verify/cli.py +816 -0
  66. mjolnir_cli/verify/docker.py +334 -0
  67. mjolnir_cli/verify/kvcache.py +180 -0
  68. mjolnir_cli/verify/legs.py +134 -0
  69. mjolnir_cli/verify/ncu.py +141 -0
  70. mjolnir_cli/verify/profile.py +312 -0
  71. mjolnir_cli/verify/report.py +177 -0
  72. mjolnir_cli/verify/results.py +157 -0
  73. mjolnir_cli/verify/spec.py +279 -0
  74. mjolnir_cli/verify/stages.py +817 -0
  75. mjolnir_cli-0.2.0.dist-info/METADATA +87 -0
  76. mjolnir_cli-0.2.0.dist-info/RECORD +80 -0
  77. mjolnir_cli-0.2.0.dist-info/WHEEL +4 -0
  78. mjolnir_cli-0.2.0.dist-info/entry_points.txt +2 -0
  79. mjolnir_cli-0.2.0.dist-info/licenses/LICENSE +202 -0
  80. mjolnir_cli-0.2.0.dist-info/licenses/NOTICE +64 -0
@@ -0,0 +1,192 @@
1
+ # Example LiteLLM proxy config template.
2
+ #
3
+ # Copy this to the litellm data dir and edit it to match your topology —
4
+ # that file is what `mjolnir litellm` reads (override the location with
5
+ # $MJOLNIR_LITELLM_TEMPLATE):
6
+ # cp litellm_config.template.example.yaml \
7
+ # ~/.local/share/mjolnir/litellm/litellm_config.template.yaml
8
+ #
9
+ # Variable substitution (envsubst-style) happens at `mjolnir litellm up`
10
+ # time, with:
11
+ # * injected from the active mjolnir model/config (the point of the CLI):
12
+ # ${MAIN_LLM_MODEL} served model name (served-model-name)
13
+ # ${MAIN_LLM_MODEL_NAME} raw model field from the config yaml
14
+ # ${RAW_MODEL_SUFFIXED} <model>-<quant>
15
+ # ${LITELLM_MAIN_MODEL_BASE_URL} default http://host.docker.internal:<vllm port>/v1
16
+ # * everything else from your env file ($MJOLNIR_LITELLM_ENV, default
17
+ # ~/.local/share/mjolnir/litellm/litellm.env — see litellm.env.example).
18
+ #
19
+ # Keep task-model sections (embeddings, stt, tts, ...) commented out unless
20
+ # you serve those models — every UNDEFINED ${VAR} in non-comment lines makes
21
+ # `mjolnir litellm up` fail with a list of the missing variables.
22
+
23
+ model_list:
24
+ # ========================================================================
25
+ # Main Model (reasoning ENABLED) — the active mjolnir model/config
26
+ # ========================================================================
27
+ - model_name: ${MAIN_LLM_MODEL}
28
+ litellm_params: &main_litellm_params
29
+ model: hosted_vllm/${MAIN_LLM_MODEL}
30
+ api_base: ${LITELLM_MAIN_MODEL_BASE_URL}
31
+ extra_body:
32
+ chat_template_kwargs:
33
+ thinking: true
34
+ enable_thinking: true
35
+ enable_reasoning: true
36
+ preserve_thinking: true
37
+ model_info: &main_model_info
38
+ supports_reasoning: True
39
+ input_cost_per_token: 0.00000058
40
+ output_cost_per_token: 0.00000301
41
+ cache_read_input_token_cost: 0.0000000833
42
+ cache_creation_input_token_cost: 0.0
43
+
44
+ # ========================================================================
45
+ # Main Model Alias (reasoning DISABLED)
46
+ # ------------------------------------------------------------------------
47
+ # Inherits boilerplate via << merge keys, overrides only the toggles.
48
+ # chat_template_kwargs INSIDE extra_body is REQUIRED for reliable
49
+ # propagation to the vLLM OpenAI-compatible server.
50
+ # ========================================================================
51
+ - model_name: ${MAIN_LLM_MODEL}-no-reasoning
52
+ litellm_params:
53
+ <<: *main_litellm_params
54
+ extra_body:
55
+ chat_template_kwargs:
56
+ thinking: false
57
+ enable_thinking: false
58
+ enable_reasoning: false
59
+ preserve_thinking: false
60
+ model_info:
61
+ <<: *main_model_info
62
+ supports_reasoning: False
63
+
64
+ # ========================================================================
65
+ # Optional task models — uncomment the sections you serve, and define
66
+ # the matching variables in your env file (litellm.env.example).
67
+ # ========================================================================
68
+
69
+ # Small LLM Task Model (port 8006 on your task-models host)
70
+ # - model_name: ${TASKS_LLM_MODEL}
71
+ # litellm_params:
72
+ # model: hosted_vllm/${TASKS_LLM_MODEL}
73
+ # api_base: ${TASK_MODELS_BASE_URL}:8006/v1
74
+
75
+ # Graph DB LLM Model (port 8000)
76
+ # - model_name: ${GRAPH_LLM_MODEL}
77
+ # litellm_params:
78
+ # model: hosted_vllm/${GRAPH_LLM_MODEL}
79
+ # api_base: ${TASK_MODELS_BASE_URL}:8000/v1
80
+
81
+ # Embeddings Model (port 8001)
82
+ # - model_name: ${EMBEDDINGS_MODEL}
83
+ # litellm_params:
84
+ # model: hosted_vllm/${EMBEDDINGS_MODEL}
85
+ # api_base: ${TASK_MODELS_BASE_URL}:8001/v1
86
+ # extra_body:
87
+ # encoding_format: float
88
+ # model_info:
89
+ # mode: embedding
90
+
91
+ # Re-Ranker Model (port 8002)
92
+ # - model_name: ${RERANKER_MODEL}
93
+ # litellm_params:
94
+ # model: hosted_vllm/${RERANKER_MODEL}
95
+ # api_base: ${TASK_MODELS_BASE_URL}:8002/v1
96
+ # model_info:
97
+ # mode: rerank
98
+
99
+ # STT Model (port 8005)
100
+ # - model_name: ${STT_MODEL}
101
+ # litellm_params:
102
+ # model: openai/${STT_MODEL}
103
+ # api_base: ${TASK_MODELS_BASE_URL}:8005/v1
104
+ # model_info:
105
+ # mode: audio_transcription
106
+
107
+ # TTS Model (port 8005)
108
+ # - model_name: ${TTS_MODEL}
109
+ # litellm_params:
110
+ # model: openai/${TTS_MODEL}
111
+ # api_base: ${TASK_MODELS_BASE_URL}:8005/v1
112
+ # model_info:
113
+ # mode: audio_speech
114
+ # voice: ${TTS_MODEL_VOICE}
115
+ # health_check_voice: ${TTS_MODEL_VOICE}
116
+
117
+ general_settings:
118
+ forward_openai_org_id: true
119
+ disable_spend_logs: false # spend logs land in the bundled postgres
120
+
121
+ user_header_mappings:
122
+ - header_name: X-OpenWebUI-User-Id
123
+ litellm_user_role: internal_user
124
+ - header_name: X-OpenWebUI-User-Email
125
+ litellm_user_role: customer
126
+
127
+ litellm_settings:
128
+ ssl_verify: false
129
+ turn_off_message_logging: true
130
+ enable_json_schema_validation: true
131
+ drop_params: true
132
+
133
+ # caching with redis (the bundled litellm_redis container)
134
+ cache: true
135
+ cache_params:
136
+ type: redis
137
+
138
+ default_fallbacks:
139
+ - ${MAIN_LLM_MODEL}
140
+
141
+ router_settings:
142
+ optional_pre_call_checks: ["responses_api_deployment_check"]
143
+
144
+ # the os.environ/... lookups resolve LITELLM_REDIS_* inside the proxy
145
+ # container (set in docker-compose.yaml's environment:)
146
+ redis_host: os.environ/LITELLM_REDIS_HOST
147
+ redis_port: os.environ/LITELLM_REDIS_PORT
148
+ redis_password: os.environ/LITELLM_REDIS_PASSWORD
149
+
150
+ model_group_alias:
151
+ "${MAIN_LLM_MODEL_NAME}":
152
+ model: ${MAIN_LLM_MODEL}
153
+ hidden: true
154
+
155
+ "${RAW_MODEL_SUFFIXED}":
156
+ model: ${MAIN_LLM_MODEL}
157
+ hidden: true
158
+
159
+ llm:
160
+ model: ${MAIN_LLM_MODEL}
161
+ hidden: false
162
+
163
+ llm-no-reasoning:
164
+ model: ${MAIN_LLM_MODEL}-no-reasoning
165
+ hidden: false
166
+
167
+ # Uncomment with the matching model_list sections:
168
+ # small-llm:
169
+ # model: ${TASKS_LLM_MODEL}
170
+ # hidden: true
171
+ # graph-llm:
172
+ # model: ${GRAPH_LLM_MODEL}
173
+ # hidden: true
174
+ # rank:
175
+ # model: ${RERANKER_MODEL}
176
+ # hidden: false
177
+ # embed:
178
+ # model: ${EMBEDDINGS_MODEL}
179
+ # hidden: true
180
+ # text-embedding-3-small:
181
+ # model: ${EMBEDDINGS_MODEL}
182
+ # hidden: true
183
+ # tts:
184
+ # model: ${TTS_MODEL}
185
+ # hidden: false
186
+ # stt:
187
+ # model: ${STT_MODEL}
188
+ # hidden: false
189
+
190
+ callback_settings:
191
+ otel:
192
+ message_logging: false
@@ -0,0 +1,89 @@
1
+ # Perses + Prometheus — vLLM observability stack
2
+
3
+ `mjolnir perses up|down|status|logs` drives this stack (docker compose under
4
+ the hood). It is **independent of the vLLM server**, on the same terms as
5
+ `docker/litellm/`: Prometheus scrapes the server's `/metrics` through
6
+ `host.docker.internal:<port>` (the resolved port, same as `mjolnir serve`),
7
+ so the stack works whether the server is up or down — while the server is
8
+ down the `vllm` target simply shows `down`.
9
+
10
+ Services (compose project `mjolnir-perses`):
11
+
12
+ | service | image | host port (default) | role |
13
+ |--------------|------------------------|---------------------|------|
14
+ | `perses` | `persesdev/perses` | `8080` | the dashboard UI (the OSS observability dashboard) |
15
+ | `prometheus` | `prom/prometheus` | `9090` | scrapes the vLLM `/metrics` every 15s (targets view: `/targets`) |
16
+
17
+ The UI: **http://127.0.0.1:8080** — the two vLLM dashboards
18
+ (*Performance Statistics*, *Query Statistics*) are already there.
19
+
20
+ ## The vLLM dashboards — vendored from vllm-project/vllm
21
+
22
+ `dashboards/` vendors `examples/observability/dashboards/perses/`
23
+ (fetched 2026-09-30) from the vLLM repo. Three adaptations make them work
24
+ standalone (every panel/query/layout is otherwise verbatim):
25
+
26
+ 1. **`kind: PersesDashboard` → `kind: Dashboard`** — the upstream files use
27
+ the k8s-operator CRD kind form; the standalone API/provisioning only
28
+ accepts `Dashboard` (`pkg/model/api/v1/kind.go::GetKind` has no
29
+ `PersesDashboard` case).
30
+ 2. **`project: ""` → `project: vllm`** — standalone Perses is
31
+ project-centric: the UI only renders a dashboard whose `metadata.project`
32
+ matches an existing `Project` resource (it groups dashboards by project
33
+ and drops the rest). The upstream files ship `project: ""`, which is
34
+ invisible — so `project.yaml` provisions a `vllm` project and both
35
+ dashboards point at it.
36
+ 3. **The `namespace=`/`service=` matchers are satisfied by target labels.**
37
+ Every `query_statistics` panel carries `namespace="$NS",service="$SVC"`
38
+ label matchers (and the `$NS`/`$SVC` variables query `up{service=~".*vllm.*"}`).
39
+ Those labels don't exist on a plain Prometheus scrape — so
40
+ `prometheus.template.yaml` attaches `namespace: mjolnir` +
41
+ `service: mjolnir-vllm` to the scrape job's target, which makes
42
+ `up{...}` and every panel matcher line up. (The `performance_statistics`
43
+ dashboard instead filters on the `model_name` label, which vLLM exports
44
+ by default.)
45
+
46
+ The Prometheus datasource itself (`global-datasource.yaml`) is provisioned
47
+ the same way — the name `accelerators-thanos-querier-datasource` is fixed by
48
+ the upstream dashboard files (the k8s-operator example they derive from);
49
+ the URL points at the compose-network `prometheus` service.
50
+
51
+ Provisioning is built into Perses (`provisioning.folders` in `perses.yml`):
52
+ at startup, and re-synced hourly, the server loads every known resource from
53
+ the read-only `dashboards/` folder. No `percli apply` step.
54
+
55
+ ## vLLM metrics — which flags are needed
56
+
57
+ **None.** Every metric both dashboards query
58
+ (`e2e_request_latency_seconds`, `time_to_first_token_seconds`,
59
+ `inter_token_latency_seconds`, `iteration_tokens_total`,
60
+ `kv_cache_usage_perc`, `num_requests_running`, `num_requests_waiting`,
61
+ `prompt_tokens_total`, `generation_tokens_total`, `request_success_total`)
62
+ is part of the **default** vLLM `/metrics` export — verified against the
63
+ live vLLM 0.31.0 server (the `mjolnir-vllm` container) in this repo.
64
+ Prometheus is on by default (the serve line never passes
65
+ `--disable-metrics`), and the dashboards filter by the `model_name` label,
66
+ which vLLM labels every request metric with (the served model name). The
67
+ existing serve flags `--enable-force-include-usage` /
68
+ `--enable-prompt-tokens-details` affect response bodies, not metrics — left
69
+ as-is.
70
+
71
+ ## Data layout
72
+
73
+ All user-persisted files in one dir — `$MJOLNIR_PERSER_DATA` or
74
+ `$MJOLNIR_DATA/perses` (default `~/.local/share/mjolnir/perses`):
75
+
76
+ ```
77
+ perses.env optional env file ($MJOLNIR_PERSER_ENV): ports, image tags,
78
+ PERSER_VLLM_TARGET (override the scrape target)
79
+ prometheus.yml rendered on every `perses up` (the scrape target)
80
+ db/ Perses file database (project + dashboards + datasource)
81
+ prom/ Prometheus TSDB (scrape history survives down/up)
82
+ ```
83
+
84
+ `perses down` keeps all of it; `perses down --purge` wipes `db/` + `prom/`.
85
+ The services run as their images' nonroot uid, so the subdirs they create
86
+ under `db/`/`prom/` are `0750` and undeletable by the host user — the purge
87
+ therefore runs a throwaway **root** `busybox` container to `rm -rf` them
88
+ (root bypasses the permissions), falling back to a host `rmtree` if docker
89
+ can't run (see `_purge_data` in `src/mjolnir-cli/mjolnir_cli/stack.py`).
@@ -0,0 +1,17 @@
1
+ # The Prometheus datasource the vLLM dashboards reference. The name is fixed
2
+ # by the upstream dashboard files (every panel/variable points at
3
+ # "accelerators-thanos-querier-datasource"); the URL is the compose-network
4
+ # prometheus service. Provisioned into Perses from this folder at startup
5
+ # (and re-synced hourly — see perses.yml).
6
+ kind: GlobalDatasource
7
+ metadata:
8
+ name: accelerators-thanos-querier-datasource
9
+ spec:
10
+ default: true
11
+ plugin:
12
+ kind: PrometheusDatasource
13
+ spec:
14
+ proxy:
15
+ kind: HTTPProxy
16
+ spec:
17
+ url: http://prometheus:9090