Skip to content

Commit 4bbe47b

Browse files
varunursekarclaude
andcommitted
harbor: score-baseline producer for pinnable baseline numbers (feedback #1)
Add an admin-only way to generate the number to pin: CanonicalVerifier .measure_baseline(replicates) admin-scores the fixed seed N times on the selection partition and each target and returns per-key mean/stddev. Exposed as POST /score/baseline and 'vero harbor score-baseline --replicates N'. Reuses the existing admin scoring machinery. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 4d98f4b commit 4bbe47b

4 files changed

Lines changed: 112 additions & 0 deletions

File tree

vero/src/vero/harbor/app.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ class SubmitRequest(BaseModel):
4343
version: str | None = None
4444

4545

46+
class ScoreBaselineRequest(BaseModel):
47+
model_config = ConfigDict(extra="forbid")
48+
49+
replicates: int = 1
50+
51+
4652
def _error(status_code: int, message: str):
4753
async def handler(_request, error):
4854
return JSONResponse(
@@ -147,6 +153,14 @@ async def finalize(authorization: Annotated[str | None, Header()] = None):
147153
require_admin(authorization)
148154
return await verifier.finalize()
149155

156+
@app.post("/score/baseline")
157+
async def score_baseline(
158+
body: ScoreBaselineRequest,
159+
authorization: Annotated[str | None, Header()] = None,
160+
):
161+
require_admin(authorization)
162+
return await verifier.measure_baseline(replicates=body.replicates)
163+
150164
@app.get("/evaluations")
151165
async def evaluations(
152166
authorization: Annotated[str | None, Header()] = None,

vero/src/vero/harbor/cli.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,25 @@ def status_command():
625625
click.echo(json.dumps(_request("GET", "/status"), indent=2))
626626

627627

628+
@harbor.command("score-baseline")
629+
@click.option(
630+
"--token-file",
631+
required=True,
632+
type=click.Path(path_type=Path, exists=True, dir_okay=False),
633+
)
634+
@click.option("--replicates", default=1, show_default=True, type=click.IntRange(min=1))
635+
def score_baseline_command(token_file, replicates):
636+
"""Admin-score the fixed seed N times to produce a pinnable baseline number."""
637+
token = read_admin_token(token_file)
638+
result = _request(
639+
"POST",
640+
"/score/baseline",
641+
payload={"replicates": replicates},
642+
headers={"Authorization": f"Bearer {token}"},
643+
)
644+
click.echo(json.dumps(result, indent=2))
645+
646+
628647
@harbor.command("finalize")
629648
@click.option(
630649
"--token-file",

vero/src/vero/harbor/verifier.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,56 @@ async def _score_target(
427427
)
428428
return reward, record.id, None
429429

430+
async def measure_baseline(self, *, replicates: int = 1) -> dict[str, JsonValue]:
431+
"""Admin-score the fixed seed to produce pinnable baseline numbers.
432+
433+
Runs `replicates` trusted evaluations of the baseline on the selection
434+
partition and each target and returns per-key mean/stddev, so a stable
435+
value can be pinned (baseline_selection_score / target baseline_reward)
436+
instead of re-scoring the seed every run."""
437+
if replicates < 1:
438+
raise ValueError("replicates must be >= 1")
439+
baseline = self.selection.baseline_candidate
440+
if baseline is None:
441+
raise NoCandidateError("no baseline candidate to score")
442+
443+
def _aggregate(values: list[float | None]) -> dict[str, JsonValue]:
444+
clean = [value for value in values if value is not None]
445+
return {
446+
"values": values,
447+
"n": len(clean),
448+
"mean": statistics.fmean(clean) if clean else None,
449+
"stddev": statistics.pstdev(clean) if len(clean) > 1 else 0.0,
450+
}
451+
452+
result: dict[str, JsonValue] = {
453+
"candidate_version": baseline.version,
454+
"replicates": replicates,
455+
}
456+
if (
457+
self.selection.backend_id is not None
458+
and self.selection.evaluation_set is not None
459+
and self.selection.objective is not None
460+
):
461+
selection_values: list[float | None] = []
462+
for _ in range(replicates):
463+
record, _ = await self._rescore_candidate(baseline)
464+
selection_values.append(
465+
record.objective.value
466+
if record is not None and record.objective is not None
467+
else None
468+
)
469+
result["selection"] = _aggregate(selection_values)
470+
targets: dict[str, JsonValue] = {}
471+
for target in self.targets:
472+
target_values: list[float | None] = []
473+
for _ in range(replicates):
474+
reward, _, error = await self._score_target(baseline, target)
475+
target_values.append(None if error is not None else reward)
476+
targets[target.reward_key] = _aggregate(target_values)
477+
result["targets"] = targets
478+
return result
479+
430480
async def _finalize(self) -> VerificationResult:
431481
try:
432482
candidate = await self._select_candidate()

vero/tests/test_v05_harbor_verifier.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,3 +561,32 @@ async def test_verifier_floor_fails_safe_when_seed_unmeasurable(tmp_path):
561561

562562
assert result.shipped is False
563563
assert "baseline floor" in result.errors.get("selection", "")
564+
565+
566+
@pytest.mark.asyncio
567+
async def test_verifier_score_baseline_produces_replicated_means(tmp_path):
568+
baseline = _candidate("baseline")
569+
engine = FakeEngine(
570+
{
571+
("baseline", "selection"): [0.5, 0.6],
572+
("baseline", "test"): [0.4, 0.5],
573+
}
574+
)
575+
576+
out = await _verifier(tmp_path, engine, baseline=baseline).measure_baseline(
577+
replicates=2
578+
)
579+
580+
assert out["candidate_version"] == "baseline"
581+
assert out["replicates"] == 2
582+
assert out["selection"]["n"] == 2
583+
assert out["selection"]["mean"] == 0.55
584+
assert out["targets"]["reward"]["n"] == 2
585+
assert out["targets"]["reward"]["mean"] == 0.45
586+
# 2 selection re-scores + 2 target scores, all admin.
587+
assert engine.calls == [
588+
("baseline", "selection"),
589+
("baseline", "selection"),
590+
("baseline", "test"),
591+
("baseline", "test"),
592+
]

0 commit comments

Comments
 (0)