← back to Animals

migrations/011_vision_audit.sql

49 lines

-- Phase 3 of the gallery quality cleanup: vision-based per-image audit
-- using local Ollama (llava). Phase 1 = regex title scrub, Phase 2 = multi-
-- source ingest + subcategory crawler. This migration adds the columns the
-- vision auditor writes back to.
--
-- Verdict vocabulary (matches src/audit/vision_audit.js prompt):
--   real_photo     -- actual photograph of a real specimen
--   art            -- painting / drawing / sculpture / statue / figurine /
--                    trading card / illustration / engraving / woodcut / AI
--   wrong_subject  -- real photo but not of the species (carriage, monument,
--                    flowers, landscape with horse barely visible, etc.)
--   low_quality    -- blurry / tiny / unrecognizable
--   unclear        -- llava genuinely could not tell (also used for errors)
--
-- Strategy:
--   art + wrong_subject -> dead_at = NOW(), category_match suffix
--   low_quality + unclear + real_photo -> kept (low quality > nothing)

BEGIN;

ALTER TABLE breed_images
  ADD COLUMN IF NOT EXISTS vision_audit_at      TIMESTAMPTZ,
  ADD COLUMN IF NOT EXISTS vision_audit_verdict TEXT,
  ADD COLUMN IF NOT EXISTS vision_audit_notes   TEXT;

-- Constrain the verdict to the allowed values so a buggy run can't poison
-- the column with arbitrary llava chatter.
DO $$
BEGIN
  IF NOT EXISTS (
    SELECT 1 FROM pg_constraint WHERE conname = 'breed_images_vision_verdict_chk'
  ) THEN
    ALTER TABLE breed_images
      ADD CONSTRAINT breed_images_vision_verdict_chk
      CHECK (vision_audit_verdict IS NULL
             OR vision_audit_verdict IN ('real_photo','art','wrong_subject','low_quality','unclear'));
  END IF;
END $$;

-- Batch-picking index — partial index on rows that still need auditing.
CREATE INDEX IF NOT EXISTS idx_breed_images_vision_pending
  ON breed_images(id) WHERE vision_audit_at IS NULL;

-- Read index for verdict breakdown reports.
CREATE INDEX IF NOT EXISTS idx_breed_images_vision_verdict
  ON breed_images(vision_audit_verdict) WHERE vision_audit_verdict IS NOT NULL;

COMMIT;