refactor(ml): remove the dead per-tag centroid subsystem (#1189)
CI / lint (push) Successful in 2s
CI / frontend-build (push) Successful in 17s
CI / backend-lint-and-test (push) Successful in 26s
CI / integration (push) Successful in 3m32s

The v2 pivot replaced per-tag SigLIP centroids with learned heads + CCIP.
Centroids were still recomputed (on every tag merge + a daily beat) but NOTHING
read them — suggestions come from heads+CCIP and apply_allowlist_tags applies
via Camie predictions, not centroids. Pure dead wiring; remove it.

Removed: CentroidService, recompute_centroid/recompute_centroids tasks, the
daily beat, POST /api/ml/recompute-centroids, the recompute-on-merge trigger,
the tag_reference_embedding table + model, the centroid_similarity_threshold +
min_reference_images settings (migration 0066), the CentroidRecomputeCard +
its store action + MaintenancePanel tile, and the centroid slider in
MLThresholdSliders. _keep_as_alias drops its vestigial has-centroid branch (the
allowlist branch already covers "could re-emit"); tag merge no longer clears a
table that no longer exists.

NOT touched (still live, parallel to heads): the Camie tagger, ImagePrediction,
and the allowlist bulk-apply — accepting a suggestion still allowlists + applies
it across the library. The tag-eval "centroid" baseline metric is unrelated
(in-memory) and stays. (image_record.centroid_scores JSON column also remains —
separate legacy field, its own micro-cleanup.)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ttrj5P7upUTueSfoJcxEqa
This commit is contained in:
2026-06-30 11:48:09 -04:00
parent 4daa3f2790
commit 3d77a38a25
19 changed files with 78 additions and 508 deletions
@@ -1,36 +0,0 @@
<template>
<MaintenanceTile
icon="mdi-vector-triangle"
title="Tag centroids"
blurb="Rebuild SigLIP centroids for similarity suggestions."
:open="busy"
>
<p class="text-body-2 mb-3">
Rebuild the per-tag SigLIP centroids that power similarity-based
suggestions. Runs nightly automatically; trigger manually after a
large tagging session.
</p>
<v-btn color="primary" rounded="pill" :loading="busy" @click="run">
<v-icon start>mdi-vector-triangle</v-icon> Recompute centroids
</v-btn>
<span v-if="done" class="ml-3 text-caption">Enqueued.</span>
<QueueStatusBar queue="ml" queue-label="ML" />
</MaintenanceTile>
</template>
<script setup>
import { toast } from '../../utils/toast.js'
import { ref } from 'vue'
import { useMLStore } from '../../stores/ml.js'
import MaintenanceTile from '../common/MaintenanceTile.vue'
import QueueStatusBar from './QueueStatusBar.vue'
const store = useMLStore()
const busy = ref(false)
const done = ref(false)
async function run() {
busy.value = true
try { await store.triggerRecomputeCentroids(); done.value = true }
catch (e) { toast({ text: e.message, type: 'error' }) }
finally { busy.value = false }
}
</script>
@@ -28,8 +28,7 @@
<div class="text-caption fc-muted mt-1">
Tagger predictions below this confidence aren't stored — raising it
keeps the image library lean. Suggestions can't be shown below the
floor; lower-confidence tags you actually want still surface through
the learned centroid path.
floor.
</div>
</v-col>
</v-row>
@@ -84,8 +83,7 @@ const store = useMLStore()
// tagger store floor (nothing below the floor is stored to surface).
const fields = [
{ key: 'suggestion_threshold_character', label: 'Character', floorMin: true },
{ key: 'suggestion_threshold_general', label: 'General', floorMin: true },
{ key: 'centroid_similarity_threshold', label: 'Centroid similarity' }
{ key: 'suggestion_threshold_general', label: 'General', floorMin: true }
]
const local = reactive({})
watch(() => store.settings, (s) => { if (s) Object.assign(local, s) }, { immediate: true })
@@ -1,9 +1,8 @@
<template>
<div class="fc-maint">
<p class="fc-muted text-body-2 mb-5">
One-off backfills, tagging config and storage tools. The ML backfill and
centroid recompute also run nightly; the allowlist auto-applies accepted
tags. Click a tile to open it.
One-off backfills, tagging config and storage tools. The ML backfill runs
nightly; the allowlist auto-applies accepted tags. Click a tile to open it.
</p>
<section class="fc-section">
@@ -11,7 +10,6 @@
<p class="fc-section__hint">Re-run tagging, thumbnails, extraction and DB upkeep.</p>
<div class="fc-tile-grid">
<MLBackfillCard />
<CentroidRecomputeCard />
<ThumbnailBackfillCard />
<ArchiveReextractCard />
<MissingFileRepairCard />
@@ -48,7 +46,6 @@
import { onMounted, onUnmounted } from 'vue'
import MLBackfillCard from './MLBackfillCard.vue'
import CentroidRecomputeCard from './CentroidRecomputeCard.vue'
import ThumbnailBackfillCard from './ThumbnailBackfillCard.vue'
import ArchiveReextractCard from './ArchiveReextractCard.vue'
import MissingFileRepairCard from './MissingFileRepairCard.vue'