modelrig 0.11.0 → 0.12.0
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.
- package/CHANGELOG.md +82 -0
- package/dist/adapters/anthropic.d.ts +4 -4
- package/dist/adapters/anthropic.d.ts.map +1 -1
- package/dist/adapters/anthropic.js +8 -1
- package/dist/adapters/deepseek.d.ts +2 -4
- package/dist/adapters/deepseek.d.ts.map +1 -1
- package/dist/adapters/deepseek.js +9 -5
- package/dist/adapters/gemini.d.ts +4 -1
- package/dist/adapters/gemini.d.ts.map +1 -1
- package/dist/adapters/gemini.js +16 -1
- package/dist/adapters/grok.d.ts +2 -4
- package/dist/adapters/grok.d.ts.map +1 -1
- package/dist/adapters/grok.js +8 -4
- package/dist/adapters/history-mapping.d.ts +126 -0
- package/dist/adapters/history-mapping.d.ts.map +1 -0
- package/dist/adapters/history-mapping.js +230 -0
- package/dist/adapters/openai-compat.d.ts +2 -4
- package/dist/adapters/openai-compat.d.ts.map +1 -1
- package/dist/adapters/openai-compat.js +9 -5
- package/dist/adapters/openai.d.ts +2 -4
- package/dist/adapters/openai.d.ts.map +1 -1
- package/dist/adapters/openai.js +8 -4
- package/dist/adapters/responses-api.d.ts.map +1 -1
- package/dist/adapters/responses-api.js +9 -4
- package/dist/artifacts/artifact.d.ts.map +1 -1
- package/dist/artifacts/artifact.js +79 -0
- package/dist/artifacts/conversation.d.ts +128 -0
- package/dist/artifacts/conversation.d.ts.map +1 -0
- package/dist/artifacts/conversation.js +172 -0
- package/dist/artifacts/index.d.ts +1 -1
- package/dist/artifacts/index.d.ts.map +1 -1
- package/dist/artifacts/media.d.ts +46 -0
- package/dist/artifacts/media.d.ts.map +1 -0
- package/dist/artifacts/media.js +88 -0
- package/dist/artifacts/run-context.d.ts +61 -2
- package/dist/artifacts/run-context.d.ts.map +1 -1
- package/dist/artifacts/run-context.js +183 -12
- package/dist/artifacts/scrub.d.ts +3 -0
- package/dist/artifacts/scrub.d.ts.map +1 -1
- package/dist/bakeoff/engine.d.ts.map +1 -1
- package/dist/bakeoff/engine.js +34 -7
- package/dist/bakeoff/eval-cases.d.ts +5 -0
- package/dist/bakeoff/eval-cases.d.ts.map +1 -1
- package/dist/bakeoff/eval-cases.js +10 -1
- package/dist/bakeoff/replay.d.ts +15 -0
- package/dist/bakeoff/replay.d.ts.map +1 -1
- package/dist/bakeoff/replay.js +19 -1
- package/dist/bakeoff/report.d.ts.map +1 -1
- package/dist/bakeoff/report.js +9 -2
- package/dist/bakeoff/turn-replay.d.ts +93 -0
- package/dist/bakeoff/turn-replay.d.ts.map +1 -0
- package/dist/bakeoff/turn-replay.js +150 -0
- package/dist/bakeoff/types.d.ts +12 -0
- package/dist/bakeoff/types.d.ts.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +1 -0
- package/dist/config.d.ts +18 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +23 -3
- package/dist/doctor-preflight.d.ts.map +1 -1
- package/dist/doctor-preflight.js +6 -1
- package/dist/feedback/grade.d.ts +7 -2
- package/dist/feedback/grade.d.ts.map +1 -1
- package/dist/feedback/grade.js +14 -0
- package/dist/feedback/outcome.d.ts +103 -0
- package/dist/feedback/outcome.d.ts.map +1 -0
- package/dist/feedback/outcome.js +175 -0
- package/dist/gateway/history-bridge.d.ts +32 -0
- package/dist/gateway/history-bridge.d.ts.map +1 -0
- package/dist/gateway/history-bridge.js +64 -0
- package/dist/gateway/serve-client.d.ts.map +1 -1
- package/dist/gateway/serve-client.js +6 -0
- package/dist/index.d.ts +44 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +110 -9
- package/dist/init/init-cli.d.ts.map +1 -1
- package/dist/init/init-cli.js +21 -4
- package/dist/init/observe-cli.js +1 -1
- package/dist/init/observe.d.ts +7 -1
- package/dist/init/observe.d.ts.map +1 -1
- package/dist/init/observe.js +74 -22
- package/dist/init/starter.d.ts +36 -0
- package/dist/init/starter.d.ts.map +1 -0
- package/dist/init/starter.js +85 -0
- package/dist/registry/build.d.ts +4 -0
- package/dist/registry/build.d.ts.map +1 -1
- package/dist/registry/generation-models.d.ts +68 -0
- package/dist/registry/generation-models.d.ts.map +1 -0
- package/dist/registry/generation-models.js +168 -0
- package/dist/registry/model-kind.d.ts +34 -0
- package/dist/registry/model-kind.d.ts.map +1 -0
- package/dist/registry/model-kind.js +40 -0
- package/dist/registry/pricing-shape.d.ts +29 -1
- package/dist/registry/pricing-shape.d.ts.map +1 -1
- package/dist/registry/pricing-shape.js +9 -0
- package/dist/registry/pricing.d.ts +26 -0
- package/dist/registry/pricing.d.ts.map +1 -1
- package/dist/registry/pricing.js +29 -0
- package/dist/registry/rows.d.ts.map +1 -1
- package/dist/registry/rows.js +3 -1
- package/dist/registry/unit-pricing.d.ts +32 -0
- package/dist/registry/unit-pricing.d.ts.map +1 -0
- package/dist/registry/unit-pricing.js +62 -0
- package/dist/routes/input-loader.d.ts +38 -0
- package/dist/routes/input-loader.d.ts.map +1 -0
- package/dist/routes/input-loader.js +80 -0
- package/dist/routes/loader.d.ts.map +1 -1
- package/dist/routes/loader.js +3 -0
- package/dist/routes/resolved-bundle.d.ts +2 -0
- package/dist/routes/resolved-bundle.d.ts.map +1 -1
- package/dist/routes/resolved-bundle.js +3 -0
- package/dist/run/cost.d.ts +28 -0
- package/dist/run/cost.d.ts.map +1 -1
- package/dist/run/cost.js +74 -0
- package/dist/run/dispatch.d.ts +4 -1
- package/dist/run/dispatch.d.ts.map +1 -1
- package/dist/run/dispatch.js +3 -0
- package/dist/run/limits.d.ts +88 -0
- package/dist/run/limits.d.ts.map +1 -0
- package/dist/run/limits.js +155 -0
- package/dist/run/messages.d.ts +199 -0
- package/dist/run/messages.d.ts.map +1 -0
- package/dist/run/messages.js +430 -0
- package/dist/run/raw-finalize.d.ts +5 -2
- package/dist/run/raw-finalize.d.ts.map +1 -1
- package/dist/run/raw-finalize.js +8 -5
- package/dist/run/raw-request.d.ts.map +1 -1
- package/dist/run/raw-request.js +2 -1
- package/dist/run/raw.d.ts +10 -4
- package/dist/run/raw.d.ts.map +1 -1
- package/dist/run/raw.js +11 -3
- package/dist/run/rawonly.d.ts +29 -5
- package/dist/run/rawonly.d.ts.map +1 -1
- package/dist/run/rawonly.js +54 -19
- package/dist/run/record-attempt.d.ts.map +1 -1
- package/dist/run/record-attempt.js +16 -6
- package/dist/run/record-call.d.ts +13 -2
- package/dist/run/record-call.d.ts.map +1 -1
- package/dist/run/record-call.js +50 -7
- package/dist/run/run.d.ts.map +1 -1
- package/dist/run/run.js +12 -8
- package/dist/telemetry/attempt-meta.d.ts +49 -1
- package/dist/telemetry/attempt-meta.d.ts.map +1 -1
- package/dist/telemetry/attempt-meta.js +45 -1
- package/dist/telemetry/exporter.d.ts.map +1 -1
- package/dist/telemetry/exporter.js +2 -1
- package/dist/telemetry/grade-mappers.d.ts +1 -1
- package/dist/telemetry/grade-mappers.d.ts.map +1 -1
- package/dist/telemetry/grade-mappers.js +7 -1
- package/dist/telemetry/grade-task.d.ts +49 -0
- package/dist/telemetry/grade-task.d.ts.map +1 -0
- package/dist/telemetry/grade-task.js +85 -0
- package/dist/telemetry/grades-sql.d.ts +16 -1
- package/dist/telemetry/grades-sql.d.ts.map +1 -1
- package/dist/telemetry/grades-sql.js +64 -4
- package/dist/telemetry/ingest-protocol.d.ts +24 -1
- package/dist/telemetry/ingest-protocol.d.ts.map +1 -1
- package/dist/telemetry/ingest-protocol.js +72 -43
- package/dist/telemetry/otel-content.d.ts +31 -0
- package/dist/telemetry/otel-content.d.ts.map +1 -0
- package/dist/telemetry/otel-content.js +106 -0
- package/dist/telemetry/otel-hierarchy.d.ts +57 -0
- package/dist/telemetry/otel-hierarchy.d.ts.map +1 -0
- package/dist/telemetry/otel-hierarchy.js +155 -0
- package/dist/telemetry/otel-normalize.d.ts +15 -1
- package/dist/telemetry/otel-normalize.d.ts.map +1 -1
- package/dist/telemetry/otel-normalize.js +24 -39
- package/dist/telemetry/sinks.d.ts +4 -1
- package/dist/telemetry/sinks.d.ts.map +1 -1
- package/dist/telemetry/sinks.js +53 -34
- package/dist/telemetry/store-migrations.d.ts.map +1 -1
- package/dist/telemetry/store-migrations.js +8 -0
- package/dist/telemetry/store.d.ts +9 -0
- package/dist/telemetry/store.d.ts.map +1 -1
- package/dist/telemetry/store.js +10 -0
- package/dist/telemetry/uniform-rows.d.ts +43 -0
- package/dist/telemetry/uniform-rows.d.ts.map +1 -0
- package/dist/telemetry/uniform-rows.js +139 -0
- package/dist/types/failures-teaching.d.ts.map +1 -1
- package/dist/types/failures-teaching.js +11 -0
- package/dist/types/failures.d.ts +1 -1
- package/dist/types/failures.d.ts.map +1 -1
- package/dist/types/failures.js +2 -0
- package/dist/types/provider.d.ts +12 -0
- package/dist/types/provider.d.ts.map +1 -1
- package/dist/types/route.d.ts +13 -0
- package/dist/types/route.d.ts.map +1 -1
- package/dist/types/telemetry.d.ts +14 -1
- package/dist/types/telemetry.d.ts.map +1 -1
- package/docs/agent-skill/SKILL.md +122 -12
- package/docs/how-it-fits.md +4 -4
- package/docs/instrumentation.md +148 -44
- package/docs/llms.txt +143 -13
- package/docs/mcp-oracle.md +15 -4
- package/docs/quickstart.md +129 -16
- package/package.json +4 -2
- package/registry/registry.json +456 -0
- package/templates/creative-approval.json +81 -0
- package/templates/support-conversation.json +82 -0
package/docs/mcp-oracle.md
CHANGED
|
@@ -1,8 +1,17 @@
|
|
|
1
1
|
# The MCP oracle
|
|
2
2
|
|
|
3
|
-
> `modelrig-oracle` is published on npm (0.
|
|
4
|
-
> `npx modelrig-oracle` commands on this page work everywhere.
|
|
3
|
+
> `modelrig-oracle` is published on npm (0.4.0, 2026-10-25) — the
|
|
4
|
+
> `npx modelrig-oracle` commands on this page work everywhere. The write tools
|
|
5
|
+
> below (grading guides, `record_grade`, `get_call_config`, the read resources)
|
|
6
|
+
> need **0.3.0 or later**; `record_outcome`, `query_conversations` and
|
|
7
|
+
> `query_registry`'s `kind` filter need **0.4.0 or later**. If you ran an earlier
|
|
8
|
+
> version, refresh once with `npx -y modelrig-oracle@latest`. Nothing else on
|
|
5
9
|
> this site depends on it: llms.txt carries the same probed facts as plain text.
|
|
10
|
+
>
|
|
11
|
+
> **Grading guides on an older oracle.** 0.2.0 (2026-08-22) does not know
|
|
12
|
+
> `grading_guide` and refuses a guide-only `set_task_settings` call — there,
|
|
13
|
+
> write the guide with `PATCH /v1/tasks/<task>/settings` instead
|
|
14
|
+
> ([Set up a grader](set-up-a-grader.md)).
|
|
6
15
|
|
|
7
16
|
**What it is:** an MCP server that lets a coding agent ask what models can
|
|
8
17
|
actually do — measured, dated, and priced by what conformance really costs —
|
|
@@ -31,7 +40,7 @@ anonymous record of the question's *shape* (see [Demand signal](#demand-signal))
|
|
|
31
40
|
|
|
32
41
|
| Tool | Answers |
|
|
33
42
|
|---|---|
|
|
34
|
-
| `query_registry` | "Which models can serve strict JSON under $1/M?" — capability predicates plus a price bound, ranked by effective cost of conformance. |
|
|
43
|
+
| `query_registry` | "Which models can serve strict JSON under $1/M?" — capability predicates plus a price bound, ranked by effective cost of conformance. `kind: image_gen` / `video_gen` / `tts` / `stt` lists the declared-only generation models instead — unprobed, never ranked, with the unit price ModelRig could source. |
|
|
35
44
|
| `get_leaderboard` | Standings, optionally for one capability. Cheap-but-unreliable ranks below pricier-but-correct, because the ranking is cost per *conformant* output. |
|
|
36
45
|
| `explain_pricing` | List price for one model, the effective cost of conformance beside it, and why they differ. |
|
|
37
46
|
| `get_call_notes` | Per-model call-shaping quirks: parameters it rejects, shapes it needs, defaults that surprise. Plus any measured disagreement with the provider's claims. |
|
|
@@ -65,7 +74,9 @@ on purpose.
|
|
|
65
74
|
| `decide_proposal` | Records a human's approve/reject on a proposal. Needs the `decision` scope. | Execute or apply the swap. |
|
|
66
75
|
| `execute_swap` | Records an approved swap and **returns** the route-YAML diff to apply via a PR. Needs the `decision` scope. | Write any file; commit to your repo. |
|
|
67
76
|
| `record_grade` | Attaches a 0–1 grade (with an optional comment) to one inference or a whole run — the signal the next cycle learns from. Needs the `grade` scope on the HTTP path. | Spend a billed call; guess attribution for an unknown subject. |
|
|
68
|
-
| `
|
|
77
|
+
| `record_outcome` | Posts a delayed business outcome (resolved, booked, approved, CTR) as a `kind: outcome` grade for a conversation id, run, inference or artifact (`POST /v1/outcomes`); `idempotency_key` makes a retry a no-op. Needs the `ingest` scope. | Calibrate a grader on its own — outcome agreement is a receipt. |
|
|
78
|
+
| `query_conversations` | Lists your agent's conversations (turns, cost, latest grade, outcomes, run-limit stops), or one conversation's turns with `run_id`. Metadata only. | Return message content. |
|
|
79
|
+
| `get_task_settings` / `set_task_settings` | Reads / writes a task's governance settings and its **grading guide** (the rubric the task's grader is taught from). `set` needs the `task-settings` scope. The task must exist: a route (registered on route sync), a `runRaw` / `recordCall` step whose call set `tags.step`, or one created with `POST /v1/tasks` (HTTP only — there is no MCP tool to list or create tasks yet; `GET /v1/tasks` lists them). | Change route config (the pass threshold lives in the route, and is refused here). |
|
|
69
80
|
| `get_call_config` | Reads a route's **current live** call-config — its version, mode, the model(s) it serves, the `effective` model + why (pin / YAML default), and any `drift`. Read-only. | Change anything. |
|
|
70
81
|
| `set_call_config` | **Sets what serves a route right now** — pins a model or starts a live A/B — on the human's behalf. A real, versioned control-plane change. | Bypass the eligibility gate or the `route-config` scope; imply it is a draft. |
|
|
71
82
|
| `rollback_call_config` | Restores a prior call-config version (re-appended as a new version — history is never deleted). | Delete history; escape the scope check. |
|
package/docs/quickstart.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# ModelRig quickstart —
|
|
1
|
+
# ModelRig quickstart — See. Grade. Improve.
|
|
2
2
|
|
|
3
3
|
**The question this page answers: how do I get from nothing to my first run on `/runs`, with its steps and artifacts, in about ten minutes?**
|
|
4
4
|
|
|
@@ -11,11 +11,13 @@ and three things happen at once:
|
|
|
11
11
|
artifacts, lineaged and integrity-hashed; see the
|
|
12
12
|
[instrumentation guide](instrumentation.md)), with cost/tokens/tier and a
|
|
13
13
|
grade recorded against your tags.
|
|
14
|
-
- **
|
|
15
|
-
authorized, and you can replay that traffic against cheaper candidates in a
|
|
14
|
+
- **Grade** — you get schema-validated output, served only by a model you
|
|
15
|
+
authorized, you attach grades from signals you already have, and you can replay that traffic against cheaper candidates in a
|
|
16
16
|
bake-off before you change anything.
|
|
17
|
-
- **
|
|
18
|
-
|
|
17
|
+
- **Improve** — a winning candidate is a proposal you review. Never a silent
|
|
18
|
+
swap: automated changes (opt-in) are proven before they apply, and a change
|
|
19
|
+
you promote in ModelRig (console or MCP) is versioned and reversible — or
|
|
20
|
+
merge it as a PR if you keep routes in git.
|
|
19
21
|
|
|
20
22
|
The path is the same whoever does the work: **mint a key → install → confirm the
|
|
21
23
|
org → define a route → wrap one pipeline execution in a run → see it on `/runs`.**
|
|
@@ -102,9 +104,16 @@ import { createRig, loadConfigFromEnv } from "modelrig";
|
|
|
102
104
|
Environment (read once, in ModelRig's config layer only):
|
|
103
105
|
|
|
104
106
|
```bash
|
|
105
|
-
|
|
107
|
+
# Provider keys: only the providers you configure get adapters. Set the ones
|
|
108
|
+
# your routes (or runRaw calls) use; these are the names the SDK reads.
|
|
109
|
+
GEMINI_API_KEY=…
|
|
106
110
|
OPENAI_API_KEY=…
|
|
107
111
|
DEEPSEEK_API_KEY=…
|
|
112
|
+
ANTHROPIC_API_KEY=…
|
|
113
|
+
XAI_API_KEY=… # grok
|
|
114
|
+
ZAI_API_KEY=… # Z.ai / Zhipu
|
|
115
|
+
MODELRIG_DEEPINFRA_API_KEY=…
|
|
116
|
+
MODELRIG_FIREWORKS_API_KEY=…
|
|
108
117
|
|
|
109
118
|
# Where your telemetry goes — pick ONE lane:
|
|
110
119
|
MODELRIG_API_KEY=rig_sk_… # hosted: rows go to ModelRig,
|
|
@@ -119,14 +128,14 @@ MODELRIG_ENVELOPE_BUDGET_USD=25 # default envelope budget
|
|
|
119
128
|
### 2. Confirm the org
|
|
120
129
|
|
|
121
130
|
<!-- BLOCK:CONFIRM_ORG -->
|
|
122
|
-
**Confirm the org before you trust an empty console.** Run `modelrig doctor` from the same environment your app runs in. It asks GET /v1/whoami which organization the key belongs to
|
|
131
|
+
**Confirm the org before you trust an empty console.** Run `modelrig doctor` from the same environment your app runs in, once your app has started with the key. It asks GET /v1/whoami which organization the key belongs to and prints the org's name and, in parentheses, its slug; the name must match the org badge in the console header. If it names a different organization, your data is landing there: switch the console to that organization, or mint a key in the one you meant (https://modelrig.dev/orgs-and-keys.html).
|
|
123
132
|
|
|
124
133
|
```bash
|
|
125
134
|
npx modelrig doctor
|
|
126
|
-
# [modelrig] key rig_sk_…AbCd → org «Your Org» ✓ (ingest https://api.modelrig.ai, …)
|
|
135
|
+
# [modelrig] key rig_sk_…AbCd → org «Your Org» (your-org) ✓ (ingest https://api.modelrig.ai, …)
|
|
127
136
|
|
|
128
|
-
# No CLI in that environment? Ask the API directly:
|
|
129
|
-
curl -H "Authorization: Bearer $MODELRIG_API_KEY" https://api.modelrig.ai/v1/whoami
|
|
137
|
+
# No CLI in that environment? Ask the API directly (same host the SDK uses):
|
|
138
|
+
curl -H "Authorization: Bearer $MODELRIG_API_KEY" "${MODELRIG_INGEST_URL:-https://api.modelrig.ai}/v1/whoami"
|
|
130
139
|
```
|
|
131
140
|
<!-- /BLOCK:CONFIRM_ORG -->
|
|
132
141
|
|
|
@@ -176,6 +185,14 @@ CRITICAL: respond with a single JSON object, no markdown fences.
|
|
|
176
185
|
Variables must be declared in `prompt.variables`; referencing an undeclared
|
|
177
186
|
variable fails at load time, not at run time.
|
|
178
187
|
|
|
188
|
+
The route references two files next to it, and both must exist or the route
|
|
189
|
+
fails to load (`schema file not found` / `prompt.system file not found`).
|
|
190
|
+
`npx modelrig init` writes this starter route's two files,
|
|
191
|
+
`modelrig/routes/schemas/support_summarize.schema.json` and
|
|
192
|
+
`modelrig/routes/prompts/support_summarize.system.md`, without overwriting
|
|
193
|
+
files you already have. Then `npx modelrig validate` checks the bundle with no
|
|
194
|
+
provider key.
|
|
195
|
+
|
|
179
196
|
The `schema` file is a JSON Schema. ModelRig validates output under **JSON
|
|
180
197
|
Schema 2020-12** as the primary dialect and **also accepts draft-07** (a schema
|
|
181
198
|
declaring either `$schema` compiles). Validation runs non-strict with union
|
|
@@ -185,6 +202,23 @@ unless you have a draft-07 schema already; both work.
|
|
|
185
202
|
|
|
186
203
|
### 4. Call it
|
|
187
204
|
|
|
205
|
+
No route yet, because you are observing first or calling providers through a
|
|
206
|
+
`rig.runRaw` seam? You don't need one:
|
|
207
|
+
|
|
208
|
+
<!-- BLOCK:RAW_RIG -->
|
|
209
|
+
**No routes yet? Build the rig raw-only.** Observing a pipeline, or recording calls your code makes itself, needs no route files. Construct the rig with `routesDir: null`: `rig.runRaw`, `rig.runRawStream` and `rig.recordCall` work at once, and `rig.run` / `rig.runBundle` refuse with a teaching error until you add routes. Without it, createRig loads ./modelrig/routes: a directory you configured that is missing throws, and a missing default directory falls back to raw-only with a one-line warning.
|
|
210
|
+
|
|
211
|
+
```ts
|
|
212
|
+
import { createRig, loadConfigFromEnv } from "modelrig";
|
|
213
|
+
|
|
214
|
+
// Raw-only on purpose: no route files needed. rig.runRaw, rig.runRawStream and
|
|
215
|
+
// rig.recordCall work; rig.run needs routes (add them later, drop routesDir: null).
|
|
216
|
+
const rig = createRig({ ...loadConfigFromEnv(), routesDir: null });
|
|
217
|
+
```
|
|
218
|
+
<!-- /BLOCK:RAW_RIG -->
|
|
219
|
+
|
|
220
|
+
With the route above in place:
|
|
221
|
+
|
|
188
222
|
```ts
|
|
189
223
|
const rig = createRig(loadConfigFromEnv());
|
|
190
224
|
|
|
@@ -200,7 +234,7 @@ result.meta.costEstimateUsd; // priced from the pinned LiteLLM snapshot
|
|
|
200
234
|
result.meta.servedTier; // vs meta.requestedTier — downgrades visible
|
|
201
235
|
result.meta.attemptsByClass; // retries consumed, per failure class
|
|
202
236
|
|
|
203
|
-
rig.close();
|
|
237
|
+
await rig.close(); // flushes telemetry; await it once at shutdown (R6)
|
|
204
238
|
```
|
|
205
239
|
|
|
206
240
|
### 5. Wrap it in a run — the standard path
|
|
@@ -240,6 +274,37 @@ await rig.close(); // flushes the exporter — call once at shutdown
|
|
|
240
274
|
|
|
241
275
|
- **Raw lane:** a `rig.runRaw` call inside a run context records a ground-truth
|
|
242
276
|
step too (since 0.5.0), so grounded/cached pipelines fill the same graph.
|
|
277
|
+
- **A call your code makes itself** (a direct provider client, a stream, an
|
|
278
|
+
embedding) is invisible until you record it:
|
|
279
|
+
|
|
280
|
+
<!-- BLOCK:RECORD_CALL -->
|
|
281
|
+
**Record a call your code makes itself.** A provider call your code makes directly (a client ModelRig has no lane for, a stream you read yourself, an embedding, a fallback) is invisible until you report it. Call `rig.recordCall` right after it returns, inside the run, with the tokens the provider reported: the call shows on /inferences as "Reported by your code", joins its run and step, and counts toward cost. It is synchronous and never throws; invalid input warns once and records nothing (`inferenceId: null`). Spread optional fields only when the provider reported them, so the call type-checks under `exactOptionalPropertyTypes`.
|
|
282
|
+
|
|
283
|
+
```ts
|
|
284
|
+
const started = Date.now();
|
|
285
|
+
const resp = await genai.models.generateContent({ model: "gemini-3.1-pro-preview", contents });
|
|
286
|
+
const u = resp.usageMetadata;
|
|
287
|
+
const finishReason = resp.candidates?.[0]?.finishReason;
|
|
288
|
+
|
|
289
|
+
const rec = rig.recordCall({
|
|
290
|
+
provider: "gemini",
|
|
291
|
+
model: "gemini-3.1-pro-preview",
|
|
292
|
+
usage: {
|
|
293
|
+
tokensIn: u?.promptTokenCount ?? 0, // total input, cached included
|
|
294
|
+
tokensOut: (u?.candidatesTokenCount ?? 0) + (u?.thoughtsTokenCount ?? 0),
|
|
295
|
+
tokensCached: u?.cachedContentTokenCount ?? 0,
|
|
296
|
+
// optional fields: spread only when the provider reported them
|
|
297
|
+
...(u?.thoughtsTokenCount !== undefined ? { reasoningTokens: u.thoughtsTokenCount } : {}),
|
|
298
|
+
},
|
|
299
|
+
servedTier: "standard", // the tier that SERVED the call: pass what the provider reports (flex, priority); it is priced at that tier
|
|
300
|
+
latencyMs: Date.now() - started,
|
|
301
|
+
stepKey: "summarize", // the step on /runs (inside run.scope / run.start)
|
|
302
|
+
...(finishReason !== undefined ? { finishReason } : {}),
|
|
303
|
+
});
|
|
304
|
+
if (rec.inferenceId !== null) rig.grade({ kind: "inference", id: rec.inferenceId }, { score: 1, kind: "deterministic" });
|
|
305
|
+
```
|
|
306
|
+
<!-- /BLOCK:RECORD_CALL -->
|
|
307
|
+
|
|
243
308
|
- **Reserved tags:** `run_id` and `step` are stamped by the SDK; the full list of
|
|
244
309
|
reserved keys is in the
|
|
245
310
|
[instrumentation guide](instrumentation.md#reserved-tag-keys-the-one-list).
|
|
@@ -260,7 +325,9 @@ warns if a rig records calls but never starts a run. If the page is empty:
|
|
|
260
325
|
```text
|
|
261
326
|
1. npx modelrig doctor, from the environment your app runs in.
|
|
262
327
|
no export sink configured → this process does not see MODELRIG_API_KEY: set it, redeploy, open a new shell.
|
|
328
|
+
malformed key → the value is truncated, quoted or padded: paste the whole rig_sk_… secret again.
|
|
263
329
|
AUTH FAILED (401 / 403) → the key is mistyped, revoked or not accepted: mint a key, set it, redeploy, open a new shell.
|
|
330
|
+
whoami unreachable → no network path to the ingest host (firewall, proxy, wrong MODELRIG_INGEST_URL): fix the route out, retry.
|
|
264
331
|
2. The org doctor prints is not the org in the badge → wrong org: switch the console, or mint a key in the org you meant.
|
|
265
332
|
3. /inferences has rows but /runs is empty → the calls are not inside run.scope / run.start.
|
|
266
333
|
4. A run is missing a step or a cost → that call is not on a ModelRig lane (see not-captured).
|
|
@@ -268,6 +335,48 @@ warns if a rig records calls but never starts a run. If the page is empty:
|
|
|
268
335
|
```
|
|
269
336
|
<!-- /BLOCK:EMPTY_CONSOLE -->
|
|
270
337
|
|
|
338
|
+
### 7. Grade it, then prove a cheaper model
|
|
339
|
+
|
|
340
|
+
<!-- BLOCK:GRADE_RUN -->
|
|
341
|
+
**Attach a grade to a call or a whole run.** A grade is your judgment: a 0–1 score with an optional comment, from a validator, a downstream accept/reject, a human or a model. Grade one call by its inference id (`result.meta.inferenceId`, or the `inferenceId` rig.recordCall returns). Grade a whole run by its run id, `run.runId` on the handle `run.start` returns: that grade shows on the run page and on /projects. A run grade whose id is the run's `episodeKey` also shows, on the run page only. `run_id` is a reserved tag the SDK stamps, not a variable your code has. A grade whose id matches no call or run attaches to nothing. The write is synchronous and local and never throws into your pipeline.
|
|
342
|
+
|
|
343
|
+
```ts
|
|
344
|
+
const run = rig.artifacts.run.start({ pipeline: "support", episodeKey: ticketId, environment: "production" });
|
|
345
|
+
const result = await rig.run("example.support_summarize", {
|
|
346
|
+
input: { ticket, product, priorContext },
|
|
347
|
+
tags: { subject: customer },
|
|
348
|
+
stepKey: "summarize",
|
|
349
|
+
});
|
|
350
|
+
run.end("succeeded");
|
|
351
|
+
|
|
352
|
+
// one call: the inference id rides on every result
|
|
353
|
+
rig.grade({ kind: "inference", id: result.meta.inferenceId }, { score: 1, kind: "deterministic", grader: "schema-check" });
|
|
354
|
+
// the whole run: its id is run.runId from run.start (shows on the run page and on /projects)
|
|
355
|
+
rig.grade({ kind: "run", id: run.runId }, { score: 0, kind: "human", comment: "missed the refund request" });
|
|
356
|
+
```
|
|
357
|
+
<!-- /BLOCK:GRADE_RUN -->
|
|
358
|
+
|
|
359
|
+
<!-- BLOCK:BAKEOFF -->
|
|
360
|
+
**Prove a cheaper model on your own traffic.** A bake-off replays your own inputs through the variants a route declares and reports the effective cost of conformance for each. `--variants` names entries in the route's `variants:` block (`default` is the route as declared), never model ids, and a variant can only narrow the route's candidates. Set `capture: true` first: replay works on traffic captured after that, not before. With no captured traffic (a run-based pipeline), promote a real /runs output to a golden (the console's make golden, or `promoteToEval`) and use `--from-eval-cases <task>`; its variants come from the route bundle named after the task. A bake-off measures and never switches anything.
|
|
361
|
+
|
|
362
|
+
```bash
|
|
363
|
+
# 1. in modelrig/routes/example.support_summarize.yaml: capture traffic, and declare
|
|
364
|
+
# a cheaper variant (narrowing only: its candidates must be in the route's list)
|
|
365
|
+
capture: true
|
|
366
|
+
variants:
|
|
367
|
+
- name: cheap
|
|
368
|
+
candidates:
|
|
369
|
+
- provider: gemini
|
|
370
|
+
model: gemini-3.1-flash-lite
|
|
371
|
+
|
|
372
|
+
# 2. after traffic accumulates, compare the route as declared (default) with cheap
|
|
373
|
+
npx modelrig bakeoff --route example.support_summarize --variants default,cheap --replay-last 50
|
|
374
|
+
|
|
375
|
+
# no captured route traffic? promote a real /runs output to a golden, then
|
|
376
|
+
npx modelrig bakeoff --from-eval-cases example.support_summarize --variants default,cheap
|
|
377
|
+
```
|
|
378
|
+
<!-- /BLOCK:BAKEOFF -->
|
|
379
|
+
|
|
271
380
|
## Change your route's model live (no redeploy)
|
|
272
381
|
|
|
273
382
|
A route's **call-config** — which model/provider serves it, and its sampling — can be
|
|
@@ -375,7 +484,9 @@ const { bundle: runnable, arm } = resolveCallConfigForRun(bundle, resolved, {
|
|
|
375
484
|
input, // stickyKey (if set) reads its unit from here…
|
|
376
485
|
// unitKey: userId, // …or pass the unit key explicitly (sticky assignment)
|
|
377
486
|
});
|
|
378
|
-
|
|
487
|
+
// arm is string | null and RunOptions.arm is optional: pass it only when one was
|
|
488
|
+
// drawn (a bare `arm` fails to compile under exactOptionalPropertyTypes).
|
|
489
|
+
const result = await rig.runBundle(runnable, { input, tags, ...(arm !== null ? { arm } : {}) });
|
|
379
490
|
// arm is null for a pin / no-override / non-experiment call ⇒ no meta.arm (byte-identical).
|
|
380
491
|
```
|
|
381
492
|
|
|
@@ -419,7 +530,7 @@ key never burns backoff time. Failures that still billed tokens (refusals,
|
|
|
419
530
|
truncations) carry their token usage, so envelopes and telemetry account the
|
|
420
531
|
real spend.
|
|
421
532
|
|
|
422
|
-
Each class — what it means, whether it retries, and how it backs off — is on [Routing & reliability](routing-reliability.md#5-failure-classes); how the whole candidate ladder runs
|
|
533
|
+
Each class — what it means, whether it retries, and how it backs off — is on [Routing & reliability](routing-reliability.md#5-failure-classes); that page also covers how the whole candidate ladder runs: the ordering, the validate → repair → fall-through sequence, and the parts that are not built yet.
|
|
423
534
|
|
|
424
535
|
## Where the telemetry goes
|
|
425
536
|
|
|
@@ -427,7 +538,9 @@ Every attempt (not just every run) writes one row to package-owned SQLite,
|
|
|
427
538
|
tagged with your `tags` — always, with no key. Setting `MODELRIG_API_KEY` turns
|
|
428
539
|
on **api export mode**: a background exporter ships batches to the ingest API
|
|
429
540
|
(`api.modelrig.ai`, override with `MODELRIG_INGEST_URL`), which the console
|
|
430
|
-
reads — fire-and-forget
|
|
541
|
+
reads — fire-and-forget: a transient failure (network, 5xx) is retried, a
|
|
542
|
+
rejected key (401/403) drops the rows and logs `AUTH FAILED`; the inference path
|
|
543
|
+
never blocks on it.
|
|
431
544
|
Inspect live rows in your local SQLite file, or in the console once the key is
|
|
432
545
|
set — never a database URL of your own.
|
|
433
546
|
|
|
@@ -438,7 +551,7 @@ only the web tier silently loses every row a worker or cron produced.
|
|
|
438
551
|
|
|
439
552
|
Turning **Optimization on** for a route (`capture: true`) is the **recommended
|
|
440
553
|
default** — your traffic is what makes the routing smarter and the bill smaller,
|
|
441
|
-
and everything it keeps you can see
|
|
554
|
+
and everything it keeps you can see and export in the console. Keeping the
|
|
442
555
|
prompts, outputs and evidence too is [content custody](content-custody.md), which
|
|
443
556
|
is **on by default** — every new org is created managed, having accepted the
|
|
444
557
|
published terms at signup — and captures into your managed store, scrubbed for the
|
|
@@ -510,4 +623,4 @@ loader's own words, is in [route-bundles.md](./route-bundles.md#when-it-doesnt-w
|
|
|
510
623
|
registry entry shows probed `structured_native`. Check the probed registry,
|
|
511
624
|
not memory.
|
|
512
625
|
|
|
513
|
-
Still stuck?
|
|
626
|
+
Still stuck? See the [Troubleshooting guide](https://modelrig.dev/troubleshooting.html).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "modelrig",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "ModelRig — capability-aware AI gateway: routes-as-code, provider adapters, typed failures, budget envelopes, and local-first telemetry.",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -63,7 +63,9 @@
|
|
|
63
63
|
"templates/catalog-cleansing.json",
|
|
64
64
|
"templates/call-disposition-qa.json",
|
|
65
65
|
"templates/financial-classification.json",
|
|
66
|
-
"templates/medical-classification.json"
|
|
66
|
+
"templates/medical-classification.json",
|
|
67
|
+
"templates/support-conversation.json",
|
|
68
|
+
"templates/creative-approval.json"
|
|
67
69
|
],
|
|
68
70
|
"scripts": {
|
|
69
71
|
"build": "tsc",
|