feat: account files carry priority, latency targets and prices
Merged
HA
2d ago+1391+1391+0123456789012345678901234567890123456789-104-104-012345678901234567890123456789
What
Account files (model_provisioning.account_limits_directory) can now hold one account's whole serving deal, per model and per serving class:
account: acme
priority: 100 # account default
models:
example/chat-model:
priority: 300 # model override
tariffs: [...] # batch prices only
classes:
standard:
realtime_inflight: 200
tariffs: [...] # realtime / playground prices
cache_tariff: {...}
ttft_ms: 1000
itl_ms: 30
priority: 500 # class override
- The old top-level
realtime_inflightshape is still accepted and meansclasses.standard.realtime_inflight. If both name the same model, the two limits must match. - Only
standardcan be configured until models carry other classes. - Limits, realtime prices and cache tariffs live per class. Model-level tariffs take batch prices only.
- An account/model pair may be configured in its account file or in an organisation overlay, not both. Startup checks this, and so does
validate-account-limits --org-overlays. - New
dwctl-model-provisioning account-schemacommand.
How
- Migration (additive): nullable
users.scheduling_priority, plus a newaccount_model_policiestable (account, model, optional class: priority, ttft_ms, itl_ms). Both have notify triggers. Older images ignore both. - Reconcile: the account files are applied in one transaction under the existing advisory lock.
- Limits keep their whole-table semantics.
- Priorities, policies and prices are owned row by row via the
account-catalogprovisioning source:- hand-written prices are adopted only when the pair is declared;
- omitted prices retire, keeping their history;
- prices owned by the organisation catalog are refused.
- The retire-omitted-prices step is shared with the organisation catalog.
- Gateway: the sync flattens class โ model โ account priority, and the per-class targets, into the onwards overlay and account. Onwards stamps them as
nvext.agent_hints.priority/nvext.router.{ttft,itl}_targeton realtime requests todynamomembers.- These are hints: the request keeps its billed class, unlike legacy overlay
targets, which still make itcustom. - Daemon (batch/flex) traffic keeps its deadline priority.
- Members that refuse scheduling fields get nothing.
- These are hints: the request keeps its billed class, unlike legacy overlay
Design choices worth a look
- The account-wide toleration preset stays where it is today, set in the console. These files don't touch it; per-model/class toleration overrides come in a follow-up.
- The account default priority is written only by the files; there is no console control.
- The limits table has no class dimension yet. Changing its key in place would break older pods' upserts mid-rollout, so the class column comes later as expand/contract, when non-standard classes exist.
Rollout
Dormant. Today's files reconcile to exactly what they do now, because they only use the old limits shape. Nothing changes until a file uses the new fields.
Tests
just lint rust: green.just test rust: 4236 passed.- New tests cover:
- format validation;
- the cross-catalogue conflict check;
- priorities, policies, limits and prices written, re-applied idempotently and cleared;
- personal accounts;
- price adoption, and the refusal of prices owned by the organisation catalog;
- gateway sync of account priority and policy;
- onwards hint stamping.
๐ค Generated with Claude Code