@root-signals/scorable-cli 0.14.0 → 0.15.1
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 +53 -0
- package/dist/commands/annotation/index.d.ts +3 -0
- package/dist/commands/annotation/index.d.ts.map +1 -0
- package/dist/commands/annotation/index.js +145 -0
- package/dist/commands/calibration-run/index.d.ts +3 -0
- package/dist/commands/calibration-run/index.d.ts.map +1 -0
- package/dist/commands/calibration-run/index.js +83 -0
- package/dist/commands/dataset-item/index.d.ts +3 -0
- package/dist/commands/dataset-item/index.d.ts.map +1 -0
- package/dist/commands/dataset-item/index.js +160 -0
- package/dist/commands/evaluator/calibrate.d.ts +3 -0
- package/dist/commands/evaluator/calibrate.d.ts.map +1 -0
- package/dist/commands/evaluator/calibrate.js +29 -0
- package/dist/commands/evaluator/create.d.ts.map +1 -1
- package/dist/commands/evaluator/create.js +3 -0
- package/dist/commands/evaluator/index.d.ts.map +1 -1
- package/dist/commands/evaluator/index.js +2 -0
- package/dist/commands/evaluator/update.d.ts.map +1 -1
- package/dist/commands/evaluator/update.js +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/lib/filter-yaml.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -336,6 +336,59 @@ scorable evaluator execute-by-name "My Evaluator" --request "What is 2+2?" --res
|
|
|
336
336
|
|
|
337
337
|
Accepts the same options as `execute`, including `--variables`.
|
|
338
338
|
|
|
339
|
+
## Labelling & Calibration
|
|
340
|
+
|
|
341
|
+
Build a labelled dataset, then calibrate a saved evaluator against it to measure how well it agrees with your expected scores.
|
|
342
|
+
|
|
343
|
+
### Dataset items
|
|
344
|
+
|
|
345
|
+
Populate a `test`-type dataset with request/response items.
|
|
346
|
+
|
|
347
|
+
```bash
|
|
348
|
+
scorable dataset-item add <dataset_id> --response "Paris" --request "Capital of France?"
|
|
349
|
+
scorable dataset-item add-bulk <dataset_id> --items '[{"response":"Paris","request":"Capital of France?"}]'
|
|
350
|
+
scorable dataset-item list <dataset_id> # latest-version items (with embedded annotations)
|
|
351
|
+
scorable dataset-item list <dataset_id> --include-archived
|
|
352
|
+
scorable dataset-item get <dataset_id> <item_id>
|
|
353
|
+
scorable dataset-item update <dataset_id> <item_id> --response "Paris, France"
|
|
354
|
+
scorable dataset-item archive <dataset_id> <item_id>
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
### Annotations
|
|
358
|
+
|
|
359
|
+
Label a dataset item (or execution log) with an expected score. Omitting `--score-config-id` uses the global identity "Score" config, so a raw expected score can be set with just `--value`.
|
|
360
|
+
|
|
361
|
+
```bash
|
|
362
|
+
scorable annotation create --dataset-item-id <item_id> --value 0.9
|
|
363
|
+
scorable annotation create --dataset-item-id <item_id> --category "👍" --score-config-id <config_id>
|
|
364
|
+
scorable annotation list --dataset <dataset_id>
|
|
365
|
+
scorable annotation get <annotation_id>
|
|
366
|
+
scorable annotation update <annotation_id> --value 0.8
|
|
367
|
+
scorable annotation delete <annotation_id>
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
### Calibration runs
|
|
371
|
+
|
|
372
|
+
Start a calibration run against a labelled dataset and read its per-example results (human vs. evaluator score, disagreement, and the request/response that was scored).
|
|
373
|
+
|
|
374
|
+
```bash
|
|
375
|
+
scorable evaluator calibrate <evaluator_id> --dataset-id <dataset_id>
|
|
376
|
+
# ...or the equivalent calibration-run command:
|
|
377
|
+
scorable calibration-run create --evaluator-id <evaluator_id> --dataset-id <dataset_id>
|
|
378
|
+
scorable calibration-run get <run_id> # poll for status + metrics
|
|
379
|
+
scorable calibration-run list --evaluator-id <evaluator_id>
|
|
380
|
+
scorable calibration-run items <run_id> # per-example results
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
### Demonstrations
|
|
384
|
+
|
|
385
|
+
Attach a labelled dataset as few-shot demonstrations on an evaluator.
|
|
386
|
+
|
|
387
|
+
```bash
|
|
388
|
+
scorable evaluator create --name "My Evaluator" ... --demonstration-dataset <dataset_id>
|
|
389
|
+
scorable evaluator update <evaluator_id> --demonstration-dataset <dataset_id>
|
|
390
|
+
```
|
|
391
|
+
|
|
339
392
|
## Custom Model Management
|
|
340
393
|
|
|
341
394
|
Bring your own LLM (BYO-LLM) — register a custom or self-hosted model, then reference it from evaluators and judges.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/annotation/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAiKjE"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import ora from "ora";
|
|
3
|
+
import { requireApiKey, getSdkClient } from "../../auth.js";
|
|
4
|
+
import { printSuccess, printError, printJson, handleSdkError } from "../../output.js";
|
|
5
|
+
export function registerAnnotationCommands(program) {
|
|
6
|
+
const annotation = new Command("annotation").description("Annotation (labelling) commands");
|
|
7
|
+
annotation
|
|
8
|
+
.command("create")
|
|
9
|
+
.description("Create an annotation on a dataset item or execution log")
|
|
10
|
+
.option("--dataset-item-id <id>", "Dataset item to annotate (mutually exclusive with --execution-log-id)")
|
|
11
|
+
.option("--execution-log-id <id>", "Execution log to annotate (mutually exclusive with --dataset-item-id)")
|
|
12
|
+
.option("--value <number>", "Score for continuous configs", parseFloat)
|
|
13
|
+
.option("--category <label>", "Label for binary/categorical configs")
|
|
14
|
+
.option("--rationale <text>", "Optional free-text justification")
|
|
15
|
+
.option("--status <status>", "draft or published (default published)")
|
|
16
|
+
.option("--score-config-id <id>", "Score config; defaults to the global identity 'Score' config")
|
|
17
|
+
.action(async (opts) => {
|
|
18
|
+
if (!opts.datasetItemId === !opts.executionLogId) {
|
|
19
|
+
printError("Exactly one of --dataset-item-id or --execution-log-id must be provided.");
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const payload = {};
|
|
23
|
+
if (opts.datasetItemId)
|
|
24
|
+
payload.datasetItemId = opts.datasetItemId;
|
|
25
|
+
if (opts.executionLogId)
|
|
26
|
+
payload.executionLogId = opts.executionLogId;
|
|
27
|
+
if (opts.value !== undefined)
|
|
28
|
+
payload.value = opts.value;
|
|
29
|
+
if (opts.category !== undefined)
|
|
30
|
+
payload.category = opts.category;
|
|
31
|
+
if (opts.rationale !== undefined)
|
|
32
|
+
payload.rationale = opts.rationale;
|
|
33
|
+
if (opts.status !== undefined)
|
|
34
|
+
payload.status = opts.status;
|
|
35
|
+
if (opts.scoreConfigId)
|
|
36
|
+
payload.scoreConfigId = opts.scoreConfigId;
|
|
37
|
+
const spinner = ora("Creating annotation...").start();
|
|
38
|
+
try {
|
|
39
|
+
const client = getSdkClient(await requireApiKey());
|
|
40
|
+
const result = await client.annotations.create(payload);
|
|
41
|
+
spinner.stop();
|
|
42
|
+
printSuccess("Annotation created!");
|
|
43
|
+
printJson(result);
|
|
44
|
+
}
|
|
45
|
+
catch (e) {
|
|
46
|
+
spinner.stop();
|
|
47
|
+
handleSdkError(e);
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
annotation
|
|
51
|
+
.command("list")
|
|
52
|
+
.description("List annotations")
|
|
53
|
+
.option("--dataset <id>", "Filter by the dataset the annotated items belong to")
|
|
54
|
+
.option("--score-config <id>", "Filter by score config id")
|
|
55
|
+
.option("--status <status>", "Filter by draft or published")
|
|
56
|
+
.option("--dataset-item <id>", "Filter by dataset item id")
|
|
57
|
+
.option("--execution-log <id>", "Filter by execution log id")
|
|
58
|
+
.action(async (opts) => {
|
|
59
|
+
const params = {};
|
|
60
|
+
if (opts.dataset)
|
|
61
|
+
params.dataset = opts.dataset;
|
|
62
|
+
if (opts.scoreConfig)
|
|
63
|
+
params.score_config = opts.scoreConfig;
|
|
64
|
+
if (opts.status)
|
|
65
|
+
params.status = opts.status;
|
|
66
|
+
if (opts.datasetItem)
|
|
67
|
+
params.dataset_item = opts.datasetItem;
|
|
68
|
+
if (opts.executionLog)
|
|
69
|
+
params.execution_log = opts.executionLog;
|
|
70
|
+
const spinner = ora("Listing annotations...").start();
|
|
71
|
+
try {
|
|
72
|
+
const client = getSdkClient(await requireApiKey());
|
|
73
|
+
const result = await client.annotations.list(params);
|
|
74
|
+
spinner.stop();
|
|
75
|
+
printJson(result.results);
|
|
76
|
+
}
|
|
77
|
+
catch (e) {
|
|
78
|
+
spinner.stop();
|
|
79
|
+
handleSdkError(e);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
annotation
|
|
83
|
+
.command("get <id>")
|
|
84
|
+
.description("Get an annotation by ID")
|
|
85
|
+
.action(async (id) => {
|
|
86
|
+
const spinner = ora("Fetching annotation...").start();
|
|
87
|
+
try {
|
|
88
|
+
const client = getSdkClient(await requireApiKey());
|
|
89
|
+
const result = await client.annotations.get(id);
|
|
90
|
+
spinner.stop();
|
|
91
|
+
printJson(result);
|
|
92
|
+
}
|
|
93
|
+
catch (e) {
|
|
94
|
+
spinner.stop();
|
|
95
|
+
handleSdkError(e);
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
annotation
|
|
99
|
+
.command("update <id>")
|
|
100
|
+
.description("Update an annotation (target is immutable)")
|
|
101
|
+
.option("--value <number>", "New score for continuous configs", parseFloat)
|
|
102
|
+
.option("--category <label>", "New label for binary/categorical configs")
|
|
103
|
+
.option("--rationale <text>", "New rationale")
|
|
104
|
+
.option("--status <status>", "draft or published")
|
|
105
|
+
.action(async (id, opts) => {
|
|
106
|
+
const payload = {};
|
|
107
|
+
if (opts.value !== undefined)
|
|
108
|
+
payload.value = opts.value;
|
|
109
|
+
if (opts.category !== undefined)
|
|
110
|
+
payload.category = opts.category;
|
|
111
|
+
if (opts.rationale !== undefined)
|
|
112
|
+
payload.rationale = opts.rationale;
|
|
113
|
+
if (opts.status !== undefined)
|
|
114
|
+
payload.status = opts.status;
|
|
115
|
+
const spinner = ora("Updating annotation...").start();
|
|
116
|
+
try {
|
|
117
|
+
const client = getSdkClient(await requireApiKey());
|
|
118
|
+
const result = await client.annotations.update(id, payload);
|
|
119
|
+
spinner.stop();
|
|
120
|
+
printSuccess("Annotation updated!");
|
|
121
|
+
printJson(result);
|
|
122
|
+
}
|
|
123
|
+
catch (e) {
|
|
124
|
+
spinner.stop();
|
|
125
|
+
handleSdkError(e);
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
annotation
|
|
129
|
+
.command("delete <id>")
|
|
130
|
+
.description("Delete an annotation")
|
|
131
|
+
.action(async (id) => {
|
|
132
|
+
const spinner = ora("Deleting annotation...").start();
|
|
133
|
+
try {
|
|
134
|
+
const client = getSdkClient(await requireApiKey());
|
|
135
|
+
await client.annotations.delete(id);
|
|
136
|
+
spinner.stop();
|
|
137
|
+
printSuccess(`Annotation ${id} deleted.`);
|
|
138
|
+
}
|
|
139
|
+
catch (e) {
|
|
140
|
+
spinner.stop();
|
|
141
|
+
handleSdkError(e);
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
program.addCommand(annotation);
|
|
145
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/calibration-run/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,wBAAgB,8BAA8B,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAiFrE"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import ora from "ora";
|
|
3
|
+
import { requireApiKey, getSdkClient } from "../../auth.js";
|
|
4
|
+
import { printSuccess, printJson, handleSdkError } from "../../output.js";
|
|
5
|
+
export function registerCalibrationRunCommands(program) {
|
|
6
|
+
const run = new Command("calibration-run").description("Calibration run commands");
|
|
7
|
+
run
|
|
8
|
+
.command("create")
|
|
9
|
+
.description("Start a calibration run against a labelled dataset")
|
|
10
|
+
.requiredOption("--evaluator-id <id>", "The saved evaluator to calibrate")
|
|
11
|
+
.requiredOption("--dataset-id <id>", "Dataset whose published annotations to calibrate against")
|
|
12
|
+
.option("--score-config-id <id>", "Score config (defaults to the dataset's continuous scores)")
|
|
13
|
+
.action(async (opts) => {
|
|
14
|
+
const payload = {
|
|
15
|
+
evaluatorId: opts.evaluatorId,
|
|
16
|
+
datasetId: opts.datasetId,
|
|
17
|
+
};
|
|
18
|
+
if (opts.scoreConfigId)
|
|
19
|
+
payload.scoreConfigId = opts.scoreConfigId;
|
|
20
|
+
const spinner = ora("Starting calibration run...").start();
|
|
21
|
+
try {
|
|
22
|
+
const client = getSdkClient(await requireApiKey());
|
|
23
|
+
const result = await client.calibrationRuns.create(payload);
|
|
24
|
+
spinner.stop();
|
|
25
|
+
printSuccess(`Calibration run ${result.id} started (status: ${result.status}).`);
|
|
26
|
+
printJson(result);
|
|
27
|
+
}
|
|
28
|
+
catch (e) {
|
|
29
|
+
spinner.stop();
|
|
30
|
+
handleSdkError(e);
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
run
|
|
34
|
+
.command("get <id>")
|
|
35
|
+
.description("Get a calibration run (poll for status and metrics)")
|
|
36
|
+
.action(async (id) => {
|
|
37
|
+
const spinner = ora("Fetching calibration run...").start();
|
|
38
|
+
try {
|
|
39
|
+
const client = getSdkClient(await requireApiKey());
|
|
40
|
+
const result = await client.calibrationRuns.get(id);
|
|
41
|
+
spinner.stop();
|
|
42
|
+
printJson(result);
|
|
43
|
+
}
|
|
44
|
+
catch (e) {
|
|
45
|
+
spinner.stop();
|
|
46
|
+
handleSdkError(e);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
run
|
|
50
|
+
.command("list")
|
|
51
|
+
.description("List calibration runs")
|
|
52
|
+
.option("--evaluator-id <id>", "Filter by evaluator external id")
|
|
53
|
+
.action(async (opts) => {
|
|
54
|
+
const spinner = ora("Listing calibration runs...").start();
|
|
55
|
+
try {
|
|
56
|
+
const client = getSdkClient(await requireApiKey());
|
|
57
|
+
const result = await client.calibrationRuns.list(opts.evaluatorId ? { evaluatorId: opts.evaluatorId } : {});
|
|
58
|
+
spinner.stop();
|
|
59
|
+
printJson(result.results);
|
|
60
|
+
}
|
|
61
|
+
catch (e) {
|
|
62
|
+
spinner.stop();
|
|
63
|
+
handleSdkError(e);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
run
|
|
67
|
+
.command("items <id>")
|
|
68
|
+
.description("List the per-example results of a calibration run")
|
|
69
|
+
.action(async (id) => {
|
|
70
|
+
const spinner = ora("Fetching calibration run items...").start();
|
|
71
|
+
try {
|
|
72
|
+
const client = getSdkClient(await requireApiKey());
|
|
73
|
+
const result = await client.calibrationRuns.listItems(id);
|
|
74
|
+
spinner.stop();
|
|
75
|
+
printJson(result.results);
|
|
76
|
+
}
|
|
77
|
+
catch (e) {
|
|
78
|
+
spinner.stop();
|
|
79
|
+
handleSdkError(e);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
program.addCommand(run);
|
|
83
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/dataset-item/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA4KlE"}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import ora from "ora";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { requireApiKey, getSdkClient } from "../../auth.js";
|
|
5
|
+
import { printSuccess, printError, printJson, handleSdkError } from "../../output.js";
|
|
6
|
+
import { parseJsonArg } from "../../utils.js";
|
|
7
|
+
export function registerDatasetItemCommands(program) {
|
|
8
|
+
const item = new Command("dataset-item").description("Dataset item commands");
|
|
9
|
+
item
|
|
10
|
+
.command("add <datasetId>")
|
|
11
|
+
.description("Add a single item to a dataset")
|
|
12
|
+
.requiredOption("--response <text>", "The response text")
|
|
13
|
+
.option("--request <text>", "The request/prompt text")
|
|
14
|
+
.option("--expected-output <text>", "The expected output")
|
|
15
|
+
.option("--metadata <json>", "Metadata JSON object")
|
|
16
|
+
.option("--change-note <text>", "Change note for this version")
|
|
17
|
+
.action(async (datasetId, opts) => {
|
|
18
|
+
const body = { response: opts.response };
|
|
19
|
+
if (opts.request !== undefined)
|
|
20
|
+
body.request = opts.request;
|
|
21
|
+
if (opts.expectedOutput !== undefined)
|
|
22
|
+
body.expected_output = opts.expectedOutput;
|
|
23
|
+
if (opts.changeNote !== undefined)
|
|
24
|
+
body.change_note = opts.changeNote;
|
|
25
|
+
if (opts.metadata !== undefined) {
|
|
26
|
+
const r = parseJsonArg(opts.metadata, z.record(z.string(), z.unknown()));
|
|
27
|
+
if (!r.ok) {
|
|
28
|
+
printError("Invalid JSON for --metadata. Expected an object.");
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
body.metadata = r.value;
|
|
32
|
+
}
|
|
33
|
+
const spinner = ora("Adding item...").start();
|
|
34
|
+
try {
|
|
35
|
+
const client = getSdkClient(await requireApiKey());
|
|
36
|
+
const result = await client.datasets.addItem(datasetId, body);
|
|
37
|
+
spinner.stop();
|
|
38
|
+
printSuccess("Dataset item added!");
|
|
39
|
+
printJson(result);
|
|
40
|
+
}
|
|
41
|
+
catch (e) {
|
|
42
|
+
spinner.stop();
|
|
43
|
+
handleSdkError(e);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
item
|
|
47
|
+
.command("add-bulk <datasetId>")
|
|
48
|
+
.description("Bulk add items to a dataset (at most 5000)")
|
|
49
|
+
.requiredOption("--items <json>", "JSON array of item objects")
|
|
50
|
+
.action(async (datasetId, opts) => {
|
|
51
|
+
const r = parseJsonArg(opts.items, z.array(z.record(z.string(), z.unknown())));
|
|
52
|
+
if (!r.ok) {
|
|
53
|
+
printError("Invalid JSON for --items. Expected an array of item objects.");
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const spinner = ora("Bulk adding items...").start();
|
|
57
|
+
try {
|
|
58
|
+
const client = getSdkClient(await requireApiKey());
|
|
59
|
+
const result = await client.datasets.addItems(datasetId, r.value);
|
|
60
|
+
spinner.stop();
|
|
61
|
+
printSuccess(`Added ${result.length} dataset items.`);
|
|
62
|
+
printJson(result);
|
|
63
|
+
}
|
|
64
|
+
catch (e) {
|
|
65
|
+
spinner.stop();
|
|
66
|
+
handleSdkError(e);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
item
|
|
70
|
+
.command("list <datasetId>")
|
|
71
|
+
.description("List the latest-version items of a dataset (with embedded annotations)")
|
|
72
|
+
.option("--include-archived", "Include archived items", false)
|
|
73
|
+
.action(async (datasetId, opts) => {
|
|
74
|
+
const spinner = ora("Listing items...").start();
|
|
75
|
+
try {
|
|
76
|
+
const client = getSdkClient(await requireApiKey());
|
|
77
|
+
const result = await client.datasets.listItems(datasetId, {
|
|
78
|
+
includeArchived: opts.includeArchived ?? false,
|
|
79
|
+
});
|
|
80
|
+
spinner.stop();
|
|
81
|
+
printJson(result.results);
|
|
82
|
+
}
|
|
83
|
+
catch (e) {
|
|
84
|
+
spinner.stop();
|
|
85
|
+
handleSdkError(e);
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
item
|
|
89
|
+
.command("get <datasetId> <itemId>")
|
|
90
|
+
.description("Get a single dataset item")
|
|
91
|
+
.action(async (datasetId, itemId) => {
|
|
92
|
+
const spinner = ora("Fetching item...").start();
|
|
93
|
+
try {
|
|
94
|
+
const client = getSdkClient(await requireApiKey());
|
|
95
|
+
const result = await client.datasets.getItem(datasetId, itemId);
|
|
96
|
+
spinner.stop();
|
|
97
|
+
printJson(result);
|
|
98
|
+
}
|
|
99
|
+
catch (e) {
|
|
100
|
+
spinner.stop();
|
|
101
|
+
handleSdkError(e);
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
item
|
|
105
|
+
.command("update <datasetId> <itemId>")
|
|
106
|
+
.description("Edit a dataset item (creates a new version)")
|
|
107
|
+
.option("--response <text>", "The response text")
|
|
108
|
+
.option("--request <text>", "The request/prompt text")
|
|
109
|
+
.option("--expected-output <text>", "The expected output")
|
|
110
|
+
.option("--metadata <json>", "Metadata JSON object")
|
|
111
|
+
.option("--change-note <text>", "Change note for this version")
|
|
112
|
+
.action(async (datasetId, itemId, opts) => {
|
|
113
|
+
const body = {};
|
|
114
|
+
if (opts.response !== undefined)
|
|
115
|
+
body.response = opts.response;
|
|
116
|
+
if (opts.request !== undefined)
|
|
117
|
+
body.request = opts.request;
|
|
118
|
+
if (opts.expectedOutput !== undefined)
|
|
119
|
+
body.expected_output = opts.expectedOutput;
|
|
120
|
+
if (opts.changeNote !== undefined)
|
|
121
|
+
body.change_note = opts.changeNote;
|
|
122
|
+
if (opts.metadata !== undefined) {
|
|
123
|
+
const r = parseJsonArg(opts.metadata, z.record(z.string(), z.unknown()));
|
|
124
|
+
if (!r.ok) {
|
|
125
|
+
printError("Invalid JSON for --metadata. Expected an object.");
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
body.metadata = r.value;
|
|
129
|
+
}
|
|
130
|
+
const spinner = ora("Updating item...").start();
|
|
131
|
+
try {
|
|
132
|
+
const client = getSdkClient(await requireApiKey());
|
|
133
|
+
const result = await client.datasets.updateItem(datasetId, itemId, body);
|
|
134
|
+
spinner.stop();
|
|
135
|
+
printSuccess("Dataset item updated!");
|
|
136
|
+
printJson(result);
|
|
137
|
+
}
|
|
138
|
+
catch (e) {
|
|
139
|
+
spinner.stop();
|
|
140
|
+
handleSdkError(e);
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
item
|
|
144
|
+
.command("archive <datasetId> <itemId>")
|
|
145
|
+
.description("Archive (soft-delete) a dataset item")
|
|
146
|
+
.action(async (datasetId, itemId) => {
|
|
147
|
+
const spinner = ora("Archiving item...").start();
|
|
148
|
+
try {
|
|
149
|
+
const client = getSdkClient(await requireApiKey());
|
|
150
|
+
await client.datasets.archiveItem(datasetId, itemId);
|
|
151
|
+
spinner.stop();
|
|
152
|
+
printSuccess(`Dataset item ${itemId} archived.`);
|
|
153
|
+
}
|
|
154
|
+
catch (e) {
|
|
155
|
+
spinner.stop();
|
|
156
|
+
handleSdkError(e);
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
program.addCommand(item);
|
|
160
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"calibrate.d.ts","sourceRoot":"","sources":["../../../src/commands/evaluator/calibrate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI,CA6BjE"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import ora from "ora";
|
|
2
|
+
import { requireApiKey, getSdkClient } from "../../auth.js";
|
|
3
|
+
import { printSuccess, printJson, handleSdkError } from "../../output.js";
|
|
4
|
+
export function registerCalibrateCommand(evaluator) {
|
|
5
|
+
evaluator
|
|
6
|
+
.command("calibrate <evaluatorId>")
|
|
7
|
+
.description("Start a calibration run for a saved evaluator against a labelled dataset")
|
|
8
|
+
.requiredOption("--dataset-id <id>", "Dataset whose published annotations to calibrate against")
|
|
9
|
+
.option("--score-config-id <id>", "Score config to calibrate against (defaults to the dataset's continuous scores)")
|
|
10
|
+
.action(async (evaluatorId, opts) => {
|
|
11
|
+
const apiKey = await requireApiKey();
|
|
12
|
+
const spinner = ora("Starting calibration run...").start();
|
|
13
|
+
try {
|
|
14
|
+
const client = getSdkClient(apiKey);
|
|
15
|
+
const run = await client.evaluators.calibrateRun(evaluatorId, {
|
|
16
|
+
datasetId: opts.datasetId,
|
|
17
|
+
...(opts.scoreConfigId !== undefined ? { scoreConfigId: opts.scoreConfigId } : {}),
|
|
18
|
+
});
|
|
19
|
+
spinner.stop();
|
|
20
|
+
printSuccess(`Calibration run ${run.id} started (status: ${run.status}). ` +
|
|
21
|
+
`Poll 'scorable calibration-run get ${run.id}' for metrics.`);
|
|
22
|
+
printJson(run);
|
|
23
|
+
}
|
|
24
|
+
catch (e) {
|
|
25
|
+
spinner.stop();
|
|
26
|
+
handleSdkError(e);
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../../src/commands/evaluator/create.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AASpC,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../../src/commands/evaluator/create.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AASpC,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI,CA4F9D"}
|
|
@@ -15,6 +15,7 @@ export function registerCreateCommand(evaluator) {
|
|
|
15
15
|
.option("--models <json>", "JSON array of model names, in priority order. E.g., '[\"gpt-5-mini\"]'")
|
|
16
16
|
.option("--overwrite", "Overwrite if evaluator with same name exists")
|
|
17
17
|
.option("--objective-version-id <id>", "Objective version ID")
|
|
18
|
+
.option("--demonstration-dataset <id>", "Dataset of labelled examples resolved into few-shot demonstrations at evaluation time.")
|
|
18
19
|
.option("--project-id <uuid>", PROJECT_ID_FLAG_DESC)
|
|
19
20
|
.action(async (opts) => {
|
|
20
21
|
if (!opts.intent && !opts.objectiveId) {
|
|
@@ -39,6 +40,8 @@ export function registerCreateCommand(evaluator) {
|
|
|
39
40
|
payload.overwrite = opts.overwrite;
|
|
40
41
|
if (opts.objectiveVersionId)
|
|
41
42
|
payload.objective_version_id = opts.objectiveVersionId;
|
|
43
|
+
if (opts.demonstrationDataset)
|
|
44
|
+
payload.demonstration_dataset_id = opts.demonstrationDataset;
|
|
42
45
|
if (opts.models) {
|
|
43
46
|
const r = parseJsonArg(opts.models, z.array(z.string()));
|
|
44
47
|
if (!r.ok) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/evaluator/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/evaluator/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAapC,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAgBhE"}
|
|
@@ -9,6 +9,7 @@ import { registerExecuteByNameCommand } from "./execute-by-name.js";
|
|
|
9
9
|
import { registerDuplicateCommand } from "./duplicate.js";
|
|
10
10
|
import { registerExportYamlCommand } from "./export-yaml.js";
|
|
11
11
|
import { registerImportYamlCommand } from "./import-yaml.js";
|
|
12
|
+
import { registerCalibrateCommand } from "./calibrate.js";
|
|
12
13
|
export function registerEvaluatorCommands(program) {
|
|
13
14
|
const evaluator = new Command("evaluator").description("Evaluator management commands");
|
|
14
15
|
registerListCommand(evaluator);
|
|
@@ -21,5 +22,6 @@ export function registerEvaluatorCommands(program) {
|
|
|
21
22
|
registerDuplicateCommand(evaluator);
|
|
22
23
|
registerExportYamlCommand(evaluator);
|
|
23
24
|
registerImportYamlCommand(evaluator);
|
|
25
|
+
registerCalibrateCommand(evaluator);
|
|
24
26
|
program.addCommand(evaluator);
|
|
25
27
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../../src/commands/evaluator/update.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AASpC,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../../src/commands/evaluator/update.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AASpC,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI,CAyE9D"}
|
|
@@ -13,6 +13,7 @@ export function registerUpdateCommand(evaluator) {
|
|
|
13
13
|
.option("--models <json>", "JSON array of model names. E.g., '[\"gpt-5.5\"]'")
|
|
14
14
|
.option("--objective-id <id>", "The new objective ID")
|
|
15
15
|
.option("--objective-version-id <id>", "The new objective version ID")
|
|
16
|
+
.option("--demonstration-dataset <id>", "Dataset of labelled examples resolved into few-shot demonstrations at evaluation time.")
|
|
16
17
|
.option("--project-id <uuid>", "Move the evaluator to this project (within the same organization). " + PROJECT_ID_FLAG_DESC)
|
|
17
18
|
.action(async (evaluatorId, opts) => {
|
|
18
19
|
const apiKey = await requireApiKey();
|
|
@@ -25,6 +26,8 @@ export function registerUpdateCommand(evaluator) {
|
|
|
25
26
|
payload.objective_id = opts.objectiveId;
|
|
26
27
|
if (opts.objectiveVersionId !== undefined)
|
|
27
28
|
payload.objective_version_id = opts.objectiveVersionId;
|
|
29
|
+
if (opts.demonstrationDataset !== undefined)
|
|
30
|
+
payload.demonstration_dataset_id = opts.demonstrationDataset;
|
|
28
31
|
if (opts.models !== undefined) {
|
|
29
32
|
const r = parseJsonArg(opts.models, z.array(z.string()));
|
|
30
33
|
if (!r.ok) {
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAIA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAIA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAwDpC,wBAAgB,SAAS,IAAI,OAAO,CAmCnC"}
|
package/dist/index.js
CHANGED
|
@@ -15,6 +15,9 @@ import { registerOtelFilterCommands } from "./commands/otel-filter/index.js";
|
|
|
15
15
|
import { registerOtelTraceCommands } from "./commands/otel-trace/index.js";
|
|
16
16
|
import { registerModelCommands } from "./commands/model/index.js";
|
|
17
17
|
import { registerProjectCommands } from "./commands/project/index.js";
|
|
18
|
+
import { registerAnnotationCommands } from "./commands/annotation/index.js";
|
|
19
|
+
import { registerCalibrationRunCommands } from "./commands/calibration-run/index.js";
|
|
20
|
+
import { registerDatasetItemCommands } from "./commands/dataset-item/index.js";
|
|
18
21
|
const { version } = createRequire(import.meta.url)("../package.json");
|
|
19
22
|
function buildBanner(ver) {
|
|
20
23
|
const logo = chalk.hex("#4D9FFF");
|
|
@@ -78,6 +81,9 @@ export function createCli() {
|
|
|
78
81
|
registerOtelTraceCommands(program);
|
|
79
82
|
registerModelCommands(program);
|
|
80
83
|
registerProjectCommands(program);
|
|
84
|
+
registerAnnotationCommands(program);
|
|
85
|
+
registerCalibrationRunCommands(program);
|
|
86
|
+
registerDatasetItemCommands(program);
|
|
81
87
|
return program;
|
|
82
88
|
}
|
|
83
89
|
if (realpathSync(fileURLToPath(import.meta.url)) === realpathSync(process.argv[1])) {
|
|
@@ -33,8 +33,8 @@ export declare const FilterYamlSchema: z.ZodObject<{
|
|
|
33
33
|
}, z.core.$strict>>>;
|
|
34
34
|
}, z.core.$strict>>;
|
|
35
35
|
role: z.ZodEnum<{
|
|
36
|
-
user: "user";
|
|
37
36
|
assistant: "assistant";
|
|
37
|
+
user: "user";
|
|
38
38
|
}>;
|
|
39
39
|
locator: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
40
40
|
kind: z.ZodLiteral<"span_attr">;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,kBAAkB,EAAE,KAAK,CAAC;QACxB,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;QACrB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;KAC9B,CAAC,CAAC;IACH,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,UAAU,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACjD;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,EAAE,eAAe,EAAE,CAAC;IAC9B,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,QAAS,SAAQ,KAAK;aAEf,QAAQ,EAAE,MAAM;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,kBAAkB,EAAE,KAAK,CAAC;QACxB,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;QACrB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;KAC9B,CAAC,CAAC;IACH,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,UAAU,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACjD;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,EAAE,eAAe,EAAE,CAAC;IAC9B,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,QAAS,SAAQ,KAAK;aAEf,QAAQ,EAAE,MAAM;IADlC,YACkB,QAAQ,EAAE,MAAM,EAChC,OAAO,EAAE,MAAM,EAIhB;CACF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@root-signals/scorable-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.1",
|
|
4
4
|
"description": "CLI for Scorable",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Scorable",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"@inquirer/prompts": "^8.3.2",
|
|
35
|
-
"@root-signals/scorable": "^0.
|
|
35
|
+
"@root-signals/scorable": "^0.12.1",
|
|
36
36
|
"chalk": "^5.6.2",
|
|
37
37
|
"cli-table3": "^0.6.5",
|
|
38
38
|
"commander": "^15.0.0",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"@types/node": "^25.5.0",
|
|
46
46
|
"oxfmt": "^0.53.0",
|
|
47
47
|
"oxlint": "^1.56.0",
|
|
48
|
-
"typescript": "^
|
|
48
|
+
"typescript": "^7.0.2",
|
|
49
49
|
"vitest": "^4.1.5"
|
|
50
50
|
},
|
|
51
51
|
"engines": {
|