Spaces:
Sleeping
Sleeping
Download scripts/lib/chat_eval/tuning.py from defenestrate/asa: direct link, hf CLI and curl.
- Browser
- Download file 7.75 kB
-
https://huggingface.co/spaces/defenestrate/asa/resolve/main/scripts/lib/chat_eval/tuning.py
- Command line
-
hf download hf://spaces/defenestrate/asa/scripts/lib/chat_eval/tuning.py
-
curl -L -o tuning.py https://huggingface.co/spaces/defenestrate/asa/resolve/main/scripts/lib/chat_eval/tuning.py
7.75 kB
| """Retrieval-tuning step logic and named constants. | |
| Pure-function module: takes analytics outputs (doc_utilization, score_summary) | |
| and a tuning state dict, returns the next state. Does no I/O. | |
| See docs/superpowers/specs/2026-05-08-retrieval-tuning-loop-design.html. | |
| """ | |
| from __future__ import annotations | |
| import copy | |
| from datetime import datetime, timezone | |
| #: Maximum cumulative penalty per doc. 0.40 = 40% score haircut. Keeps a | |
| #: stuck doc retrievable when nothing else is in the room. | |
| MAX_PENALTY = 0.40 | |
| #: Per-step penalty increment. With once-daily cadence, full saturation | |
| #: takes >= 8 consecutive steps on the same doc. | |
| PENALTY_DELTA = 0.05 | |
| #: A doc is eligible for a penalty increment iff its util_pct (over the | |
| #: window) is below this threshold. Same 0-100 scale as | |
| #: analytics.doc_utilization()'s util_pct field. | |
| UTIL_PENALTY_THRESHOLD = 30.0 | |
| #: Minimum retrievals in the window before a doc is eligible for action. | |
| #: Cuts noise from one-off retrievals. | |
| MIN_RETRIEVALS_FOR_ACTION = 10 | |
| #: Per-dimension regression floor on a 1-5 scale. If any rubric dimension's | |
| #: post-step mean drops by >= this value vs. pre-step, freeze + rollback. | |
| REGRESSION_THRESHOLD = 0.30 | |
| #: Minimum judged turns in the post-step window before regression check | |
| #: is meaningful. Below this, skip the check (and skip proposing a step). | |
| MIN_TURNS_FOR_REGRESSION_CHECK = 20 | |
| #: Tuning state schema version. Bump on incompatible schema change. | |
| TUNING_STATE_VERSION = 1 | |
| #: Penalty value at or above which a doc is excluded from kind-quota fill. | |
| #: Below the floor, penalties only adjust within-kind ordering (already true). | |
| #: 0.30 is six consecutive penalty steps, signalling the tuner is sure. | |
| QUOTA_INELIGIBILITY_FLOOR = 0.30 | |
| def empty_state() -> dict: | |
| """Default tuning state: no penalties, not frozen.""" | |
| return { | |
| "version": TUNING_STATE_VERSION, | |
| "updated_at": None, | |
| "frozen": False, | |
| "frozen_reason": None, | |
| "step_count": 0, | |
| "penalties": {}, | |
| } | |
| def now_utc_iso() -> str: | |
| """ISO-8601 UTC timestamp with second precision: '2026-05-08T18:45:03Z'.""" | |
| return datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ") | |
| def propose_step( | |
| util: dict[str, dict], | |
| *, | |
| current_state: dict, | |
| ) -> dict | None: | |
| """Propose at most one penalty increment for the lowest-util eligible doc. | |
| `util`: output of analytics.doc_utilization() filtered to the working | |
| window. Each value has retrieved_count, used_count, util_pct. | |
| `current_state`: the live retrieval_tuning state (read-only here). | |
| Caller (cli._cmd_tune) is responsible for short-circuiting on | |
| current_state["frozen"] before invoking this function — the | |
| frozen check is not performed here. | |
| Returns a step_action dict matching the audit-log shape, or None when | |
| no doc is eligible (all above threshold, or all already at MAX_PENALTY, | |
| or below MIN_RETRIEVALS_FOR_ACTION). | |
| """ | |
| pens = current_state.get("penalties", {}) | |
| eligible: list[tuple[str, dict]] = [] | |
| for doc_id, info in util.items(): | |
| if info["retrieved_count"] < MIN_RETRIEVALS_FOR_ACTION: | |
| continue | |
| if info["util_pct"] >= UTIL_PENALTY_THRESHOLD: | |
| continue | |
| if pens.get(doc_id, 0.0) >= MAX_PENALTY: | |
| continue | |
| eligible.append((doc_id, info)) | |
| if not eligible: | |
| return None | |
| # Lowest util_pct first; ties broken by highest retrieved_count. | |
| eligible.sort(key=lambda kv: (kv[1]["util_pct"], -kv[1]["retrieved_count"])) | |
| doc_id, info = eligible[0] | |
| before = float(pens.get(doc_id, 0.0)) | |
| after = min(before + PENALTY_DELTA, MAX_PENALTY) | |
| return { | |
| "kind": "penalty_increment", | |
| "doc_id": doc_id, | |
| "delta": round(after - before, 4), | |
| "penalty_before": round(before, 4), | |
| "penalty_after": round(after, 4), | |
| "reason": ( | |
| f"util_pct={info['util_pct']} over {info['retrieved_count']} " | |
| f"retrievals" | |
| ), | |
| } | |
| def check_regression( | |
| scores_before: dict[str, float], | |
| scores_after: dict[str, float], | |
| *, | |
| judged_turns: int, | |
| before_stats: dict[str, dict] | None = None, | |
| after_stats: dict[str, dict] | None = None, | |
| ) -> dict: | |
| """Pure check: did any dimension drop by >= REGRESSION_THRESHOLD? | |
| Returns a dict matching the audit log's `regression_check` shape. | |
| Sets `skipped=True` (and `any_dimension_regressed=False`) when there | |
| aren't enough turns to evaluate. | |
| When `before_stats` and `after_stats` are provided (each shaped as | |
| {dim: {mean, std, n}} per analytics.score_summary_with_stats), the | |
| return value also includes a confidence block with sample sizes and a | |
| Welch's t on the max-drop dimension. Telemetry only — does not gate | |
| the freeze decision. | |
| """ | |
| if judged_turns < MIN_TURNS_FOR_REGRESSION_CHECK: | |
| return { | |
| "any_dimension_regressed": False, | |
| "max_drop_dimension": None, | |
| "max_drop_value": 0.0, | |
| "threshold": REGRESSION_THRESHOLD, | |
| "skipped": True, | |
| } | |
| shared = set(scores_before.keys()) & set(scores_after.keys()) | |
| drops = { | |
| d: scores_before[d] - scores_after[d] | |
| for d in shared | |
| } | |
| if not drops: | |
| return { | |
| "any_dimension_regressed": False, | |
| "max_drop_dimension": None, | |
| "max_drop_value": 0.0, | |
| "threshold": REGRESSION_THRESHOLD, | |
| "skipped": False, | |
| } | |
| max_dim, max_drop = max(drops.items(), key=lambda kv: kv[1]) | |
| out = { | |
| "any_dimension_regressed": max_drop >= REGRESSION_THRESHOLD, | |
| "max_drop_dimension": max_dim, | |
| "max_drop_value": round(max_drop, 4), | |
| "threshold": REGRESSION_THRESHOLD, | |
| "skipped": False, | |
| } | |
| if ( | |
| before_stats and after_stats | |
| and max_dim in before_stats and max_dim in after_stats | |
| ): | |
| b = before_stats[max_dim] | |
| a = after_stats[max_dim] | |
| n_b, n_a = b["n"], a["n"] | |
| s_b, s_a = b["std"], a["std"] | |
| # Welch's t and pooled std (descriptive). Guard against n<2 / std=0. | |
| denom_sq = ( | |
| (s_b * s_b / n_b if n_b else 0.0) | |
| + (s_a * s_a / n_a if n_a else 0.0) | |
| ) | |
| denom = denom_sq ** 0.5 if denom_sq > 0 else 0.0 | |
| t_stat = round(max_drop / denom, 4) if denom > 0 else None | |
| std_pooled = round(((s_b * s_b + s_a * s_a) / 2) ** 0.5, 4) | |
| out["confidence"] = { | |
| "n_before": n_b, | |
| "n_after": n_a, | |
| "max_drop_t_stat": t_stat, | |
| "max_drop_std_pooled": std_pooled, | |
| "interpretation": "informational_only", | |
| } | |
| return out | |
| def apply_step(state: dict, step_action: dict) -> dict: | |
| """Return a new state with the step applied. Does not mutate `state`.""" | |
| new = copy.deepcopy(state) | |
| if step_action["kind"] == "penalty_increment": | |
| new["penalties"][step_action["doc_id"]] = round( | |
| float(step_action["penalty_after"]), 4 | |
| ) | |
| new["step_count"] = int(state.get("step_count", 0)) + 1 | |
| new["updated_at"] = now_utc_iso() | |
| return new | |
| def rollback_step(state: dict, rolled_back_step: dict, *, reason: str) -> dict: | |
| """Restore the prior penalty value and set frozen=True.""" | |
| new = copy.deepcopy(state) | |
| sa = rolled_back_step["step_action"] | |
| doc_id = sa["doc_id"] | |
| before = float(sa["penalty_before"]) | |
| if before > 0.0: | |
| new["penalties"][doc_id] = round(before, 4) | |
| else: | |
| new["penalties"].pop(doc_id, None) | |
| new["frozen"] = True | |
| new["frozen_reason"] = reason | |
| new["updated_at"] = now_utc_iso() | |
| # step_count stays as-is — audit log is monotonic. | |
| return new | |