@zhuoyuezs/ml-platform 0.2.8 → 0.2.10
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/CI-ARTIFACT.md +2 -2
- package/checksums.json +74 -54
- package/package.json +1 -1
- package/release.json +19 -19
- package/runtime/business-client/README.md +64 -4
- package/runtime/business-client/package-lock.json +2 -2
- package/runtime/business-client/package.json +1 -1
- package/runtime/business-client/src/catalog.js +25 -6
- package/runtime/business-client/src/cli.js +177 -7
- package/runtime/business-client/src/http.js +192 -32
- package/skills/data-source-exploration/SKILL.md +12 -1
- package/skills/data-source-exploration/agents/openai.yaml +2 -2
- package/skills/data-source-exploration/references/data-platform.md +83 -0
- package/skills/feature-management/SKILL.md +29 -11
- package/skills/feature-management/agents/openai.yaml +2 -2
- package/skills/feature-management/references/commands.md +64 -7
- package/skills/feature-management/references/contracts.md +124 -6
- package/skills/feature-management/references/data-platform-mapping.md +104 -0
- package/skills/feature-management/references/operator-authoring.md +116 -8
- package/skills/feature-management/references/platform-capability-guide.md +6 -0
- package/skills/feature-management/references/supervised-datasets.md +13 -0
- package/skills/model-deployment-management/SKILL.md +7 -0
- package/skills/model-deployment-management/references/contracts.md +6 -0
- package/skills/model-deployment-management/references/operations.md +28 -1
- package/skills/model-deployment-management/references/troubleshooting.md +8 -0
- package/skills/model-lifecycle-management/SKILL.md +27 -5
- package/skills/model-lifecycle-management/agents/openai.yaml +2 -2
- package/skills/model-lifecycle-management/references/ablation.md +111 -0
- package/skills/model-lifecycle-management/references/discovery.md +18 -3
- package/skills/model-lifecycle-management/references/evaluation.md +188 -1
- package/skills/model-lifecycle-management/references/experiment-runs.md +59 -0
- package/skills/model-lifecycle-management/references/model-comparison.md +11 -9
- package/skills/model-lifecycle-management/references/packaging.md +46 -0
- package/skills/model-lifecycle-management/references/training-contracts.md +172 -1
- package/skills/model-lifecycle-management/references/training.md +60 -0
- package/skills/prediction-report-management/SKILL.md +43 -8
|
@@ -51,6 +51,43 @@ Inspect `get-metric-definition regression.mae v1` before relying on this metric.
|
|
|
51
51
|
Release mode additionally requires at least one required validation rule with a
|
|
52
52
|
business-approved threshold; do not invent thresholds to obtain PASS.
|
|
53
53
|
|
|
54
|
+
`regression.hit_rate:v1` is available for point-prediction regression metrics.
|
|
55
|
+
Set `parameters.tolerance` in the metric entry; tolerance is a finite,
|
|
56
|
+
nonnegative absolute error in the target's units, and equality counts as a hit:
|
|
57
|
+
|
|
58
|
+
```json
|
|
59
|
+
{
|
|
60
|
+
"name": "regression.hit_rate", "version": "v1",
|
|
61
|
+
"targets": ["future_pressure"], "calculation_space": "business",
|
|
62
|
+
"parameters": {"tolerance": 5.0}
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
The result is the fraction of valid rows whose absolute prediction error is at
|
|
67
|
+
most the tolerance. The resolved tolerance is recorded in each MetricResult and
|
|
68
|
+
must match when results are summarized or compared. It is an absolute threshold,
|
|
69
|
+
not a percentage; choose it using the target's unit and business acceptance
|
|
70
|
+
criteria.
|
|
71
|
+
|
|
72
|
+
To calculate per-day metrics on China Standard Time dates, add the time bucket
|
|
73
|
+
contract to the registered EvaluationConfig:
|
|
74
|
+
|
|
75
|
+
```json
|
|
76
|
+
{
|
|
77
|
+
"time_buckets": {
|
|
78
|
+
"width": "1d",
|
|
79
|
+
"timezone": "Asia/Shanghai",
|
|
80
|
+
"alignment": "left"
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
`timezone` accepts IANA timezone names and defaults to `UTC`. Daily buckets use
|
|
86
|
+
local calendar midnights and half-open intervals, so a bucket is keyed by the
|
|
87
|
+
local date; use `dimension: "time_bucket"` when creating an analysis view from
|
|
88
|
+
the resulting EvaluationResult IDs. The configured timezone is part of the
|
|
89
|
+
immutable EvaluationConfig identity.
|
|
90
|
+
|
|
54
91
|
For a fixed-length multi-step forecast, `regression.mae` and
|
|
55
92
|
`regression.rmse` cover only the terminal point at the maximum trained horizon.
|
|
56
93
|
Use `regression.trajectory_mae` and `regression.trajectory_rmse` for a release
|
|
@@ -100,12 +137,144 @@ not prove Worker dependency availability. Validate before submitting and confirm
|
|
|
100
137
|
the approved Worker supports the model plugin. Successful training in another
|
|
101
138
|
image does not establish evaluation support.
|
|
102
139
|
|
|
140
|
+
## Clustering evaluation
|
|
141
|
+
|
|
142
|
+
A clustering ModelArtifact (with `output_bindings`) is evaluated only by an
|
|
143
|
+
EvaluationConfig with `task_type: "clustering"`. Supervised configs reject
|
|
144
|
+
clustering artifacts, and clustering configs reject supervised artifacts.
|
|
145
|
+
There are no labels: the Worker loads the frozen model, predicts assignments
|
|
146
|
+
for the requested rowset, and computes metrics. It never refits the model or
|
|
147
|
+
its preprocessing and never relabels clusters.
|
|
148
|
+
|
|
149
|
+
Example release `evaluation-config.json`. The thresholds are placeholders and
|
|
150
|
+
must be business-approved before use:
|
|
151
|
+
|
|
152
|
+
```json
|
|
153
|
+
{
|
|
154
|
+
"name": "process_regimes_release",
|
|
155
|
+
"version": "v1",
|
|
156
|
+
"task_type": "clustering",
|
|
157
|
+
"mode": "release",
|
|
158
|
+
"metrics": [
|
|
159
|
+
{"name": "clustering.silhouette", "calculation_space": "transformed"},
|
|
160
|
+
{"name": "clustering.davies_bouldin", "calculation_space": "transformed"},
|
|
161
|
+
{"name": "clustering.cluster_count"},
|
|
162
|
+
{"name": "clustering.min_cluster_share"}
|
|
163
|
+
],
|
|
164
|
+
"validation": [
|
|
165
|
+
{"metric": "clustering.silhouette", "operator": ">=", "threshold": 0.25},
|
|
166
|
+
{"metric": "clustering.min_cluster_share", "operator": ">=", "threshold": 0.05}
|
|
167
|
+
],
|
|
168
|
+
"clustering": {"sample_limit": 5000, "sample_seed": 0}
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
The `clustering` object is optional and accepted only for `task_type:
|
|
173
|
+
"clustering"`:
|
|
174
|
+
|
|
175
|
+
- `sample_limit` (>= 2, default 5000) bounds the silhouette computation. Larger
|
|
176
|
+
rowsets are sampled deterministically with `sample_seed` (default 0). Other
|
|
177
|
+
metrics use every valid row.
|
|
178
|
+
- `reference_label_column` (optional) names an independent DataSchema column
|
|
179
|
+
with role `label` or `metadata`, never a model feature. It is required by the
|
|
180
|
+
external metrics `clustering.adjusted_rand_index` and
|
|
181
|
+
`clustering.normalized_mutual_info`, and is only a comparison reference,
|
|
182
|
+
never a training input.
|
|
183
|
+
- `distance_metric` currently accepts only `euclidean`.
|
|
184
|
+
|
|
185
|
+
Clustering configs reject `baseline`, comparison rules, sample weights and
|
|
186
|
+
package (code) metrics. Built-in `clustering.*` metrics and expression metrics
|
|
187
|
+
over them are supported:
|
|
188
|
+
|
|
189
|
+
| Metric | Inputs | Direction | Calculation spaces |
|
|
190
|
+
| --- | --- | --- | --- |
|
|
191
|
+
| `clustering.silhouette` | features, assignment | maximize | `business`, `transformed` |
|
|
192
|
+
| `clustering.davies_bouldin` | features, assignment | minimize | `business`, `transformed` |
|
|
193
|
+
| `clustering.calinski_harabasz` | features, assignment | maximize | `business`, `transformed` |
|
|
194
|
+
| `clustering.cluster_count` | assignment | neutral | `business` |
|
|
195
|
+
| `clustering.min_cluster_share` | assignment | maximize | `business` |
|
|
196
|
+
| `clustering.adjusted_rand_index` | assignment, reference label | maximize | `business` |
|
|
197
|
+
| `clustering.normalized_mutual_info` | assignment, reference label | maximize | `business` |
|
|
198
|
+
|
|
199
|
+
For feature-based metrics, `business` uses the raw FeatureSet values from the
|
|
200
|
+
DatasetArtifact. `transformed` uses the model's own train-fitted preprocessing
|
|
201
|
+
(the plugin's `transform`), which is the space the estimator clustered in and
|
|
202
|
+
is identical to `business` when the model has no preprocessing. Prefer
|
|
203
|
+
`transformed` for gates on models trained with a scaler or PCA, and record the
|
|
204
|
+
chosen space. `cluster_count` and `min_cluster_share` describe only the
|
|
205
|
+
non-empty clusters observed in the evaluated rowset. A trained cluster that
|
|
206
|
+
receives no rows there is not counted.
|
|
207
|
+
|
|
208
|
+
Example `evaluation-request.json`; `targets` is exactly the assignment output:
|
|
209
|
+
|
|
210
|
+
```json
|
|
211
|
+
{
|
|
212
|
+
"model_artifact_id": "replace_clustering_artifact_id",
|
|
213
|
+
"dataset": {
|
|
214
|
+
"project": "default",
|
|
215
|
+
"dataset_id": "replace_dataset_id",
|
|
216
|
+
"manifest_hash": "replace_with_exact_artifact_manifest_hash"
|
|
217
|
+
},
|
|
218
|
+
"rowset": "test",
|
|
219
|
+
"targets": ["cluster_id"],
|
|
220
|
+
"config": {"name": "process_regimes_release", "version": "v1"},
|
|
221
|
+
"execution": {"executor": "kubernetes", "resources": {"cpu": "2", "memory": "4Gi"}}
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
The rowset comes from the original TrainingRun's `data.splits`. Prefer a
|
|
226
|
+
holdout pool (`validation` or `test`). When the run declared no splits, the
|
|
227
|
+
only accepted rowset is `all`, which is the complete training population.
|
|
228
|
+
Evaluating `all` or `train` measures the population that fitted the model.
|
|
229
|
+
Label any such Result as in-sample in every report, and do not present it as
|
|
230
|
+
held-out evidence; the platform does not add that label for you.
|
|
231
|
+
|
|
232
|
+
Decision semantics follow the shared release policy. Exploratory mode is
|
|
233
|
+
always `INCONCLUSIVE`. In release mode:
|
|
234
|
+
|
|
235
|
+
- When a metric cannot be computed meaningfully (fewer than two non-empty
|
|
236
|
+
clusters, no more rows than clusters, zero dispersion, non-finite inputs),
|
|
237
|
+
the platform records reason `CLUSTERING_DEGENERATE` and writes no number.
|
|
238
|
+
- When a `transformed` metric is requested but the model runtime has no
|
|
239
|
+
`transform`, the platform records `CLUSTERING_TRANSFORM_UNAVAILABLE`.
|
|
240
|
+
- A required rule on such a missing metric is `INCONCLUSIVE`, and that
|
|
241
|
+
outranks a `FAIL` in another rule, so the decision is `INCONCLUSIVE`.
|
|
242
|
+
- Any configured metric that is missing makes `evidence_status` `INCOMPLETE`.
|
|
243
|
+
|
|
244
|
+
Fix the population or configuration rather than dropping the metric to get a
|
|
245
|
+
PASS.
|
|
246
|
+
|
|
247
|
+
Each Result stores `clustering_diagnostics.json` beside the standard artifacts.
|
|
248
|
+
It records the assignment and score outputs, feature order and hash, distance
|
|
249
|
+
metric, sampling parameters, whether the transformed space was available,
|
|
250
|
+
cluster sizes per slice, and the status of each metric (`computed`,
|
|
251
|
+
`degenerate` or `unavailable`, with sampled-row counts). The prediction
|
|
252
|
+
artifact carries the assignment and score per row key. List them with
|
|
253
|
+
`get-evaluation-result-artifacts <result-id>` and download sha256-verified
|
|
254
|
+
copies with `download-evaluation-result-artifact <result-id> --out-dir DIR
|
|
255
|
+
[--file NAME]`.
|
|
256
|
+
|
|
257
|
+
Registration requires all of the following:
|
|
258
|
+
|
|
259
|
+
- one Result for the same artifact with `decision=PASS`,
|
|
260
|
+
`evidence_status=COMPLETE` and compatibility `ok`;
|
|
261
|
+
- no required summary-level rule;
|
|
262
|
+
- a model runtime that reports `production_ready=true`.
|
|
263
|
+
|
|
264
|
+
```bash
|
|
265
|
+
ml-platform --profile server register-model-artifact <artifact-id> \
|
|
266
|
+
--evaluation-id <evaluation-result-id>
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
Training feedback (`cluster_count`, `min_cluster_share`,
|
|
270
|
+
`assignment_score_mean` in `metrics.json`) is not registration evidence.
|
|
271
|
+
|
|
103
272
|
## Diagnose before another build or training run
|
|
104
273
|
|
|
105
274
|
| Symptom | Actual check and next action |
|
|
106
275
|
| --- | --- |
|
|
107
276
|
| `requires a named split` | Inherited TrainingRun `data.splits` is not a dictionary and requested rowset is not `all`. Inspect the original training request, not only manifest/resolved/Parquet splits. This check has no horizon-zero branch. |
|
|
108
|
-
| `rowset is not declared` | Inspect `data.splits` role keys (`train`, `validation`, `test`), nonempty value arrays, assignment column and observed values. Manifest `training` can map to consumer role `train`. |
|
|
277
|
+
| `rowset is not declared` | Inspect `data.splits` role keys (`train`, `validation`, `test`). For an ordinary binding, check nonempty value arrays, assignment column and observed values. For `mode: derived`, check the timezone-aware `strategy: time_range` ranges and the resolved row counts. Manifest `training` can map to consumer role `train`. |
|
|
109
278
|
| DataSchema mismatch | Compare the full schema with the trained Job's hash, including split columns, roles and dtypes. Do not remove columns or falsify hashes to pass. |
|
|
110
279
|
| Label leakage | Materialize label columns separately from FeatureSet order; input selection alone cannot repair the contract. |
|
|
111
280
|
| Chronos-2 runtime unavailable | Record executor, error stage/Job, runtime identity and Worker image evidence. The prediction plugin cannot load a dependency; request runtime support from the platform owner. New dataset/model versions do not install dependencies. |
|
|
@@ -183,6 +352,23 @@ ml-platform --profile server publish-executable-package <name> <version>
|
|
|
183
352
|
|
|
184
353
|
Custom metric packages must be deterministic, digest-bound, network-restricted, verified, and separately authorized for publication.
|
|
185
354
|
|
|
355
|
+
The published wheel entrypoint is called as `entrypoint(inputs, context)` in an
|
|
356
|
+
isolated evaluation worker. `inputs` contains only the declared arrays (for
|
|
357
|
+
example `label`, `prediction`, `probability`, and `weight`). `context` contains
|
|
358
|
+
the frozen metric identity and the resolved parameters for this evaluation under
|
|
359
|
+
`context["parameters"]`; read that mapping instead of relying on package or
|
|
360
|
+
process globals. Parameter validation happens when the EvaluationConfig is
|
|
361
|
+
resolved, and the resolved values are persisted in the MetricResult and its
|
|
362
|
+
comparison/summary evidence. A package metric that declares no parameter schema
|
|
363
|
+
must reject supplied parameters.
|
|
364
|
+
|
|
365
|
+
```python
|
|
366
|
+
def score(inputs, context):
|
|
367
|
+
tolerance = float(context["parameters"]["tolerance"])
|
|
368
|
+
error = abs(inputs["prediction"] - inputs["label"])
|
|
369
|
+
return float((error <= tolerance).mean())
|
|
370
|
+
```
|
|
371
|
+
|
|
186
372
|
```bash
|
|
187
373
|
ml-platform --profile server validate-evaluation-run evaluation-request.json
|
|
188
374
|
ml-platform --profile server submit-evaluation evaluation-request.json
|
|
@@ -199,6 +385,7 @@ An EvaluationRunRequest binds ModelArtifact(s), a frozen DatasetArtifact rowset,
|
|
|
199
385
|
ml-platform --profile server get-evaluation-result <result-id>
|
|
200
386
|
ml-platform --profile server get-evaluation-result-metrics <result-id>
|
|
201
387
|
ml-platform --profile server get-evaluation-result-artifacts <result-id>
|
|
388
|
+
ml-platform --profile server download-evaluation-result-artifact <result-id> --out-dir /tmp/eval-<result-id> --file predictions.parquet
|
|
202
389
|
ml-platform --profile server summarize-evaluation-run <run-id>
|
|
203
390
|
ml-platform --profile server get-evaluation-summary <summary-id>
|
|
204
391
|
```
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# ExperimentRun
|
|
2
|
+
|
|
3
|
+
`ExperimentRun` is the platform control-plane record for a finite comparison
|
|
4
|
+
over one frozen `DatasetArtifact`. It supports model comparison, feature/input
|
|
5
|
+
ablation and a small candidate matrix while reusing existing TrainingRun,
|
|
6
|
+
TrainingJob, ModelArtifact, EvaluationRun, EvaluationResult and
|
|
7
|
+
EvaluationComparison records.
|
|
8
|
+
|
|
9
|
+
It does not implement AutoML, a general DAG engine, automatic model selection,
|
|
10
|
+
packaging or deployment. The Skill owns the modeling method and stopping rules;
|
|
11
|
+
the platform owns durable candidate state and reconciliation.
|
|
12
|
+
|
|
13
|
+
## Lifecycle
|
|
14
|
+
|
|
15
|
+
Use the installed `ml-platform` CLI:
|
|
16
|
+
|
|
17
|
+
```text
|
|
18
|
+
ml-platform create-experiment-run SPEC.json
|
|
19
|
+
ml-platform validate-experiment-run RUN_ID
|
|
20
|
+
ml-platform submit-experiment-run RUN_ID
|
|
21
|
+
ml-platform get-experiment-run RUN_ID
|
|
22
|
+
ml-platform list-experiment-candidates RUN_ID --limit 50 --offset 0
|
|
23
|
+
ml-platform reconcile-experiment-run RUN_ID
|
|
24
|
+
ml-platform cancel-experiment-run RUN_ID
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Create is idempotent for the same `experiment_run_id` and immutable
|
|
28
|
+
`spec_hash`. Always validate before submit. Validation resolves every candidate's
|
|
29
|
+
TrainingJob snapshot and has no training side effects. Submit is the mutation
|
|
30
|
+
that may create TrainingJob records, subject to `max_parallelism`.
|
|
31
|
+
|
|
32
|
+
## Candidate contract
|
|
33
|
+
|
|
34
|
+
The spec must contain at least two candidates, a baseline candidate, one
|
|
35
|
+
DatasetArtifact identity and one evaluation contract. Each candidate carries a
|
|
36
|
+
complete TrainingRun v4 JSON object, a stable `candidate_id`, an optional
|
|
37
|
+
hypothesis and parent candidate, and an execution policy. Candidate FeatureSets
|
|
38
|
+
may be different exact-version subset/order projections of the same wide
|
|
39
|
+
DatasetArtifact. Labels, split membership, temporal semantics, evaluation
|
|
40
|
+
configuration and comparison population remain shared.
|
|
41
|
+
|
|
42
|
+
## Recovery rules
|
|
43
|
+
|
|
44
|
+
`UNKNOWN` means the platform cannot prove whether a remote submission happened.
|
|
45
|
+
Reconcile first queries the durable TrainingJob/EvaluationRun records. It may
|
|
46
|
+
resume only when the lifecycle record proves no remote submission was reached;
|
|
47
|
+
it never blindly retries an unknown Kubernetes operation. An unknown candidate
|
|
48
|
+
also stops new candidate submissions until it is reconciled. A known terminal
|
|
49
|
+
failure is preserved and does not consume a parallel slot for independent
|
|
50
|
+
candidates.
|
|
51
|
+
|
|
52
|
+
## Completion
|
|
53
|
+
|
|
54
|
+
Every candidate must be `RESULT_READY`, `FAILED`, `SKIPPED` or otherwise
|
|
55
|
+
accounted for. The service calls the existing EvaluationComparison implementation
|
|
56
|
+
only after complete results exist. `COMPLETE` with `ranking_allowed=true` requires
|
|
57
|
+
complete evidence, comparable population and a release-mode EvaluationConfig;
|
|
58
|
+
otherwise the run is `INCONCLUSIVE`. A result never authorizes registration,
|
|
59
|
+
packaging or deployment by itself.
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
# Comparing models within one experiment
|
|
2
2
|
|
|
3
|
+
Feature or input ablation is the controlled one-factor variant of this
|
|
4
|
+
workflow. Read [ablation.md](ablation.md) for the baseline, removal-set and
|
|
5
|
+
round-closeout rules; the comparison gates below still apply.
|
|
6
|
+
|
|
3
7
|
Use one documented goal and user-authorized scope: metric, target, candidate
|
|
4
8
|
constraints and any maximum number of training submissions. Preserve that goal
|
|
5
9
|
when a follow-up changes a constraint or asks for verification. Reuse existing
|
|
6
10
|
authorization when it covers the next action; ask only for missing decisions.
|
|
7
11
|
No TUI, session service, or Runtime-specific tool is required for this method.
|
|
12
|
+
Persist the candidate set and execution links in an `ExperimentRun`; see
|
|
13
|
+
[experiment-runs.md](experiment-runs.md) for its CLI lifecycle.
|
|
8
14
|
|
|
9
15
|
## Shared scope and candidate execution
|
|
10
16
|
|
|
@@ -45,9 +51,8 @@ forecast horizon, and do not let trajectory construction cross split
|
|
|
45
51
|
boundaries. Compare complete platform-produced EvaluationResults only after
|
|
46
52
|
each candidate passes its own TrainingRun and evaluation preflight.
|
|
47
53
|
|
|
48
|
-
For each candidate, record its hypothesis, exact changed inputs
|
|
49
|
-
|
|
50
|
-
directory. Submit within the user's authorization, observe the TrainingJob,
|
|
54
|
+
For each candidate, record its hypothesis, exact changed inputs and parent
|
|
55
|
+
candidate in the ExperimentRun spec. Submit within the user's authorization, observe the TrainingJob,
|
|
51
56
|
validate the resulting ModelArtifact, then submit and inspect governed
|
|
52
57
|
evaluation. Explain the observed result before choosing another candidate.
|
|
53
58
|
Do not resubmit after an unknown outcome: reconcile the existing Job or retry
|
|
@@ -57,12 +62,9 @@ the authorization described in the training reference.
|
|
|
57
62
|
## Rounds, failure evidence and stopping
|
|
58
63
|
|
|
59
64
|
A round groups candidates that test a related hypothesis under the frozen
|
|
60
|
-
comparison scope.
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
status, result IDs, per-candidate reflection and the round's next decision.
|
|
64
|
-
This is an agent work record, not a new platform resource or required tool.
|
|
65
|
-
Update it after submissions and observations so another coding agent can resume.
|
|
65
|
+
comparison scope. ExperimentRun and its candidates are the durable execution
|
|
66
|
+
record. Keep any additional method reflection in the agent's working directory
|
|
67
|
+
without duplicating platform status or IDs.
|
|
66
68
|
|
|
67
69
|
When a candidate fails, inspect the actual Job status, attempts and diagnostic
|
|
68
70
|
evidence. Distinguish a model execution failure from a runtime/infrastructure
|
|
@@ -159,3 +159,49 @@ ml-platform --profile server cancel-model-package <package-id> --package-version
|
|
|
159
159
|
```
|
|
160
160
|
|
|
161
161
|
Cancellation requires exact-package authorization. Do not rebuild an immutable failed version; correct inputs and create a new semantic package version. This Skill does not deploy images or write model-center delivery status.
|
|
162
|
+
|
|
163
|
+
## Clustering packages and requests
|
|
164
|
+
|
|
165
|
+
A clustering ModelArtifact has `output_bindings` and no `target_bindings`. Its
|
|
166
|
+
Serving contract reports `task_type=clustering`, `horizon_mode=null`, no
|
|
167
|
+
supported horizons, and `output_schema.kind=clustering` with the `cluster_id`
|
|
168
|
+
assignment and one score (`distance_to_center` or `cluster_probability`).
|
|
169
|
+
|
|
170
|
+
Package it with the ordinary request shape and `"input_modes": ["inline"]`.
|
|
171
|
+
Add `feature_lookup` only when the generic retrieval conditions above hold. A
|
|
172
|
+
clustering `feature_lookup_test` must omit `horizon` and `output_window`.
|
|
173
|
+
The platform-generated image smoke test sends exactly one inline row, in
|
|
174
|
+
ModelSignature column order, with no horizon. It requires one successful
|
|
175
|
+
result with `prediction.kind=clustering`, an integer `cluster_id` >= 0 and a
|
|
176
|
+
finite score.
|
|
177
|
+
|
|
178
|
+
Packaging includes every model file the artifact declares, including the v2
|
|
179
|
+
preprocessing sidecar. The Serving image must provide the scikit-learn version
|
|
180
|
+
recorded in a v2 model file, otherwise model loading fails and the package
|
|
181
|
+
cannot become `READY`. Use the clustering runtime binding from the same Runtime
|
|
182
|
+
Release rather than another image.
|
|
183
|
+
|
|
184
|
+
An inline request carries exactly one row, whose column names match the
|
|
185
|
+
ModelSignature order exactly. Its timestamp must not be later than
|
|
186
|
+
`cutoff_time`. Clustering requests reject `horizon` and `output_window`:
|
|
187
|
+
|
|
188
|
+
```json
|
|
189
|
+
{
|
|
190
|
+
"input_mode": "inline",
|
|
191
|
+
"cutoff_time": "2026-01-01T08:00:00+08:00",
|
|
192
|
+
"inputs": {
|
|
193
|
+
"timestamps": ["2026-01-01T08:00:00+08:00"],
|
|
194
|
+
"values": [{"pressure": 0.82, "temperature": 1180.0, "flow": 3.4}]
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
ml-platform predict-model /absolute/path/to/cluster-request.json \
|
|
201
|
+
--serving-url https://process-regimes.example
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
The single result returns `prediction.kind=clustering`, `cluster_id` and the
|
|
205
|
+
score field, and has no `horizon` or `target_time`. Report the `model_version`
|
|
206
|
+
(artifact ID) with each assignment, because cluster ids are not comparable
|
|
207
|
+
across artifacts.
|
|
@@ -112,6 +112,173 @@ capability requires it; do not attach it just because the task is a forecast.
|
|
|
112
112
|
For the platform's detailed diagnostic and label-statistics procedure, read
|
|
113
113
|
[`feature-management/references/supervised-datasets.md`](../../feature-management/references/supervised-datasets.md).
|
|
114
114
|
|
|
115
|
+
## Unsupervised clustering runs
|
|
116
|
+
|
|
117
|
+
Use this method for tabular clustering SystemModels such as
|
|
118
|
+
`kmeans_clusterer:v1` and `gaussian_mixture_clusterer:v1`. Confirm that the
|
|
119
|
+
inspected SystemModel advertises `tasks=["clustering"]`; do not reuse a
|
|
120
|
+
supervised Trainer for clustering.
|
|
121
|
+
|
|
122
|
+
```json
|
|
123
|
+
{
|
|
124
|
+
"schema_version": "ml_data_platform.training_run/v4",
|
|
125
|
+
"run_id": "process_regimes_kmeans_01",
|
|
126
|
+
"experiment": "process_regimes",
|
|
127
|
+
"task": {"kind": "clustering", "objective": "clustering"},
|
|
128
|
+
"data": {
|
|
129
|
+
"artifact": {
|
|
130
|
+
"project": "default", "dataset_id": "process_features",
|
|
131
|
+
"manifest_hash": "REPLACE_WITH_RETURNED_MANIFEST_HASH"
|
|
132
|
+
},
|
|
133
|
+
"features": {"feature_set": {
|
|
134
|
+
"project": "default", "name": "process_cluster_inputs", "version": "v1"
|
|
135
|
+
}},
|
|
136
|
+
"labels": [],
|
|
137
|
+
"splits": {
|
|
138
|
+
"assignment_column": "rowset_split", "train": ["training"],
|
|
139
|
+
"validation": ["validation"], "test": ["test"]
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
"input_adapter": {"kind": "tabular"},
|
|
143
|
+
"label_transform": {"name": "identity", "version": "v1"},
|
|
144
|
+
"trainer": {
|
|
145
|
+
"project": "default", "name": "kmeans_clusterer", "version": "v1",
|
|
146
|
+
"parameters": {
|
|
147
|
+
"n_clusters": 4, "n_init": 20, "random_state": 42,
|
|
148
|
+
"preprocessing": {"scaler": "robust", "pca_variance": 0.95}
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
"reproducibility": {"seed": 42, "deterministic": true}
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Validation enforces these rules:
|
|
156
|
+
|
|
157
|
+
- `task.objective` is `clustering`, `data.labels` is empty, `input_adapter.kind`
|
|
158
|
+
is `tabular`, and `label_transform` is `identity:v1`. Do not declare
|
|
159
|
+
`data.temporal`, `forecast_target_adapter` or label materializations for the
|
|
160
|
+
model; clustering has no supervised target.
|
|
161
|
+
- The model FeatureSet is non-empty. Every column is a numeric
|
|
162
|
+
`role=feature` column available `at_prediction` or `static`, and every
|
|
163
|
+
artifact row's value is finite and non-null. Correct data gaps in the
|
|
164
|
+
DatasetArtifact; the trainer does not impute.
|
|
165
|
+
- `data.splits` is optional. Without it, every artifact row is a training row.
|
|
166
|
+
With it, the cluster count must be between 2 and the train-pool row count.
|
|
167
|
+
Validation and test pools may be empty. Splits matter for preprocessing,
|
|
168
|
+
because transforms are fitted on train rows only.
|
|
169
|
+
- `trainer.parameters` is strict. Unknown keys, booleans in integer fields,
|
|
170
|
+
integral floats such as `4.0`, and out-of-range values are rejected before
|
|
171
|
+
scheduling. Read the authoritative schema with
|
|
172
|
+
`get-system-model kmeans_clusterer v1` or
|
|
173
|
+
`get-system-model gaussian_mixture_clusterer v1`.
|
|
174
|
+
|
|
175
|
+
| SystemModel | Cluster count (default) | Other estimator fields (defaults) |
|
|
176
|
+
| --- | --- | --- |
|
|
177
|
+
| `kmeans_clusterer:v1` | `n_clusters` >= 2 (8) | `init` `k-means++`/`random`; `n_init` >= 1 or `auto` (`auto`); `max_iter` >= 1 (300); `tol` >= 0 (1e-4) |
|
|
178
|
+
| `gaussian_mixture_clusterer:v1` | `n_components` >= 2 (2) | `covariance_type` `full`/`tied`/`diag`/`spherical` (`full`); `init_params` `kmeans`/`k-means++`/`random`/`random_from_data` (`kmeans`); `n_init` >= 1 (1); `max_iter` >= 1 (100); `tol` >= 0 (1e-3); `reg_covar` >= 0 (1e-6) |
|
|
179
|
+
|
|
180
|
+
Both models also accept `random_state` (0..2^32-1; when it is unset, the
|
|
181
|
+
Worker uses the run's `reproducibility.seed`, which it injects as `seed` at
|
|
182
|
+
run time and which overrides any `seed` in the parameters) and an optional
|
|
183
|
+
`preprocessing` object with exactly two fields:
|
|
184
|
+
|
|
185
|
+
- `scaler`: `"robust"` or `null`. A robust scaler centers each column on its
|
|
186
|
+
train-pool median and divides by its interquartile range.
|
|
187
|
+
- `pca_variance`: a float strictly between 0 and 1, or `null`. PCA keeps the
|
|
188
|
+
fewest components that explain that fraction of train-pool variance and runs
|
|
189
|
+
after the scaler.
|
|
190
|
+
|
|
191
|
+
The trainer fits both transforms on train rows only and freezes them in the
|
|
192
|
+
artifact. Validation, test, evaluation and Serving rows are transformed and
|
|
193
|
+
assigned without refitting. Clustering distances and scores are computed in
|
|
194
|
+
this transformed space.
|
|
195
|
+
|
|
196
|
+
Apart from that runtime `seed`, clustering parameters are not filled from
|
|
197
|
+
top-level `reproducibility`.
|
|
198
|
+
`effective_trainer_parameters` contains exactly the submitted keys, and omitted
|
|
199
|
+
fields use the schema defaults inside the Worker. Set the cluster count,
|
|
200
|
+
`random_state` and `n_init` explicitly when the run must be reproducible and
|
|
201
|
+
reviewable. Changing any of them requires a new `run_id`.
|
|
202
|
+
|
|
203
|
+
### Choosing the cluster count and preprocessing
|
|
204
|
+
|
|
205
|
+
The defaults are silent. If the Run omits the cluster count, KMeans trains 8
|
|
206
|
+
clusters and Gaussian Mixture 2; if it omits `preprocessing`, no scaling or PCA
|
|
207
|
+
is applied. Validation does not warn, and `effective_trainer_parameters` echoes
|
|
208
|
+
only the submitted keys, so the default does not show up in the evidence you
|
|
209
|
+
review. Never submit a clustering Run that relies on either default.
|
|
210
|
+
|
|
211
|
+
Cluster count. Ask the user whether the business has a fixed number of regimes
|
|
212
|
+
or categories. If it does, use that number and record who confirmed it. If it
|
|
213
|
+
does not, select K with a documented method before treating any Run as final:
|
|
214
|
+
|
|
215
|
+
1. Agree a candidate range with the user (for example 2–10), bounded by how
|
|
216
|
+
many clusters the business can name and act on and by the train-pool size.
|
|
217
|
+
2. Fix everything except K: the same DatasetArtifact, model FeatureSet,
|
|
218
|
+
`preprocessing`, `n_init` and `random_state`. Each K is a separate
|
|
219
|
+
TrainingRun with its own `run_id`. Get authorization for the whole scan,
|
|
220
|
+
and follow [model-comparison.md](model-comparison.md) for recording
|
|
221
|
+
candidates, failures and stopping.
|
|
222
|
+
3. Evaluate every candidate with one shared clustering EvaluationConfig
|
|
223
|
+
([evaluation.md](evaluation.md)): `clustering.silhouette` (higher is
|
|
224
|
+
better), `clustering.davies_bouldin` (lower is better),
|
|
225
|
+
`clustering.calinski_harabasz` and `clustering.min_cluster_share`. Compare
|
|
226
|
+
transformed-space metrics only between runs with identical preprocessing;
|
|
227
|
+
use `calculation_space: "business"` when the comparison spans different
|
|
228
|
+
preprocessing.
|
|
229
|
+
4. Check stability: retrain the leading candidates with two or three other
|
|
230
|
+
`random_state` values (or on subsamples) and compare the assignments, for
|
|
231
|
+
example with adjusted Rand index. Compute this in the workspace and label it
|
|
232
|
+
exploratory; it is not a governed EvaluationResult. A K whose clusters
|
|
233
|
+
change between seeds is not a stable business vocabulary.
|
|
234
|
+
5. Show the user the leading candidates with cluster sizes and per-cluster
|
|
235
|
+
feature profiles in business units, and let the business judge whether the
|
|
236
|
+
clusters can be named and acted on. Metrics rarely give one clear winner,
|
|
237
|
+
so the final K is a business decision backed by the evidence above. Record
|
|
238
|
+
the range, metrics, stability result and decision.
|
|
239
|
+
|
|
240
|
+
Preprocessing. Ask, or justify from the data, instead of accepting the
|
|
241
|
+
default:
|
|
242
|
+
|
|
243
|
+
- `scaler`: KMeans and Gaussian Mixture are distance-based, so a column with a
|
|
244
|
+
large numeric range dominates. Use `"robust"` when columns have different
|
|
245
|
+
units or scales, or contain outliers. Use `null` only when every column
|
|
246
|
+
shares one unit and absolute differences are meaningful to the business
|
|
247
|
+
(for example, a set of temperatures where a 10-degree gap means the same
|
|
248
|
+
thing in every column), and record that reason.
|
|
249
|
+
- `pca_variance`: use it when many input columns are strongly correlated and
|
|
250
|
+
would otherwise count the same signal several times. A higher fraction
|
|
251
|
+
(0.95–0.99) keeps more detail; a lower one removes more noise. PCA makes
|
|
252
|
+
clusters harder to explain in business terms, so leave it `null` unless the
|
|
253
|
+
correlation is shown and the user accepts the trade-off.
|
|
254
|
+
|
|
255
|
+
Write the chosen K and `preprocessing` explicitly in `trainer.parameters`, even
|
|
256
|
+
when they equal the defaults.
|
|
257
|
+
|
|
258
|
+
A successful clustering Job writes training feedback (`cluster_count`,
|
|
259
|
+
`min_cluster_share`, `assignment_score_mean`) on the training `evaluation.split`,
|
|
260
|
+
which defaults to `auto`. This is diagnostic evidence only. The ModelSignature
|
|
261
|
+
outputs are `cluster_id` (int64) plus `distance_to_center` for KMeans or
|
|
262
|
+
`cluster_probability` for Gaussian Mixture. Cluster ids are meaningful only
|
|
263
|
+
within one immutable ModelArtifact.
|
|
264
|
+
|
|
265
|
+
The model file (`model.kmeans.json` or `model.gmm.json`) records its format:
|
|
266
|
+
|
|
267
|
+
- `<kind>_clustering/v1`: no preprocessing; estimator sidecar only.
|
|
268
|
+
- `<kind>_clustering/v2`: preprocessing is present. The file additionally
|
|
269
|
+
lists `transform_file` in `model_files`, records the training-time
|
|
270
|
+
`scikit_learn_version`, the preprocessing config, and the fitted summary:
|
|
271
|
+
scaler type, PCA component count, retained explained-variance ratio and
|
|
272
|
+
input feature order.
|
|
273
|
+
|
|
274
|
+
Loading refuses an unknown format, a missing estimator or transform sidecar,
|
|
275
|
+
or a v2 file whose recorded scikit-learn version differs from the runtime.
|
|
276
|
+
A v1 file records no scikit-learn version. Its safety relies on the training,
|
|
277
|
+
evaluation and Serving images of one Runtime Release sharing the same locked
|
|
278
|
+
scikit-learn stack, so keep v1 artifacts on images from that release line. Resolve a
|
|
279
|
+
version mismatch by using the Runtime Release binding whose image matches the
|
|
280
|
+
training runtime, or by retraining. Never edit artifact files.
|
|
281
|
+
|
|
115
282
|
## Chronos-2 LoRA parameters
|
|
116
283
|
|
|
117
284
|
Chronos-2 fine-tuning settings belong under `trainer.parameters`; they are
|
|
@@ -227,7 +394,11 @@ weather observations.
|
|
|
227
394
|
|
|
228
395
|
Inspect `data_schema.json`, `resolved_manifest.json` and the feature Parquet via
|
|
229
396
|
`download-dataset-artifact DATASET_ID MANIFEST_HASH --project PROJECT --out-dir DIR`
|
|
230
|
-
(repeat `--file` for selective downloads).
|
|
397
|
+
(repeat `--file` for selective downloads). `MANIFEST_HASH` is the artifact
|
|
398
|
+
manifest hash from `list-dataset-artifacts` or `artifact.manifest_hash` of a
|
|
399
|
+
succeeded `build-registered-dataset --wait`, not the registered manifest hash.
|
|
400
|
+
After training, `download-model-artifact ARTIFACT_ID --out-dir DIR [--file NAME]`
|
|
401
|
+
returns sha256-verified ModelArtifact files such as `runtime.json` and the model file. In TrainingRun v4, the FeatureSet
|
|
231
402
|
reference defines the ordered model inputs. It may be a registered exact-version
|
|
232
403
|
subset of the DatasetArtifact's materialized FeatureSet, in its own order. The
|
|
233
404
|
platform freezes both identities and the projected dependency contract in the
|
|
@@ -15,6 +15,11 @@ FeatureSet order and evaluation runtime before the first Job. See
|
|
|
15
15
|
do not try similar names or re-register trainers to bypass approval.
|
|
16
16
|
- ARIMA supports the v1 single-target adapter for single-channel CPU
|
|
17
17
|
forecasting; it does not support covariates or the v2 adapter.
|
|
18
|
+
- Clustering (`task.kind=clustering`) is unsupervised, CPU-only and tabular.
|
|
19
|
+
It uses TrainingRun v4 with `labels: []` and no temporal binding, optional
|
|
20
|
+
splits, and a strict parameter schema that includes train-fitted
|
|
21
|
+
`preprocessing`. Read the clustering section of
|
|
22
|
+
[training-contracts.md](training-contracts.md) before authoring the Run.
|
|
18
23
|
- Chronos-2 supports the legacy v1 single-target adapter and the v2
|
|
19
24
|
covariate-aware adapter. v2 jointly forecasts ordered target channels and
|
|
20
25
|
accepts numeric `past_only` and `known_future` covariates. Do not silently
|
|
@@ -49,6 +54,40 @@ it does not reconstruct it from manifest `rowset_splits`. Save the submitted
|
|
|
49
54
|
TrainingRun JSON, validation output, Job ID and ModelArtifact ID in the user's
|
|
50
55
|
working directory so later diagnosis needs no source repository.
|
|
51
56
|
|
|
57
|
+
For a second experiment over the same immutable DatasetArtifact, a TrainingRun
|
|
58
|
+
may freeze a time based split without adding a split column to the artifact:
|
|
59
|
+
|
|
60
|
+
```json
|
|
61
|
+
{
|
|
62
|
+
"splits": {
|
|
63
|
+
"mode": "derived",
|
|
64
|
+
"strategy": "time_range",
|
|
65
|
+
"source_rowsets": ["all"],
|
|
66
|
+
"ranges": {
|
|
67
|
+
"train": {"start": "2026-01-01T00:00:00+08:00", "end": "2026-07-01T00:00:00+08:00"},
|
|
68
|
+
"validation": {"start": "2026-07-01T00:00:00+08:00", "end": "2026-08-01T00:00:00+08:00"},
|
|
69
|
+
"test": {"start": "2026-08-01T00:00:00+08:00", "end": "2026-09-01T00:00:00+08:00"}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
`time_range` uses timezone aware, left closed/right open prediction time
|
|
76
|
+
intervals and requires unique row keys. The platform freezes each role's row
|
|
77
|
+
identity in the resolved TrainingJob and rechecks it in the Worker. Samples
|
|
78
|
+
whose `label_time` reaches or passes their role's end are excluded and counted
|
|
79
|
+
in the validation snapshot; if that leaves no train samples, validation fails.
|
|
80
|
+
Training time evaluation must explicitly use `train` or `validation`; `test`
|
|
81
|
+
is reserved for an independent EvaluationRun. For `chronological_ratio`, provide
|
|
82
|
+
`ratios` with `train`, `validation` and `test` values summing to `1`; equal
|
|
83
|
+
prediction timestamps stay together. Actual counts may differ from requested
|
|
84
|
+
ratios, and the algorithm version and row identities are frozen in the Job
|
|
85
|
+
snapshot. Derived splits currently use all artifact rows as candidates; use
|
|
86
|
+
`assignment_column` for artifacts containing auxiliary history or truth rows.
|
|
87
|
+
Only `time_range` and `chronological_ratio` are supported. Confirm the selected
|
|
88
|
+
training and evaluation Worker images support derived splits before submission.
|
|
89
|
+
Existing `assignment_column` contracts keep their original behavior.
|
|
90
|
+
|
|
52
91
|
## Commands
|
|
53
92
|
|
|
54
93
|
Read [training-contracts.md](training-contracts.md) when authoring a Run or Job
|
|
@@ -87,6 +126,27 @@ ml-platform --profile server cancel-training-job <job-id>
|
|
|
87
126
|
|
|
88
127
|
Retry and cancellation require exact-Job authorization. Never change a run contract while retrying; create a new immutable run when semantic inputs change.
|
|
89
128
|
|
|
129
|
+
## Clustering training sequence
|
|
130
|
+
|
|
131
|
+
Every step below is a separate gate. Registration and submission still need
|
|
132
|
+
explicit authorization.
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
ml-platform --profile server get-system-model kmeans_clusterer v1 --project default
|
|
136
|
+
ml-platform --profile server validate-training-run cluster-run.json
|
|
137
|
+
ml-platform --profile server register-training-run cluster-run.json
|
|
138
|
+
ml-platform --profile server validate-training-job cluster-job-request.json
|
|
139
|
+
ml-platform --profile server submit-training-job cluster-job-request.json
|
|
140
|
+
ml-platform --profile server get-training-job <job-id>
|
|
141
|
+
ml-platform --profile server validate-model-artifact <artifact-id>
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
The Job request uses `"device": "cpu"`; clustering SystemModels advertise no
|
|
145
|
+
other device. Before submission, confirm that `effective_trainer_parameters`
|
|
146
|
+
equals the submitted `trainer.parameters`. After success, validate the exact
|
|
147
|
+
`status.artifact_id`; the artifact must carry clustering `output_bindings`
|
|
148
|
+
instead of `target_bindings`.
|
|
149
|
+
|
|
90
150
|
## Chronos-2 fine-tuning parameters
|
|
91
151
|
|
|
92
152
|
Configure Chronos-2 algorithm parameters only under
|