# CLIP Score Challenge Eine produktionsnahe Gradio-App, die Benutzertexte gegen einen festen Bildpool bewertet. Die App nutzt die Transformers-Bibliothek mit dem Modell `jinaai/jina-clip-v2` für Text- und Bild-Embeddings und speichert alle Scores in einer externen PostgreSQL-Datenbank. ## Features - Fester Bildpool aus `images.csv` (nur externe URLs, keine Uploads) - Vorberechnete Bild-Embeddings (Kosinus-Ähnlichkeit → Score 0–1000) - Deutschsprachige UI mit Leaderboard (global, pro Bild, eigene letzten Scores) - Persistenz via PostgreSQL (SQLAlchemy + psycopg2) - Keine Moderation, kein Rate-Limit - Skript zur Vorberechnung der Embeddings - Automatische Schema-Erstellung beim Start - Light-Tests (Score-Mapping + DB Roundtrip) ## Projektstruktur ``` . ├── app.py # Gradio UI & Callback-Logik ├── db.py # Datenbank-Modelle & Hilfsfunktionen ├── model.py # CLIP-Laden, Embeddings, Score-Berechnung ├── precompute_embeddings.py # Skript zum Vorberechnen der Bild-Embeddings ├── images.csv # Bildpool (image_id, image_url, clip_model, embedding_path) ├── embeddings/ # Embeddings (z. B. `.json`, initial leer, Skript befüllt) ├── tests/ # Pytest-Tests ├── requirements.txt ├── runtime.txt # Python-Version für HF Spaces (3.10) ├── .env.example # Beispiel für lokale Entwicklung └── README.md ``` ## Vorbereitung 1. **Python 3.10** installieren (lokal oder via venv/conda). 2. Repository klonen und Abhängigkeiten installieren: ```bash pip install -r requirements.txt ``` 3. `.env` anlegen (siehe `.env.example`) oder `DATABASE_URL` direkt exportieren. ```bash export DATABASE_URL=postgresql+psycopg2://user:pass@host:5432/dbname ``` ## Embeddings vorrechnen Das Skript lädt jedes Bild aus `images.csv`, berechnet das CLIP-Embedding und speichert es unter `embedding_path`. ```bash python precompute_embeddings.py --csv images.csv --model-name jinaai/jina-clip-v2 ``` Hinweise: - Die Bild-URLs müssen öffentlich erreichbar sein. - Beim ersten Lauf wird das Modell automatisch aus Hugging Face geladen (~1x pro Space, Internetverbindung erforderlich). - Embedding-Dateien werden im `embeddings/` Ordner gespeichert. Wenn der Dateiname auf `.json` endet, erzeugt das Skript eine textbasierte Datei, die sich problemlos versionieren lässt. Für `.npy` bleibt das Verhalten unverändert. ## Lokale Entwicklung 1. Embeddings berechnen (siehe oben). 2. App starten: ```bash python app.py ``` 3. Gradio öffnet standardmäßig `http://127.0.0.1:7860`. ## Tests ```bash pytest ``` ## Deployment auf Hugging Face Spaces 1. **Space anlegen** - Typ: *Gradio* - Runtime: Python 3.10 (`runtime.txt` ist bereits enthalten) 2. **Secrets setzen** - Im Space `Settings` → `New secret` - Schlüssel: `DATABASE_URL` - Wert: PostgreSQL-Verbindungsstring (z. B. von Neon/Supabase) 3. **Embeddings bereitstellen** - Lokal `precompute_embeddings.py` ausführen - Für PRs ohne Binärdateien empfiehlt sich ein `.json`-Suffix im Feld `embedding_path` der `images.csv`. Das Skript erzeugt dann eine reine Textdatei (`embedding`-Array), die direkt eingecheckt werden kann. - Alternativ können Binärdateien (`.npy`) manuell im Space hochgeladen werden. 4. **Code pushen** - Repo-Inhalt in den Space pushen (oder per `Add file` hochladen) 5. **Space starten** - Beim Start erstellt `app.py` automatisch das DB-Schema (`users`, `scores` + Indizes) - UI erscheint mit deutschem Leaderboard ## Datenbankschema - `users`: speichert `username` (kanonisch, lowercase) und `display_name` - `scores`: enthält `username`, `canonical_username`, `image_id`, `score`, `similarity`, `text`, `created_at` - Mehrere Scores pro Benutzer sind erlaubt, keine Deduplication ## Hinweise - Scores werden deterministisch berechnet (gleicher Text + Bild → gleicher Score) - Keine IP- oder personenbezogene Daten werden geloggt - Für produktiven Einsatz unbedingt abgesicherte Postgres-Instanz verwenden - Bei neuen Bildern `images.csv` erweitern, Skript erneut laufen lassen und die erzeugten Embeddings (z. B. `.json`) committen bzw. hochladen Viel Spaß beim Scoren! 🎯