Replace OpenCLIP ViT-B/32 (512-d, ~78% recall) with SigLIP2 ViT-B/16 (768-d, ~84% recall) as the default embedding model for significantly better image-text retrieval quality. - New SigLIP2Embedder class with 384px input and SigLIP normalization - ONNX export pipeline for SigLIP2 visual + textual encoders - Migration 0010: resize embeddings.vector from 512 to 768 dimensions - Config-driven model selection: "siglip2_vitb16" (default) or "openclip_vitb32" (legacy) — both models can coexist - Content classifier follows the configured embedder family - Existing embeddings cleared on migration; vision backfill regenerates Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
47 lines
1.7 KiB
Python
47 lines
1.7 KiB
Python
"""
|
|
ONNX Runtime backend — default CPU inference for all vision models.
|
|
|
|
Each create_* method returns a concrete implementation of the
|
|
corresponding ABC from base.py. Models are loaded from ONNX files
|
|
under settings.vision.models_dir, downloaded on first boot by
|
|
bootstrap_models.py.
|
|
"""
|
|
import logging
|
|
|
|
from app.config import VisionSettings
|
|
from app.services.vision.base import Embedder, OCREngine, ObjectDetector, FaceProcessor, ContentClassifier
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class ONNXBackend:
|
|
"""Factory for ONNX Runtime-based vision model instances."""
|
|
|
|
def __init__(self, vision_settings: VisionSettings):
|
|
self._settings = vision_settings
|
|
|
|
def create_embedder(self) -> Embedder:
|
|
model_name = self._settings.embedder.name
|
|
if model_name.startswith("siglip2"):
|
|
from app.services.vision.embed import SigLIP2Embedder
|
|
return SigLIP2Embedder(self._settings)
|
|
else:
|
|
from app.services.vision.embed import OpenCLIPEmbedder
|
|
return OpenCLIPEmbedder(self._settings)
|
|
|
|
def create_ocr(self) -> OCREngine:
|
|
from app.services.vision.ocr import RapidOCREngine
|
|
return RapidOCREngine(self._settings)
|
|
|
|
def create_detector(self) -> ObjectDetector:
|
|
from app.services.vision.detect import YOLOv8Detector
|
|
return YOLOv8Detector(self._settings)
|
|
|
|
def create_face_processor(self) -> FaceProcessor:
|
|
from app.services.vision.insightface_processor import InsightFaceProcessor
|
|
return InsightFaceProcessor(self._settings)
|
|
|
|
def create_classifier(self) -> ContentClassifier:
|
|
from app.services.vision.classify import CLIPContentClassifier
|
|
return CLIPContentClassifier(self._settings)
|