@tuned-tensor/local 0.2.9 → 0.4.0
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.
- package/CHANGELOG.md +86 -0
- package/README.md +110 -201
- package/dist/active-model.d.ts +16 -0
- package/dist/active-model.js +88 -0
- package/dist/active-model.js.map +1 -0
- package/dist/artifacts.d.ts +5 -4
- package/dist/artifacts.js +57 -33
- package/dist/artifacts.js.map +1 -1
- package/dist/compare.d.ts +1 -8
- package/dist/compare.js +1 -23
- package/dist/compare.js.map +1 -1
- package/dist/contracts.d.ts +234 -365
- package/dist/contracts.js +95 -224
- package/dist/contracts.js.map +1 -1
- package/dist/dataset.d.ts +11 -4
- package/dist/dataset.js +67 -125
- package/dist/dataset.js.map +1 -1
- package/dist/doctor.d.ts +2 -3
- package/dist/doctor.js +23 -161
- package/dist/doctor.js.map +1 -1
- package/dist/evaluation.d.ts +11 -71
- package/dist/evaluation.js +212 -572
- package/dist/evaluation.js.map +1 -1
- package/dist/general-regression.d.ts +10 -0
- package/dist/general-regression.js +16 -0
- package/dist/general-regression.js.map +1 -0
- package/dist/huggingface-cache.d.ts +8 -7
- package/dist/huggingface-cache.js +16 -8
- package/dist/huggingface-cache.js.map +1 -1
- package/dist/index.d.ts +2 -10
- package/dist/index.js +358 -627
- package/dist/index.js.map +1 -1
- package/dist/local-project.d.ts +1 -11
- package/dist/local-project.js +33 -61
- package/dist/local-project.js.map +1 -1
- package/dist/model-registry.d.ts +3 -16
- package/dist/model-registry.js +76 -292
- package/dist/model-registry.js.map +1 -1
- package/dist/model-server.d.ts +7 -3
- package/dist/model-server.js +34 -25
- package/dist/model-server.js.map +1 -1
- package/dist/orchestrator.d.ts +11 -25
- package/dist/orchestrator.js +393 -563
- package/dist/orchestrator.js.map +1 -1
- package/dist/prefetch.d.ts +1 -5
- package/dist/prefetch.js +14 -19
- package/dist/prefetch.js.map +1 -1
- package/dist/process-runner.d.ts +10 -29
- package/dist/process-runner.js +63 -169
- package/dist/process-runner.js.map +1 -1
- package/dist/process-training.d.ts +0 -1
- package/dist/process-training.js +10 -87
- package/dist/process-training.js.map +1 -1
- package/dist/store.d.ts +1 -3
- package/dist/store.js +92 -290
- package/dist/store.js.map +1 -1
- package/docs/architecture.md +87 -152
- package/docs/spark.md +66 -97
- package/examples/dry-runner.json +14 -0
- package/examples/general-regression.jsonl +4 -0
- package/examples/local-runner.json +13 -6
- package/examples/smoke-spec.json +41 -0
- package/package.json +6 -6
- package/training/local-runner/pyproject.toml +0 -5
- package/training/local-runner/src/evaluate.py +89 -234
- package/training/local-runner/src/model_contract.py +47 -0
- package/training/local-runner/src/prefetch.py +18 -4
- package/training/local-runner/src/serve.py +60 -117
- package/training/local-runner/src/sft_data.py +97 -0
- package/training/local-runner/src/train.py +146 -346
- package/training/local-runner/uv.lock +0 -1197
- package/dist/labeling-sanitize.d.ts +0 -31
- package/dist/labeling-sanitize.js +0 -158
- package/dist/labeling-sanitize.js.map +0 -1
- package/dist/labeling.d.ts +0 -155
- package/dist/labeling.js +0 -496
- package/dist/labeling.js.map +0 -1
- package/dist/openrouter.d.ts +0 -29
- package/dist/openrouter.js +0 -66
- package/dist/openrouter.js.map +0 -1
- package/dist/server.d.ts +0 -9
- package/dist/server.js +0 -211
- package/dist/server.js.map +0 -1
- package/docs/local-workflow-remediation-2026-07-13.md +0 -130
- package/docs/local-workflow-ux-review-2026-07-13.md +0 -458
- package/examples/dpo-preferences.jsonl +0 -2
- package/examples/dpo-run-request.json +0 -34
- package/examples/smoke-run-request.json +0 -34
- package/training/local-runner/src/train_dpo.py +0 -286
|
@@ -1,458 +0,0 @@
|
|
|
1
|
-
# TT Local end-to-end workflow and UX review
|
|
2
|
-
|
|
3
|
-
Date: 2026-07-13
|
|
4
|
-
Reviewed release: `@tuned-tensor/local@0.2.7`
|
|
5
|
-
Repository commit: `3b18464` (`main`)
|
|
6
|
-
Scope: install, init, preflight, validation, base-model download, real fine-tuning,
|
|
7
|
-
evaluation, reports, persisted state, recovery, dashboard, and the handoff to model
|
|
8
|
-
inference.
|
|
9
|
-
|
|
10
|
-
## Executive summary
|
|
11
|
-
|
|
12
|
-
The core training and persistence path works on the DGX Spark once two configuration
|
|
13
|
-
workarounds are applied. A real SFT run completed, its PEFT adapter was loaded for
|
|
14
|
-
candidate evaluation on CUDA, the model archive was valid, the local store was
|
|
15
|
-
internally consistent, and the index could be rebuilt.
|
|
16
|
-
|
|
17
|
-
The current first-run UX is not ready to be presented as a smooth default workflow.
|
|
18
|
-
The most important blockers are:
|
|
19
|
-
|
|
20
|
-
1. Explicit prefetch and runtime model loading use different Hugging Face cache
|
|
21
|
-
layouts, causing a duplicate multi-gigabyte download.
|
|
22
|
-
2. The public no-config quickstart and default evaluator do not select the bundled
|
|
23
|
-
uv project, so `doctor` can pass immediately before `run` fails on `import torch`.
|
|
24
|
-
3. Resuming a run can silently reuse a model trained with old hyperparameters or
|
|
25
|
-
old runner/evaluation configuration.
|
|
26
|
-
4. An empty model directory can be accepted, reported, and indexed as a completed
|
|
27
|
-
model; there is no artifact manifest or verification command.
|
|
28
|
-
5. Subcommand help and unknown-option handling are unsafe: `tt-local run --help`
|
|
29
|
-
starts a run.
|
|
30
|
-
6. There is no tested, documented inference-serving handoff for a TT Local adapter.
|
|
31
|
-
|
|
32
|
-
These should be addressed before optimizing lower-level polish.
|
|
33
|
-
|
|
34
|
-
## What was tested
|
|
35
|
-
|
|
36
|
-
### Automated and packaged checks
|
|
37
|
-
|
|
38
|
-
All existing checks passed:
|
|
39
|
-
|
|
40
|
-
- `npm run typecheck`
|
|
41
|
-
- `npm test`: 79 passed, 0 failed
|
|
42
|
-
- Node test coverage: 91.71% lines, 81.19% branches, 89.39% functions
|
|
43
|
-
- `npm pack --dry-run`: 75 files, 115.7 kB package
|
|
44
|
-
- fresh-prefix installation of the packed `0.2.7` package
|
|
45
|
-
- Python syntax compilation for all bundled runner scripts
|
|
46
|
-
- relevant `tuned-tensor-cli` model-serving tests: 29 passed, 0 failed
|
|
47
|
-
|
|
48
|
-
The high aggregate coverage does not cover the risky integration boundaries well:
|
|
49
|
-
|
|
50
|
-
- `src/index.ts`: 34.97% lines
|
|
51
|
-
- `src/doctor.ts`: 30.00% lines
|
|
52
|
-
- `src/prefetch.ts`: 75.32% lines, 35.71% branches
|
|
53
|
-
- no real Hugging Face download test
|
|
54
|
-
- no subprocess-level CLI contract tests
|
|
55
|
-
- no Python unit/integration tests
|
|
56
|
-
- CI covers Ubuntu x64, not Linux ARM64/DGX Spark or CUDA
|
|
57
|
-
|
|
58
|
-
### Mac dry and command-backed checks
|
|
59
|
-
|
|
60
|
-
A new project was initialized, validated, dry-run, listed, reported, served through
|
|
61
|
-
the dashboard, and rebuilt from its canonical files. JSON, JSONL, SQLite, spec, run,
|
|
62
|
-
event, report, and model records were inspected.
|
|
63
|
-
|
|
64
|
-
Additional reproductions:
|
|
65
|
-
|
|
66
|
-
- `doctor` returned nonzero on a dry-run/no-inference config only because the Mac
|
|
67
|
-
lacks `nvidia-smi`.
|
|
68
|
-
- `validate` printed a generated run ID, but the subsequent spec-based `run`
|
|
69
|
-
generated a different ID.
|
|
70
|
-
- a staged `prepare` invocation printed `"status": "completed"` while persisted
|
|
71
|
-
state remained `preparing`.
|
|
72
|
-
- changing `n_epochs` from 3 to 9 under the same run ID reused every stage and left
|
|
73
|
-
the persisted training hyperparameters at 3.
|
|
74
|
-
- a non-dry custom trainer that exited zero and wrote no files completed the run and
|
|
75
|
-
registered an empty model directory.
|
|
76
|
-
- `tt-local run --help` queued and began a real run path.
|
|
77
|
-
|
|
78
|
-
### DGX Spark real workflow
|
|
79
|
-
|
|
80
|
-
Environment and result:
|
|
81
|
-
|
|
82
|
-
- audit workspace: `/home/eve/tt-local-audit-20260713-XnkDGt`
|
|
83
|
-
- run ID: `f9938d55-1c7d-40f1-9055-de8de5c57ddb`
|
|
84
|
-
- model ID: `local-f9938d55-1c7d-40f1-9055-de8de5c57ddb`
|
|
85
|
-
- resumed full workflow: 97.42 seconds
|
|
86
|
-
- baseline: about 30.9 seconds
|
|
87
|
-
- training stage: about 36.1 seconds; actual three-step trainer runtime 1.55 seconds
|
|
88
|
-
- candidate evaluation: about 30.1 seconds
|
|
89
|
-
- observed GPU memory: 3,760 MiB
|
|
90
|
-
- peak RSS: about 4.79 GB
|
|
91
|
-
|
|
92
|
-
Persistence checks:
|
|
93
|
-
|
|
94
|
-
- model archive: 18,821,402 bytes
|
|
95
|
-
- SHA-256: `ad5b329e89d35c271933c484924a056e4d76ad154823ff78df4e2597ab6404b4`
|
|
96
|
-
- `gzip -t` passed
|
|
97
|
-
- tar inspection passed
|
|
98
|
-
- adapter safetensors/config, tokenizer, chat template, and README were present
|
|
99
|
-
- the training-output tar and convenience copy had the same hash
|
|
100
|
-
- artifact/store request and report copies matched
|
|
101
|
-
- SQLite `integrity_check` returned `ok`
|
|
102
|
-
- store contained 1 spec, 1 run, 38 events, and 1 model
|
|
103
|
-
- `store rebuild-index`, `runs list/get/report/watch`, and `models list/get` passed
|
|
104
|
-
- the dashboard health, run, report, model, and spec APIs returned HTTP 200
|
|
105
|
-
- no audit process or server remains active
|
|
106
|
-
|
|
107
|
-
The successful run required both of these workarounds:
|
|
108
|
-
|
|
109
|
-
1. point `paths.baseModel` directly at the existing cached snapshot;
|
|
110
|
-
2. set `evaluation.inference.project` to `training/local-runner`.
|
|
111
|
-
|
|
112
|
-
## Workflow review
|
|
113
|
-
|
|
114
|
-
| Step | Result | UX assessment |
|
|
115
|
-
|---|---|---|
|
|
116
|
-
| Install package | Pass | Package contains the bundled scripts, but `tt-local --version` is unsupported and the package omits `uv.lock`. |
|
|
117
|
-
| `init` | Pass | Creates a runnable three-epoch placeholder and no runner config; accidental placeholder training is possible. |
|
|
118
|
-
| `doctor` | Misleading | Checks generic uv/Python and `nvidia-smi`, not the exact training/evaluator environments, Torch/CUDA, disk, cache, credentials, or writability. |
|
|
119
|
-
| `validate` | Partial | Schema validation passes, but does not validate placeholder content or runtime prerequisites and prints an ephemeral run ID. |
|
|
120
|
-
| `models prefetch` | Fail | Uses a cache layout different from training/evaluation and hides multi-GB progress unless `--verbose`. |
|
|
121
|
-
| Baseline | Workaround required | Default evaluator misses the bundled uv project; configured cache is also applied too late in Python. |
|
|
122
|
-
| Training | Pass with workaround | Real LoRA training and archive generation worked on Spark. |
|
|
123
|
-
| Candidate evaluation | Pass with workaround | Proved that the saved adapter tar can be extracted and loaded with its base model on CUDA. |
|
|
124
|
-
| Report and state | Pass with caveats | Reports and canonical copies persist, but stale errors and staged-state inconsistencies remain. |
|
|
125
|
-
| Recovery | Pass with caveats | SQLite rebuild works when canonical records exist; a trained artifact is not indexed until the final report completes. |
|
|
126
|
-
| Dashboard | Pass | `tt-local serve` is a state/report dashboard, not model inference. |
|
|
127
|
-
| Model inference server | Missing | `tt-local models serve` does not exist, and the separate hosted CLI handoff is not tested for TT Local adapters. |
|
|
128
|
-
|
|
129
|
-
## Release-blocking findings
|
|
130
|
-
|
|
131
|
-
### TT-L-001: prefetch and runtime caches are inconsistent
|
|
132
|
-
|
|
133
|
-
Severity: critical
|
|
134
|
-
|
|
135
|
-
`prefetch.py` calls `snapshot_download(cache_dir=paths.modelCache)`, which stores a
|
|
136
|
-
repository directly beneath that directory. Training treats the same value as
|
|
137
|
-
`HF_HOME`, whose Hub cache is beneath `<modelCache>/hub`. Evaluation passes the
|
|
138
|
-
cache in a JSON payload and changes `HF_HOME` only after importing Transformers and
|
|
139
|
-
Hugging Face libraries, so their cached path constants do not change.
|
|
140
|
-
|
|
141
|
-
Spark evidence:
|
|
142
|
-
|
|
143
|
-
- existing complete cache:
|
|
144
|
-
`/home/eve/.cache/huggingface/hub/models--Qwen--Qwen3.5-2B`
|
|
145
|
-
- existing size: 4,571,197,824 bytes
|
|
146
|
-
- prefetch began a second copy at:
|
|
147
|
-
`/home/eve/.cache/huggingface/models--Qwen--Qwen3.5-2B`
|
|
148
|
-
- stopped after 101.92 seconds and 291,373,218 bytes of duplicate growth
|
|
149
|
-
|
|
150
|
-
Relevant code:
|
|
151
|
-
|
|
152
|
-
- `training/local-runner/src/prefetch.py:54-67`
|
|
153
|
-
- `src/process-training.ts:224-239`
|
|
154
|
-
- `training/local-runner/src/evaluate.py:15-18,303-312`
|
|
155
|
-
- `src/evaluation.ts:332-374`
|
|
156
|
-
|
|
157
|
-
Required adjustment:
|
|
158
|
-
|
|
159
|
-
- define one cache contract (`HF_HOME` or `HF_HUB_CACHE`) and use it identically in
|
|
160
|
-
prefetch, training, baseline, candidate, and serving;
|
|
161
|
-
- set environment variables before Python imports;
|
|
162
|
-
- persist model revision/commit, snapshot path, file count, and byte count;
|
|
163
|
-
- add fresh, cached, interrupted, corrupt, gated, unwritable, and low-disk tests.
|
|
164
|
-
|
|
165
|
-
### TT-L-002: the documented/default packaged run does not select its Python project
|
|
166
|
-
|
|
167
|
-
Severity: critical
|
|
168
|
-
|
|
169
|
-
The homepage advertises `tt-local doctor` followed by `tt-local run` without a
|
|
170
|
-
config. Default config does not set the bundled uv project. The first Spark run and
|
|
171
|
-
a clean packaged run launched the evaluator as `uv run python .../evaluate.py` and
|
|
172
|
-
failed with `ModuleNotFoundError: No module named 'torch'`. `doctor` had passed.
|
|
173
|
-
|
|
174
|
-
Relevant code and docs:
|
|
175
|
-
|
|
176
|
-
- `src/contracts.ts:294-383`
|
|
177
|
-
- `src/process-runner.ts:30-49`
|
|
178
|
-
- `src/doctor.ts:43-109`
|
|
179
|
-
- sibling web repo `tuned-tensor/src/app/page.tsx:24-30,174-187`
|
|
180
|
-
|
|
181
|
-
Required adjustment:
|
|
182
|
-
|
|
183
|
-
- make both bundled training and bundled evaluation default to the installed
|
|
184
|
-
`training/local-runner` project;
|
|
185
|
-
- make `doctor` resolve and execute the exact commands that `run` will use;
|
|
186
|
-
- run imports for Torch, Transformers, PEFT, and Hugging Face Hub and assert CUDA
|
|
187
|
-
availability/device details when CUDA was requested.
|
|
188
|
-
|
|
189
|
-
### TT-L-003: resume invalidation omits hyperparameters and effective config
|
|
190
|
-
|
|
191
|
-
Severity: critical correctness
|
|
192
|
-
|
|
193
|
-
The stage source fingerprint includes the spec snapshot and selected dataset/eval
|
|
194
|
-
metadata, but not `request.hyperparameters` or most resolved training/evaluation
|
|
195
|
-
configuration. Existing baseline, training, and candidate files are then reused by
|
|
196
|
-
existence.
|
|
197
|
-
|
|
198
|
-
Reproduction: change `n_epochs` from 3 to 9 and rerun the same run ID. The CLI
|
|
199
|
-
reported reuse for prepare, baseline, training, and candidate; generated
|
|
200
|
-
`hyperparameters.json` still contained 3.
|
|
201
|
-
|
|
202
|
-
Relevant code:
|
|
203
|
-
|
|
204
|
-
- `src/orchestrator.ts:157-174,397-433`
|
|
205
|
-
- `src/orchestrator.ts:454-523,567-624`
|
|
206
|
-
|
|
207
|
-
Required adjustment:
|
|
208
|
-
|
|
209
|
-
- fingerprint the normalized full request, effective training config, effective
|
|
210
|
-
evaluation/generation/scoring config, package/runtime version, model revision,
|
|
211
|
-
dataset hashes, and parent artifact manifest;
|
|
212
|
-
- record per-stage input fingerprints and explain reuse/invalidation in CLI output;
|
|
213
|
-
- add a matrix of resume tests changing one input at a time.
|
|
214
|
-
|
|
215
|
-
### TT-L-004: model completion has no artifact validity contract
|
|
216
|
-
|
|
217
|
-
Severity: critical correctness
|
|
218
|
-
|
|
219
|
-
Training directories are created before the command runs. Any command that exits
|
|
220
|
-
zero can therefore fall back to an empty `training/model` directory. Candidate
|
|
221
|
-
evaluation with provider `none` or a permissive custom command does not prove the
|
|
222
|
-
artifact is loadable, yet the run and model are marked completed.
|
|
223
|
-
|
|
224
|
-
A non-dry `/usr/bin/true` trainer reproduced this: no model files were written, but
|
|
225
|
-
the run completed and `models list` registered the empty directory. Dry runs also
|
|
226
|
-
register empty simulated models.
|
|
227
|
-
|
|
228
|
-
Relevant code:
|
|
229
|
-
|
|
230
|
-
- `src/artifacts.ts:63-70`
|
|
231
|
-
- `src/process-training.ts:265-305`
|
|
232
|
-
- `src/orchestrator.ts:666-740`
|
|
233
|
-
- `src/store.ts:605-642`
|
|
234
|
-
|
|
235
|
-
Required adjustment:
|
|
236
|
-
|
|
237
|
-
- validate expected PEFT/full-model files after training;
|
|
238
|
-
- write an atomic `artifact-manifest.json` containing framework, format, base model
|
|
239
|
-
and revision, files, sizes, and SHA-256 values;
|
|
240
|
-
- add `tt-local models verify <id-or-path>`;
|
|
241
|
-
- never register a dry-run model as real/servable;
|
|
242
|
-
- reject empty/custom artifacts unless their declared artifact contract passes.
|
|
243
|
-
|
|
244
|
-
### TT-L-005: CLI option parsing can start unintended work
|
|
245
|
-
|
|
246
|
-
Severity: critical UX/safety
|
|
247
|
-
|
|
248
|
-
Only top-level help is recognized. Unknown options are silently discarded.
|
|
249
|
-
Observed behavior:
|
|
250
|
-
|
|
251
|
-
```text
|
|
252
|
-
tt-local --version -> Unknown command
|
|
253
|
-
tt-local models prefetch --help -> attempts the command
|
|
254
|
-
tt-local runs report --help -> looks up run "--help"
|
|
255
|
-
tt-local run --help -> queues and starts a run
|
|
256
|
-
```
|
|
257
|
-
|
|
258
|
-
A typo such as `--dryrun` can therefore start a real local job.
|
|
259
|
-
|
|
260
|
-
Relevant code:
|
|
261
|
-
|
|
262
|
-
- `src/index.ts:100-188,305-320,373-439`
|
|
263
|
-
|
|
264
|
-
Required adjustment:
|
|
265
|
-
|
|
266
|
-
- use a strict command parser with per-command help, `--version`, required-value
|
|
267
|
-
validation, mutually exclusive options, and rejection of unknown flags;
|
|
268
|
-
- add subprocess-level tests for every command before long-running work begins.
|
|
269
|
-
|
|
270
|
-
### TT-L-006: LLM-judge behavior can silently change metric semantics
|
|
271
|
-
|
|
272
|
-
Severity: critical evaluation correctness
|
|
273
|
-
|
|
274
|
-
The public real-run example sets `scoring.mode=llm_judge` and exports
|
|
275
|
-
`OPENROUTER_API_KEY`, but omits the required `llm` block. The implementation then
|
|
276
|
-
silently uses exact match. If `llm` exists but the key is initially absent, the
|
|
277
|
-
exact-match baseline is not marked as fallback and may be cached; adding the key
|
|
278
|
-
later can compare a cached exact-match baseline with a judge-scored candidate.
|
|
279
|
-
|
|
280
|
-
Relevant code and docs:
|
|
281
|
-
|
|
282
|
-
- `src/contracts.ts:350-390`
|
|
283
|
-
- `src/evaluation.ts:552-582,592-725,775-873`
|
|
284
|
-
- sibling web repo `tuned-tensor/src/app/docs/local-training/page.tsx:95-132`
|
|
285
|
-
|
|
286
|
-
Required adjustment:
|
|
287
|
-
|
|
288
|
-
- fail preflight when judge mode is requested but its model/config/key is absent,
|
|
289
|
-
unless the user explicitly opts into fallback;
|
|
290
|
-
- record all fallback scoring as fallback and never cache it as a judge baseline;
|
|
291
|
-
- include judge availability in the cache key or invalidate on availability change;
|
|
292
|
-
- make the documented example assert `judge_scored_count > 0`.
|
|
293
|
-
|
|
294
|
-
## High-priority gaps
|
|
295
|
-
|
|
296
|
-
### Artifact discovery is coupled to successful evaluation/reporting
|
|
297
|
-
|
|
298
|
-
`training-report.json` is written after a successful trainer, but the model record is
|
|
299
|
-
created only in `completeRun`, after candidate evaluation and report generation. If
|
|
300
|
-
evaluation times out or the judge fails, the trained artifact remains on disk but is
|
|
301
|
-
absent from `models list`; index rebuild cannot recover a model record that was never
|
|
302
|
-
written.
|
|
303
|
-
|
|
304
|
-
Register a verified artifact immediately after training. Track training success,
|
|
305
|
-
evaluation success, and report success as separate states.
|
|
306
|
-
|
|
307
|
-
### `doctor` and `validate` do not preflight the real job
|
|
308
|
-
|
|
309
|
-
Missing checks include:
|
|
310
|
-
|
|
311
|
-
- exact installed training and evaluator commands;
|
|
312
|
-
- Python imports and CUDA-enabled Torch;
|
|
313
|
-
- requested device, GPU memory, and model fit;
|
|
314
|
-
- cache/artifact/store writability and free disk headroom;
|
|
315
|
-
- model reachability, revision, gated-model token, and partial cache state;
|
|
316
|
-
- configured judge/model/key;
|
|
317
|
-
- placeholder spec content and dataset readability/shape.
|
|
318
|
-
|
|
319
|
-
GPU checks should be conditional: a dry run, CPU command backend, or MPS workflow
|
|
320
|
-
should not fail solely because `nvidia-smi` is absent.
|
|
321
|
-
|
|
322
|
-
### No supported TT Local inference-serving endpoint
|
|
323
|
-
|
|
324
|
-
`tt-local serve` is the dashboard. `tt-local models serve` is unknown. The separate
|
|
325
|
-
`tt models serve` command was not installed on the Spark and has no real integration
|
|
326
|
-
test against the exact TT Local adapter tar. Code review also shows a likely mismatch:
|
|
327
|
-
TT Local nests archive files beneath `model/`, while the other CLI passes the archive
|
|
328
|
-
extraction root directly and its reference runtime is not designed around an explicit
|
|
329
|
-
base-model-plus-PEFT-adapter contract.
|
|
330
|
-
|
|
331
|
-
Add `tt-local models serve <local-model-id>` or a fully tested documented bridge.
|
|
332
|
-
Acceptance requires `/health`, `/v1/models`, and a real `/v1/chat/completions` request
|
|
333
|
-
using the saved artifact and its recorded base revision.
|
|
334
|
-
|
|
335
|
-
### Cancellation does not cancel subprocess work
|
|
336
|
-
|
|
337
|
-
`runs cancel` writes `cancel.requested` and changes metadata, but the orchestrator and
|
|
338
|
-
process runner never read the marker or terminate the child. Work can continue and a
|
|
339
|
-
later event can overwrite cancelled state. Cancellation must signal the process group,
|
|
340
|
-
wait for exit, and preserve a terminal cancelled state.
|
|
341
|
-
|
|
342
|
-
### Staged commands leave nonterminal persisted state
|
|
343
|
-
|
|
344
|
-
An individual stage prints `status: completed`, while the store remains in a running
|
|
345
|
-
state such as `preparing` or `training`. `runs watch` only exits for completed, failed,
|
|
346
|
-
or cancelled and can hang after a deliberately completed stage. Represent stage
|
|
347
|
-
completion explicitly and make watch aware of the requested terminal stage.
|
|
348
|
-
|
|
349
|
-
### Successful resume preserves a stale failure
|
|
350
|
-
|
|
351
|
-
The successful Spark resume is `completed`, but `runs get` and the dashboard still
|
|
352
|
-
expose the earlier `ModuleNotFoundError` in the `error` field, including after index
|
|
353
|
-
rebuild. Clear superseded errors when a run is retried and succeeds, while preserving
|
|
354
|
-
them in attempt history/events.
|
|
355
|
-
|
|
356
|
-
### Force/retry can retain stale model-directory files
|
|
357
|
-
|
|
358
|
-
Source refresh deletes report JSON files but not training model/output directories.
|
|
359
|
-
Stale files can be included in a later archive. Use a new attempt directory or clear
|
|
360
|
-
only the stage-owned directory before recomputation, then publish atomically.
|
|
361
|
-
|
|
362
|
-
## Medium-priority UX and documentation gaps
|
|
363
|
-
|
|
364
|
-
- `info` does not show the installed version; `--version` is unsupported.
|
|
365
|
-
- `init` creates placeholder training data that passes validation and defaults to
|
|
366
|
-
three epochs, but creates no runner config.
|
|
367
|
-
- `validate` prints an unpersisted run ID different from the eventual spec-based run.
|
|
368
|
-
- prefetch progress is hidden by default and its help does not advertise `--verbose`.
|
|
369
|
-
- prefetch attempts are not indexed or discoverable through a cache-status command.
|
|
370
|
-
- `runs watch` is documented after a blocking foreground run, when it is no longer
|
|
371
|
-
useful; document a second terminal, explicit run ID, or detached execution.
|
|
372
|
-
- `paths.modelCache`, artifact paths, and store paths need one clear path-resolution
|
|
373
|
-
rule; current relative paths resolve from process CWD rather than config location.
|
|
374
|
-
- `HF_TOKEN` setup for gated models is not documented.
|
|
375
|
-
- “Files and Store” omits the model directory, copied tar, store report copy, and
|
|
376
|
-
`models/<id>/model.json`.
|
|
377
|
-
- model tar is stored twice; deduplicate or document the durability reason.
|
|
378
|
-
- weight-loading progress is mislabeled as training progress; the Spark run reported
|
|
379
|
-
0/320 to 320/320 shard loading before its real 3/3 training steps.
|
|
380
|
-
- the default 120-second timeout covers uv startup, model loading/download, and the
|
|
381
|
-
whole evaluation batch. A one-example warm-cache Spark evaluation took about 30s.
|
|
382
|
-
- the published npm package omits `training/local-runner/uv.lock`, weakening runtime
|
|
383
|
-
reproducibility and allowing dependency drift.
|
|
384
|
-
- a store-recovered report can retain stale absolute artifact URIs after artifacts
|
|
385
|
-
are moved or removed.
|
|
386
|
-
- a successful resume updates artifact-side request data but may leave canonical
|
|
387
|
-
store request/spec data stale.
|
|
388
|
-
|
|
389
|
-
## Recommended target workflow
|
|
390
|
-
|
|
391
|
-
The ideal first-run path should be short, explicit, and self-verifying:
|
|
392
|
-
|
|
393
|
-
```bash
|
|
394
|
-
tt-local --version
|
|
395
|
-
tt-local init --name "Support Bot" --model Qwen/Qwen3.5-2B --profile spark
|
|
396
|
-
|
|
397
|
-
# Edit tunedtensor.json, then:
|
|
398
|
-
tt-local doctor tunedtensor.json --config local-runner.json
|
|
399
|
-
tt-local models prefetch tunedtensor.json --config local-runner.json
|
|
400
|
-
tt-local models verify-base tunedtensor.json --config local-runner.json
|
|
401
|
-
|
|
402
|
-
tt-local run tunedtensor.json --config local-runner.json --detach
|
|
403
|
-
tt-local runs watch <run-id> --config local-runner.json
|
|
404
|
-
tt-local runs report <run-id> --config local-runner.json
|
|
405
|
-
tt-local models verify local-<run-id> --config local-runner.json
|
|
406
|
-
|
|
407
|
-
tt-local models serve local-<run-id> --spec tunedtensor.json
|
|
408
|
-
```
|
|
409
|
-
|
|
410
|
-
Suggested behavior:
|
|
411
|
-
|
|
412
|
-
- `init --profile spark` writes both a spec and a safe durable config.
|
|
413
|
-
- `doctor` prints an effective-plan summary: exact commands, paths, device, model
|
|
414
|
-
revision, cached/download bytes, disk headroom, eval count, scoring mode, and
|
|
415
|
-
expected artifact contract.
|
|
416
|
-
- prefetch shows byte progress by default and finishes with a verifiable snapshot
|
|
417
|
-
manifest.
|
|
418
|
-
- `run` emits/persists the run ID before any model work and supports detach/watch.
|
|
419
|
-
- completed training makes a verified model discoverable even if evaluation fails.
|
|
420
|
-
- final output includes copy-paste report, verify, and serve commands.
|
|
421
|
-
|
|
422
|
-
## Acceptance test plan
|
|
423
|
-
|
|
424
|
-
1. **Clean packaged quickstart:** install the tarball without global ML packages;
|
|
425
|
-
init, doctor, prefetch, run, report, verify, and serve with no source checkout.
|
|
426
|
-
2. **Fresh and warm Spark paths:** Linux ARM64/CUDA with empty cache, then cached
|
|
427
|
-
retry; assert no duplicate bytes and identical model revision.
|
|
428
|
-
3. **Download resilience:** interrupt/resume, corrupt snapshot, gated model without
|
|
429
|
-
token, unwritable cache, insufficient disk, and visible progress.
|
|
430
|
-
4. **Resume correctness:** change each hyperparameter/config/input under one run ID;
|
|
431
|
-
assert exactly the dependent stages are invalidated.
|
|
432
|
-
5. **Artifact contract:** empty output, partial adapter, corrupt tar, wrong base model,
|
|
433
|
-
and checksum mismatch must fail before model registration.
|
|
434
|
-
6. **Failure after training:** force candidate/judge/report failure and assert the
|
|
435
|
-
verified trained model remains listed and servable.
|
|
436
|
-
7. **Dry-run contract:** no real model record, no cache download, terminal dry-run
|
|
437
|
-
status, and valid orchestration artifacts.
|
|
438
|
-
8. **Judge correctness:** documented config performs judge calls, records the judge
|
|
439
|
-
model, never caches silent fallback, and reports fallback prominently.
|
|
440
|
-
9. **Serving handoff:** exact emitted tar plus recorded base revision passes health,
|
|
441
|
-
model listing, and a real chat request.
|
|
442
|
-
10. **CLI contract:** help/version, unknown flags, missing values, JSON mode, exit
|
|
443
|
-
codes, staged watch, cancellation, and detached lifecycle.
|
|
444
|
-
11. **Persistence/recovery:** process restart, SQLite rebuild, moved roots, missing or
|
|
445
|
-
corrupt canonical files, and stale-error clearing on successful retry.
|
|
446
|
-
12. **Platform matrix:** Ubuntu x64, Linux ARM64, Mac dry run/MPS as supported, plus a
|
|
447
|
-
periodic real DGX Spark CUDA job.
|
|
448
|
-
|
|
449
|
-
## Residual audit data
|
|
450
|
-
|
|
451
|
-
The Spark audit intentionally did not delete generated data:
|
|
452
|
-
|
|
453
|
-
- audit workspace: about 74.7 MB
|
|
454
|
-
- interrupted duplicate prefetch data: about 291.2 MB
|
|
455
|
-
- total audit-related disk growth: about 366.4 MB
|
|
456
|
-
|
|
457
|
-
No existing project, run, or model was overwritten or deleted. Cleanup should be a
|
|
458
|
-
separate deliberate action after the cache-location fix is understood.
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
{"prompt":"Summarize status: build passed, one flaky test retried successfully.","chosen":"Build passed; one flaky test passed after retry.","rejected":"Everything is broken and the build failed."}
|
|
2
|
-
{"prompt":"Reply to customer: refund was issued yesterday.","chosen":"Your refund was issued yesterday and should appear shortly.","rejected":"We cannot help with this request."}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"run_id": "44444444-4444-4444-8444-444444444444",
|
|
3
|
-
"user_id": "local-user",
|
|
4
|
-
"behavior_spec_id": "55555555-5555-4555-8555-555555555555",
|
|
5
|
-
"run_number": 1,
|
|
6
|
-
"training_method": "dpo",
|
|
7
|
-
"spec_snapshot": {
|
|
8
|
-
"name": "Local DPO Assistant",
|
|
9
|
-
"description": "Tiny local DPO smoke request.",
|
|
10
|
-
"system_prompt": "Answer concisely and accurately.",
|
|
11
|
-
"guidelines": [
|
|
12
|
-
"Prefer direct, factual replies."
|
|
13
|
-
],
|
|
14
|
-
"constraints": [
|
|
15
|
-
"Do not invent negative status."
|
|
16
|
-
],
|
|
17
|
-
"base_model": "Qwen/Qwen3.5-2B",
|
|
18
|
-
"examples": [
|
|
19
|
-
{
|
|
20
|
-
"input": "Summarize status: build passed, one flaky test retried successfully.",
|
|
21
|
-
"output": "Build passed; one flaky test passed after retry."
|
|
22
|
-
}
|
|
23
|
-
]
|
|
24
|
-
},
|
|
25
|
-
"hyperparameters": {
|
|
26
|
-
"n_epochs": 1,
|
|
27
|
-
"dpo_beta": 0.1,
|
|
28
|
-
"save_adapter_only": true
|
|
29
|
-
},
|
|
30
|
-
"dataset_prebuilt": {
|
|
31
|
-
"training": "file://examples/dpo-preferences.jsonl",
|
|
32
|
-
"format": "preference_jsonl"
|
|
33
|
-
}
|
|
34
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"run_id": "11111111-1111-4111-8111-111111111111",
|
|
3
|
-
"user_id": "local-user",
|
|
4
|
-
"behavior_spec_id": "22222222-2222-4222-8222-222222222222",
|
|
5
|
-
"run_number": 1,
|
|
6
|
-
"spec_snapshot": {
|
|
7
|
-
"name": "Local Smoke Assistant",
|
|
8
|
-
"description": "Tiny local runner smoke test.",
|
|
9
|
-
"system_prompt": "Answer in a concise, literal style.",
|
|
10
|
-
"guidelines": [
|
|
11
|
-
"Prefer the expected label when the input is a label request."
|
|
12
|
-
],
|
|
13
|
-
"constraints": [
|
|
14
|
-
"Do not include extra commentary."
|
|
15
|
-
],
|
|
16
|
-
"base_model": "Qwen/Qwen3.5-2B",
|
|
17
|
-
"examples": [
|
|
18
|
-
{
|
|
19
|
-
"input": "Classify sentiment: I love this product.",
|
|
20
|
-
"output": "positive"
|
|
21
|
-
},
|
|
22
|
-
{
|
|
23
|
-
"input": "Classify sentiment: This was disappointing.",
|
|
24
|
-
"output": "negative"
|
|
25
|
-
}
|
|
26
|
-
]
|
|
27
|
-
},
|
|
28
|
-
"hyperparameters": {
|
|
29
|
-
"n_epochs": 1,
|
|
30
|
-
"augment": false,
|
|
31
|
-
"use_llm_judge": false,
|
|
32
|
-
"save_adapter_only": true
|
|
33
|
-
}
|
|
34
|
-
}
|