decision-toolkit 0.3.0__tar.gz → 0.4.0__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.
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/CHANGELOG.md +27 -1
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/PKG-INFO +10 -10
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/README.md +9 -9
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/docs/CATALOG_PROPOSAL.md +14 -12
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/docs/CLI.md +6 -4
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/docs/EXAMPLES.md +3 -3
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/docs/RELEASE.md +11 -8
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/docs/REST.md +19 -19
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/docs/VARIANTS.md +41 -33
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/docs/models/open-jev-deberta-v3-large.md +1 -1
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/pyproject.toml +1 -1
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/src/decision_toolkit/__init__.py +1 -1
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/src/decision_toolkit/catalog.py +18 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/src/decision_toolkit/cli.py +34 -22
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/src/decision_toolkit/contracts/openai_decisions_beta.py +1 -1
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/src/decision_toolkit/contracts/systemone_v1.py +0 -1
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/src/decision_toolkit/registry.py +8 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/src/decision_toolkit/server.py +69 -16
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/tests/test_cli.py +10 -5
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/tests/test_server.py +52 -8
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/uv.lock +1 -1
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/.github/workflows/ci.yml +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/.github/workflows/docs.yml +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/.github/workflows/release.yml +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/.gitignore +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/CONTRIBUTING.md +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/LICENSE +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/SECURITY.md +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/THIRD_PARTY_NOTICES.md +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/bench/README.md +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/bench/__init__.py +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/bench/load.py +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/bench/results/2026-10-20-calibration.json +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/bench/results/2026-10-20-load.json +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/bench/results/2026-10-20-smoke.json +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/bench/run.py +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/bench/suites/calibration.jsonl +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/bench/suites/smoke.jsonl +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/docs/BENCH.md +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/docs/CORE.md +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/docs/OPERATIONS.md +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/docs/ROADMAP.md +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/docs/index.md +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/docs/models/README.md +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/docs/models/gliner2.5-decide.md +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/docs/models/gliner2.5-multi.md +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/docs/models/julia-1.md +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/docs/models/laya-multilingual.md +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/docs/models/laya.md +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/docs/models/opendecider-nano.md +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/docs/models/strands-decider-2b.md +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/src/decision_toolkit/__main__.py +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/src/decision_toolkit/adapters/__init__.py +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/src/decision_toolkit/adapters/base.py +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/src/decision_toolkit/adapters/gliner2.py +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/src/decision_toolkit/adapters/gliner2_decide.py +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/src/decision_toolkit/adapters/julia.py +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/src/decision_toolkit/adapters/laya.py +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/src/decision_toolkit/adapters/opendecider.py +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/src/decision_toolkit/adapters/openjev.py +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/src/decision_toolkit/adapters/strands_decider.py +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/src/decision_toolkit/calibration.py +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/src/decision_toolkit/config.py +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/src/decision_toolkit/contracts/__init__.py +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/src/decision_toolkit/contracts/common.py +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/src/decision_toolkit/contracts/mapping.py +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/src/decision_toolkit/decision_model.py +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/src/decision_toolkit/engine/__init__.py +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/src/decision_toolkit/errors.py +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/src/decision_toolkit/limits.py +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/src/decision_toolkit/metrics.py +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/src/decision_toolkit/models.py +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/src/decision_toolkit/observability.py +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/src/decision_toolkit/py.typed +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/src/decision_toolkit/results.py +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/src/decision_toolkit/schema.py +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/src/decision_toolkit/tracing.py +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/tests/__init__.py +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/tests/conftest.py +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/tests/test_adapters_gliner2.py +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/tests/test_adapters_gliner2_decide.py +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/tests/test_adapters_julia.py +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/tests/test_adapters_laya.py +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/tests/test_adapters_opendecider.py +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/tests/test_adapters_openjev.py +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/tests/test_adapters_strands.py +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/tests/test_bench.py +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/tests/test_catalog.py +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/tests/test_config.py +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/tests/test_contracts_conformance.py +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/tests/test_core_phase1.py +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/tests/test_decision_model.py +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/tests/test_fuzz_rest.py +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/tests/test_integration_gliner2.py +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/tests/test_models.py +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/tests/test_operations.py +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/tests/test_results.py +0 -0
- {decision_toolkit-0.3.0 → decision_toolkit-0.4.0}/tests/test_schema.py +0 -0
|
@@ -1,8 +1,32 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
All notable changes to this project are documented here. Version `0.
|
|
3
|
+
All notable changes to this project are documented here. Version `0.4.0` is
|
|
4
4
|
published on PyPI.
|
|
5
5
|
|
|
6
|
+
## [0.4.0] — 2026-10-21
|
|
7
|
+
|
|
8
|
+
REST variant-selection correction. Quantizations are selected through standard
|
|
9
|
+
model aliases (`id@variant`), not a non-standard `variant` body field. The same
|
|
10
|
+
REST process can load two variants of one base model in separate registry slots.
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- Removed `variant` from System One and OpenAI request bodies; standard clients
|
|
15
|
+
now see only the public request fields.
|
|
16
|
+
- Added `catalog-id@variant` model aliases to `/v1/models` and
|
|
17
|
+
`/v1/models/{id}`. The standard `model` field selects the alias.
|
|
18
|
+
- Registry keys and slots are per alias, so `laya-multilingual@fp16` and
|
|
19
|
+
`laya-multilingual@fp32` load independently and concurrently.
|
|
20
|
+
- Updated README, REST, variants, examples and CLI help so REST never shows a
|
|
21
|
+
variant field in a standard request body.
|
|
22
|
+
|
|
23
|
+
## [0.3.1] — 2026-10-21
|
|
24
|
+
|
|
25
|
+
Catalog UX patch: `dtk models list` now prints one row per variant, with
|
|
26
|
+
`variant`, quantization, role, size, cache state and the exact download/select
|
|
27
|
+
commands. `dtk models variants` prints both commands for every variant. No
|
|
28
|
+
model, adapter or REST contract changes.
|
|
29
|
+
|
|
6
30
|
## [0.3.0] — 2026-10-21
|
|
7
31
|
|
|
8
32
|
Catalog expansion: three verified ONNX decision models and eight variants.
|
|
@@ -185,6 +209,8 @@ README correction. No code or model behavior changed.
|
|
|
185
209
|
- Typed `DecisionModel` API with lifecycle, batching, async, usage, warnings,
|
|
186
210
|
normalized confidence, capabilities, structured events and atomic model store.
|
|
187
211
|
|
|
212
|
+
[0.4.0]: https://pypi.org/project/decision-toolkit/0.4.0/
|
|
213
|
+
[0.3.1]: https://pypi.org/project/decision-toolkit/0.3.1/
|
|
188
214
|
[0.3.0]: https://pypi.org/project/decision-toolkit/0.3.0/
|
|
189
215
|
[0.2.1]: https://pypi.org/project/decision-toolkit/0.2.1/
|
|
190
216
|
[0.2.0]: https://pypi.org/project/decision-toolkit/0.2.0/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: decision-toolkit
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Local-first toolkit for open-weights decision models: one ONNX engine, one adapter per model contract, typed choice/yes-no/score decisions with probabilities on CPU.
|
|
5
5
|
Project-URL: Homepage, https://github.com/gia-uh/decision-toolkit
|
|
6
6
|
Project-URL: Repository, https://github.com/gia-uh/decision-toolkit
|
|
@@ -59,7 +59,7 @@ and CLI. `dtk --help` and every subcommand help also include runnable examples.
|
|
|
59
59
|
## Installation
|
|
60
60
|
|
|
61
61
|
```bash
|
|
62
|
-
uv pip install decision-toolkit # library + CLI (0.
|
|
62
|
+
uv pip install decision-toolkit # library + CLI (0.4.0 on PyPI)
|
|
63
63
|
uv pip install "decision-toolkit[onnx]" # + onnxruntime, tokenizers (the model runtime)
|
|
64
64
|
uv pip install "decision-toolkit[server]" # + REST server (FastAPI)
|
|
65
65
|
```
|
|
@@ -67,7 +67,7 @@ uv pip install "decision-toolkit[server]" # + REST server (FastAPI)
|
|
|
67
67
|
The project is managed with [uv](https://docs.astral.sh/uv/) and ships a committed `uv.lock`. Published
|
|
68
68
|
wheels remain compatible with `pip` for environments that do not use uv.
|
|
69
69
|
|
|
70
|
-
PyPI: <https://pypi.org/project/decision-toolkit/0.
|
|
70
|
+
PyPI: <https://pypi.org/project/decision-toolkit/0.4.0/>. See
|
|
71
71
|
[docs/RELEASE.md](https://github.com/gia-uh/decision-toolkit/blob/main/docs/RELEASE.md)
|
|
72
72
|
for the Trusted Publishing flow and clean-install checks.
|
|
73
73
|
|
|
@@ -208,7 +208,7 @@ adapters (there is no generic "any ONNX" adapter).
|
|
|
208
208
|
| `julia-1` | `julia` | **m0** — verified: 100/100 argmax parity, 329 ms | `fp32`* (618 MB) |
|
|
209
209
|
| `opendecider-nano` | `opendecider` | **m0** — official build; prompt ported from pinned code (530 ms) | `q8f16`* (469 MB); `fp16` (792 MB) |
|
|
210
210
|
| `laya-multilingual` | `laya` | **m0** — fused ONNX; upstream parity (37 ms) | `fp16`* (682 MB); `fp32` (1326 MB) |
|
|
211
|
-
| `open-jev-deberta-v3-large` | `open-jev` | **m0** —
|
|
211
|
+
| `open-jev-deberta-v3-large` | `open-jev` | **m0** — Open-Jev DeBERTa v3 large repro; 0.854 in-domain (241 ms) | `fp16`* (884 MB); `fp32` (1758 MB); `q4` (487 MB); `q4f16` (357 MB) |
|
|
212
212
|
| `strands-decider-2b` | `strands-decider` | **m0** — reference fixture match (719 ms) | `q4f16`* (1114 MB); `q8` (1821 MB) |
|
|
213
213
|
|
|
214
214
|
**Only `m0` models are in the catalog.** Researched-but-unavailable models
|
|
@@ -225,7 +225,7 @@ own repo files, size and role. A `*` in the table above marks the default.
|
|
|
225
225
|
`dtk models list` always shows every catalogued variant and what is cached:
|
|
226
226
|
|
|
227
227
|
```bash
|
|
228
|
-
dtk models list #
|
|
228
|
+
dtk models list # one row per variant; * = default
|
|
229
229
|
dtk models list --quant # add the quantization labels
|
|
230
230
|
dtk models variants gliner2.5-multi # full details for one model
|
|
231
231
|
```
|
|
@@ -248,11 +248,11 @@ dtk models current --json # {"current": "...", "variant": "fp32"}
|
|
|
248
248
|
dtk decide --model gliner2.5-multi --variant fp16 --state "..." --q 'cat=choice:a|b'
|
|
249
249
|
```
|
|
250
250
|
|
|
251
|
-
From Python: `DecisionModel("gliner2.5-multi", variant="fp32")`. REST
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
variant
|
|
255
|
-
|
|
251
|
+
From Python: `DecisionModel("gliner2.5-multi", variant="fp32")`. In REST,
|
|
252
|
+
quantizations are **model aliases**: use `"model": "gliner2.5-multi@fp32"` in the
|
|
253
|
+
standard `model` field. The base id uses the server/persisted default. There is
|
|
254
|
+
no `variant` field in the request body; `/v1/models` lists both the base model
|
|
255
|
+
and every alias, and two aliases can be loaded concurrently.
|
|
256
256
|
|
|
257
257
|
A variant becomes default only after passing the parity gate (top-1 ≥ 99%,
|
|
258
258
|
mean |Δp| ≤ 0.02, accuracy delta ≤ 1 pp against the fp32 build on a fixed
|
|
@@ -21,7 +21,7 @@ and CLI. `dtk --help` and every subcommand help also include runnable examples.
|
|
|
21
21
|
## Installation
|
|
22
22
|
|
|
23
23
|
```bash
|
|
24
|
-
uv pip install decision-toolkit # library + CLI (0.
|
|
24
|
+
uv pip install decision-toolkit # library + CLI (0.4.0 on PyPI)
|
|
25
25
|
uv pip install "decision-toolkit[onnx]" # + onnxruntime, tokenizers (the model runtime)
|
|
26
26
|
uv pip install "decision-toolkit[server]" # + REST server (FastAPI)
|
|
27
27
|
```
|
|
@@ -29,7 +29,7 @@ uv pip install "decision-toolkit[server]" # + REST server (FastAPI)
|
|
|
29
29
|
The project is managed with [uv](https://docs.astral.sh/uv/) and ships a committed `uv.lock`. Published
|
|
30
30
|
wheels remain compatible with `pip` for environments that do not use uv.
|
|
31
31
|
|
|
32
|
-
PyPI: <https://pypi.org/project/decision-toolkit/0.
|
|
32
|
+
PyPI: <https://pypi.org/project/decision-toolkit/0.4.0/>. See
|
|
33
33
|
[docs/RELEASE.md](https://github.com/gia-uh/decision-toolkit/blob/main/docs/RELEASE.md)
|
|
34
34
|
for the Trusted Publishing flow and clean-install checks.
|
|
35
35
|
|
|
@@ -170,7 +170,7 @@ adapters (there is no generic "any ONNX" adapter).
|
|
|
170
170
|
| `julia-1` | `julia` | **m0** — verified: 100/100 argmax parity, 329 ms | `fp32`* (618 MB) |
|
|
171
171
|
| `opendecider-nano` | `opendecider` | **m0** — official build; prompt ported from pinned code (530 ms) | `q8f16`* (469 MB); `fp16` (792 MB) |
|
|
172
172
|
| `laya-multilingual` | `laya` | **m0** — fused ONNX; upstream parity (37 ms) | `fp16`* (682 MB); `fp32` (1326 MB) |
|
|
173
|
-
| `open-jev-deberta-v3-large` | `open-jev` | **m0** —
|
|
173
|
+
| `open-jev-deberta-v3-large` | `open-jev` | **m0** — Open-Jev DeBERTa v3 large repro; 0.854 in-domain (241 ms) | `fp16`* (884 MB); `fp32` (1758 MB); `q4` (487 MB); `q4f16` (357 MB) |
|
|
174
174
|
| `strands-decider-2b` | `strands-decider` | **m0** — reference fixture match (719 ms) | `q4f16`* (1114 MB); `q8` (1821 MB) |
|
|
175
175
|
|
|
176
176
|
**Only `m0` models are in the catalog.** Researched-but-unavailable models
|
|
@@ -187,7 +187,7 @@ own repo files, size and role. A `*` in the table above marks the default.
|
|
|
187
187
|
`dtk models list` always shows every catalogued variant and what is cached:
|
|
188
188
|
|
|
189
189
|
```bash
|
|
190
|
-
dtk models list #
|
|
190
|
+
dtk models list # one row per variant; * = default
|
|
191
191
|
dtk models list --quant # add the quantization labels
|
|
192
192
|
dtk models variants gliner2.5-multi # full details for one model
|
|
193
193
|
```
|
|
@@ -210,11 +210,11 @@ dtk models current --json # {"current": "...", "variant": "fp32"}
|
|
|
210
210
|
dtk decide --model gliner2.5-multi --variant fp16 --state "..." --q 'cat=choice:a|b'
|
|
211
211
|
```
|
|
212
212
|
|
|
213
|
-
From Python: `DecisionModel("gliner2.5-multi", variant="fp32")`. REST
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
variant
|
|
217
|
-
|
|
213
|
+
From Python: `DecisionModel("gliner2.5-multi", variant="fp32")`. In REST,
|
|
214
|
+
quantizations are **model aliases**: use `"model": "gliner2.5-multi@fp32"` in the
|
|
215
|
+
standard `model` field. The base id uses the server/persisted default. There is
|
|
216
|
+
no `variant` field in the request body; `/v1/models` lists both the base model
|
|
217
|
+
and every alias, and two aliases can be loaded concurrently.
|
|
218
218
|
|
|
219
219
|
A variant becomes default only after passing the parity gate (top-1 ≥ 99%,
|
|
220
220
|
mean |Δp| ≤ 0.02, accuracy delta ≤ 1 pp against the fp32 build on a fixed
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
# Catalog proposal: three ONNX decision models
|
|
2
2
|
|
|
3
3
|
**Date:** 2026-10-21
|
|
4
|
-
**Status:**
|
|
5
|
-
**Scope:** add Laya multilingual, Open-Jev DeBERTa v3 large and Strands Decider 2B
|
|
4
|
+
**Status:** published in `0.3.0`
|
|
5
|
+
**Scope:** add Laya multilingual, Open-Jev DeBERTa v3 large and Strands Decider 2B
|
|
6
|
+
**Release:** <https://pypi.org/project/decision-toolkit/0.3.0/>
|
|
6
7
|
|
|
7
8
|
## Executive summary
|
|
8
9
|
|
|
@@ -57,14 +58,14 @@ ONNX Runtime 1.31.0, CPU):
|
|
|
57
58
|
|---|---|---:|
|
|
58
59
|
| Laya multilingual | fp16 | 37.4 ms |
|
|
59
60
|
| Laya multilingual | fp32 | 34.1 ms |
|
|
60
|
-
| Open-Jev | fp16 | 241.2 ms |
|
|
61
|
-
| Open-Jev | fp32 | 78.2 ms |
|
|
62
|
-
| Open-Jev | q4 | 56.0 ms |
|
|
63
|
-
| Open-Jev | q4f16 | 219.4 ms |
|
|
61
|
+
| Open-Jev DeBERTa v3 large | fp16 | 241.2 ms |
|
|
62
|
+
| Open-Jev DeBERTa v3 large | fp32 | 78.2 ms |
|
|
63
|
+
| Open-Jev DeBERTa v3 large | q4 | 56.0 ms |
|
|
64
|
+
| Open-Jev DeBERTa v3 large | q4f16 | 219.4 ms |
|
|
64
65
|
| Strands Decider 2B | q4f16 | 719.3 ms |
|
|
65
66
|
| Strands Decider 2B | q8 | 1467.2 ms |
|
|
66
67
|
|
|
67
|
-
The Open-Jev 4-bit paths are size/edge choices; they are not assumed to be
|
|
68
|
+
The Open-Jev DeBERTa v3 large 4-bit paths are size/edge choices; they are not assumed to be
|
|
68
69
|
faster or more accurate. Strands is a 2B model and is intentionally slower
|
|
69
70
|
than the other catalog entries.
|
|
70
71
|
|
|
@@ -72,7 +73,7 @@ than the other catalog entries.
|
|
|
72
73
|
|
|
73
74
|
- **Laya multilingual:** upstream conversion reports fp32 max |Δp| 1e-4 and
|
|
74
75
|
fp16 0.035 against PyTorch; local fp16/fp32 agree on the audit answers.
|
|
75
|
-
- **Open-Jev:** upstream reports 0.854 in-domain and 0.690 OOD accuracy, plus
|
|
76
|
+
- **Open-Jev DeBERTa v3 large:** upstream reports 0.854 in-domain and 0.690 OOD accuracy, plus
|
|
76
77
|
0.022 in-domain ECE. Local fp16/fp32 agree on the published example; q4
|
|
77
78
|
variants are explicitly edge builds.
|
|
78
79
|
- **Strands Decider 2B:** reference fixture matches within 0.018 max
|
|
@@ -84,7 +85,7 @@ independent reproduction of the full upstream training evaluation.
|
|
|
84
85
|
## Quantization policy
|
|
85
86
|
|
|
86
87
|
- Default variants are chosen for a balance of quality, size and CPU latency:
|
|
87
|
-
Laya fp16, Open-Jev fp16, Strands q4f16.
|
|
88
|
+
Laya fp16, Open-Jev DeBERTa v3 large fp16, Strands q4f16.
|
|
88
89
|
- `fp32` remains a quality variant where published.
|
|
89
90
|
- `q4`/`q4f16`/`q8` are exposed, but their thresholds must be validated on the
|
|
90
91
|
user's data; no silent fallback exists.
|
|
@@ -98,10 +99,11 @@ independent reproduction of the full upstream training evaluation.
|
|
|
98
99
|
runtime checks. A larger acceptance run is still desirable.
|
|
99
100
|
2. **Strands CPU cost.** q8 takes ~1.5 s per simple question; this is suitable
|
|
100
101
|
for local/agentic workflows, not high-throughput serving.
|
|
101
|
-
3. **Quantization drift.** Open-Jev q4 and Strands q4f16 can move near-ties;
|
|
102
|
+
3. **Quantization drift.** Open-Jev DeBERTa v3 large q4 and Strands q4f16 can move near-ties;
|
|
102
103
|
the model cards call this out.
|
|
103
|
-
4. **Coverage.** Laya multilingual is weak on low-resource languages;
|
|
104
|
-
is English-only and weak on unseen score scales;
|
|
104
|
+
4. **Coverage.** Laya multilingual is weak on low-resource languages;
|
|
105
|
+
Open-Jev DeBERTa v3 large is English-only and weak on unseen score scales;
|
|
106
|
+
Strands is a 2B model with
|
|
105
107
|
its own upstream limitations.
|
|
106
108
|
5. **No image/box support.** The catalog remains text-only.
|
|
107
109
|
|
|
@@ -184,10 +184,12 @@ classification or serve command overrides it for that command. If `--variant`
|
|
|
184
184
|
is omitted, the catalog default is used unless `dtk models use` selected another
|
|
185
185
|
one.
|
|
186
186
|
|
|
187
|
-
`models list
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
187
|
+
`models list` text output has **one row per variant**, with `id`, `variant`,
|
|
188
|
+
`quant`, `role`, `size` and `cached`, followed by the exact download/select
|
|
189
|
+
commands. `--license` and `--adapter` add catalog columns; `--quant` is accepted
|
|
190
|
+
for compatibility because quantization is always shown. `--json` returns the
|
|
191
|
+
nested model tree: one object per model, each with its `variants` and
|
|
192
|
+
`cached_variants`.
|
|
191
193
|
|
|
192
194
|
See [Variants and quantization](VARIANTS.md) for the full table and cache
|
|
193
195
|
layout.
|
|
@@ -165,7 +165,8 @@ curl -s http://127.0.0.1:8000/v1/decisions \
|
|
|
165
165
|
}' | jq
|
|
166
166
|
```
|
|
167
167
|
|
|
168
|
-
`variant`
|
|
168
|
+
Use the model alias `id@variant` for a specific quantization; the base id uses
|
|
169
|
+
the server's default. There is no `variant` field in the request body.
|
|
169
170
|
|
|
170
171
|
### Model per request and auth
|
|
171
172
|
|
|
@@ -176,8 +177,7 @@ curl -s http://127.0.0.1:8000/v1/systemone \
|
|
|
176
177
|
-H "Authorization: Bearer secret" \
|
|
177
178
|
-H "Content-Type: application/json" \
|
|
178
179
|
-d '{
|
|
179
|
-
"model": "gliner2.5-
|
|
180
|
-
"variant": "q4f16",
|
|
180
|
+
"model": "gliner2.5-multi@fp32",
|
|
181
181
|
"state": "I want my money back.",
|
|
182
182
|
"questions": {
|
|
183
183
|
"intent": {"type": "choice", "instructions": "What is the request?",
|
|
@@ -10,7 +10,9 @@ and selection in the CLI and documentation; `0.1.7` aligned variant selection
|
|
|
10
10
|
across the library, CLI and REST API; `0.2.0` corrected the REST conformance
|
|
11
11
|
claims and wire shapes to the published TypeSafe and OpenAI schemas; `0.2.1`
|
|
12
12
|
changed the public documentation URLs to this repository's Pages site; `0.3.0`
|
|
13
|
-
added the Laya multilingual, Open-Jev and Strands Decider ONNX models.
|
|
13
|
+
added the Laya multilingual, Open-Jev DeBERTa v3 large and Strands Decider ONNX models; `0.3.1` made the catalog list one row per variant with exact commands; `0.4.0`
|
|
14
|
+
replaced the non-standard REST `variant` body field with standard model aliases
|
|
15
|
+
(`id@variant`).
|
|
14
16
|
|
|
15
17
|
## Local build and verification
|
|
16
18
|
|
|
@@ -37,7 +39,7 @@ Clean install test (no `PYTHONPATH`):
|
|
|
37
39
|
```bash
|
|
38
40
|
uv venv --python 3.12 /tmp/dtk-wheel
|
|
39
41
|
uv pip install --python /tmp/dtk-wheel/bin/python \
|
|
40
|
-
dist/decision_toolkit-0.
|
|
42
|
+
dist/decision_toolkit-0.4.0-py3-none-any.whl
|
|
41
43
|
uv pip check --python /tmp/dtk-wheel/bin/python
|
|
42
44
|
/tmp/dtk-wheel/bin/dtk --version
|
|
43
45
|
/tmp/dtk-wheel/bin/dtk models list --json
|
|
@@ -48,7 +50,7 @@ With inference and server extras:
|
|
|
48
50
|
|
|
49
51
|
```bash
|
|
50
52
|
uv pip install --python /tmp/dtk-wheel/bin/python \
|
|
51
|
-
"dist/decision_toolkit-0.
|
|
53
|
+
"dist/decision_toolkit-0.4.0-py3-none-any.whl[onnx,server,tracing]"
|
|
52
54
|
/tmp/dtk-wheel/bin/dtk decide --model gliner2.5-decide ...
|
|
53
55
|
/tmp/dtk-wheel/bin/dtk serve --model gliner2.5-decide --warmup --port 8016
|
|
54
56
|
curl -s http://127.0.0.1:8016/health
|
|
@@ -82,8 +84,8 @@ No long-lived PyPI token is needed; the workflow uses GitHub OIDC
|
|
|
82
84
|
4. Create and push an annotated tag:
|
|
83
85
|
|
|
84
86
|
```bash
|
|
85
|
-
git tag -a v0.
|
|
86
|
-
git push origin v0.
|
|
87
|
+
git tag -a v0.4.0 -m "decision-toolkit 0.4.0"
|
|
88
|
+
git push origin v0.4.0
|
|
87
89
|
```
|
|
88
90
|
|
|
89
91
|
5. `.github/workflows/release.yml` builds once, publishes to **TestPyPI**, then
|
|
@@ -132,9 +134,9 @@ to TestPyPI without publishing to PyPI or creating a GitHub release.
|
|
|
132
134
|
|
|
133
135
|
## Published release
|
|
134
136
|
|
|
135
|
-
`0.
|
|
137
|
+
`0.4.0` is published through Trusted Publishing on 2026-10-21:
|
|
136
138
|
|
|
137
|
-
<https://pypi.org/project/decision-toolkit/0.
|
|
139
|
+
<https://pypi.org/project/decision-toolkit/0.4.0/>
|
|
138
140
|
|
|
139
141
|
`0.1.0` was the first release; `0.1.1` refreshed the PyPI description; `0.1.2`
|
|
140
142
|
validated the OIDC TestPyPI → PyPI flow; `0.1.3` added post-publish install
|
|
@@ -144,7 +146,8 @@ published to TestPyPI only; `0.1.5` fixed TestPyPI resolution; `0.1.6` added
|
|
|
144
146
|
complete variant/quantization visibility and CLI selection; `0.1.7` aligned
|
|
145
147
|
selection across library, CLI and REST; `0.2.0` corrected the REST conformance
|
|
146
148
|
claims and wire shapes; `0.2.1` changed the public documentation URLs; `0.3.0`
|
|
147
|
-
added the three new ONNX decision models.
|
|
149
|
+
added the three new ONNX decision models; `0.3.1` made the catalog list one row per variant; `0.4.0` moved REST variant
|
|
150
|
+
selection to standard model aliases.
|
|
148
151
|
|
|
149
152
|
The tag-triggered workflow remains the preferred path for future releases once
|
|
150
153
|
the TestPyPI/PyPI trusted publishers and protected environments are configured.
|
|
@@ -49,25 +49,25 @@ limitations listed below.
|
|
|
49
49
|
Toolkit-only metadata is under `x_decision_toolkit`, never mixed into standard
|
|
50
50
|
fields. `/v1/decision-models` is the rich, non-standard catalog endpoint.
|
|
51
51
|
|
|
52
|
-
## Variants
|
|
53
|
-
|
|
54
|
-
Neither TypeSafe nor OpenAI has a `variant` request field
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
`/v1/models
|
|
68
|
-
expose the
|
|
69
|
-
|
|
70
|
-
|
|
52
|
+
## Variants as model aliases
|
|
53
|
+
|
|
54
|
+
Neither TypeSafe nor OpenAI has a `variant` request field. The toolkit therefore
|
|
55
|
+
publishes each quantization as a **model alias**:
|
|
56
|
+
|
|
57
|
+
```json
|
|
58
|
+
{"model": "gliner2.5-multi@fp32", "state": "...", "questions": {...}}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
The `model` field is the standard field. `gliner2.5-multi` uses the server's
|
|
62
|
+
default (or the persisted `dtk models use` selection); `gliner2.5-multi@fp32`
|
|
63
|
+
selects that exact variant. Both aliases are listed by `/v1/models`, and the
|
|
64
|
+
registry loads them in separate slots, so two variants of one base model can be
|
|
65
|
+
used by the same server process.
|
|
66
|
+
|
|
67
|
+
`/v1/models/gliner2.5-multi@fp32`, `/v1/decision-models`, `/v1/info` and `/ready`
|
|
68
|
+
expose the alias, variant, default, cached state and current selection. The
|
|
69
|
+
response metadata under `x_decision_toolkit.variant` is an extension; the
|
|
70
|
+
request body remains standard. See [Variants and quantization](VARIANTS.md).
|
|
71
71
|
|
|
72
72
|
## System One (TypeSafe API schema 0.2.0)
|
|
73
73
|
|
|
@@ -18,23 +18,23 @@ have not passed the catalog gates are not exposed as variants.
|
|
|
18
18
|
A `*` marks the default variant. It is used when `--variant` is omitted and no
|
|
19
19
|
other variant was selected with `dtk models use`.
|
|
20
20
|
|
|
21
|
-
| Model | Variant | Quantization | Size | Role |
|
|
22
|
-
| --- | --- | --- | ---: | --- |
|
|
23
|
-
| `gliner2.5-multi` | `fp16` * | fp16 encoder + fp32 classifier | 577.1 MB | default |
|
|
24
|
-
| `gliner2.5-multi` | `fp32` | fp32 encoder + fp32 classifier | 1131.9 MB | quality |
|
|
25
|
-
| `gliner2.5-decide` | `q4f16` * | q4/fp16 | 523.5 MB | default |
|
|
26
|
-
| `laya` | `q8` * | int8 | 527.9 MB | default |
|
|
27
|
-
| `julia-1` | `fp32` * | fp32 | 618.2 MB | default |
|
|
28
|
-
| `opendecider-nano` | `q8f16` * | int8/fp16 | 468.8 MB | default |
|
|
29
|
-
| `opendecider-nano` | `fp16` | fp16 | 791.9 MB | quality |
|
|
30
|
-
| `laya-multilingual` | `fp16` * | fp16 | 681.8 MB | default |
|
|
31
|
-
| `laya-multilingual` | `fp32` | fp32 | 1325.6 MB | quality |
|
|
32
|
-
| `open-jev-deberta-v3-large` | `fp16` * | fp16 | 883.5 MB | default |
|
|
33
|
-
| `open-jev-deberta-v3-large` | `fp32` | fp32 | 1757.9 MB | quality |
|
|
34
|
-
| `open-jev-deberta-v3-large` | `q4` | q4 | 486.7 MB | edge |
|
|
35
|
-
| `open-jev-deberta-v3-large` | `q4f16` | q4/fp16 | 357.0 MB | edge |
|
|
36
|
-
| `strands-decider-2b` | `q4f16` * | q4/fp16 | 1113.6 MB | default |
|
|
37
|
-
| `strands-decider-2b` | `q8` | int8 | 1821.4 MB | quality |
|
|
21
|
+
| Model | Variant | Quantization | Size | Role | Download |
|
|
22
|
+
| --- | --- | --- | ---: | --- | --- |
|
|
23
|
+
| `gliner2.5-multi` | `fp16` * | fp16 encoder + fp32 classifier | 577.1 MB | default | `dtk models download gliner2.5-multi --variant fp16` |
|
|
24
|
+
| `gliner2.5-multi` | `fp32` | fp32 encoder + fp32 classifier | 1131.9 MB | quality | `dtk models download gliner2.5-multi --variant fp32` |
|
|
25
|
+
| `gliner2.5-decide` | `q4f16` * | q4/fp16 | 523.5 MB | default | `dtk models download gliner2.5-decide --variant q4f16` |
|
|
26
|
+
| `laya` | `q8` * | int8 | 527.9 MB | default | `dtk models download laya --variant q8` |
|
|
27
|
+
| `julia-1` | `fp32` * | fp32 | 618.2 MB | default | `dtk models download julia-1 --variant fp32` |
|
|
28
|
+
| `opendecider-nano` | `q8f16` * | int8/fp16 | 468.8 MB | default | `dtk models download opendecider-nano --variant q8f16` |
|
|
29
|
+
| `opendecider-nano` | `fp16` | fp16 | 791.9 MB | quality | `dtk models download opendecider-nano --variant fp16` |
|
|
30
|
+
| `laya-multilingual` | `fp16` * | fp16 | 681.8 MB | default | `dtk models download laya-multilingual --variant fp16` |
|
|
31
|
+
| `laya-multilingual` | `fp32` | fp32 | 1325.6 MB | quality | `dtk models download laya-multilingual --variant fp32` |
|
|
32
|
+
| `open-jev-deberta-v3-large` | `fp16` * | fp16 | 883.5 MB | default | `dtk models download open-jev-deberta-v3-large --variant fp16` |
|
|
33
|
+
| `open-jev-deberta-v3-large` | `fp32` | fp32 | 1757.9 MB | quality | `dtk models download open-jev-deberta-v3-large --variant fp32` |
|
|
34
|
+
| `open-jev-deberta-v3-large` | `q4` | q4 | 486.7 MB | edge | `dtk models download open-jev-deberta-v3-large --variant q4` |
|
|
35
|
+
| `open-jev-deberta-v3-large` | `q4f16` | q4/fp16 | 357.0 MB | edge | `dtk models download open-jev-deberta-v3-large --variant q4f16` |
|
|
36
|
+
| `strands-decider-2b` | `q4f16` * | q4/fp16 | 1113.6 MB | default | `dtk models download strands-decider-2b --variant q4f16` |
|
|
37
|
+
| `strands-decider-2b` | `q8` | int8 | 1821.4 MB | quality | `dtk models download strands-decider-2b --variant q8` |
|
|
38
38
|
|
|
39
39
|
Models with a single row have only one catalogued, verified build. That does
|
|
40
40
|
not mean other conversions do not exist upstream; it means they have not passed
|
|
@@ -45,8 +45,8 @@ the parity, hash and license gates for this catalog.
|
|
|
45
45
|
The same catalog variant is used by the library, CLI and REST API. Selection
|
|
46
46
|
precedence is:
|
|
47
47
|
|
|
48
|
-
1. an explicit per-call
|
|
49
|
-
|
|
48
|
+
1. an explicit per-call variant in the library or CLI
|
|
49
|
+
(`DecisionModel(..., variant=...)`, `--variant`);
|
|
50
50
|
2. the CLI/server configuration (`dtk models use`, or `dtk serve --variant`);
|
|
51
51
|
3. the catalog default marked with `*`.
|
|
52
52
|
|
|
@@ -54,17 +54,18 @@ precedence is:
|
|
|
54
54
|
| --- | --- | --- |
|
|
55
55
|
| Library | `DecisionModel("gliner2.5-multi", variant="fp32")` | persisted variant for the current model, else catalog default |
|
|
56
56
|
| CLI | `--variant fp32` | variant selected by `dtk models use`, else catalog default |
|
|
57
|
-
| REST
|
|
57
|
+
| REST | `"model": "gliner2.5-multi@fp32"` (model alias) | base model id; server `--variant`/persisted default |
|
|
58
58
|
|
|
59
59
|
`DecisionModel.variant` and the CLI report the selected variant (`id@variant` in
|
|
60
60
|
`dtk models current`). REST responses expose it under the namespaced
|
|
61
61
|
`x_decision_toolkit.variant` extension; `/v1/decision-models` includes
|
|
62
62
|
`current` and `current_variant`, plus all `variants` and `cached_variants`.
|
|
63
|
-
`variant` is **not** part of TypeSafe or OpenAI
|
|
64
|
-
|
|
63
|
+
`variant` is **not** part of TypeSafe or OpenAI, and standard REST clients must
|
|
64
|
+
not send it. They select only `model`; the local server chooses the quantization
|
|
65
|
+
from `--variant` or the persisted default. A server started with
|
|
65
66
|
`--model`/`--variant` reports that default in `/v1/info` and `/ready`.
|
|
66
67
|
|
|
67
|
-
The variant must have been downloaded before a library call or REST
|
|
68
|
+
The variant must have been downloaded before a library call or REST alias
|
|
68
69
|
loads it. An unknown variant returns a model-not-found error; a known but
|
|
69
70
|
missing cache entry returns a model-not-downloaded error.
|
|
70
71
|
|
|
@@ -87,12 +88,15 @@ dtk models variants opendecider-nano --json
|
|
|
87
88
|
Example:
|
|
88
89
|
|
|
89
90
|
```text
|
|
90
|
-
id
|
|
91
|
-
gliner2.5-multi fp16
|
|
92
|
-
gliner2.5-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
91
|
+
id variant quant role size cached
|
|
92
|
+
gliner2.5-multi fp16* fp16 default 577.1 MB ✓
|
|
93
|
+
gliner2.5-multi fp32 fp32 quality 1131.9 MB ✓
|
|
94
|
+
gliner2.5-decide q4f16* q4/fp16 default 523.5 MB ✓
|
|
95
|
+
laya q8* int8 default 527.9 MB ✓
|
|
96
|
+
|
|
97
|
+
* default variant.
|
|
98
|
+
download: dtk models download <id> --variant <name>
|
|
99
|
+
select: dtk models use <id> --variant <name>
|
|
96
100
|
```
|
|
97
101
|
|
|
98
102
|
## Download a different quantization
|
|
@@ -159,14 +163,18 @@ from decision_toolkit import DecisionModel
|
|
|
159
163
|
model = DecisionModel("gliner2.5-multi", variant="fp32")
|
|
160
164
|
```
|
|
161
165
|
|
|
162
|
-
|
|
166
|
+
For REST, select a quantization through the standard `model` field using the
|
|
167
|
+
alias `id@variant`:
|
|
163
168
|
|
|
164
169
|
```json
|
|
165
|
-
{"model": "gliner2.5-multi", "
|
|
166
|
-
"questions": {"cat": {"type": "choice", "instructions": "What kind?",
|
|
167
|
-
"criteria": {"meeting": null, "other": null}}}}
|
|
170
|
+
{"model": "gliner2.5-multi@fp32", "state": "...", "questions": {}}
|
|
168
171
|
```
|
|
169
172
|
|
|
173
|
+
The base id (`gliner2.5-multi`) uses the server `--variant`/persisted default.
|
|
174
|
+
`/v1/models` lists base models and every alias, and the registry can hold two
|
|
175
|
+
aliases of the same base model in separate slots. Do not add a `variant` field
|
|
176
|
+
to the request body.
|
|
177
|
+
|
|
170
178
|
The variant must already be downloaded. If you name an unknown variant, the
|
|
171
179
|
error lists the catalogued choices, for example:
|
|
172
180
|
|
|
@@ -65,7 +65,7 @@ and re-check thresholds. See [Variants and quantization](../VARIANTS.md).
|
|
|
65
65
|
(upstream in-domain 0.85 vs OOD 0.69).
|
|
66
66
|
- Score on unseen level sets is weak in the upstream evaluation.
|
|
67
67
|
- It chooses among supplied options; it cannot generate explanations.
|
|
68
|
-
- This is an independent
|
|
68
|
+
- This is an independent Open-Jev DeBERTa v3 large reproduction, not an official TypeSafe model.
|
|
69
69
|
|
|
70
70
|
## Usage
|
|
71
71
|
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "decision-toolkit"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.4.0"
|
|
8
8
|
description = "Local-first toolkit for open-weights decision models: one ONNX engine, one adapter per model contract, typed choice/yes-no/score decisions with probabilities on CPU."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.12"
|
|
@@ -7,7 +7,7 @@ questions with a calibrated probability for every option, on CPU.
|
|
|
7
7
|
|
|
8
8
|
from __future__ import annotations
|
|
9
9
|
|
|
10
|
-
__version__ = "0.
|
|
10
|
+
__version__ = "0.4.0"
|
|
11
11
|
|
|
12
12
|
from .adapters import register_adapter
|
|
13
13
|
from .calibration import brier_score, expected_calibration_error, threshold_sweep
|
|
@@ -703,6 +703,23 @@ def get(model_id: str) -> CatalogModel | None:
|
|
|
703
703
|
return CATALOG_BY_ID.get(model_id)
|
|
704
704
|
|
|
705
705
|
|
|
706
|
+
def parse_alias(model_id: str) -> tuple[str, str | None]:
|
|
707
|
+
"""Split a REST model alias ``catalog-id@variant``.
|
|
708
|
+
|
|
709
|
+
Plain ids and non-catalog paths are returned unchanged. This is the
|
|
710
|
+
standard-compatible way to select a quantization: the OpenAI/TypeSafe
|
|
711
|
+
``model`` field remains a single string; no non-standard ``variant`` body
|
|
712
|
+
field is needed.
|
|
713
|
+
"""
|
|
714
|
+
if "@" not in model_id:
|
|
715
|
+
return model_id, None
|
|
716
|
+
base, variant_name = model_id.rsplit("@", 1)
|
|
717
|
+
model = get(base)
|
|
718
|
+
if model is not None and any(variant.name == variant_name for variant in model.variants):
|
|
719
|
+
return base, variant_name
|
|
720
|
+
return model_id, None
|
|
721
|
+
|
|
722
|
+
|
|
706
723
|
def select_variant(model: CatalogModel, name: str | None = None) -> Variant:
|
|
707
724
|
"""Choose a variant by name, or the model's default."""
|
|
708
725
|
if name is None:
|
|
@@ -732,5 +749,6 @@ __all__ = [
|
|
|
732
749
|
"ModelInfo",
|
|
733
750
|
"Variant",
|
|
734
751
|
"get",
|
|
752
|
+
"parse_alias",
|
|
735
753
|
"select_variant",
|
|
736
754
|
]
|
|
@@ -709,35 +709,43 @@ def _cmd_models(args: argparse.Namespace) -> int:
|
|
|
709
709
|
if as_json:
|
|
710
710
|
_json_out(payloads)
|
|
711
711
|
return EXIT_OK
|
|
712
|
-
headers = ["", "id", "
|
|
712
|
+
headers = ["", "id", "variant", "quant", "role", "size", "cached"]
|
|
713
713
|
if args.show_adapter:
|
|
714
|
-
headers.
|
|
714
|
+
headers.insert(2, "adapter")
|
|
715
715
|
if args.show_license:
|
|
716
|
-
headers.
|
|
717
|
-
if args.show_quant:
|
|
718
|
-
headers.append("quant")
|
|
719
|
-
headers.append("cached")
|
|
716
|
+
headers.insert(3, "license")
|
|
720
717
|
rows = []
|
|
721
718
|
for model, payload in zip(catalog.CATALOG, payloads):
|
|
722
719
|
default = model.default_variant
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
if args.show_quant:
|
|
733
|
-
row.append(
|
|
734
|
-
", ".join(variant.quant for variant in model.variants) or "—"
|
|
720
|
+
cached_variants = set(payload["cached_variants"])
|
|
721
|
+
if not model.variants:
|
|
722
|
+
rows.append(["", model.id, "—", "—", "—", "—", "—"])
|
|
723
|
+
continue
|
|
724
|
+
for variant in model.variants:
|
|
725
|
+
is_current = model.id == current and (
|
|
726
|
+
current_variant == variant.name
|
|
727
|
+
if current_variant is not None
|
|
728
|
+
else variant is default
|
|
735
729
|
)
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
730
|
+
label = f"{variant.name}*" if variant is default else variant.name
|
|
731
|
+
row: list[Any] = [
|
|
732
|
+
"★" if is_current else "",
|
|
733
|
+
model.id,
|
|
734
|
+
label,
|
|
735
|
+
variant.quant,
|
|
736
|
+
variant.role,
|
|
737
|
+
f"{variant.size_mb:.1f} MB",
|
|
738
|
+
"✓" if variant.name in cached_variants else "",
|
|
739
|
+
]
|
|
740
|
+
if args.show_adapter:
|
|
741
|
+
row.insert(2, model.adapter)
|
|
742
|
+
if args.show_license:
|
|
743
|
+
row.insert(3, model.license)
|
|
744
|
+
rows.append(row)
|
|
739
745
|
_print_table(headers, rows)
|
|
740
|
-
print("\n* default variant.
|
|
746
|
+
print("\n* default variant.")
|
|
747
|
+
print("download: dtk models download <id> --variant <name>")
|
|
748
|
+
print("select: dtk models use <id> --variant <name>")
|
|
741
749
|
return EXIT_OK
|
|
742
750
|
|
|
743
751
|
if command == "variants":
|
|
@@ -777,6 +785,10 @@ def _cmd_models(args: argparse.Namespace) -> int:
|
|
|
777
785
|
f" download: dtk models download {model.id} "
|
|
778
786
|
f"--variant {variant.name}"
|
|
779
787
|
)
|
|
788
|
+
print(
|
|
789
|
+
f" use: dtk models use {model.id} "
|
|
790
|
+
f"--variant {variant.name}"
|
|
791
|
+
)
|
|
780
792
|
if not model.variants:
|
|
781
793
|
print(" (no downloadable ONNX variant yet)")
|
|
782
794
|
else:
|