fix: load LAION V2 directly via transformers (trust_remote_code); drop stale wrapper; pin requirements

This commit is contained in:
Kareem Horstink
2026-08-23 16:27:36 +00:00
parent 027788707e
commit 62f65a2d8e
2 changed files with 26 additions and 21 deletions
+6 -6
View File
@@ -1,13 +1,13 @@
# Photo Judgers — Requirements # Photo Judgers — Requirements
# Install in conda env: pip install -r requirements.txt # Install in conda env: pip install -r requirements.txt
# #
# simple-aesthetics-predictor automatically installs torch + transformers. # We load the LAION V2 model directly via transformers (trust_remote_code),
# We avoid pinning torchvision/torchaudio here to prevent version mismatch # so we do NOT depend on the stale `simple-aesthetics-predictor` wrapper
# with the torch that simple-aesthetics-predictor resolves. Pillow is needed # (breaks with modern transformers). torch is required by transformers.
# for image loading; tqdm for progress bars.
simple-aesthetics-predictor transformers>=4.40
transformers torch>=2.1
torchvision
Pillow Pillow
tqdm tqdm
numpy numpy
+20 -15
View File
@@ -1,12 +1,23 @@
"""LAION Aesthetic Predictor V2 scorer.""" """LAION Aesthetic Predictor V2 scorer.
Loads the V2 model directly from HuggingFace via transformers'
`trust_remote_code` mechanism. This avoids the `simple-aesthetics-predictor`
wrapper package, which is stale (last release Dec 2024) and breaks with
modern transformers (circular import in `dependency_versions_check`).
"""
from typing import Optional from typing import Optional
class LaionScorer: class LaionScorer:
"""LAION V2 aesthetic scorer — CLIP-based, 0-10 scale.""" """LAION V2 aesthetic scorer — CLIP-based, 0-10 scale."""
name = "LAION Aesthetic Predictor V2" name = "LAION Aesthetic Predictor V2"
description = "CLIP-based aesthetic scoring (0-10 scale)" description = "CLIP-based aesthetic scoring (0-10 scale)"
# V2 trained on SAC + LAION-Logos + AVA (current best per research)
MODEL_ID = "shunk031/aesthetics-predictor-v2-sac-logos-ava1-l14-linearMSE"
def __init__(self, cache_dir: str = "models") -> None: def __init__(self, cache_dir: str = "models") -> None:
self.model = None # type: ignore[assignment] self.model = None # type: ignore[assignment]
self.processor = None # type: ignore[assignment] self.processor = None # type: ignore[assignment]
@@ -17,24 +28,18 @@ class LaionScorer:
"""Load model weights (downloads ~2GB on first run).""" """Load model weights (downloads ~2GB on first run)."""
try: try:
import torch # noqa: F401 import torch # noqa: F401
from transformers import AutoProcessor, AutoModel
# Package on PyPI is `simple-aesthetics-predictor`, but the print(" Loading LAION V2 model... (first run downloads ~2GB)")
# importable module is `aesthetics_predictor` (no `simple_`).
from aesthetics_predictor import AestheticsPredictorV2Linear
from transformers import CLIPProcessor
print(f" Loading LAION V2 model... (first run downloads ~2GB)")
print(f" Cache directory: {self._cache_dir}") print(f" Cache directory: {self._cache_dir}")
# V2 trained on SAC + LAION-Logos + AVA (current best per research) self.model = AutoModel.from_pretrained(
model_id = "shunk031/aesthetics-predictor-v2-sac-logos-ava1-l14-linearMSE" self.MODEL_ID,
self.model = AestheticsPredictorV2Linear.from_pretrained(
model_id,
cache_dir=self._cache_dir, cache_dir=self._cache_dir,
trust_remote_code=True,
) )
self.processor = CLIPProcessor.from_pretrained( self.processor = AutoProcessor.from_pretrained(
model_id, self.MODEL_ID,
cache_dir=self._cache_dir, cache_dir=self._cache_dir,
) )
self.model.eval() self.model.eval()
@@ -74,4 +79,4 @@ class LaionScorer:
def unload(self) -> None: def unload(self) -> None:
"""Clean up model references.""" """Clean up model references."""
self.model = None # type: ignore[assignment] self.model = None # type: ignore[assignment]
self.processor = None # type: ignore[assignment] self.processor = None # type: ignore[assignment]