625336b6b4
Live data showed the v1 flat 0.75 cosine over-fired — ~64% of matched images got
3-10 character guesses dominated by the most-referenced characters (a 27-ref
character clears a low bar on many images). A sweep showed 0.85 collapses the
noise (noisy multi-matches 47→3) while keeping the confident single-character
matches.
- ml_settings.ccip_match_threshold (migration 0063, default 0.85); match_image
reads it (override still accepted). DEFAULT_SIM_THRESHOLD fallback 0.75→0.85.
- Exposed in GET/PATCH /api/ml/settings (validated 0.5–0.999).
- Slider in the GPU agent card ("Character-match strictness") — tune live, no
redeploy, same observe-and-tune loop as auto-apply.
Test: a ~0.9-cosine figure matches at 0.85, dropped at 0.95.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ttrj5P7upUTueSfoJcxEqa
34 lines
917 B
Python
34 lines
917 B
Python
"""ml_settings.ccip_match_threshold — tunable CCIP character-match cut (#114)
|
|
|
|
The v1 matcher used a flat 0.75 cosine; live data showed that over-fires (a
|
|
high-reference character matched a scatter of images). 0.85 keeps the confident
|
|
single-character matches and drops the noise. Tunable from the GPU agent card.
|
|
|
|
Revision ID: 0063
|
|
Revises: 0062
|
|
Create Date: 2026-06-29
|
|
"""
|
|
from typing import Sequence, Union
|
|
|
|
import sqlalchemy as sa
|
|
from alembic import op
|
|
|
|
revision: str = "0063"
|
|
down_revision: Union[str, None] = "0062"
|
|
branch_labels: Union[str, Sequence[str], None] = None
|
|
depends_on: Union[str, Sequence[str], None] = None
|
|
|
|
|
|
def upgrade() -> None:
|
|
op.add_column(
|
|
"ml_settings",
|
|
sa.Column(
|
|
"ccip_match_threshold", sa.Float(), nullable=False,
|
|
server_default="0.85",
|
|
),
|
|
)
|
|
|
|
|
|
def downgrade() -> None:
|
|
op.drop_column("ml_settings", "ccip_match_threshold")
|