chore: retire the tag-eval harness — it proved the heads system, job done (operator-approved)
The head-vs-centroid eval (#1130) existed to prove the 'frozen embedding + trained head' spine; the operator accepted the tagging system and dropped the harness. Removed per rule 22: TagEvalCard + store, /api/tag_eval blueprint, tag_eval_run ml task, recover-stalled-tag-eval-runs sweep + beat entry, TagEvalRun model + table (migration 0073), and its tests. The eval's data loaders + metric helpers were NOT eval-specific — the nightly heads trainer runs on them — so they moved verbatim to services/ml/training_data.py (heads.py import updated; behavior unchanged). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CDgx8bQS5YrGRK76v8HUnM
This commit is contained in:
@@ -38,7 +38,6 @@ def all_blueprints() -> list[Blueprint]:
|
||||
from .suggestions import suggestions_bp
|
||||
from .system_activity import system_activity_bp
|
||||
from .system_backup import system_backup_bp
|
||||
from .tag_eval import tag_eval_bp
|
||||
from .tags import tags_bp
|
||||
from .thumbnails import thumbnails_bp
|
||||
return [
|
||||
@@ -58,7 +57,6 @@ def all_blueprints() -> list[Blueprint]:
|
||||
import_admin_bp,
|
||||
suggestions_bp,
|
||||
aliases_bp,
|
||||
tag_eval_bp,
|
||||
heads_bp,
|
||||
gpu_bp,
|
||||
ccip_bp,
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
"""Tag-eval API (#1130): trigger + revisit the head-vs-centroid eval.
|
||||
|
||||
The run + full report live in the tag_eval_run row, so the admin card rehydrates
|
||||
from GET (history / detail) on mount — the report survives navigation rather than
|
||||
living in transient frontend state.
|
||||
"""
|
||||
|
||||
from quart import Blueprint, jsonify, request
|
||||
from sqlalchemy import select
|
||||
|
||||
from ..extensions import get_session
|
||||
from ..models import TagEvalRun
|
||||
from ..services.ml.tag_eval import EvalAlreadyRunning, start_tag_eval_run
|
||||
|
||||
tag_eval_bp = Blueprint("tag_eval", __name__, url_prefix="/api/tag-eval")
|
||||
|
||||
|
||||
def _serialize(run: TagEvalRun, *, include_report: bool) -> dict:
|
||||
out = {
|
||||
"id": run.id,
|
||||
"params": run.params,
|
||||
"status": run.status,
|
||||
"started_at": run.started_at.isoformat() if run.started_at else None,
|
||||
"finished_at": run.finished_at.isoformat() if run.finished_at else None,
|
||||
"error": run.error,
|
||||
}
|
||||
if include_report:
|
||||
out["report"] = run.report
|
||||
return out
|
||||
|
||||
|
||||
@tag_eval_bp.route("", methods=["POST"])
|
||||
async def create():
|
||||
body = await request.get_json(silent=True) or {}
|
||||
params = body.get("params") or body or {}
|
||||
async with get_session() as session:
|
||||
try:
|
||||
run_id = await session.run_sync(
|
||||
lambda s: start_tag_eval_run(s, params)
|
||||
)
|
||||
except EvalAlreadyRunning as running:
|
||||
return jsonify({
|
||||
"error": "eval_already_running",
|
||||
"running_id": int(running.args[0]),
|
||||
}), 409
|
||||
await session.commit()
|
||||
return jsonify({"run_id": run_id, "status": "running"}), 202
|
||||
|
||||
|
||||
@tag_eval_bp.route("", methods=["GET"])
|
||||
async def history():
|
||||
try:
|
||||
limit = min(int(request.args.get("limit", "20")), 100)
|
||||
except ValueError:
|
||||
return jsonify({"error": "invalid_limit"}), 400
|
||||
async with get_session() as session:
|
||||
rows = (await session.execute(
|
||||
select(TagEvalRun).order_by(TagEvalRun.id.desc()).limit(limit)
|
||||
)).scalars().all()
|
||||
# List is light — no full report (the detail endpoint carries it).
|
||||
return jsonify({"runs": [_serialize(r, include_report=False) for r in rows]})
|
||||
|
||||
|
||||
@tag_eval_bp.route("/<int:run_id>", methods=["GET"])
|
||||
async def detail(run_id: int):
|
||||
async with get_session() as session:
|
||||
run = await session.get(TagEvalRun, run_id)
|
||||
if run is None:
|
||||
return jsonify({"error": "not_found"}), 404
|
||||
return jsonify(_serialize(run, include_report=True))
|
||||
Reference in New Issue
Block a user