@zhuoyuezs/ml-platform 0.1.8 → 0.1.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.
Files changed (34) hide show
  1. package/README.md +7 -3
  2. package/package.json +1 -1
  3. package/checksums.json +0 -155
  4. package/release.json +0 -52
  5. package/runtime/business-client/README.md +0 -78
  6. package/runtime/business-client/package-lock.json +0 -19
  7. package/runtime/business-client/package.json +0 -23
  8. package/runtime/business-client/src/catalog.js +0 -206
  9. package/runtime/business-client/src/cli.js +0 -533
  10. package/runtime/business-client/src/config.js +0 -56
  11. package/runtime/business-client/src/http.js +0 -254
  12. package/skills/feature-management/SKILL.md +0 -479
  13. package/skills/feature-management/agents/openai.yaml +0 -4
  14. package/skills/feature-management/assets/catalog-template/catalog.json +0 -23
  15. package/skills/feature-management/assets/catalog-template/datasets/example_temperature_training.v1.json +0 -40
  16. package/skills/feature-management/assets/catalog-template/feature_sets/example_temperature_core.v1.json +0 -14
  17. package/skills/feature-management/assets/catalog-template/features/example_temperature_mean_5m.v1.json +0 -28
  18. package/skills/feature-management/assets/catalog-template/operator_package/pyproject.toml +0 -12
  19. package/skills/feature-management/assets/catalog-template/operator_package/src/business_feature_operator_template/__init__.py +0 -39
  20. package/skills/feature-management/assets/catalog-template/operator_package/tests/test_operator.py +0 -83
  21. package/skills/feature-management/assets/catalog-template/operators/example_temperature_features.v1.json +0 -58
  22. package/skills/feature-management/assets/catalog-template/parameters/example_temperature.v1.json +0 -58
  23. package/skills/feature-management/references/commands.md +0 -358
  24. package/skills/feature-management/references/contracts.md +0 -719
  25. package/skills/feature-management/references/operator-authoring.md +0 -175
  26. package/skills/feature-management/references/platform-capability-guide.md +0 -75
  27. package/skills/feature-management/references/supervised-datasets.md +0 -101
  28. package/skills/model-lifecycle-management/SKILL.md +0 -38
  29. package/skills/model-lifecycle-management/agents/openai.yaml +0 -4
  30. package/skills/model-lifecycle-management/references/discovery.md +0 -89
  31. package/skills/model-lifecycle-management/references/evaluation.md +0 -172
  32. package/skills/model-lifecycle-management/references/packaging.md +0 -51
  33. package/skills/model-lifecycle-management/references/training-contracts.md +0 -139
  34. package/skills/model-lifecycle-management/references/training.md +0 -81
@@ -1,83 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import unittest
4
- from types import SimpleNamespace
5
-
6
- import pandas as pd
7
-
8
- from business_feature_operator_template import compute_features
9
-
10
-
11
- class ComputeFeaturesTest(unittest.TestCase):
12
- def context(
13
- self,
14
- timestamps: list[str] | None = None,
15
- values: list[float | None] | None = None,
16
- targets: list[str] | None = None,
17
- requested: list[str] | None = None,
18
- ) -> SimpleNamespace:
19
- timestamps = timestamps or [
20
- "2026-07-01 09:54:00",
21
- "2026-07-01 09:56:00",
22
- "2026-07-01 10:00:00",
23
- "2026-07-01 10:01:00",
24
- ]
25
- values = values or [10.0, 20.0, 30.0, 40.0]
26
- source = pd.DataFrame({"timestamp": pd.DatetimeIndex(timestamps), "value": values})
27
- return SimpleNamespace(
28
- requested_output_columns=requested or ["example_temperature_mean_5m"],
29
- inputs=[
30
- SimpleNamespace(
31
- parameter="example_temperature",
32
- key="example_temperature:v1",
33
- )
34
- ],
35
- metric_frames={"example_temperature:v1": source},
36
- target_times=pd.DatetimeIndex(targets or ["2026-07-01 10:00:00", "2026-07-01 10:02:00"]),
37
- config={"window": "5min"},
38
- )
39
-
40
- def test_formula_uses_the_confirmed_mean(self) -> None:
41
- result = compute_features(self.context())
42
- self.assertEqual(result["example_temperature_mean_5m"].tolist(), [25.0, 35.0])
43
-
44
- def test_excludes_event_at_open_left_window_boundary(self) -> None:
45
- result = compute_features(self.context(["2026-07-01 09:55:00", "2026-07-01 09:56:00"], [10.0, 20.0]))
46
- self.assertEqual(result["example_temperature_mean_5m"].iloc[0], 20.0)
47
-
48
- def test_includes_event_exactly_at_cutoff(self) -> None:
49
- result = compute_features(self.context(["2026-07-01 10:00:00"], [30.0]))
50
- self.assertEqual(result["example_temperature_mean_5m"].iloc[0], 30.0)
51
-
52
- def test_excludes_event_after_cutoff(self) -> None:
53
- result = compute_features(self.context(["2026-07-01 10:00:01"], [40.0]))
54
- self.assertTrue(pd.isna(result["example_temperature_mean_5m"].iloc[0]))
55
-
56
- def test_uses_last_value_for_duplicate_event_time(self) -> None:
57
- result = compute_features(self.context(["2026-07-01 10:00:00", "2026-07-01 10:00:00"], [10.0, 30.0]))
58
- self.assertEqual(result["example_temperature_mean_5m"].iloc[0], 30.0)
59
-
60
- def test_empty_history_returns_null(self) -> None:
61
- result = compute_features(self.context(["2026-07-01 09:00:00"], [10.0]))
62
- self.assertTrue(pd.isna(result["example_temperature_mean_5m"].iloc[0]))
63
-
64
- def test_requested_output_is_exactly_the_supported_subset(self) -> None:
65
- result = compute_features(self.context(requested=["example_temperature_mean_5m"]))
66
- self.assertEqual(list(result.columns), ["event_time", "example_temperature_mean_5m"])
67
-
68
- def test_preserves_requested_event_time_order(self) -> None:
69
- targets = ["2026-07-01 10:02:00", "2026-07-01 10:00:00"]
70
- result = compute_features(self.context(targets=targets))
71
- self.assertEqual(list(result["event_time"]), list(pd.DatetimeIndex(targets)))
72
-
73
- def test_output_dtype_is_float64(self) -> None:
74
- result = compute_features(self.context())
75
- self.assertEqual(str(result["example_temperature_mean_5m"].dtype), "float64")
76
-
77
- def test_rejects_unknown_requested_output(self) -> None:
78
- with self.assertRaisesRegex(ValueError, "unsupported output columns"):
79
- compute_features(self.context(requested=["unknown_feature"]))
80
-
81
-
82
- if __name__ == "__main__":
83
- unittest.main()
@@ -1,58 +0,0 @@
1
- {
2
- "schema_version": "ml_data_platform.operator/v1",
3
- "project": "replace_with_project",
4
- "name": "example_temperature_features",
5
- "version": "v1",
6
- "type": "feature",
7
- "function_hash": "example_temperature_features.formulas.v1",
8
- "entrypoint": "business_feature_operator_template:compute_features",
9
- "code_hash": null,
10
- "package_uri": null,
11
- "code_artifact": null,
12
- "input_schema": {
13
- "parameters": [
14
- "replace_with_project/example_temperature:v1"
15
- ],
16
- "prediction": {
17
- "required": true,
18
- "minimum_horizon": "0min",
19
- "maximum_horizon": "0min"
20
- },
21
- "history_requirements": [
22
- {
23
- "anchor": "cutoff",
24
- "lookback": "5min",
25
- "output_columns": [
26
- "example_temperature_mean_5m"
27
- ]
28
- }
29
- ]
30
- },
31
- "output_schema": {
32
- "columns": [
33
- "event_time",
34
- "example_temperature_mean_5m"
35
- ]
36
- },
37
- "config_schema": {
38
- "properties": {
39
- "window": {
40
- "type": "string"
41
- }
42
- },
43
- "required": [
44
- "window"
45
- ]
46
- },
47
- "runtime": {
48
- "engine": "python_entrypoint",
49
- "network": "none"
50
- },
51
- "resources": {
52
- "timeout_seconds": 60
53
- },
54
- "deterministic": true,
55
- "supports_batch": true,
56
- "supports_online": false,
57
- "owner": "replace_with_business_owner"
58
- }
@@ -1,58 +0,0 @@
1
- {
2
- "schema_version": "ml_data_platform.parameter/v1",
3
- "project": "replace_with_project",
4
- "name": "example_temperature",
5
- "display_name": "Example temperature",
6
- "version": "v1",
7
- "data_type": "time_series",
8
- "unit": "degC",
9
- "expected_frequency": "1min",
10
- "source": {
11
- "adapter": "postgresql_direct",
12
- "mode": "direct_column",
13
- "schema": "process_data",
14
- "table": "sensor_readings",
15
- "time_column": "event_time",
16
- "value_column": "temperature",
17
- "metric_name": "example_temperature",
18
- "unit_column": "unit",
19
- "filters": {
20
- "furnace_id": "BF12"
21
- }
22
- },
23
- "time_semantics": {
24
- "event_time_field": "event_time",
25
- "ingested_at_field": "ingested_at",
26
- "timezone": "Asia/Shanghai",
27
- "availability": {
28
- "strategy": "source_field",
29
- "field": "ingested_at",
30
- "accuracy": "exact"
31
- }
32
- },
33
- "availability_sla": {
34
- "max_delay": "PT10M"
35
- },
36
- "value_field": "value",
37
- "quality_rules": {
38
- "valid_range": [0.0, 2000.0],
39
- "allow_missing": true,
40
- "rules": [
41
- {
42
- "id": "finite_source_values",
43
- "stage": "normalized_source",
44
- "check": {
45
- "type": "finite"
46
- },
47
- "acceptance": {
48
- "max_violation_rate": 0.0,
49
- "min_evaluated_rows": 1,
50
- "min_comparable_rate": 0.0
51
- },
52
- "enforcement": "fail",
53
- "description": "Reject non-finite source values before preprocessing."
54
- }
55
- ]
56
- },
57
- "owner": "replace_with_business_owner"
58
- }
@@ -1,358 +0,0 @@
1
- # Platform Commands
2
-
3
- Use the `ml-platform` executable installed on `PATH` by the same ML Platform release as this Skill. The Skill contains no client runtime or launcher. Do not require a platform source checkout. Use the same API target for discovery, dry-run, publication, resolve, and build.
4
-
5
- ## Contents
6
-
7
- 1. Select a target
8
- 2. Discover Registry state
9
- 3. Test and build an Operator
10
- 4. Validate and publish a catalog
11
- 5. Resolve and build a dataset
12
- 6. Fetch realtime inference data
13
- 7. Inspect and change Registry lifecycle state
14
- 8. Inspect and download an artifact
15
- 9. Prohibited shortcuts
16
-
17
- ## Select A Target
18
-
19
- Verify the installed CLI before using the Skill:
20
-
21
- ```bash
22
- command -v ml-platform
23
- ml-platform version
24
- ml-platform --help
25
- ```
26
-
27
- Configure the server API for business users:
28
-
29
- ```bash
30
- ml-platform configure --api-url http://<platform-api-host>:8060
31
- ml-platform --profile server show-config
32
- ml-platform --profile server health
33
- ```
34
-
35
- The URL is environment-specific and must be supplied by the user, an approved
36
- `ML_PLATFORM_API_URL`, or the saved value from `ml-platform configure`. Do not
37
- hardcode an internal address in this Skill or in a catalog. `show-config` displays
38
- the effective target before discovery, dry-run, publication, build, or artifact
39
- commands.
40
-
41
- Do not place database, MinIO, or source credentials in commands when the server profile can use managed Secrets.
42
-
43
- ## Discover Registry State
44
-
45
- ```bash
46
- ml-platform --profile server list-parameters -q <stable-name>
47
- ml-platform --profile server list-operators -q <stable-name>
48
- ml-platform --profile server list-features -q <stable-name>
49
- ml-platform --profile server list-feature-sets -q <stable-name>
50
- ml-platform --profile server list-datasets -q <stable-dataset-id>
51
- ```
52
-
53
- Run each command separately. Check `ml-platform --help` and the specific
54
- subcommand help before adding flags. In the deployed 0.6.x CLI, `list-*`
55
- commands print JSON by default and do not accept a `--json` flag.
56
- If a deployed release rejects the global `--profile server` prefix, treat that
57
- as CLI compatibility drift: record the syntax error, inspect `show-config` and
58
- the subcommand help, then retry the same read-only command without the rejected
59
- flag only if the installed help permits it. Do not report this as API/network
60
- unavailability or switch to a direct HTTP client.
61
-
62
- By default each `list-*` command auto-pages through the whole result set and
63
- prints a **bare JSON array** of every matching item, so it never silently stops
64
- at the server's default page size. Use `-q` for a case-insensitive identifier
65
- substring search. To fetch one explicit page instead, pass `--limit` (1-500)
66
- and/or `--offset`; in that single-page mode the command prints the
67
- `{"items": [...], "total": ..., "limit": ..., "offset": ...}` envelope so you can
68
- resume with the next `--offset`. Note that `--offset` paging is not stable
69
- under concurrent writes: if items are added or removed between page requests,
70
- boundary rows can be skipped or repeated. A stable cursor is planned as a
71
- follow-up. Catalog `apply` and `apply --dry-run` page
72
- through the entire Registry automatically. Filter structured JSON with a JSON
73
- parser when the output is large. Do not scrape it with fragile text replacement.
74
-
75
- Every `list-*` registry command (except `list-jobs`) accepts `--project <name>`
76
- to restrict results to a single project. Omit it to list across all projects:
77
-
78
- ```bash
79
- ml-platform --profile server list-parameters --project <project>
80
- ml-platform --profile server list-feature-sets --project <project>
81
- ```
82
-
83
- ## Projects
84
-
85
- A project is an isolated namespace over the whole registry. The real identity of
86
- every asset is `project/name:version`, so the same `name:version` can exist
87
- independently under different projects and never collide. The platform ships a
88
- built-in `default` project used whenever a project is not specified.
89
-
90
- Project is supplied differently for writes vs reads:
91
-
92
- Manage projects through the business client as well:
93
-
94
- ```bash
95
- ml-platform create-project <project> --display-name "<display name>" --description "<description>"
96
- ml-platform list-projects
97
- ml-platform get-project <project>
98
- ml-platform delete-project <project>
99
- ```
100
-
101
- `delete-project` is subject to the server's protection and only succeeds for an
102
- empty project. Project commands are server-only and do not modify local storage.
103
-
104
- - Creation: the project an asset is published under comes from the optional
105
- `project` field in its own JSON spec (defaults to `default` when omitted). Set
106
- `"project": "<name>"` in the spec to publish into a non-default project.
107
- - `apply --project <project>` scopes the comparison snapshot the catalog is
108
- validated against (omit to compare against `default`);
109
- - `list-* --project <project>` filters discovery to that project;
110
- - `get-dataset-artifact` / `download-dataset-artifact` take the project as their
111
- first positional argument (defaults to `default`).
112
-
113
- Before choosing names, discover within the target project: identical names in a
114
- different project are unrelated and must not be reused across projects to mean the
115
- same thing. Cross-project references are rejected by the platform.
116
-
117
- ## Test And Build An Operator
118
-
119
- From the Operator package directory:
120
-
121
- ```bash
122
- uv run python -m unittest discover -s tests -p 'test_*.py'
123
- ```
124
-
125
- Build the package:
126
-
127
- ```bash
128
- uv build <catalog>/operator_package \
129
- --wheel \
130
- --out-dir <catalog>/operator_package/dist
131
- ```
132
-
133
- Confirm that `catalog.json` references the exact generated filename.
134
-
135
- ## Validate And Publish A Catalog
136
-
137
- Validate against the intended server Registry without mutation:
138
-
139
- ```bash
140
- ml-platform --profile server apply <catalog-directory> --dry-run
141
- ```
142
-
143
- Review the returned counts and conflicts. After explicit user approval, publish:
144
-
145
- ```bash
146
- ml-platform --profile server apply <catalog-directory>
147
- ```
148
-
149
- Add `--project <project>` to publish into a specific project and compare against
150
- that project's snapshot only. Without it, the catalog is applied to the built-in
151
- `default` project:
152
-
153
- ```bash
154
- ml-platform --profile server apply <catalog-directory> --project <project> --dry-run
155
- ml-platform --profile server apply <catalog-directory> --project <project>
156
- ```
157
-
158
- `apply` processes dependencies in this order:
159
-
160
- ```text
161
- Parameter -> Operator package/Operator -> Feature -> FeatureSet -> Dataset
162
- ```
163
-
164
- The cross-store publication is not transactional. If an error occurs, report the returned progress summary and rerun only after understanding which immutable assets were already published.
165
-
166
- ## Resolve And Build A Dataset
167
-
168
- For an existing registered DatasetManifest, use the Registry identity only; no
169
- local Catalog or Manifest path is needed:
170
-
171
- ```bash
172
- ml-platform --profile server list-projects
173
- ml-platform --profile server list-datasets --project <project>
174
- ml-platform --profile server \
175
- get-dataset <dataset_id> <dataset_version> --project <project>
176
- ml-platform --profile server \
177
- resolve-dataset <dataset_id> <dataset_version> --project <project>
178
- ```
179
-
180
- After the user confirms the exact triple and authorizes one build:
181
-
182
- ```bash
183
- ml-platform --profile server \
184
- build-registered-dataset <dataset_id> <dataset_version> \
185
- --project <project> \
186
- --partition-duration 1d \
187
- --max-parallelism 1 \
188
- --wait
189
- ```
190
-
191
- The command first fetches that immutable DatasetManifest from the API and sends
192
- the validated response to the resolve/build endpoint. It never searches the
193
- current repository for a similarly named file. Record the API source,
194
- `project/dataset_id:dataset_version`, manifest hash, Job ID, terminal status,
195
- and artifact reference.
196
-
197
- When authoring a new or changed contract that has not been registered yet, use
198
- the local-file commands below.
199
-
200
- Resolve without fetching source data:
201
-
202
- ```bash
203
- ml-platform --profile server \
204
- resolve-manifest <catalog>/datasets/<dataset>.json \
205
- --out /tmp/<dataset>.resolved.json
206
- ```
207
-
208
- Submit and wait for a server build:
209
-
210
- ```bash
211
- ml-platform --profile server \
212
- build-dataset <catalog>/datasets/<dataset>.json \
213
- --partition-duration 1d \
214
- --max-parallelism 1 \
215
- --wait
216
- ```
217
-
218
- `--partition-duration` is an execution control and does not change the
219
- DatasetManifest hash. The initial implementation is sequential, so keep
220
- `--max-parallelism 1`. Completed partitions are checkpointed and resumed by
221
- default; use `--no-resume` only to force a clean execution.
222
-
223
- Record the returned `job_id`, `dataset_id`, and `manifest_hash`. If a separate wait is needed:
224
-
225
- ```bash
226
- ml-platform --profile server wait-job <job_id>
227
- ml-platform --profile server get-job <job_id>
228
- ```
229
-
230
- With explicit user authorization, stop a running build through the server CLI:
231
-
232
- ```bash
233
- ml-platform --profile server cancel-job <job_id>
234
- ```
235
-
236
- Cancellation is terminal for that Job; it does not change the immutable
237
- DatasetManifest and it does not automatically resubmit with different
238
- partition or parallelism settings. Check `get-job` after the request and
239
- record the returned terminal status.
240
-
241
- ## Fetch Realtime Inference Data
242
-
243
- Fetch one causal-cutoff row in memory:
244
-
245
- ```bash
246
- ml-platform --profile server \
247
- fetch-inference-data <catalog>/datasets/<dataset>.json \
248
- --cutoff-time 2026-07-31T10:00:00+08:00
249
- ```
250
-
251
- Optional flags `--max-workers`, `--max-source-lag-hours`,
252
- `--no-validate-freshness`, and `--allow-missing` override individual
253
- `realtime_fetch` fields for this request. Prefer the versioned manifest policy;
254
- use overrides only when the user explicitly requests different runtime behavior.
255
-
256
- This command calls `POST /inference-data/fetch`. It does not submit a build Job,
257
- write parquet, or publish a DatasetArtifact. Treat HTTP `503` as retryable source
258
- freshness/missing-data failure and HTTP `400` as a contract error that requires a
259
- manifest or request change.
260
-
261
- For a deployment-bound row or full sequence context, prepare one JSON object
262
- containing `feature_retrieval`, `cutoff_time`, and `entity_keys`, then run:
263
-
264
- ```bash
265
- ml-platform --profile server fetch-inference-context /tmp/inference-context.json
266
- ```
267
-
268
- The `FeatureRetrievalSpec` must bind an existing inference-mode DatasetManifest
269
- by project, dataset id, version, and manifest hash; its FeatureSet and contract
270
- signature must match the resolved online contract. Context mode also fixes
271
- `context_length`, `frequency`, `context_end`, `stride`, input-adapter hash, and
272
- temporal-binding hash. Do not replace these immutable deployment bindings with
273
- ad-hoc CLI flags. As with row fetch, this operation writes no artifact.
274
-
275
- ## Inspect And Change Registry Lifecycle State
276
-
277
- Lifecycle commands apply only to Parameter, Feature, and FeatureSet versions.
278
- Before a mutation, inspect the exact resource and its references:
279
-
280
- ```bash
281
- ml-platform --profile server get-parameter-lifecycle <name> <version> --project <project>
282
- ml-platform --profile server list-parameter-references <name> <version> --project <project> --direct
283
- ml-platform --profile server list-parameter-references <name> <version> --project <project>
284
- ```
285
-
286
- Equivalent `get-*-lifecycle` and `list-*-references` commands exist for
287
- `feature` and `feature-set`. The default reference query returns the transitive
288
- closure; `--direct` returns only immediate dependents.
289
-
290
- After explicit authorization for the exact resource, soft-delete it with
291
- auditable metadata:
292
-
293
- ```bash
294
- ml-platform --profile server delete-parameter <name> <version> \
295
- --project <project> --actor <actor> --reason '<reason>' \
296
- --idempotency-key <stable-key>
297
- ```
298
-
299
- Restore uses the same audit fields and is rejected if the resource's own
300
- dependencies are not active:
301
-
302
- ```bash
303
- ml-platform --profile server restore-parameter <name> <version> \
304
- --project <project> --actor <actor> --reason '<reason>' \
305
- --idempotency-key <stable-key>
306
- ```
307
-
308
- These operations never erase immutable specs, historical references, or
309
- contract hashes. Do not use the Operator or Dataset deletion commands as a
310
- substitute; they have separate lifecycle rules.
311
-
312
- ## Inspect And Download An Artifact
313
-
314
- ```bash
315
- ml-platform --profile server \
316
- get-dataset-artifact <dataset_id> <manifest_hash> --project <project>
317
-
318
- ml-platform --profile server \
319
- download-dataset-artifact <dataset_id> <manifest_hash> \
320
- --project <project> \
321
- --out-dir /tmp/<dataset_id>-artifact
322
- ```
323
-
324
- `--project` defaults to `default`; pass the owning project when the dataset lives
325
- elsewhere, or the lookup returns `artifact_not_found`.
326
-
327
- The download command writes progress to stderr after response headers arrive.
328
- Interpret a timeout with no progress line as a request/header or first-byte
329
- failure. Interpret a timeout after one or more `artifact download: received ...`
330
- lines as an incomplete response body. In either case, report the timeout and
331
- keep downloaded-file validation incomplete; do not replace the supported CLI
332
- with direct HTTP or object-store access. A successful metadata query remains
333
- valid metadata-only evidence, but it does not prove Parquet schema, column
334
- order, or file-content hashes.
335
-
336
- Inspect at least:
337
-
338
- ```text
339
- dataset_manifest.json
340
- resolved_manifest.json
341
- validation.json
342
- lineage.json
343
- feature_computations/computation_manifest.json
344
- feature_computations/executions/*.json
345
- feature_dataset.parquet
346
- ```
347
-
348
- Use a structured Parquet reader for schema, row count, column order, and missing-rate inspection.
349
-
350
- ## Prohibited Shortcuts
351
-
352
- - Do not use `seed-demo v95` for business catalogs.
353
- - Do not call individual `add-*` commands when catalog `apply` is available for an end-to-end publication.
354
- - Do not use any `delete-*`, `restore-*`, `cancel-job`, or force overwrite operation unless separately requested.
355
- - Do not build images, deploy Kubernetes, or change service configuration in this workflow.
356
- - Do not claim a successful publication from `--dry-run` output.
357
- - Do not claim Chronon compile/backfill from a successful first-phase Operator build.
358
- - Do not use `build-dataset` to serve a single realtime inference cutoff.