orizu 0.3.5 → 0.3.6
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/README.md +25 -3
- package/dist/help.js +611 -0
- package/dist/index.js +268 -15
- package/dist/skill-installer.js +180 -0
- package/package.json +3 -3
- package/scripts/vendor-orizu-skill.mjs +54 -0
- package/src/help.ts +676 -0
- package/src/index.ts +353 -15
- package/src/skill-installer.ts +260 -0
- package/vendor/orizu-gepa-python/src/orizu_gepa/cli.py +14 -0
- package/vendor/orizu-gepa-python/src/orizu_gepa/optimizer.py +46 -0
- package/vendor/skills/orizu-cli/SKILL.md +185 -0
- package/vendor/skills/orizu-cli/agents/openai.yaml +4 -0
- package/vendor/skills/orizu-cli/references/building-apps.md +1461 -0
- package/vendor/skills/orizu-cli/references/building-judges.md +218 -0
- package/vendor/skills/orizu-cli/references/cli-reference.md +324 -0
- package/vendor/skills/orizu-cli/references/optimization-reports.md +174 -0
- package/vendor/skills/orizu-cli/references/optimization-with-gepa.md +291 -0
- package/vendor/skills/orizu-cli/references/primer.md +245 -0
- package/vendor/skills/orizu-cli/references/prompt-control-plane.md +830 -0
- package/vendor/skills/orizu-cli/scripts/test-app.mjs +492 -0
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
# Evals & Orizu Primer
|
|
2
|
+
|
|
3
|
+
> **Core idea:** You can't improve what you can't measure — but measuring the wrong thing is worse than not measuring at all. This doc walks from raw failure logs to a continuously-running evaluation loop, and shows how Orizu operationalizes each step.
|
|
4
|
+
|
|
5
|
+
The loop has four steps:
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
Upload → Annotate → Judge → Optimize
|
|
9
|
+
▲ │
|
|
10
|
+
└────────── new traces ──────────┘
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
The CLI covers the full operational loop. Human annotation still happens through apps/tasks, while judge/scorer logic and optimization execution run locally and report back through the prompt control plane. Each step depends on the output of the previous; don't skip ahead.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Step 0: Error Analysis (do this before writing any eval)
|
|
18
|
+
|
|
19
|
+
The most common mistake teams make is jumping straight to evals before they understand what's actually failing. Error analysis is the prerequisite.
|
|
20
|
+
|
|
21
|
+
**How to do it:**
|
|
22
|
+
|
|
23
|
+
1. **Collect traces** — Gather a diverse sample of 100+ traces from production or your own real/synthetic usage. Diversity matters more than volume.
|
|
24
|
+
2. **Annotate freely (open coding)** — Review each trace and write brief, unstructured notes about what went wrong. Be specific: *"hallucinated a fact," "misread the user's name," "failed to use the calculator tool."*
|
|
25
|
+
3. **Group & categorize** — Cluster similar notes into named failure modes (tone violation, failed tool call, etc.).
|
|
26
|
+
4. **Prioritize by frequency** — Count how often each category appears.
|
|
27
|
+
|
|
28
|
+
**When to stop:** Keep adding traces until you stop discovering new failure modes (theoretical saturation).
|
|
29
|
+
|
|
30
|
+
**Decision: should you even write a formal eval for this failure?**
|
|
31
|
+
- If you haven't observed it, no — do error analysis first.
|
|
32
|
+
- If the fix is one-shot and obvious, no — just fix it.
|
|
33
|
+
- If fixing it requires repeated iteration (prompt tweaks, retries, structural changes), yes — that's where evals shine.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Step 1: Upload — gather diverse traces
|
|
38
|
+
|
|
39
|
+
### Why
|
|
40
|
+
|
|
41
|
+
- Mix production traces with a **random sample**. Thumbs-down feedback alone is biased toward extreme failures and misses the subtle ones.
|
|
42
|
+
- Aim for **~100+ diverse traces**. Stop adding when you stop discovering new failure modes.
|
|
43
|
+
- **Sampling strategies** (use a mix):
|
|
44
|
+
- Random — surfaces unexpected issues; always include.
|
|
45
|
+
- Clustering — semantic groups reveal failure patterns.
|
|
46
|
+
- Outlier analysis — long latency, many turns, high token counts.
|
|
47
|
+
- Classification — use existing evals or a small model to surface known-bad traces.
|
|
48
|
+
- Explicit feedback — high signal but sparse.
|
|
49
|
+
- **Synthetic data** when real traces are scarce: define structured dimensions (Feature × Persona × Scenario), seed from real logs, generate many candidates, filter for difficulty. Don't ask the model "generate 50 test cases" cold — it produces generic, repetitive output. Increase complexity iteratively.
|
|
50
|
+
- For multi-turn agent failures, use the **N-1 method**: collect minimally-reproduced error traces and use the N-1 turns before the error as test cases.
|
|
51
|
+
|
|
52
|
+
### In Orizu
|
|
53
|
+
|
|
54
|
+
Datasets are the unit of upload. Each row has a canonical `id`; payload is the rest of the JSON object. Supported formats: `csv`, `json`, `jsonl`.
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
# Upload a fresh batch
|
|
58
|
+
orizu datasets upload \
|
|
59
|
+
--project <teamSlug>/<projectSlug> \
|
|
60
|
+
--file <traces.jsonl> \
|
|
61
|
+
--name "Support traces — 2026-W18"
|
|
62
|
+
|
|
63
|
+
# Append later batches
|
|
64
|
+
orizu datasets append --dataset <datasetId> --file <more.jsonl>
|
|
65
|
+
|
|
66
|
+
# Edit specific rows in place (each row in --file must include canonical id)
|
|
67
|
+
orizu datasets edit-rows --dataset <datasetId> --file <edits.jsonl>
|
|
68
|
+
|
|
69
|
+
# Delete rows by canonical id
|
|
70
|
+
orizu datasets delete-rows --dataset <datasetId> --row-ids <id1,id2>
|
|
71
|
+
|
|
72
|
+
# Lock when ready for labeling — locked datasets reject append/edit/delete
|
|
73
|
+
orizu datasets lock --dataset <datasetId> --reason "Freeze for QA round 1"
|
|
74
|
+
|
|
75
|
+
# Snapshot/branch a dataset
|
|
76
|
+
orizu datasets clone --dataset <datasetId> --name "Support traces copy"
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Full surface: `cli-reference.md`.
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Step 2: Annotate — binary labels per failure mode
|
|
84
|
+
|
|
85
|
+
### Why
|
|
86
|
+
|
|
87
|
+
- **Binary, not Likert.** Pass/fail forces a ship/no-ship decision; 3/5 doesn't. Annotators on Likert scales default to middle values and you lose signal.
|
|
88
|
+
- **One question per failure mode.** Don't bundle correctness, tone, and helpfulness into one rating — you won't know which is failing.
|
|
89
|
+
- **Annotate failures you've actually observed.** Hypothetical-failure labels are low-value.
|
|
90
|
+
- **Custom UI per task.** Generic annotation interfaces collapse signal. The labeler should be tailored to your data and the specific binary questions you're asking.
|
|
91
|
+
|
|
92
|
+
A good eval metric has these properties:
|
|
93
|
+
- It measures an error you've observed.
|
|
94
|
+
- It relates to a non-trivial issue you'll iterate on.
|
|
95
|
+
- It's scoped to a specific failure (not "overall quality").
|
|
96
|
+
- It has a binary outcome.
|
|
97
|
+
- It's verifiable — humans or an LLM judge can reliably assess it.
|
|
98
|
+
|
|
99
|
+
### In Orizu
|
|
100
|
+
|
|
101
|
+
Two artifacts: an **app** (custom labeler UI) and a **task** (the labeling round + assignments).
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
# 1. Create the labeler app, bound to the dataset
|
|
105
|
+
orizu apps create \
|
|
106
|
+
--project <teamSlug>/<projectSlug> \
|
|
107
|
+
--name "Support QA Labeler" \
|
|
108
|
+
--dataset <datasetId> \
|
|
109
|
+
--file ./labeler/App.tsx \
|
|
110
|
+
--input-schema ./labeler/input.json \
|
|
111
|
+
--output-schema ./labeler/output.json
|
|
112
|
+
|
|
113
|
+
# 2. Create the task draft
|
|
114
|
+
orizu tasks create \
|
|
115
|
+
--project <teamSlug>/<projectSlug> \
|
|
116
|
+
--dataset <datasetId> \
|
|
117
|
+
--app <appId> \
|
|
118
|
+
--title "Support QA — Round 1" \
|
|
119
|
+
--instructions "Label per rubric v1" \
|
|
120
|
+
--labels-per-item 2
|
|
121
|
+
|
|
122
|
+
# 3. Open the returned task URL and test the draft manually before assigning.
|
|
123
|
+
orizu tasks publish --task <taskId> --assignees <userId1,userId2>
|
|
124
|
+
|
|
125
|
+
# 4. Track progress
|
|
126
|
+
orizu tasks status --task <taskId>
|
|
127
|
+
|
|
128
|
+
# 5. Export labels for downstream judge work
|
|
129
|
+
orizu tasks export --task <taskId> --format jsonl --out ./labels.jsonl
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Authoring the labeler app — contract, design principles, and common patterns: see `building-apps.md`. Includes an offline smoke test (`scripts/test-app.mjs`, runs on plain `node`).
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## Step 3: Judge — turn labels into automated evaluators
|
|
137
|
+
|
|
138
|
+
### Why
|
|
139
|
+
|
|
140
|
+
- **Code assertions first.** If a failure is a rule (keyword present, tool called, format valid), write a code check. Fast, free, deterministic.
|
|
141
|
+
- **LLM-as-a-judge for nuanced criteria only.** Powerful but slow and expensive — reserve for failures code can't catch.
|
|
142
|
+
- **Validate every judge against human labels.** A judge that doesn't agree with humans is a misaligned metric.
|
|
143
|
+
- Track **TPR (True Positive Rate)** and **TNR (True Negative Rate)** separately, not accuracy. Accuracy is misleading on imbalanced data. Target both > 90%.
|
|
144
|
+
- **A 100% pass rate is a smell** — your evals are saturated. Add harder cases.
|
|
145
|
+
- **Three common eval mistakes:**
|
|
146
|
+
1. Skipping the data — using off-the-shelf metrics ("Helpfulness," "Faithfulness") that don't measure your specific failures.
|
|
147
|
+
2. Trusting the LLM judge without validating it against human labels.
|
|
148
|
+
3. Celebrating perfect scores instead of pushing harder cases.
|
|
149
|
+
|
|
150
|
+
There are three **types** of automated evals:
|
|
151
|
+
- **Code-based assertions** — rule-based, deterministic. Use whenever possible.
|
|
152
|
+
- **LLM-as-a-judge** — for subjective/nuanced criteria. Validate before trusting.
|
|
153
|
+
- **Guardrails** — run in the request/response path to block failures before they reach users. Usually code-based or small classifiers, not LLMs.
|
|
154
|
+
|
|
155
|
+
### In Orizu
|
|
156
|
+
|
|
157
|
+
This work is still authored by the agent in code, but Orizu now stores the versioned evaluator artifacts and score results:
|
|
158
|
+
|
|
159
|
+
1. Export labeled data: `orizu tasks export --task <id> --format jsonl --out labels.jsonl`
|
|
160
|
+
2. For each failure mode, choose code assertion or LLM-judge.
|
|
161
|
+
3. Build the judge.
|
|
162
|
+
4. Validate against the labels (train/dev/test split, TPR/TNR).
|
|
163
|
+
5. Push the judge prompt and runner when it is an LLM judge, register a scorer, then submit score runs for prompt versions or optimization candidates.
|
|
164
|
+
|
|
165
|
+
Control-plane commands: `prompt-control-plane.md`. Detailed authoring walkthrough — code assertion patterns, LLM-judge prompt scaffold, train/dev/test split, TPR/TNR computation, saturation checks: `building-judges.md`.
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## Step 4: Optimize — hill-climb against validated judges
|
|
170
|
+
|
|
171
|
+
### Why
|
|
172
|
+
|
|
173
|
+
- Only optimize against judges you've validated. Otherwise you Goodhart your way to a worse system that scores higher.
|
|
174
|
+
- Compare before/after on the **same eval suite** — don't trust vibes.
|
|
175
|
+
- Improvements compound: new traces from the improved system feed back into Upload and reveal the next layer of failures.
|
|
176
|
+
|
|
177
|
+
### In Orizu
|
|
178
|
+
|
|
179
|
+
Done locally, reported to Orizu:
|
|
180
|
+
|
|
181
|
+
1. Package the candidate execution as a runner, or use the customer's existing local app wrapper.
|
|
182
|
+
2. Register validated scorers.
|
|
183
|
+
3. Run the bundled Orizu GEPA-style text optimizer, or a custom optimizer against the scorer set.
|
|
184
|
+
4. Stream optimization events to Orizu, promote accepted candidates, and submit comparable scores.
|
|
185
|
+
5. Diff before/after on the eval suite. Ship if it holds; new traces feed back to step 1.
|
|
186
|
+
|
|
187
|
+
Control-plane commands: `prompt-control-plane.md`. Detailed walkthrough — GEPA mechanics, optional DSPy context for customers already using it, and before/after comparison: `optimization-with-gepa.md`.
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## Deploying Continuously
|
|
192
|
+
|
|
193
|
+
Evals aren't just for development. Deploy them in three modes:
|
|
194
|
+
|
|
195
|
+
| | **CI/CD** | **Online Monitoring** | **Guardrails** |
|
|
196
|
+
|--------------|------------------------|-----------------------------------|--------------------------------------|
|
|
197
|
+
| **Goal** | Prevent regressions | Discover new failures, track perf | Enforce safety, block bad responses |
|
|
198
|
+
| **When** | Pre-merge (PR) | Async, post-response | Synchronous, pre-response |
|
|
199
|
+
| **How** | Unit tests, LLM-judge | LLM-judge, A/B testing | Unit tests, small classifiers |
|
|
200
|
+
| **Data** | Curated test cases | Sampled production traffic | 100% of live traffic |
|
|
201
|
+
| **On fail** | Block merge | Trigger alert | Block, retry, or fallback |
|
|
202
|
+
|
|
203
|
+
**The optimization loop:** error analysis → evals → CI/CD prevents regressions → online monitoring catches new failures → repeat.
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## Finding Failure Hotspots in Multi-Step Agents
|
|
208
|
+
|
|
209
|
+
When an agent has many steps (Plan → Search → Code → Finalize), build a **Transition Failure Matrix** to spot where it breaks down most often:
|
|
210
|
+
|
|
211
|
+
1. List all states.
|
|
212
|
+
2. Build a matrix: rows = "From" state, columns = "To" state.
|
|
213
|
+
3. For each failure, find the last successful transition before the error and add +1 to that cell.
|
|
214
|
+
|
|
215
|
+
Hotspots tell you which transition to fix first. Example: `GenSQL → ExecSQL` count of 12 → your SQL generation is producing invalid queries.
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## Quick Reference: Mental Model
|
|
220
|
+
|
|
221
|
+
```
|
|
222
|
+
Production Traffic
|
|
223
|
+
↓
|
|
224
|
+
Sample Traces ←─────────────────────────────┐
|
|
225
|
+
↓ │
|
|
226
|
+
Error Analysis (annotate → group → prioritize)│
|
|
227
|
+
↓ │
|
|
228
|
+
Worth an eval? (observed? requires iteration?)│
|
|
229
|
+
↓ │
|
|
230
|
+
Annotate (binary, observed, custom UI) │
|
|
231
|
+
↓ │
|
|
232
|
+
Build Judge (code-first, LLM-as-judge if needed)
|
|
233
|
+
↓ │
|
|
234
|
+
Validate Judge (TPR > 90%, TNR > 90%) │
|
|
235
|
+
↓ │
|
|
236
|
+
Optimize (GEPA-style search against scorers) │
|
|
237
|
+
↓ │
|
|
238
|
+
Deploy (CI/CD + Online Monitoring + Guardrails)
|
|
239
|
+
↓ │
|
|
240
|
+
New traces flow in ───────────────────────────┘
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
*Source material draws on Hamel Husain's [Applied AI Evals](https://evals.info).*
|