modelctl-mlflow 1.1.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- modelctl_mlflow-1.1.2/LICENSE +21 -0
- modelctl_mlflow-1.1.2/PKG-INFO +312 -0
- modelctl_mlflow-1.1.2/README.md +297 -0
- modelctl_mlflow-1.1.2/modelctl/__init__.py +7 -0
- modelctl_mlflow-1.1.2/modelctl/__main__.py +5 -0
- modelctl_mlflow-1.1.2/modelctl/cli.py +277 -0
- modelctl_mlflow-1.1.2/modelctl/core.py +766 -0
- modelctl_mlflow-1.1.2/modelctl/tags.py +130 -0
- modelctl_mlflow-1.1.2/modelctl_mlflow.egg-info/PKG-INFO +312 -0
- modelctl_mlflow-1.1.2/modelctl_mlflow.egg-info/SOURCES.txt +14 -0
- modelctl_mlflow-1.1.2/modelctl_mlflow.egg-info/dependency_links.txt +1 -0
- modelctl_mlflow-1.1.2/modelctl_mlflow.egg-info/entry_points.txt +2 -0
- modelctl_mlflow-1.1.2/modelctl_mlflow.egg-info/requires.txt +1 -0
- modelctl_mlflow-1.1.2/modelctl_mlflow.egg-info/top_level.txt +1 -0
- modelctl_mlflow-1.1.2/pyproject.toml +27 -0
- modelctl_mlflow-1.1.2/setup.cfg +4 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: modelctl-mlflow
|
|
3
|
+
Version: 1.1.2
|
|
4
|
+
Summary: Small MLflow Model Registry utility for versioning arbitrary model payloads.
|
|
5
|
+
Author: rexologue
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Keywords: cli,utilities,mlflow,registry
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Operating System :: OS Independent
|
|
10
|
+
Requires-Python: >=3.10
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Requires-Dist: mlflow>=2.9
|
|
14
|
+
Dynamic: license-file
|
|
15
|
+
|
|
16
|
+
# modelctl-mlflow
|
|
17
|
+
|
|
18
|
+
`modelctl` is a small CLI wrapper around MLflow Model Registry for storing, verifying, promoting and pulling arbitrary model payloads.
|
|
19
|
+
|
|
20
|
+
The tool does not try to interpret a payload as a specific ML framework. A registered version is always:
|
|
21
|
+
|
|
22
|
+
```text
|
|
23
|
+
small metadata package + opaque payload directory
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
MLflow backend storage keeps metadata: runs, versions, aliases, tags and source URIs. MLflow artifact storage keeps the actual payload bytes.
|
|
27
|
+
|
|
28
|
+
## Installation
|
|
29
|
+
|
|
30
|
+
Install as a CLI tool with uv:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
uv tool install modelctl-mlflow
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Run once without installing the tool globally:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
uvx --from modelctl-mlflow modelctl --help
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Install with pip:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
pip install modelctl-mlflow
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
For local development from a checkout:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
pip install -e .
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
or:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
uv pip install -e .
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
After installation, the CLI command is:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
modelctl --help
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
The PyPI package name is `modelctl-mlflow`; the installed command is `modelctl`.
|
|
67
|
+
|
|
68
|
+
## Quick start
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
modelctl register ./model my-model
|
|
72
|
+
modelctl list my-model
|
|
73
|
+
modelctl info my-model@champion
|
|
74
|
+
modelctl pull my-model@champion ./downloaded-model
|
|
75
|
+
modelctl verify my-model@champion ./downloaded-model
|
|
76
|
+
modelctl promote my-model 3 champion
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Commands print machine-readable JSON to stdout. Human-readable progress and errors are printed to stderr.
|
|
80
|
+
|
|
81
|
+
## MLflow connection
|
|
82
|
+
|
|
83
|
+
Default tracking URI:
|
|
84
|
+
|
|
85
|
+
```text
|
|
86
|
+
http://localhost:5000
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Override host and port:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
modelctl list <model_name> --host <host> --port <port>
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Or pass a full tracking URI:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
modelctl list <model_name> --tracking-uri <tracking_uri>
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
MLflow authentication is handled by MLflow itself through its usual environment variables, for example `MLFLOW_TRACKING_USERNAME` and `MLFLOW_TRACKING_PASSWORD`.
|
|
102
|
+
|
|
103
|
+
## Register
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
modelctl register <payload_dir> <model_name>
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
With explicit aliases:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
modelctl register <payload_dir> <model_name> --alias <alias_a> --alias <alias_b>
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Default alias behavior:
|
|
116
|
+
|
|
117
|
+
```text
|
|
118
|
+
first version -> baseline + champion
|
|
119
|
+
later versions -> candidate
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
During registration, `modelctl`:
|
|
123
|
+
|
|
124
|
+
```text
|
|
125
|
+
1. connects to MLflow
|
|
126
|
+
2. computes a stable SHA256 payload hash
|
|
127
|
+
3. starts a short technical MLflow run
|
|
128
|
+
4. writes metadata files
|
|
129
|
+
5. logs payload bytes to the artifact store under model/payload
|
|
130
|
+
6. creates a Model Registry version
|
|
131
|
+
7. writes modelctl.payload_hash to Model Version tags
|
|
132
|
+
8. attaches aliases
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
The registration result is printed as JSON. Human-readable progress is printed to stderr.
|
|
136
|
+
|
|
137
|
+
## Metadata tags
|
|
138
|
+
|
|
139
|
+
Two optional metadata namespaces are supported:
|
|
140
|
+
|
|
141
|
+
```text
|
|
142
|
+
general - stable descriptive metadata
|
|
143
|
+
training - training, dataset, evaluation or build metadata
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Full metadata dictionaries are stored as JSON artifacts. A flattened searchable projection is also written to MLflow Model Version tags.
|
|
147
|
+
|
|
148
|
+
Register with JSON metadata:
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
modelctl register <payload_dir> <model_name> --general-tags-json <general.json> --training-tags-json <training.json>
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Register with inline metadata:
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
modelctl register <payload_dir> <model_name> --general-tag <key>=<value> --training-tag <key>=<value>
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Inline values are parsed as JSON when possible, so numbers, booleans, objects and lists are supported.
|
|
161
|
+
|
|
162
|
+
## Artifact layout
|
|
163
|
+
|
|
164
|
+
Every registered version stores this package in the artifact store:
|
|
165
|
+
|
|
166
|
+
```text
|
|
167
|
+
model/
|
|
168
|
+
├── MLmodel
|
|
169
|
+
├── manifest.json
|
|
170
|
+
├── payload.sha256.json
|
|
171
|
+
├── metadata/
|
|
172
|
+
│ ├── general_tags.json
|
|
173
|
+
│ └── training_tags.json
|
|
174
|
+
└── payload/
|
|
175
|
+
└── ... payload contents ...
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
`model/payload/` contains the actual registered payload.
|
|
179
|
+
|
|
180
|
+
`model/payload.sha256.json` contains the hash contract:
|
|
181
|
+
|
|
182
|
+
```json
|
|
183
|
+
{
|
|
184
|
+
"created_by": "modelctl",
|
|
185
|
+
"hash_algorithm": "sha256",
|
|
186
|
+
"hash_scope": "payload_tree_v1",
|
|
187
|
+
"payload_hash": "sha256:...",
|
|
188
|
+
"schema_version": "1.0"
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
The same hash is always written to Model Version tags as:
|
|
193
|
+
|
|
194
|
+
```text
|
|
195
|
+
modelctl.payload_hash=sha256:...
|
|
196
|
+
modelctl.source_uri=runs:/<run_id>/model
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
That tag is the fast path for hash-only verification because it can be read from the registry without downloading the payload.
|
|
200
|
+
|
|
201
|
+
## Pull
|
|
202
|
+
|
|
203
|
+
Download payload only:
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
modelctl pull <model_ref> <output_dir>
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
Download the full package:
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
modelctl pull <model_ref> <output_dir> --full-package
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
Supported refs:
|
|
216
|
+
|
|
217
|
+
```text
|
|
218
|
+
<model_name>@<alias>
|
|
219
|
+
<model_name>:<version>
|
|
220
|
+
models:/<model_name>@<alias>
|
|
221
|
+
models:/<model_name>/<version>
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
By default, `pull` verifies the downloaded payload hash against `modelctl.payload_hash`. To skip this verification:
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
modelctl pull <model_ref> <output_dir> --no-verify
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
If the destination already exists, pass `--overwrite`:
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
modelctl pull <model_ref> <output_dir> --overwrite
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
`pull --overwrite` is intentionally safe: the existing destination is not removed before download. The new artifact is downloaded into a staging directory next to the destination, verified, and only then swapped into place. If download or verification fails, the previous destination is kept.
|
|
237
|
+
|
|
238
|
+
## Verify
|
|
239
|
+
|
|
240
|
+
Compare an existing directory with the payload hash stored in the registry:
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
modelctl verify <model_ref> <path>
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
Both payload-only directories and full modelctl packages are accepted. If `<path>` is a full package, `modelctl` verifies `<path>/payload`.
|
|
247
|
+
|
|
248
|
+
Exit codes:
|
|
249
|
+
|
|
250
|
+
```text
|
|
251
|
+
0 - hash matches
|
|
252
|
+
1 - command failed
|
|
253
|
+
2 - hash mismatch
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
Example JSON shape:
|
|
257
|
+
|
|
258
|
+
```json
|
|
259
|
+
{
|
|
260
|
+
"actual_payload_hash": "sha256:...",
|
|
261
|
+
"expected_payload_hash": "sha256:...",
|
|
262
|
+
"matches": true,
|
|
263
|
+
"model_uri": "models:/<model_name>@<alias>",
|
|
264
|
+
"path": "<path>",
|
|
265
|
+
"ref": "<model_ref>"
|
|
266
|
+
}
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
## List
|
|
270
|
+
|
|
271
|
+
```bash
|
|
272
|
+
modelctl list <model_name>
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
Shows versions, aliases, registry source URI, status, creation time and payload hash.
|
|
276
|
+
|
|
277
|
+
## Info
|
|
278
|
+
|
|
279
|
+
```bash
|
|
280
|
+
modelctl info <model_ref>
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
Shows one resolved registry version with all Model Version tags.
|
|
284
|
+
|
|
285
|
+
## Promote
|
|
286
|
+
|
|
287
|
+
```bash
|
|
288
|
+
modelctl promote <model_name> <version> <alias>
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
Promotion only moves an alias. It does not copy or modify artifacts.
|
|
292
|
+
|
|
293
|
+
## Hash semantics
|
|
294
|
+
|
|
295
|
+
The payload hash includes:
|
|
296
|
+
|
|
297
|
+
```text
|
|
298
|
+
relative file paths
|
|
299
|
+
file bytes
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
The payload hash ignores:
|
|
303
|
+
|
|
304
|
+
```text
|
|
305
|
+
absolute paths
|
|
306
|
+
file mtimes
|
|
307
|
+
owners
|
|
308
|
+
groups
|
|
309
|
+
permissions
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
This makes the digest stable across machines, mount points and container environments.
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
# modelctl-mlflow
|
|
2
|
+
|
|
3
|
+
`modelctl` is a small CLI wrapper around MLflow Model Registry for storing, verifying, promoting and pulling arbitrary model payloads.
|
|
4
|
+
|
|
5
|
+
The tool does not try to interpret a payload as a specific ML framework. A registered version is always:
|
|
6
|
+
|
|
7
|
+
```text
|
|
8
|
+
small metadata package + opaque payload directory
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
MLflow backend storage keeps metadata: runs, versions, aliases, tags and source URIs. MLflow artifact storage keeps the actual payload bytes.
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
Install as a CLI tool with uv:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
uv tool install modelctl-mlflow
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Run once without installing the tool globally:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
uvx --from modelctl-mlflow modelctl --help
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Install with pip:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
pip install modelctl-mlflow
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
For local development from a checkout:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
pip install -e .
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
or:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
uv pip install -e .
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
After installation, the CLI command is:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
modelctl --help
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
The PyPI package name is `modelctl-mlflow`; the installed command is `modelctl`.
|
|
52
|
+
|
|
53
|
+
## Quick start
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
modelctl register ./model my-model
|
|
57
|
+
modelctl list my-model
|
|
58
|
+
modelctl info my-model@champion
|
|
59
|
+
modelctl pull my-model@champion ./downloaded-model
|
|
60
|
+
modelctl verify my-model@champion ./downloaded-model
|
|
61
|
+
modelctl promote my-model 3 champion
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Commands print machine-readable JSON to stdout. Human-readable progress and errors are printed to stderr.
|
|
65
|
+
|
|
66
|
+
## MLflow connection
|
|
67
|
+
|
|
68
|
+
Default tracking URI:
|
|
69
|
+
|
|
70
|
+
```text
|
|
71
|
+
http://localhost:5000
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Override host and port:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
modelctl list <model_name> --host <host> --port <port>
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Or pass a full tracking URI:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
modelctl list <model_name> --tracking-uri <tracking_uri>
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
MLflow authentication is handled by MLflow itself through its usual environment variables, for example `MLFLOW_TRACKING_USERNAME` and `MLFLOW_TRACKING_PASSWORD`.
|
|
87
|
+
|
|
88
|
+
## Register
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
modelctl register <payload_dir> <model_name>
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
With explicit aliases:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
modelctl register <payload_dir> <model_name> --alias <alias_a> --alias <alias_b>
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Default alias behavior:
|
|
101
|
+
|
|
102
|
+
```text
|
|
103
|
+
first version -> baseline + champion
|
|
104
|
+
later versions -> candidate
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
During registration, `modelctl`:
|
|
108
|
+
|
|
109
|
+
```text
|
|
110
|
+
1. connects to MLflow
|
|
111
|
+
2. computes a stable SHA256 payload hash
|
|
112
|
+
3. starts a short technical MLflow run
|
|
113
|
+
4. writes metadata files
|
|
114
|
+
5. logs payload bytes to the artifact store under model/payload
|
|
115
|
+
6. creates a Model Registry version
|
|
116
|
+
7. writes modelctl.payload_hash to Model Version tags
|
|
117
|
+
8. attaches aliases
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
The registration result is printed as JSON. Human-readable progress is printed to stderr.
|
|
121
|
+
|
|
122
|
+
## Metadata tags
|
|
123
|
+
|
|
124
|
+
Two optional metadata namespaces are supported:
|
|
125
|
+
|
|
126
|
+
```text
|
|
127
|
+
general - stable descriptive metadata
|
|
128
|
+
training - training, dataset, evaluation or build metadata
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Full metadata dictionaries are stored as JSON artifacts. A flattened searchable projection is also written to MLflow Model Version tags.
|
|
132
|
+
|
|
133
|
+
Register with JSON metadata:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
modelctl register <payload_dir> <model_name> --general-tags-json <general.json> --training-tags-json <training.json>
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Register with inline metadata:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
modelctl register <payload_dir> <model_name> --general-tag <key>=<value> --training-tag <key>=<value>
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Inline values are parsed as JSON when possible, so numbers, booleans, objects and lists are supported.
|
|
146
|
+
|
|
147
|
+
## Artifact layout
|
|
148
|
+
|
|
149
|
+
Every registered version stores this package in the artifact store:
|
|
150
|
+
|
|
151
|
+
```text
|
|
152
|
+
model/
|
|
153
|
+
├── MLmodel
|
|
154
|
+
├── manifest.json
|
|
155
|
+
├── payload.sha256.json
|
|
156
|
+
├── metadata/
|
|
157
|
+
│ ├── general_tags.json
|
|
158
|
+
│ └── training_tags.json
|
|
159
|
+
└── payload/
|
|
160
|
+
└── ... payload contents ...
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
`model/payload/` contains the actual registered payload.
|
|
164
|
+
|
|
165
|
+
`model/payload.sha256.json` contains the hash contract:
|
|
166
|
+
|
|
167
|
+
```json
|
|
168
|
+
{
|
|
169
|
+
"created_by": "modelctl",
|
|
170
|
+
"hash_algorithm": "sha256",
|
|
171
|
+
"hash_scope": "payload_tree_v1",
|
|
172
|
+
"payload_hash": "sha256:...",
|
|
173
|
+
"schema_version": "1.0"
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
The same hash is always written to Model Version tags as:
|
|
178
|
+
|
|
179
|
+
```text
|
|
180
|
+
modelctl.payload_hash=sha256:...
|
|
181
|
+
modelctl.source_uri=runs:/<run_id>/model
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
That tag is the fast path for hash-only verification because it can be read from the registry without downloading the payload.
|
|
185
|
+
|
|
186
|
+
## Pull
|
|
187
|
+
|
|
188
|
+
Download payload only:
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
modelctl pull <model_ref> <output_dir>
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Download the full package:
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
modelctl pull <model_ref> <output_dir> --full-package
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Supported refs:
|
|
201
|
+
|
|
202
|
+
```text
|
|
203
|
+
<model_name>@<alias>
|
|
204
|
+
<model_name>:<version>
|
|
205
|
+
models:/<model_name>@<alias>
|
|
206
|
+
models:/<model_name>/<version>
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
By default, `pull` verifies the downloaded payload hash against `modelctl.payload_hash`. To skip this verification:
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
modelctl pull <model_ref> <output_dir> --no-verify
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
If the destination already exists, pass `--overwrite`:
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
modelctl pull <model_ref> <output_dir> --overwrite
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
`pull --overwrite` is intentionally safe: the existing destination is not removed before download. The new artifact is downloaded into a staging directory next to the destination, verified, and only then swapped into place. If download or verification fails, the previous destination is kept.
|
|
222
|
+
|
|
223
|
+
## Verify
|
|
224
|
+
|
|
225
|
+
Compare an existing directory with the payload hash stored in the registry:
|
|
226
|
+
|
|
227
|
+
```bash
|
|
228
|
+
modelctl verify <model_ref> <path>
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
Both payload-only directories and full modelctl packages are accepted. If `<path>` is a full package, `modelctl` verifies `<path>/payload`.
|
|
232
|
+
|
|
233
|
+
Exit codes:
|
|
234
|
+
|
|
235
|
+
```text
|
|
236
|
+
0 - hash matches
|
|
237
|
+
1 - command failed
|
|
238
|
+
2 - hash mismatch
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
Example JSON shape:
|
|
242
|
+
|
|
243
|
+
```json
|
|
244
|
+
{
|
|
245
|
+
"actual_payload_hash": "sha256:...",
|
|
246
|
+
"expected_payload_hash": "sha256:...",
|
|
247
|
+
"matches": true,
|
|
248
|
+
"model_uri": "models:/<model_name>@<alias>",
|
|
249
|
+
"path": "<path>",
|
|
250
|
+
"ref": "<model_ref>"
|
|
251
|
+
}
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
## List
|
|
255
|
+
|
|
256
|
+
```bash
|
|
257
|
+
modelctl list <model_name>
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
Shows versions, aliases, registry source URI, status, creation time and payload hash.
|
|
261
|
+
|
|
262
|
+
## Info
|
|
263
|
+
|
|
264
|
+
```bash
|
|
265
|
+
modelctl info <model_ref>
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
Shows one resolved registry version with all Model Version tags.
|
|
269
|
+
|
|
270
|
+
## Promote
|
|
271
|
+
|
|
272
|
+
```bash
|
|
273
|
+
modelctl promote <model_name> <version> <alias>
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
Promotion only moves an alias. It does not copy or modify artifacts.
|
|
277
|
+
|
|
278
|
+
## Hash semantics
|
|
279
|
+
|
|
280
|
+
The payload hash includes:
|
|
281
|
+
|
|
282
|
+
```text
|
|
283
|
+
relative file paths
|
|
284
|
+
file bytes
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
The payload hash ignores:
|
|
288
|
+
|
|
289
|
+
```text
|
|
290
|
+
absolute paths
|
|
291
|
+
file mtimes
|
|
292
|
+
owners
|
|
293
|
+
groups
|
|
294
|
+
permissions
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
This makes the digest stable across machines, mount points and container environments.
|