cemi-cli 0.1.1__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.
Files changed (32) hide show
  1. cemi_cli-0.1.1/PKG-INFO +362 -0
  2. cemi_cli-0.1.1/README.md +349 -0
  3. cemi_cli-0.1.1/cemi/__init__.py +3 -0
  4. cemi_cli-0.1.1/cemi/api.py +49 -0
  5. cemi_cli-0.1.1/cemi/auth.py +107 -0
  6. cemi_cli-0.1.1/cemi/cli.py +629 -0
  7. cemi_cli-0.1.1/cemi/config.py +78 -0
  8. cemi_cli-0.1.1/cemi/contract.py +474 -0
  9. cemi_cli-0.1.1/cemi/decision_layer.py +353 -0
  10. cemi_cli-0.1.1/cemi/defaults.py +16 -0
  11. cemi_cli-0.1.1/cemi/examples/__init__.py +3 -0
  12. cemi_cli-0.1.1/cemi/examples/test_writer.py +50 -0
  13. cemi_cli-0.1.1/cemi/local_server.py +704 -0
  14. cemi_cli-0.1.1/cemi/workspace_dist/assets/bc28cd3b23be4b191421f0ead27bb2b9b7c23ff5-BAdrl-eN.png +0 -0
  15. cemi_cli-0.1.1/cemi/workspace_dist/assets/index-APOCwJvs.js +234 -0
  16. cemi_cli-0.1.1/cemi/workspace_dist/assets/index-S1cVBpyp.css +1 -0
  17. cemi_cli-0.1.1/cemi/workspace_dist/index.html +45 -0
  18. cemi_cli-0.1.1/cemi/writer.py +1239 -0
  19. cemi_cli-0.1.1/cemi_cli.egg-info/PKG-INFO +362 -0
  20. cemi_cli-0.1.1/cemi_cli.egg-info/SOURCES.txt +30 -0
  21. cemi_cli-0.1.1/cemi_cli.egg-info/dependency_links.txt +1 -0
  22. cemi_cli-0.1.1/cemi_cli.egg-info/entry_points.txt +2 -0
  23. cemi_cli-0.1.1/cemi_cli.egg-info/requires.txt +7 -0
  24. cemi_cli-0.1.1/cemi_cli.egg-info/top_level.txt +1 -0
  25. cemi_cli-0.1.1/pyproject.toml +35 -0
  26. cemi_cli-0.1.1/setup.cfg +4 -0
  27. cemi_cli-0.1.1/tests/test_local_gateway_smoke.py +150 -0
  28. cemi_cli-0.1.1/tests/test_multi_model_benchmark.py +274 -0
  29. cemi_cli-0.1.1/tests/test_multi_model_gateway_e2e.py +298 -0
  30. cemi_cli-0.1.1/tests/test_retroactive_save_dir.py +64 -0
  31. cemi_cli-0.1.1/tests/test_single_model_train_eval.py +292 -0
  32. cemi_cli-0.1.1/tests/test_writer_contract.py +146 -0
@@ -0,0 +1,362 @@
1
+ Metadata-Version: 2.4
2
+ Name: cemi-cli
3
+ Version: 0.1.1
4
+ Summary: CEMI: An Edge AI MLOps Tool for Model Compression and Embedded Deployment
5
+ Requires-Python: >=3.9
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: click>=8.0
8
+ Requires-Dist: msal>=1.0
9
+ Requires-Dist: requests>=2.31
10
+ Requires-Dist: rich>=13.0
11
+ Provides-Extra: dev
12
+ Requires-Dist: pytest>=7.0; extra == "dev"
13
+
14
+ # CEMI CLI
15
+
16
+ ## Install
17
+
18
+ ### From PyPI
19
+
20
+ The recommended public distribution is the published package from PyPI:
21
+
22
+ ```bash
23
+ pip install cemi-cli
24
+ ```
25
+
26
+ This is the preferred install path because it:
27
+
28
+ - avoids a source checkout
29
+ - avoids requiring Node/Vite on tester machines
30
+ - installs the exact published CLI package
31
+
32
+ ### From source (developer install only)
33
+
34
+ Install locally (from repo root):
35
+
36
+ ```bash
37
+ pip install -e ./cli
38
+ ```
39
+
40
+ ## Local-only quick start (canonical flow)
41
+
42
+ 1. **Install**: install from PyPI with `pip install cemi-cli`, or use `pip install -e ./cli` for development.
43
+ 2. **In your script**: `create_writer(project="...", log_dir="...")` — runs go to `log_dir/runs/`, artifacts to `log_dir/artifacts/`. Default `log_dir` is `.cemi`.
44
+ 3. **Start the gateway** (same path as `log_dir`): `cemi gateway` or `cemi gateway --save-dir /path/to/log_dir`.
45
+ 4. **Open the workspace**: `cemi view` or open `http://127.0.0.1:3141/workspace`. No login; runs and metrics appear in the UI.
46
+
47
+ **Contract**: Writer and gateway must use the same directory: Writer writes `log_dir/runs/<run_id>.jsonl` and `log_dir/artifacts/<run_id>/...`; gateway reads that directory via `--save-dir` (default `.cemi`).
48
+
49
+ **Defaults (local):** Default directory is `.cemi` (current working directory). Default gateway port is `3141`. Default project is `default`. To use another directory, pass the same path to `create_writer(log_dir=...)` and `cemi gateway --save-dir <path>`.
50
+
51
+ **Custom port:** If you run `cemi gateway -p 3142`, set `CEMI_LOCAL_SERVER_URL=http://127.0.0.1:3142` so the Writer's artifact URLs (from `add_local_file_artifact`) point to the same server. Otherwise the UI may 404 when loading artifacts.
52
+
53
+ **Verify install:** From repo root: `pip install -e ./cli && pip install -e './cli[dev]' && pytest cli/tests/ -q` to run tests.
54
+
55
+ **Troubleshooting:** For common issues (no runs, artifact 404, custom port), see the root README **Troubleshooting** section.
56
+
57
+ ---
58
+
59
+ ## Monitoring another repo (e.g. compression-engine)
60
+
61
+ If you have a separate training or compression repo (e.g. **compression-engine** with MNIST benchmarks, PTQ, QAT), you can monitor its experiments in CEMI by adding only **Writer calls** to your existing code—no new training recipes.
62
+
63
+ **Compression-engine (actual repo):** Entry point is `python -m engine.main --config <config.yaml>` with optional `--log-dir .cemi`. The YAML config sets `benchmark.models` (e.g. resnet18, mobilenetv2, vit-tiny) and `benchmark.compression.method` (ptq or qat). One run creates one CEMI run per model. Example configs: `benchmark_config_cemi_test.yaml`, `benchmark_config_PTQ.yaml`, `benchmark_config_QAT.yaml`.
64
+
65
+ ### What to add in the training repo (only Writer calls)
66
+
67
+ 1. **Create a writer** — Either:
68
+ - `create_writer(project="...", log_dir=...)` with `log_dir` from your script’s CLI arg (e.g. `--log-dir`, default `.cemi`), or
69
+ - When run under `cemi start`, use `create_writer_from_env()` so the script uses `CEMI_SAVE_DIR` and `CEMI_RUN_ID` set by the CLI.
70
+ 2. **Per run** — In your existing training/inference loop:
71
+ - `start_run(name=..., tags=...)` (e.g. tags: `method=ptq`, `method=qat`, `model=resnet18`).
72
+ - `log_parameter` and `log_metric` in the same places you already compute them.
73
+ - `add_local_file_artifact(path=..., kind="model")` for ONNX or checkpoints so the UI can serve them.
74
+ - `log_summary_metrics(...)`, `end_run(status="succeeded"|"failed")`, `emit_run_record()`.
75
+
76
+ Do not wire a new training recipe; only instrument existing loops.
77
+
78
+ ### How to run (pip user, minimal env)
79
+
80
+ Run from your **compression-engine repo** directory (where your training/benchmark script lives). No CEMI repo script to run—your code does the training; CEMI only records it.
81
+
82
+ - **Option A — Gateway and view first, then run your script:**
83
+ Terminal 1: `cemi gateway --save-dir .cemi` (or `cemi view --save-dir .cemi` to start gateway and open UI).
84
+ Terminal 2: `python -m engine.main --config benchmark_config_cemi_test.yaml --log-dir .cemi`
85
+
86
+ - **Option B — One command (gateway + UI + your script):**
87
+ `cemi start --save-dir .cemi --project compression-engine -- python -m engine.main --config benchmark_config_cemi_test.yaml`
88
+ Your script uses `create_writer_from_env()` so it picks up `CEMI_SAVE_DIR` and `CEMI_RUN_ID`; no need to pass `--log-dir` when run via `cemi start`.
89
+
90
+ ### Success criteria
91
+
92
+ Run **your** training/benchmark script from the compression-engine repo (the code that runs is in that repo, not in CEMI). Three runs (e.g. 3 models on MNIST, one PTQ, one QAT) should appear in the CEMI workspace with metrics and artifacts. Use the same `log_dir` / `--save-dir` for the Writer and the gateway.
93
+
94
+ **Where to run:** From the **compression-engine repo** directory: `cemi start --save-dir .cemi --project compression-engine -- python -m engine.main --config benchmark_config_cemi_test.yaml`. Config sets models and compression method (ptq/qat); one CEMI run per model. CEMI does not provide a separate “demo run” script—you run your existing code with writer calls added.
95
+
96
+ ---
97
+
98
+ ## Package behavior
99
+
100
+ This package is intentionally local-only by default.
101
+
102
+ | Command | Auth required? | Data destination |
103
+ |---------|----------------|------------------|
104
+ | `cemi start -- python train.py` | No | Local files under `save_dir` plus the local gateway |
105
+ | `cemi view` | No | Opens the local workspace UI pointing at the local gateway |
106
+ | `cemi gateway` | No | Serves the local workspace and reads local run/artifact files |
107
+ | `cemi stop` | No | Stops local background services started by the CLI |
108
+
109
+ ---
110
+
111
+ ## Local-first flow (no account)
112
+
113
+ 1. Install the CLI and add the Writer to your training script (see **Writer usage** below).
114
+ 2. Start a run with your script:
115
+ - `cemi start -- python train.py` — Ensures a local gateway is available, sets a local run id, wires env vars, and opens the workspace UI.
116
+
117
+ In local mode, the workspace UI is served directly by the gateway at:
118
+
119
+ - `http://127.0.0.1:3141/workspace`
120
+
121
+ When the workspace UI calls `GET /api/health` on the configured `VITE_API_BASE_URL`, the local gateway responds with:
122
+
123
+ ```json
124
+ { "status": "ok", "mode": "local" }
125
+ ```
126
+
127
+ This tells the UI to **skip any login flow** and go straight to the `/workspace` area to visualize your local runs.
128
+
129
+ No login required; everything stays on your machine.
130
+
131
+ ---
132
+
133
+ ## Retroactive local viewing (job already running)
134
+
135
+ If your training/validation job is **already running** and writing to a directory, use the same path for the gateway:
136
+
137
+ - Your code uses `create_writer(project="...", log_dir="/path/to/dir")` so events are in `log_dir/runs/<run_id>.jsonl` and `log_dir/artifacts/<run_id>/...`.
138
+ - Later (in another terminal, or a machine that can read that directory), start the gateway with the same path: `cemi gateway --save-dir /path/to/dir`, then `cemi view` or open `http://127.0.0.1:3141/workspace`.
139
+
140
+ Example:
141
+
142
+ ```python
143
+ from cemi.writer import create_writer
144
+
145
+ writer = create_writer(project="demo", log_dir="/tmp/cemi-demo")
146
+ writer.start_run(name="retroactive-demo")
147
+ writer.log_metric(name="loss", value=0.5, step=1)
148
+ writer.emit_run_record()
149
+ ```
150
+
151
+ Then later:
152
+
153
+ ```bash
154
+ cemi gateway --save-dir /tmp/cemi-demo
155
+ cemi view
156
+ ```
157
+
158
+ ---
159
+
160
+ ## Environment variables
161
+
162
+ **For local-only use:** none required. Prefer passing `log_dir` to `create_writer(project, log_dir)` so your script and the gateway share the same directory. Optional env vars (used by `create_writer_from_env()` and `cemi start`):
163
+
164
+ - **CEMI_SAVE_DIR** — Base directory for runs and artifacts; same as `log_dir` in `create_writer`. Gateway `--save-dir` should match.
165
+ - **CEMI_LOCAL_DIR** — Override for run JSONL directory (default: `<log_dir>/runs`).
166
+ - **CEMI_ARTIFACTS_DIR** — Override for artifacts (default: `<log_dir>/artifacts`).
167
+ - **CEMI_LOCAL_SERVER_URL** — URL of the local gateway if you want the Writer to stream live to `cemi gateway`.
168
+ - **CEMI_SINK** — Local sink selection such as `local` or `local+local_server`.
169
+
170
+ ---
171
+
172
+ ## Usage
173
+
174
+ ```bash
175
+ cemi # welcome banner + usage
176
+ cemi help # help and usage
177
+ cemi config # show local config
178
+ cemi start -- python train.py
179
+ # local run: ensure gateway, open workspace UI, run your command
180
+ cemi view # open local workspace UI (no run created)
181
+ cemi gateway # start local gateway server (read .cemi/runs, accept POST /api/events)
182
+ cemi gateway --save-dir /path/to/save_dir
183
+ # retroactive local: read /path/to/save_dir/runs and serve /path/to/save_dir/artifacts
184
+ cemi view --save-dir /path/to/save_dir
185
+ # open workspace UI for that directory (gateway must use same path)
186
+ cemi view --dev-ui # use Vite dev server for workspace (only when running from repo; after pip install use embedded workspace)
187
+ cemi --help # full CLI help
188
+ ```
189
+
190
+ ---
191
+
192
+ ## Writer usage
193
+
194
+ **Local-only (recommended):** use `create_writer(project, log_dir)` so runs and artifacts go to `log_dir/runs/` and `log_dir/artifacts/`. Use the same path with `cemi gateway --save-dir <log_dir>` so the workspace can read them.
195
+
196
+ ```python
197
+ from cemi.writer import create_writer
198
+
199
+ writer = create_writer(project="my-project", log_dir=".cemi") # default log_dir is .cemi
200
+ writer.start_run(name="My run")
201
+ writer.log_parameter(key="learning_rate", value=0.001)
202
+ writer.log_metric(name="loss", value=0.5, step=1)
203
+ writer.log_summary_metrics({"final_accuracy": 0.95})
204
+ writer.emit_run_record()
205
+ writer.end_run(status="succeeded")
206
+ writer.emit_run_record()
207
+ ```
208
+
209
+ **With CLI:** when you run `cemi start -- python train.py`, the CLI sets `CEMI_RUN_ID`, `CEMI_PROJECT_ID`, `CEMI_SAVE_DIR`, and `CEMI_LOCAL_SERVER_URL`. Use `create_writer_from_env()` so the Writer uses those env vars and the same local directory as the gateway.
210
+
211
+ ---
212
+
213
+ ## Local data and operations
214
+
215
+ ### What gets written to disk
216
+
217
+ - Run snapshots are appended as JSONL under `save_dir/runs/<run_id>.jsonl`.
218
+ - Copied artifacts are stored under `save_dir/artifacts/<run_id>/`.
219
+ - Local CLI config is stored under `~/.cemi/config.json`.
220
+ - PID files used by `cemi stop` are stored under `~/.cemi/pids/`.
221
+
222
+ ### Where files live by default
223
+
224
+ - If you do not pass `log_dir` or `--save-dir`, the default save directory is `.cemi` in the current working directory.
225
+ - The default layout is:
226
+
227
+ ```text
228
+ .cemi/
229
+ runs/
230
+ artifacts/
231
+ ```
232
+
233
+ - Per-user local state lives under `~/.cemi/`.
234
+
235
+ ### Artifact sensitivity
236
+
237
+ Artifacts may include model binaries, checkpoints, reports, or copied local files.
238
+ Treat `add_local_file_artifact()` as publishing that file to anyone who can access
239
+ your local gateway on your machine. Do not attach secrets, credentials, private
240
+ datasets, or files you would not want copied into the artifact store.
241
+
242
+ ### Gateway bind address
243
+
244
+ The gateway should stay bound to `127.0.0.1` only. It is
245
+ intended for local use on the same machine and should not be exposed on a LAN
246
+ or public interface.
247
+
248
+ ### Browser behavior
249
+
250
+ - `cemi view` opens the browser automatically after the local gateway starts.
251
+ - `cemi start` opens the browser automatically before it launches your command.
252
+ - `cemi gateway` does not open the browser by itself.
253
+
254
+ ### Stop background processes
255
+
256
+ Use:
257
+
258
+ ```bash
259
+ cemi stop
260
+ ```
261
+
262
+ This stops background gateway/frontend processes started by `cemi start --dev-ui`
263
+ or `cemi view --dev-ui`.
264
+
265
+ ### Clear old state
266
+
267
+ To clear old local run data for the current project directory:
268
+
269
+ ```bash
270
+ rm -rf .cemi
271
+ ```
272
+
273
+ To clear per-user CLI state:
274
+
275
+ ```bash
276
+ rm -rf ~/.cemi
277
+ ```
278
+
279
+ Only do this if you are sure you no longer need the saved runs, artifacts, config,
280
+ or PID files.
281
+
282
+ ### Reset a broken local setup
283
+
284
+ 1. Run `cemi stop`.
285
+ 2. Remove stale project state with `rm -rf .cemi` if needed.
286
+ 3. Remove per-user state with `rm -rf ~/.cemi` if config or PID files are stale.
287
+ 4. Reinstall the published package from PyPI.
288
+
289
+ ### Uninstall
290
+
291
+ ```bash
292
+ pip uninstall cemi-cli
293
+ ```
294
+
295
+ If you also want to remove local state, delete `.cemi` in your project directory
296
+ and `~/.cemi` in your home directory.
297
+
298
+ ---
299
+
300
+ ## Model PTQ (ONNXRuntime) quickstart (local)
301
+
302
+ This is a quick local path for **baseline vs INT8 PTQ** monitoring.
303
+
304
+ ### 0) Install the CLI (one-time)
305
+
306
+ From repo root:
307
+
308
+ ```bash
309
+ python3 -m venv .venv
310
+ source .venv/bin/activate
311
+ pip install -e ./cli
312
+ ```
313
+
314
+ ### 1) Start the local gateway
315
+
316
+ Terminal A:
317
+
318
+ ```bash
319
+ export CEMI_LOCAL_DIR=".cemi/runs"
320
+ export CEMI_ARTIFACTS_DIR=".cemi/artifacts"
321
+ cemi gateway
322
+ ```
323
+
324
+ ### 2) Open the embedded workspace UI
325
+
326
+ In a browser, open:
327
+
328
+ - `http://127.0.0.1:3141/workspace`
329
+
330
+ Or run:
331
+
332
+ ```bash
333
+ cemi view
334
+ ```
335
+
336
+ ### 3) Log two runs (baseline + int8 PTQ) with ONNX artifacts
337
+
338
+ Terminal C (repo root, venv active):
339
+
340
+ ```bash
341
+ # Baseline
342
+ python3 scripts/model_ptq_onnxrt_demo.py \
343
+ --variant baseline \
344
+ --model-onnx /path/to/baseline.onnx \
345
+ --summary-metric accuracy=0.765 \
346
+ --summary-metric loss=0.42 \
347
+ --summary-metric energy_j=12.5
348
+
349
+ # INT8 PTQ
350
+ python3 scripts/model_ptq_onnxrt_demo.py \
351
+ --variant int8_ptq \
352
+ --model-onnx /path/to/int8_ptq.onnx \
353
+ --summary-metric accuracy=0.753 \
354
+ --summary-metric loss=0.45 \
355
+ --summary-metric energy_j=10.9
356
+ ```
357
+
358
+ What you get:
359
+ - Runs appear in the workspace Runs table immediately (local-only).
360
+ - You can open a run and the **Graph** tab will load the `.onnx` artifact in the Netron viewer (fetched from the local gateway).
361
+ - Latency samples / throughput will be logged automatically if `onnxruntime` + `numpy` are installed; otherwise you can log your own metrics from your training loop using the Writer.
362
+