| # 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! 🎯 |