Text Classification
cortiq
Laya
English
cmf
jev
decision-making
structured-output
tool-selection
semantic-routing
on-device
metal
vulkan
intent-classification
resonance-routing
Instructions to use infosave/cmf-decision with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- cortiq
How to use infosave/cmf-decision with cortiq:
# one Rust binary, no additional dependencies cargo install cortiq-cli # or a prebuilt binary from github.com/infosave2007/cmf/releases hf download infosave/cmf-decision --include "*.cmf" --local-dir . ls *.cmf # some repos ship more than one quantization
cortiq run FILE.cmf --prompt "What is the capital of France?"
cortiq serve FILE.cmf --port 8080 # OpenAI-compatible server
- Laya
How to use infosave/cmf-decision with Laya:
# No code snippets available yet for this library. # To use this model, check the repository files and the library's documentation. # Want to help? PRs adding snippets are welcome at: # https://github.com/huggingface/huggingface.js
- Notebooks
- Google Colab
- Kaggle
0.8.6: auto-skills (API.md 3.2/3.3/6, ORACLE.md Auto-skills, Exploration)
Browse files
API.md
CHANGED
|
@@ -359,6 +359,56 @@ matter to the oracle alone). With L = the option ids of a choice question:
|
|
| 359 |
| `superset` | one skill's labels plus labels it does not know | the oracle only; its answer teaches that skill only for a key with `learning_allowed` |
|
| 360 |
| `untrained` | anything else, and every `score` / `noul` question | the oracle only; without it the request is 422 |
|
| 361 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 362 |
`cmf.skill` names the skill and skips the search (an unknown id is 400). An
|
| 363 |
answer is `certified: true` only for an exact match on a string `state`, the
|
| 364 |
`balanced` or `quality-first` profile, a skill whose gate is certified, and a
|
|
@@ -408,7 +458,7 @@ curl -s "$CORTIQ/v1/skills/banking77" -H "Authorization: Bearer $KEY" \
|
|
| 408 |
| `source`, `skill`, `match`, `certified` | where the answer came from; section 3.2 |
|
| 409 |
| `gate` | `accepted`, `p_top` and `tau`, `novelty` and `theta`, `is_novel`, `margin`, `profile` |
|
| 410 |
| `errors` | reconstruction errors of the 5 best labels (all of them with `cmf.explain`) |
|
| 411 |
-
| `flags` | e.g. `oracle_disabled`, `no_key` (with `oracle_disabled`: the key variable is not set), `bad_key` (with `oracle_disabled`: it holds something that is not a key), `consent_off`, `budget`, `stopped`, `oracle_unavailable`, `pii_redacted` |
|
| 412 |
| `confident` | the answer can be used as is (gate accepted and not novel, or a valid oracle answer) |
|
| 413 |
| `complexity` | `{score, tier, factors: {base, ambiguity, novelty, margin, length}}`, the cortiq-router formula |
|
| 414 |
| `routing` | `{target, reason}` when `routing_tiers` maps the tier |
|
|
@@ -530,10 +580,10 @@ curl -s "$CORTIQ/v1/feedback" -H "Authorization: Bearer $KEY" \
|
|
| 530 |
| Path | Access | Returns |
|
| 531 |
|---|---|---|
|
| 532 |
| `GET /v1/models` | open | the model in the shape of an OpenRouter provider listing (`id`, `pricing` as USD-per-token strings, `context_length` 512, `max_output_length` 255) plus `cmf.skills` with each gate |
|
| 533 |
-
| `GET /v1/skills` | key | every skill: `id`, `taxonomy_version`, `labels`, `certified`, `tau`, `theta`, `temperature`
|
| 534 |
| `GET /v1/skills/{id}` | key | the same plus `tasks`, the whole `gate` and `rubric` (`instructions`, `criteria`; `null` without one) |
|
| 535 |
| `GET /v1/usage` | key | the caller's account (router format; `x-cmf-extensions: 1` adds token and cost totals) |
|
| 536 |
-
| `GET /healthz` | open | status, model, generation, skills, `oracle` (on/off) and `oracle_status` (`ready`, `no_key`, `bad_key`, `disabled`, `budget_exhausted`, `budget_too_small`, `stopped: <reason>`; section 5) |
|
| 537 |
|
| 538 |
Without `--jev-compatible`, `/v1/models` has only the native OpenRouter-style
|
| 539 |
listing shape; Cortiq Decision is not listed on OpenRouter. With the adapter
|
|
@@ -762,7 +812,7 @@ unset the admin API answers 404 `ADMIN_DISABLED`.
|
|
| 762 |
| `POST / GET /v1/admin/keys`, `DELETE /v1/admin/keys/{account}`, `DELETE /v1/admin/keys/hash/{hash12}` | create (raw key returned once), list, revoke |
|
| 763 |
| `GET /v1/admin/usage` | usage of every account |
|
| 764 |
| `GET /v1/admin/oracle`, `POST /v1/admin/oracle {"enabled", "budget_usd", "max_calls"}` | oracle status: `status` (`ready`; `no_key` — the key variable is unset or empty; `bad_key` — it holds something that is not a key, never sent; `disabled` — not configured or switched off by the admin; `budget_exhausted` — something was spent and the budget (what is left cannot hold the smallest possible call, or a call it refused) or `max_calls` is used up; `budget_too_small` — nothing spent, and the budget cannot hold one call, `min_call_usd`, or `max_calls` is 0; `stopped: <reason>` — a stop rule), `configured` = `oracle.enabled` of the configuration, `enabled` = not switched off by a stop rule or the admin, `key_present`, `key_ok`, `key_problem` (by position and length, never a byte of the key), `key_trimmed` (surrounding whitespace was trimmed), `key_env` (the variable's name, never its value), `model`, `max_price`, `min_call_usd` (the least budget a call needs: the smallest possible call's reservation, or, once the budget refused a longer call — a budget below the smallest call included — that call's, the larger), spent, calls, stop reason, `last_error` (the code of the last failed call; both from a closed code set, another value read back from `oracle.state` is `unknown_code`); switch it and lower limits within the configuration (kept in `oracle.state` across restarts: when one of them refuses the next call, `cmf.hint` and the startup line name it and the `POST /v1/admin/oracle` that lifts it) |
|
| 765 |
-
| `GET /v1/admin/learning` | buffer, cache, quarantine, attempts, promotions, recent events |
|
| 766 |
| `GET /v1/admin/generations`, `POST /v1/admin/rollback {"generation": N}` | generations; serve generation N (0 = the base file) |
|
| 767 |
| `GET /v1/admin/shadow` | agreement statistics in shadow mode, and the routed requests not compared since the start (section 8) |
|
| 768 |
|
|
@@ -803,7 +853,11 @@ unknown key is an error. The defaults:
|
|
| 803 |
"max_tokens_per_question": 64, "deadline_s": 30, "budget_usd": 1.0, "max_calls": 10000,
|
| 804 |
"max_errors": 30, "redact_pii": true, "title": "cortiq-decision", "data_collection": null},
|
| 805 |
"cache": {"enabled": true, "threshold": 0.97, "cap": 50000},
|
| 806 |
-
"learning": {"enabled": true, "refit_min_new": 25, "dedup": 0.995, "cold_start": true, "synchronous": false
|
|
|
|
|
|
|
|
|
|
|
|
|
| 807 |
"feedback": {"pending_cap": 50000},
|
| 808 |
"complexity_weights": {"base": 0.4, "ambiguity": 0.25, "novelty": 0.15, "margin": 0.1, "length": 0.1},
|
| 809 |
"complexity_tiers": [{"tier": "low", "max": 0.33}, {"tier": "medium", "max": 0.66}, {"tier": "high", "max": 1.0}],
|
|
@@ -817,7 +871,22 @@ part of the file: the admin token and the OpenRouter key are read from the
|
|
| 817 |
environment variables it names. `auth.plans` may override the plan table.
|
| 818 |
`oracle.base_url` must be https, or plain http to a loopback address only (a
|
| 819 |
local proxy). The oracle, cache and learning sections are explained in
|
| 820 |
-
[ORACLE.md](ORACLE.md).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 821 |
override the `oracle` section (and `--no-oracle-learning` sets
|
| 822 |
`learning.enabled` false); a file that sets `oracle.provider` keeps its
|
| 823 |
`max_price` unless `--oracle-max-price` is given.
|
|
|
|
| 359 |
| `superset` | one skill's labels plus labels it does not know | the oracle only; its answer teaches that skill only for a key with `learning_allowed` |
|
| 360 |
| `untrained` | anything else, and every `score` / `noul` question | the oracle only; without it the request is 422 |
|
| 361 |
|
| 362 |
+
**Auto-skills (0.8.6).** A choice question no skill fits (`untrained` because
|
| 363 |
+
of its options, not an ambiguous one and not one forced with `cmf.skill`) is
|
| 364 |
+
learned from the oracle's answers when the caller's key has `learning_allowed`
|
| 365 |
+
and `learning.auto_skills` is on (the default). Its *contract* is the whole
|
| 366 |
+
question — `instructions` and `criteria` with their descriptions, not the id
|
| 367 |
+
set: the key is `auto-<12 hex of the sha256 of the canonical JSON of {type,
|
| 368 |
+
instructions, criteria}>` with the criteria keys sorted (so the criteria in
|
| 369 |
+
any order are one contract, while other instructions, a changed description,
|
| 370 |
+
a dropped or an added option are each another contract — `{yes, no}` under
|
| 371 |
+
"Is this spam?" and under "Is this urgent?" are two skills that never answer
|
| 372 |
+
each other's question, and positional ids `{A, B, C, D}` whose descriptions
|
| 373 |
+
change with every request are never learned as one). The answers accumulate
|
| 374 |
+
as examples of that skill, and once enough evidence is there (2 labels with ≥
|
| 375 |
+
`auto_min_rows` fit rows, the active labels holding ≥ `auto_min_coverage` of
|
| 376 |
+
the examples, a macro agreement with the oracle on a held-out fifth of the
|
| 377 |
+
rows ≥ `auto_min_agreement`) the skill is fitted, written as a generation and
|
| 378 |
+
served: the same contract is then `exact`, `action: local`, `skill: auto-…`,
|
| 379 |
+
always `certified: false` (`decision_path` `router:uncertified`). An
|
| 380 |
+
auto-skill is matched by its contract alone — never as a `subset` or
|
| 381 |
+
`superset` — so to be learned and then answered locally a client keeps the
|
| 382 |
+
question stable: the same `instructions` text, the same option ids with the
|
| 383 |
+
same descriptions (`null` descriptions, and absent instructions, count as
|
| 384 |
+
such and stay stable). Labels the oracle rarely picks stay *quarantined*: they
|
| 385 |
+
count as known within the contract, get probability 0, and a text of such a
|
| 386 |
+
label is expected to abstain on novelty and keep teaching it. A
|
| 387 |
+
young auto-skill's gate comes from a handful of rows, so a local answer also
|
| 388 |
+
needs `p_top ≥ learning.auto_tau` (0.90; `balanced` and `quality-first`) and
|
| 389 |
+
its temperature is floored at `learning.auto_temperature_min` (0.02 — a clean
|
| 390 |
+
calibration subset fits T at its lower bound, where every `p_top` is 1);
|
| 391 |
+
whatever abstains escalates and teaches, and later attempts refit the whole
|
| 392 |
+
skill under a regression gate. *Exploration* is the one exception to the hard
|
| 393 |
+
rule that a gate-accepted question never reaches the oracle: while a label of
|
| 394 |
+
an auto-skill is quarantined, a question the gate accepted is escalated anyway
|
| 395 |
+
when the text's hash says so (`u64le(sha256(φ_P))` ≡ 0 modulo
|
| 396 |
+
`learning.auto_explore_every`, 8 — one text in eight; 0 turns it off), because
|
| 397 |
+
the gate confidently names a quarantined label's texts as a neighbour and they
|
| 398 |
+
would otherwise never teach it. The oracle's answer is served (`action:
|
| 399 |
+
oracle` / `cache`, `decision_path` `escalate→…`, the flag `explore`, the
|
| 400 |
+
`gate` block still `accepted: true`) and learned as usual, so the rare label
|
| 401 |
+
collects examples at a quarter of its traffic until it activates; a refused
|
| 402 |
+
or failed call leaves the local answer. Only auto-skills explore, only while
|
| 403 |
+
a label is quarantined, and only when the answer could teach (the oracle
|
| 404 |
+
consented, learning on, a key with `learning_allowed`); `cortiq decide`,
|
| 405 |
+
shadow mode and `/v1/route` never do. Its rubric is the contract — the first
|
| 406 |
+
caller's instructions and criteria verbatim — visible through
|
| 407 |
+
`/v1/skills/{id}` to every key (as cached answers are shared across accounts).
|
| 408 |
+
Limits, who teaches and the state directory's compatibility:
|
| 409 |
+
[ORACLE.md](ORACLE.md#auto-skills). When a data skill and auto-skills fit a
|
| 410 |
+
question equally, the data skill answers.
|
| 411 |
+
|
| 412 |
`cmf.skill` names the skill and skips the search (an unknown id is 400). An
|
| 413 |
answer is `certified: true` only for an exact match on a string `state`, the
|
| 414 |
`balanced` or `quality-first` profile, a skill whose gate is certified, and a
|
|
|
|
| 458 |
| `source`, `skill`, `match`, `certified` | where the answer came from; section 3.2 |
|
| 459 |
| `gate` | `accepted`, `p_top` and `tau`, `novelty` and `theta`, `is_novel`, `margin`, `profile` |
|
| 460 |
| `errors` | reconstruction errors of the 5 best labels (all of them with `cmf.explain`) |
|
| 461 |
+
| `flags` | e.g. `oracle_disabled`, `no_key` (with `oracle_disabled`: the key variable is not set), `bad_key` (with `oracle_disabled`: it holds something that is not a key), `consent_off`, `budget`, `stopped`, `oracle_unavailable`, `pii_redacted`, `explore` (a gate-accepted question of an auto-skill answered by the oracle for exploration, section 3.2) |
|
| 462 |
| `confident` | the answer can be used as is (gate accepted and not novel, or a valid oracle answer) |
|
| 463 |
| `complexity` | `{score, tier, factors: {base, ambiguity, novelty, margin, length}}`, the cortiq-router formula |
|
| 464 |
| `routing` | `{target, reason}` when `routing_tiers` maps the tier |
|
|
|
|
| 580 |
| Path | Access | Returns |
|
| 581 |
|---|---|---|
|
| 582 |
| `GET /v1/models` | open | the model in the shape of an OpenRouter provider listing (`id`, `pricing` as USD-per-token strings, `context_length` 512, `max_output_length` 255) plus `cmf.skills` with each gate |
|
| 583 |
+
| `GET /v1/skills` | key | every skill: `id`, `taxonomy_version`, `labels` (the active ones), `certified`, `tau`, `theta`, `temperature`, `has_rubric` (whether it has a rubric; the rubric itself is per skill) and, since 0.8.6, `auto` (an auto-skill), `active_labels` (their count), `quarantined_labels` (the labels not scored yet) and `examples` (learned rows); auto-skills are listed after the file's skills |
|
| 584 |
| `GET /v1/skills/{id}` | key | the same plus `tasks`, the whole `gate` and `rubric` (`instructions`, `criteria`; `null` without one) |
|
| 585 |
| `GET /v1/usage` | key | the caller's account (router format; `x-cmf-extensions: 1` adds token and cost totals) |
|
| 586 |
+
| `GET /healthz` | open | status, model, generation, skills (every served skill), `auto_skills` (0.8.6), `oracle` (on/off) and `oracle_status` (`ready`, `no_key`, `bad_key`, `disabled`, `budget_exhausted`, `budget_too_small`, `stopped: <reason>`; section 5) |
|
| 587 |
|
| 588 |
Without `--jev-compatible`, `/v1/models` has only the native OpenRouter-style
|
| 589 |
listing shape; Cortiq Decision is not listed on OpenRouter. With the adapter
|
|
|
|
| 812 |
| `POST / GET /v1/admin/keys`, `DELETE /v1/admin/keys/{account}`, `DELETE /v1/admin/keys/hash/{hash12}` | create (raw key returned once), list, revoke |
|
| 813 |
| `GET /v1/admin/usage` | usage of every account |
|
| 814 |
| `GET /v1/admin/oracle`, `POST /v1/admin/oracle {"enabled", "budget_usd", "max_calls"}` | oracle status: `status` (`ready`; `no_key` — the key variable is unset or empty; `bad_key` — it holds something that is not a key, never sent; `disabled` — not configured or switched off by the admin; `budget_exhausted` — something was spent and the budget (what is left cannot hold the smallest possible call, or a call it refused) or `max_calls` is used up; `budget_too_small` — nothing spent, and the budget cannot hold one call, `min_call_usd`, or `max_calls` is 0; `stopped: <reason>` — a stop rule), `configured` = `oracle.enabled` of the configuration, `enabled` = not switched off by a stop rule or the admin, `key_present`, `key_ok`, `key_problem` (by position and length, never a byte of the key), `key_trimmed` (surrounding whitespace was trimmed), `key_env` (the variable's name, never its value), `model`, `max_price`, `min_call_usd` (the least budget a call needs: the smallest possible call's reservation, or, once the budget refused a longer call — a budget below the smallest call included — that call's, the larger), spent, calls, stop reason, `last_error` (the code of the last failed call; both from a closed code set, another value read back from `oracle.state` is `unknown_code`); switch it and lower limits within the configuration (kept in `oracle.state` across restarts: when one of them refuses the next call, `cmf.hint` and the startup line name it and the `POST /v1/admin/oracle` that lifts it) |
|
| 815 |
+
| `GET /v1/admin/learning` | buffer, cache, quarantine, attempts, promotions, recent events; since 0.8.6 `auto_contracts`, `auto_skipped` and `auto_skills` (per contract: `id`, `labels`, `examples` per label — the rows an attempt fits: the served learned rows plus the pending buffer examples, each row once — `created_unix`, `served`) |
|
| 816 |
| `GET /v1/admin/generations`, `POST /v1/admin/rollback {"generation": N}` | generations; serve generation N (0 = the base file) |
|
| 817 |
| `GET /v1/admin/shadow` | agreement statistics in shadow mode, and the routed requests not compared since the start (section 8) |
|
| 818 |
|
|
|
|
| 853 |
"max_tokens_per_question": 64, "deadline_s": 30, "budget_usd": 1.0, "max_calls": 10000,
|
| 854 |
"max_errors": 30, "redact_pii": true, "title": "cortiq-decision", "data_collection": null},
|
| 855 |
"cache": {"enabled": true, "threshold": 0.97, "cap": 50000},
|
| 856 |
+
"learning": {"enabled": true, "refit_min_new": 25, "dedup": 0.995, "cold_start": true, "synchronous": false,
|
| 857 |
+
"auto_skills": true, "auto_min_rows": 10, "auto_k": 8, "auto_tau": 0.9,
|
| 858 |
+
"auto_min_agreement": 0.8, "auto_min_coverage": 0.8, "auto_max_skills": 256,
|
| 859 |
+
"auto_max_labels": 64, "auto_max_examples_per_label": 1000,
|
| 860 |
+
"auto_temperature_min": 0.02, "auto_explore_every": 8},
|
| 861 |
"feedback": {"pending_cap": 50000},
|
| 862 |
"complexity_weights": {"base": 0.4, "ambiguity": 0.25, "novelty": 0.15, "margin": 0.1, "length": 0.1},
|
| 863 |
"complexity_tiers": [{"tier": "low", "max": 0.33}, {"tier": "medium", "max": 0.66}, {"tier": "high", "max": 1.0}],
|
|
|
|
| 871 |
environment variables it names. `auth.plans` may override the plan table.
|
| 872 |
`oracle.base_url` must be https, or plain http to a loopback address only (a
|
| 873 |
local proxy). The oracle, cache and learning sections are explained in
|
| 874 |
+
[ORACLE.md](ORACLE.md). The `learning.auto_*` keys govern auto-skills
|
| 875 |
+
(section 3.2, [ORACLE.md](ORACLE.md#auto-skills)): `auto_skills` learns
|
| 876 |
+
untrained choice contracts at all; `auto_min_rows` fit rows (≥ 2) a label
|
| 877 |
+
needs to be active; `auto_k` the rank of its topologies; `auto_tau` the
|
| 878 |
+
confidence floor of a local answer (0..1; a serving parameter — `cortiq
|
| 879 |
+
decide` uses the default); `auto_min_agreement` the macro agreement with the
|
| 880 |
+
oracle required to activate and `auto_min_coverage` the share of the
|
| 881 |
+
contract's examples its active labels must hold (both 0..1); `auto_max_skills`
|
| 882 |
+
how many contracts are learned at most and `auto_max_labels` (2..255) how
|
| 883 |
+
many options one may have — a contract past either is answered by the
|
| 884 |
+
oracle and not learned; `auto_max_examples_per_label` (≤ 5000) replaces the
|
| 885 |
+
per-label buffer cap for auto-skills; `auto_temperature_min` (0..1) floors
|
| 886 |
+
the gate temperature an attempt records (0: the fitted T, whose lower bound
|
| 887 |
+
makes every `p_top` 1); `auto_explore_every` (an integer, 0 = off) explores
|
| 888 |
+
one text in that many while a label is quarantined — the one case in which a
|
| 889 |
+
gate-accepted question reaches the oracle, auto-skills only. `cortiq serve --oracle MODEL` and its companions
|
| 890 |
override the `oracle` section (and `--no-oracle-learning` sets
|
| 891 |
`learning.enabled` false); a file that sets `oracle.provider` keeps its
|
| 892 |
`max_price` unless `--oracle-max-price` is given.
|
ORACLE.md
CHANGED
|
@@ -72,7 +72,9 @@ says first whether it is ready — [Check your setup](#check-your-setup)).
|
|
| 72 |
|
| 73 |
Superset questions (a skill's labels plus new ones) are decided by the oracle
|
| 74 |
only; for a caller with `learning_allowed` the answer teaches that skill, and
|
| 75 |
-
a new label starts a cold start.
|
|
|
|
|
|
|
| 76 |
|
| 77 |
## Self-learning
|
| 78 |
|
|
@@ -127,7 +129,130 @@ a new label starts a cold start.
|
|
| 127 |
every label that got new examples, however few (there is no threshold of
|
| 128 |
25 here), checks each challenger on the holdout and re-certifies the gate
|
| 129 |
once at the end; if a certified gate would be lost, every promotion of the
|
| 130 |
-
skill is undone (see API.md, section 7).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 131 |
|
| 132 |
## Budget and stop rules
|
| 133 |
|
|
@@ -535,7 +660,8 @@ warning: removed the LOCK of state directory cortiq-decision.cmf.state left by p
|
|
| 535 |
(`oracle_allowed: true`, like imported router keys); `--oracle-allowed=false`
|
| 536 |
makes one that never escalates, and `--oracle-budget-usd` caps one key's
|
| 537 |
oracle spending. Teaching the shared skills is a separate permission,
|
| 538 |
-
`--learning-allowed` (off by default)
|
|
|
|
| 539 |
/v1/admin/keys` keep the router's default (`oracle_allowed` only when the
|
| 540 |
body says so).
|
| 541 |
|
|
|
|
| 72 |
|
| 73 |
Superset questions (a skill's labels plus new ones) are decided by the oracle
|
| 74 |
only; for a caller with `learning_allowed` the answer teaches that skill, and
|
| 75 |
+
a new label starts a cold start. A choice question no skill fits is learned
|
| 76 |
+
into an *auto-skill* of its own ([Auto-skills](#auto-skills)), for such a
|
| 77 |
+
caller only.
|
| 78 |
|
| 79 |
## Self-learning
|
| 80 |
|
|
|
|
| 129 |
every label that got new examples, however few (there is no threshold of
|
| 130 |
25 here), checks each challenger on the holdout and re-certifies the gate
|
| 131 |
once at the end; if a certified gate would be lost, every promotion of the
|
| 132 |
+
skill is undone (see API.md, section 7). An auto-skill (below) learns
|
| 133 |
+
online only.
|
| 134 |
+
|
| 135 |
+
### Auto-skills
|
| 136 |
+
|
| 137 |
+
A choice question whose option ids match no skill (`match: untrained`, not
|
| 138 |
+
an ambiguous one — several skills fit — and not one forced with `cmf.skill`)
|
| 139 |
+
goes to the oracle on every new text and, until 0.8.5, was never learned. Since
|
| 140 |
+
0.8.6 its *contract* becomes a skill of its own:
|
| 141 |
+
|
| 142 |
+
* **Key.** The contract is the question itself: `auto-` + the first 12 hex
|
| 143 |
+
characters of the sha256 of the canonical JSON of `{type, instructions,
|
| 144 |
+
criteria}` — the instructions as sent (`null` when absent), the criteria
|
| 145 |
+
object with its keys sorted and every description kept. The criteria in
|
| 146 |
+
any order are one contract; other instructions, a changed description, a
|
| 147 |
+
dropped or an added option are each another contract, learned separately.
|
| 148 |
+
The id set alone is not the key: two clients using `{yes, no}` under
|
| 149 |
+
different questions get two skills, and a multiple-choice benchmark whose
|
| 150 |
+
positional ids `{A, B, C, D}` carry a new description per request is never
|
| 151 |
+
learned as one skill (every request is its own contract, bounded by
|
| 152 |
+
`auto_max_skills`). To be learned, a client keeps its question stable —
|
| 153 |
+
the same instructions text, the same ids with the same descriptions. The
|
| 154 |
+
first request's instructions and criteria are stored verbatim as the
|
| 155 |
+
skill's rubric (the id is recomputed from it), visible through
|
| 156 |
+
`/v1/skills/{id}` to every key. The contract is written to `learn.log`
|
| 157 |
+
before its first example, so a restart rebuilds it.
|
| 158 |
+
* **Who teaches.** Only a caller whose key has `learning_allowed` (the explicit
|
| 159 |
+
open mode `auth.require: false` has it; the implicit open mode of a loopback
|
| 160 |
+
address never teaches). The rule "a question that is exactly the skill's own
|
| 161 |
+
teaches it" does not apply to auto-skills: their rubric *is* the contract
|
| 162 |
+
every caller sends. `learning.auto_skills: false` turns the learning off;
|
| 163 |
+
the oracle answers as before.
|
| 164 |
+
* **Examples.** Each answer is an example of the auto-skill under the
|
| 165 |
+
contract's label (the dedup of 0.995 applies). The labels are closed: a
|
| 166 |
+
feedback with a label outside the contract is refused (a request with one
|
| 167 |
+
more id is another contract, learned on its own).
|
| 168 |
+
At most `learning.auto_max_examples_per_label` (1000) examples per label.
|
| 169 |
+
* **Activation.** When a label collects 25 new examples (the usual trigger)
|
| 170 |
+
the whole skill is attempted: one row in five — by a hash of the row itself,
|
| 171 |
+
so a row never moves between the fit and the calibration subset as more
|
| 172 |
+
arrive — is held out; a label with ≥ `auto_min_rows` (10) fit rows is
|
| 173 |
+
*eligible* and fitted (rank `auto_k`, 8), the others stay quarantined; the
|
| 174 |
+
attempt needs two eligible labels including the triggering one and, the
|
| 175 |
+
first time, the eligible labels must hold ≥ `auto_min_coverage` (0.8) of
|
| 176 |
+
the contract's rows. T and θ are certified on the held-out rows as at build
|
| 177 |
+
time (Ï„ certifies only with 100 accepted odd rows, so the skill reports
|
| 178 |
+
`certified: false` for a long time, and its winners are `cold_start` ones —
|
| 179 |
+
never certified). The first activation (`auto_start`) requires a macro
|
| 180 |
+
agreement of the fitted skill with the oracle's labels on the held-out rows
|
| 181 |
+
≥ `auto_min_agreement` (0.8) and ≥ 0.5 per label; a later attempt
|
| 182 |
+
(`auto_refit`, the whole skill refitted) must not regress the champion on
|
| 183 |
+
the same rows (the holdout rule). A promotion writes a generation that
|
| 184 |
+
carries the auto-skill entirely; every other skill is byte for byte the
|
| 185 |
+
same.
|
| 186 |
+
* **Serving.** The contract is then decided locally, `match: exact`,
|
| 187 |
+
`skill: auto-…`, `certified: false`. An auto-skill is matched by its
|
| 188 |
+
contract alone: a part of its ids, a superset, other instructions or another
|
| 189 |
+
description is another contract (`untrained`, learned on its own), never a
|
| 190 |
+
`subset` or `superset` of the auto-skill. A quarantined label still counts
|
| 191 |
+
as known within the contract: it gets probability 0, and a text of it is
|
| 192 |
+
expected to abstain on novelty and keep teaching it. Because θ and T of a
|
| 193 |
+
young auto-skill come from a handful of rows (θ is close to the largest
|
| 194 |
+
novelty of the even half, T may sit at a bound), a local answer also needs
|
| 195 |
+
`p_top ≥ learning.auto_tau` (0.9) under `balanced` and `quality-first`
|
| 196 |
+
(`cost-saver` keeps its θ-only rule), and the T an attempt records is
|
| 197 |
+
floored at `learning.auto_temperature_min` (0.02): a clean held-out subset
|
| 198 |
+
fits T at its lower bound, where every `p_top` is 1 and the `auto_tau`
|
| 199 |
+
floor never bites. An abstention escalates and teaches as any other. The
|
| 200 |
+
agreement gate is the real guard while the subset is small; the gate
|
| 201 |
+
improves with every refit. Rejected examples are never forgotten: a
|
| 202 |
+
contract polluted by a noisy oracle needs more consistent examples, not a
|
| 203 |
+
reset (or a rollback to a generation before it).
|
| 204 |
+
* **Exploration.** The hard rule — a question the gate accepted never
|
| 205 |
+
reaches the oracle — has exactly one exception, for auto-skills only and
|
| 206 |
+
only while one of their labels is quarantined: the gate names such a
|
| 207 |
+
label's texts as a neighbour with full confidence (measured on a stand: all
|
| 208 |
+
21 texts of a quarantined label answered locally as another label at
|
| 209 |
+
`p_top` 1), so without it the label could never learn. One text in
|
| 210 |
+
`learning.auto_explore_every` (8; `u64le(sha256(φ_P))` modulo it is 0, a
|
| 211 |
+
property of the text, never of the order; 0 turns it off) is escalated
|
| 212 |
+
although accepted: the oracle's answer is served (`action: oracle` /
|
| 213 |
+
`cache`, the flag `explore`, the `gate` block still reports `accepted:
|
| 214 |
+
true`) and learned as usual, so the rare label collects examples at a
|
| 215 |
+
quarter of its traffic until the next attempt activates it, after which
|
| 216 |
+
the contract explores no more. A refused or failed call leaves the local
|
| 217 |
+
answer. Exploration draws only when the answer could teach: the oracle
|
| 218 |
+
consented, learning and `auto_skills` on, a key with `learning_allowed`;
|
| 219 |
+
data skills, `cortiq decide`, shadow mode and `/v1/route` never explore.
|
| 220 |
+
* **Limits.** A contract is learned only with 2..`auto_max_labels` (64) option
|
| 221 |
+
ids and while fewer than `auto_max_skills` (256) contracts are registered;
|
| 222 |
+
otherwise the oracle answers and nothing is recorded (`auto_skipped` in
|
| 223 |
+
`GET /v1/admin/learning`, one warning an hour, never the ids). Every
|
| 224 |
+
generation re-carries every auto-skill's rows: with many contracts run
|
| 225 |
+
`cortiq decision materialize` from time to time and serve the materialised
|
| 226 |
+
file (it holds the auto-skills as ordinary skills; `decide --labels` and
|
| 227 |
+
`verify` read it; such a file needs cortiq ≥ 0.8.6). A served auto-skill
|
| 228 |
+
keeps learning wherever its contract comes from: the contract record of
|
| 229 |
+
`learn.log`, or — a materialised file on a fresh state directory, a
|
| 230 |
+
`learn.log` lost while the generations were kept — the skill's own labels
|
| 231 |
+
and rubric, registered (and written to `learn.log`) at start and after a
|
| 232 |
+
rollback.
|
| 233 |
+
* **Routing.** `/v1/route` without `taxonomy_id` still means the file's only
|
| 234 |
+
data skill; an auto-skill is routed by its id (its question is then the
|
| 235 |
+
whole contract from the rubric). `cortiq decide --labels` never names an
|
| 236 |
+
auto-skill by labels alone: `--skill auto-…` names it and its rubric
|
| 237 |
+
supplies the contract. When a data skill and auto-skills fit a question
|
| 238 |
+
equally, the data skill answers; two auto-skills of one contract cannot
|
| 239 |
+
exist (the contract is the id).
|
| 240 |
+
* **Admin.** `GET /v1/admin/learning` lists `auto_skills` (id, labels,
|
| 241 |
+
`examples` per label — the rows the next attempt fits: the served learned
|
| 242 |
+
rows of the label plus the buffer examples not among them, each row once,
|
| 243 |
+
so their sum is the attempt's `rows.total` — what is served),
|
| 244 |
+
`auto_contracts` and `auto_skipped`;
|
| 245 |
+
attempts carry `kind: auto_start | auto_refit` and an `auto` block with the
|
| 246 |
+
eligible and quarantined labels, the rows and the agreement. `/healthz`
|
| 247 |
+
adds `auto_skills`. Rollback to an earlier generation drops the skill from
|
| 248 |
+
the served model (the contract is untrained again; its examples stay and
|
| 249 |
+
start it over at the next trigger).
|
| 250 |
+
* **Compatibility.** A 0.8.5 binary opening a 0.8.6 state directory truncates
|
| 251 |
+
`learn.log` at the first contract record and refuses a generation that
|
| 252 |
+
carries an auto-skill (the same rule as the `LOCK` of 0.7.9: never run an
|
| 253 |
+
older binary on a newer state directory). The cache scope of a contract
|
| 254 |
+
changes from the contract to the skill at its activation, so its first
|
| 255 |
+
requests after that miss the cache (they are answered locally anyway).
|
| 256 |
|
| 257 |
## Budget and stop rules
|
| 258 |
|
|
|
|
| 660 |
(`oracle_allowed: true`, like imported router keys); `--oracle-allowed=false`
|
| 661 |
makes one that never escalates, and `--oracle-budget-usd` caps one key's
|
| 662 |
oracle spending. Teaching the shared skills is a separate permission,
|
| 663 |
+
`--learning-allowed` (off by default); it alone lets a caller's untrained
|
| 664 |
+
contracts become [auto-skills](#auto-skills). Keys made through `POST
|
| 665 |
/v1/admin/keys` keep the router's default (`oracle_allowed` only when the
|
| 666 |
body says so).
|
| 667 |
|