core/calibration/params.py
Shay 366f7a08c4
Add cognitive eval harness and calibration replay (#30)
* feat: add cognitive eval harness with CLI integration

20 eval cases across 8 categories (definition, comparison, cause,
procedure, recall, correction, verification, unknown). Metrics:
intent accuracy, term capture, surface groundedness, versor closure,
trace determinism. CLI: `core eval cognition [--json] [--report PATH]`.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: add operator calibration replay with deterministic grid search

Bounded parameter tuning via eval replay evidence. Grid search over
salience_top_k and inhibition_threshold with invariant regression
guard (versor closure must not regress). Frozen CalibrationParams,
before/after metrics, no pack or identity mutation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-15 07:41:36 -07:00

52 lines
1.6 KiB
Python

"""Calibration parameter space — bounded, deterministic, immutable."""
from __future__ import annotations
from dataclasses import dataclass
from itertools import product
@dataclass(frozen=True, slots=True)
class CalibrationParams:
salience_top_k: int = 16
inhibition_threshold: float = 0.3
teaching_retrieval_limit: int = 8
def as_dict(self) -> dict[str, int | float]:
return {
"salience_top_k": self.salience_top_k,
"inhibition_threshold": self.inhibition_threshold,
"teaching_retrieval_limit": self.teaching_retrieval_limit,
}
DEFAULT_PARAMS = CalibrationParams()
PARAM_GRID: dict[str, tuple] = {
"salience_top_k": (8, 12, 16),
"inhibition_threshold": (0.2, 0.3, 0.4),
}
def grid_candidates(
grid: dict[str, tuple] | None = None,
base: CalibrationParams = DEFAULT_PARAMS,
) -> tuple[CalibrationParams, ...]:
"""Generate all candidate parameter sets from a grid.
Each candidate varies exactly one axis from the base; the grid is
a deterministic Cartesian product over the provided axes.
"""
g = grid or PARAM_GRID
keys = sorted(g.keys())
values = [g[k] for k in keys]
candidates = []
for combo in product(*values):
overrides = dict(zip(keys, combo))
candidate = CalibrationParams(
salience_top_k=overrides.get("salience_top_k", base.salience_top_k),
inhibition_threshold=overrides.get("inhibition_threshold", base.inhibition_threshold),
teaching_retrieval_limit=base.teaching_retrieval_limit,
)
candidates.append(candidate)
return tuple(candidates)