Files
zeekay 45338077fd hanzo-research 0.3.0: measure what the org does not already hold
key(run) is the sha256 the cloud derives as a run's key: benchmark,
split, system, version, k, temperature, max_tokens, embedder, reader and
the four digests, each as text and NUL-terminated.  tests/test_measure.py
holds the vectors hanzo-inc/cloud's apps/research TestKeyVector does.
Run keeps the crate's fields; the key is computed, not carried.

Research.measure(identity, fn, force=False) asks for a complete run under
that key and returns the latest to end without calling fn.  A miss, a
partial run or force calls fn, records the run and returns it as read
back.  fn may not change an identity field.

Arena.post_run follows the arena: it answers the latest run held per
benchmark, or that nothing was queued, and spends nothing, so confirm,
endpoint and attempts go.  Admission becomes Measurements.

Claude-Session: https://claude.ai/code/session_01M8RoubcPN71KgJuZ8LdBUL
2026-10-15 14:53:44 -07:00

588 lines
16 KiB
Python

"""Wire types of `/v1/research`: the records hanzo-inc/cloud `apps/research` stores and returns.
Field names, order and JSON are the server's (`record.go`, `research.go`) and the Rust
crate's (`wire.rs`, `lib.rs`) where the crate agrees with the server: `Comparison` carries
`a`, `b` and `config` (the crate reads `differences`, which the server never writes) and
`Stored` carries `ref`. Reads are tolerant as the crate's are: an unknown
key is ignored, a missing one takes its default, and a null list reads as empty. A
pointer the server declares (`k`, `temperature`, `questions`, a measure's `lo`) stays
`None` when absent, never 0: absence is the record declining to say.
"""
from __future__ import annotations
import os
import enum
import json
import math
import types
import base64
import typing
import decimal
import hashlib
import binascii
import datetime
import subprocess
import dataclasses
from typing import Any, Mapping, TypeVar, Iterator
from dataclasses import field, dataclass
__all__ = [
"Split",
"Benchmark",
"Measure",
"Run",
"Study",
"Paper",
"Difference",
"Delta",
"Comparison",
"Census",
"Gap",
"Listing",
"Batch",
"Stored",
"Artifact",
"Record",
"Ack",
"KindTotal",
"Totals",
"Summary",
"completion",
"IDENTITY",
"key",
"load",
"dump",
"token",
"claims",
"claimed",
"left",
"scope",
"now",
]
T = TypeVar("T")
class Wire:
"""A record on the wire: `dump()` is its JSON object, `load(data)` reads one back."""
def dump(self) -> dict[str, Any]:
return {f.name: _out(getattr(self, f.name)) for f in dataclasses.fields(self)} # type: ignore[arg-type]
@classmethod
def load(cls: type[T], data: Mapping[str, Any] | None) -> T:
return load(cls, data)
@dataclass
class Split(Wire):
"""One named division of a benchmark's items, as the benchmark defines it."""
name: str = ""
items: int = 0
definition: str = ""
@dataclass
class Benchmark(Wire):
"""The task: a standardized test, its dataset and terms, its splits, its official metric."""
project: str = ""
id: str = ""
title: str = ""
version: str = ""
dataset: str = ""
license: str = ""
origin: str = ""
splits: list[Split] = field(default_factory=list)
metric: str = ""
metrics: list[str] = field(default_factory=list)
citation: str = ""
notes: str = ""
revision: str = ""
canonical: bool = False
when: str = ""
@dataclass
class Measure(Wire):
"""One reported number: the slice it covers, the quantity, its value and interval."""
category: str = ""
metric: str = ""
value: float = 0.0
lo: float | None = None
hi: float | None = None
n: int | None = None
of: int | None = None
@dataclass
class Run(Wire):
"""One execution: what was measured, by which system, at which commit, over which data."""
project: str = ""
id: str = ""
benchmark: str = ""
split: str = ""
system: str = ""
version: str = ""
baseline: bool = False
study: str = ""
embedder: str = ""
reader: str = ""
k: int | None = None
temperature: float | None = None
max_tokens: int | None = None
prompt: str = ""
prompt_digest: str = ""
dataset_digest: str = ""
store_digest: str = ""
facts_digest: str = ""
commit: str = ""
questions: int | None = None
answered: int | None = None
when: str = ""
ended: str = ""
by: str = ""
completion: str = ""
measures: list[Measure] = field(default_factory=list)
notes: str = ""
revision: str = ""
canonical: bool = False
visibility: str = ""
trainable: bool = False
publishable: bool = False
def put(
self,
category: str,
metric: str,
value: Any,
n: int | None = None,
of: int | None = None,
lo: float | None = None,
hi: float | None = None,
) -> Run:
"""Record a measure when `value` is a finite number; anything else records nothing."""
if isinstance(value, bool) or not isinstance(value, (int, float)) or not math.isfinite(value):
return self
self.measures.append(Measure(category, metric, float(value), lo, hi, n, of))
return self
def measure(self, category: str, metric: str) -> Measure | None:
"""The measure recorded for (category, metric), or None."""
return next((m for m in self.measures if m.category == category and m.metric == metric), None)
def completion(run: Run) -> str:
"""Completion as the server derives it from `questions`, `answered` and `ended`."""
q, a = run.questions, run.answered
if q is None or a is None:
return "unknown"
if a > q:
return "inconsistent"
if a < q:
return "partial"
return "complete" if run.ended.strip() else "unknown"
# What decides a run's number, in the order `key` hashes it. Who ran it, when, at which commit
# and what it found are not here: two executions of one configuration are one measurement.
IDENTITY = (
"benchmark",
"split",
"system",
"version",
"k",
"temperature",
"max_tokens",
"embedder",
"reader",
"prompt_digest",
"dataset_digest",
"store_digest",
"facts_digest",
)
def key(run: Run | Mapping[str, Any]) -> str:
"""A run's measurement identity, the `key` the server derives on read and `?key=` filters on.
The hex SHA-256 of the `IDENTITY` fields in order, each as text followed by one NUL byte.
Absent is the empty string; `k` and `max_tokens` are decimal integers; `temperature` is the
shortest decimal that reads back as the same float, never in exponent form (0, 0.7,
0.0000001). hanzo-inc/cloud `apps/research` TestKeyVector holds the vectors this package's
tests hold.
"""
d = run.dump() if isinstance(run, Wire) else run
h = hashlib.sha256()
for f in IDENTITY:
h.update(_identity(f, d.get(f)).encode())
h.update(b"\0")
return h.hexdigest()
def _identity(f: str, v: Any) -> str:
if v is None:
return ""
if f in ("k", "max_tokens"):
if isinstance(v, bool) or not isinstance(v, int):
raise TypeError(f"{f} must be an int, got {v!r}")
return str(v)
if f == "temperature":
if isinstance(v, bool) or not isinstance(v, (int, float)):
raise TypeError(f"temperature must be a number, got {v!r}")
return format(decimal.Decimal(repr(float(v))).normalize(), "f")
if not isinstance(v, str):
raise TypeError(f"{f} must be a str, got {v!r}")
return v
@dataclass
class Study(Wire):
"""The question a set of runs was run to answer, and the answer it reached."""
project: str = ""
id: str = ""
title: str = ""
question: str = ""
finding: str = ""
revision: str = ""
canonical: bool = False
when: str = ""
@dataclass
class Paper(Wire):
"""Writing that cites runs; the edge points from the paper to the runs only."""
project: str = ""
id: str = ""
title: str = ""
authors: list[str] = field(default_factory=list)
venue: str = ""
doi: str = ""
url: str = ""
status: str = ""
cites: list[str] = field(default_factory=list)
study: str = ""
revision: str = ""
canonical: bool = False
when: str = ""
@dataclass
class Difference(Wire):
"""One configuration field two runs disagree about, both values as text."""
field: str = ""
a: str = ""
b: str = ""
@dataclass
class Delta(Wire):
"""One (category, metric) both runs measured, and the change from the first to the second."""
category: str = ""
metric: str = ""
a: float = 0.0
b: float = 0.0
change: float = 0.0
overlap: bool | None = None
@dataclass
class Comparison(Wire):
"""Two runs side by side; `blocks` are why they may not be compared, read first."""
a: Run | None = None
b: Run | None = None
comparable: bool = False
blocks: list[str] = dataclasses.field(default_factory=list)
config: list[Difference] = dataclasses.field(default_factory=list)
deltas: list[Delta] = dataclasses.field(default_factory=list)
@dataclass
class Census(Wire):
"""How many runs of a listing read complete, partial, inconsistent and unknown."""
complete: int = 0
partial: int = 0
inconsistent: int = 0
unknown: int = 0
@dataclass
class Gap(Wire):
"""A run field, and how many runs of a listing do not state it."""
field: str = ""
runs: int = 0
@dataclass
class Listing(Wire):
"""A listing's rows. A run listing also carries its completion census and its gaps."""
data: list[Any] = dataclasses.field(default_factory=list)
total: int = 0
completion: Census | None = None
gaps: list[Gap] = dataclasses.field(default_factory=list)
def __iter__(self) -> Iterator[Any]:
return iter(self.data)
def __len__(self) -> int:
return len(self.data)
def __getitem__(self, i: int) -> Any:
return self.data[i]
@dataclass
class Batch(Wire):
"""What a record write filed: the project, the versions new to it, the canonical count."""
project: str = ""
recorded: int = 0
canonical: int = 0
@dataclass
class Stored(Wire):
"""An artifact write: the server's hash of the bytes, its address, and whether it was new."""
sha256: str = ""
ref: str = ""
created: bool = False
rolled_up: bool = False
@dataclass
class Artifact(Wire):
"""A diary artifact (a snapshot or a report), content-addressed by the server.
The server reads the first block; the second is the crate's transport metadata,
sent as the crate sends it and ignored by today's server.
"""
sha256: str = ""
content: str = ""
kind: str = ""
ref: str = ""
run_id: str = ""
project: str = ""
visibility: str = ""
retention_class: str = ""
git_sha: str = ""
git_branch: str = ""
git_dirty: bool = False
lib_versions: dict[str, str] = dataclasses.field(default_factory=dict)
ts: int = 0
artifact_id: str = ""
content_sha256: str = ""
media_type: str = ""
canonicalization: str = ""
compression: str = ""
uncompressed_size: int = 0
@dataclass
class Record(Wire):
"""One stored experiment version, as the canonical experiment listing returns it."""
project: str = ""
id: str = ""
revision: str = ""
status: str = ""
canonical: bool = False
visibility: str = ""
trainable: bool = False
publishable: bool = False
kind: str = ""
subject: str = ""
task: str = ""
metric: str = ""
value: float = 0.0
n: int = 0
n_total: int = 0
cost_usd: float = 0.0
meta: Any = None
git_sha: str = ""
git_branch: str = ""
git_dirty: bool = False
lib_versions: dict[str, str] = dataclasses.field(default_factory=dict)
ts: int = 0
@dataclass
class Ack(Wire):
"""An experiment ingest: what this call added and what the org's store now holds."""
project: str = ""
experiments_ingested: int = 0
attempts_ingested: int = 0
canonical_experiments: int = 0
experiments_retained: int = 0
canonical_attempts: int = 0
attempts_retained: int = 0
rolled_up: bool = False
@dataclass
class KindTotal(Wire):
"""One experiment kind's slice of the totals."""
kind: str = ""
experiments: int = 0
cost_usd: float = 0.0
@dataclass
class Totals(Wire):
"""The headline aggregate, canonical and retained side by side, with a per-kind breakdown."""
project: str = ""
projects: int = 0
experiments: int = 0
experiments_retained: int = 0
attempts: int = 0
attempts_retained: int = 0
models: int = 0
benchmarks: int = 0
cost_usd: float = 0.0
by_kind: list[KindTotal] = dataclasses.field(default_factory=list)
@dataclass
class Summary(Wire):
"""One project of the org with its canonical and retained counts."""
project: str = ""
experiments: int = 0
experiments_retained: int = 0
attempts: int = 0
attempts_retained: int = 0
models: int = 0
benchmarks: int = 0
cost_usd: float = 0.0
kinds: list[str] = dataclasses.field(default_factory=list)
# ── (de)serialization ─────────────────────────────────────────────────────────
def dump(record: Any) -> Any:
"""A wire record, a mapping, or a list of either, as plain JSON values."""
return _out(record)
def load(cls: type[T], data: Mapping[str, Any] | None) -> T:
"""Read a dataclass from JSON: unknown keys ignored, missing ones defaulted, null lists empty."""
hints = typing.get_type_hints(cls)
kw = {}
src = data or {}
for f in dataclasses.fields(cls): # type: ignore[arg-type]
if f.name in src:
kw[f.name] = _in(hints[f.name], src[f.name])
return cls(**kw)
def _out(v: Any) -> Any:
if isinstance(v, Wire):
return v.dump()
if dataclasses.is_dataclass(v) and not isinstance(v, type):
return {f.name: _out(getattr(v, f.name)) for f in dataclasses.fields(v)}
if isinstance(v, enum.Enum):
return v.value
if isinstance(v, (list, tuple)):
return [_out(x) for x in v]
if isinstance(v, Mapping):
return {k: _out(x) for k, x in v.items()}
return v
def _in(tp: Any, v: Any) -> Any:
origin = typing.get_origin(tp)
args = typing.get_args(tp)
if origin in (typing.Union, types.UnionType):
if v is None:
return None
inner = [a for a in args if a is not type(None)]
return _in(inner[0], v) if len(inner) == 1 else v
if origin is list:
return [_in(args[0], x) for x in (v or [])] if args else list(v or [])
if origin is dict:
return {k: _in(args[1], x) for k, x in (v or {}).items()} if args else dict(v or {})
if isinstance(tp, type) and dataclasses.is_dataclass(tp):
cls: Any = tp
return load(cls, v) if isinstance(v, Mapping) else cls()
if isinstance(tp, type) and issubclass(tp, enum.Enum):
return tp(v)
if tp is str:
return "" if v is None else v
if tp is bool:
return bool(v)
if tp is float:
return 0.0 if v is None else float(v)
if tp is int:
return 0 if v is None else int(v)
return v
# ── the token, its claims, and time ─────────────────────────────────────────────
def token() -> str:
"""`HANZO_API_KEY`, else what `hanzo auth token` prints; "" when neither gives one."""
t = os.environ.get("HANZO_API_KEY", "").strip()
if t:
return t
try:
out = subprocess.run(["hanzo", "auth", "token"], capture_output=True, text=True, timeout=60)
except (OSError, subprocess.SubprocessError):
return ""
return out.stdout.strip() if out.returncode == 0 else ""
def claims(tok: str) -> dict[str, Any] | None:
"""A JWT's claims, read without verifying it (the server verifies); None for a token that is not a JWT."""
parts = tok.split(".")
if len(parts) != 3:
return None
body = parts[1]
try:
out = json.loads(base64.urlsafe_b64decode(body + "=" * (-len(body) % 4)))
except (ValueError, binascii.Error):
return None
return out if isinstance(out, dict) else None
def claimed(tok: str) -> str | None:
"""The project a JWT's claims name, `default` when none; None for a token that is not a JWT."""
c = claims(tok)
return None if c is None else scope(str(c.get("project") or ""))
def left(tok: str) -> int | None:
"""Seconds until a JWT's `exp`; None for a token that is not a JWT or names no expiry."""
c = claims(tok)
exp = None if c is None else c.get("exp")
if not isinstance(exp, (int, float)) or isinstance(exp, bool):
return None
return int(exp) - int(datetime.datetime.now(datetime.timezone.utc).timestamp())
def scope(project: str) -> str:
"""A project as the server scopes it: empty is the default project."""
return project.strip() or "default"
def now() -> str:
"""Now as RFC 3339 in UTC, to the second."""
return datetime.datetime.now(datetime.timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")