# ADR 0006: Embedding-Modell-Migration text-embedding-v3 → v4 **Status:** accepted **Datum:** 2026-04-11 **Issue:** #123 **Kontext:** #105 Clustering, #108 Empfehlungen ## Kontext Bis 2026-04-11 wurden alle Wahlprogramm-Chunks (69 Programme, ~18k Chunks) mit `text-embedding-v3` (1024 Dimensionen) indexiert. Für die geplanten Features **#105 Antrag-Clustering** und **#108 Empfehlungen ähnlicher Anträge** brauchen wir Embeddings für die Assessments selbst, nicht nur für Programm-Chunks. Bei der Modellwahl stellte sich die Frage: dasselbe Modell für beide Seiten oder darf eine Seite neuer sein? **Kritisch:** v3- und v4-Embeddings liegen in unterschiedlichen Vektorräumen. Cosine-Distance zwischen einem v3- und einem v4-Vektor ist mathematisch gültig, aber semantisch Unsinn. Eine Vermischung macht die Citation-Binding- Logik aus ADR 0001 kaputt und blockiert jede zukünftige Feature, die Antrag-zu-Programm-Ähnlichkeit berechnet. ## Entscheidung Vollständige Migration **beider Seiten** (Wahlprogramm-Chunks + Assessments) auf `text-embedding-v4` (1024 Dimensionen, gleiches Default wie v3). **Begründung:** - Alibaba DashScope preist v3 und v4 **identisch** ($0.07 / 1M Tokens) - v4 ist strikt besser auf MTEB (68.36 vs 63.39 overall, 59.30 vs 55.41 retrieval) - v4 unterstützt 100+ Sprachen (v3: 50+), relevant für Zitate mit Fremdwörtern - v4 bietet flexible Dimensionen 64–2048, wir bleiben aber auf 1024 (v3-kompatibel) - Die einmaligen Reindex-Kosten belaufen sich auf **~$0.50** für alle Programme - v3 wird vermutlich mittelfristig deprecated; wir vermeiden eine zweite Migration später Die Alternative "v3 für Programme, v4 für Assessments" wurde verworfen, weil sie die zukünftige Kompatibilität für Antrag-zu-Programm-Ähnlichkeit permanent blockiert. ## Migrations-Strategie (Zero-Downtime) **Zwei getrennte Settings** (`settings.embedding_model_write`, `settings.embedding_model_read`) ermöglichen einen stufenweisen Switch ohne Prod-Downtime: | Phase | WRITE | READ | Zustand | |---|---|---|---| | 0 | v3 | v3 | Pre-Migration (alter Zustand) | | 1 | **v4** | v3 | Code deployed, Reindex läuft im Hintergrund, Prod läuft weiter auf v3-Rows | | 2 | v4 | **v4** | Reindex fertig, Flag geflippt, neue Queries nutzen v4-Rows | | 3 | v4 | v4 | Cleanup: alte v3-Rows gelöscht | **Schema-Änderungen:** - `chunks`: neue Spalte `model TEXT NOT NULL DEFAULT 'text-embedding-v3'` + Index `idx_chunks_model` - `assessments`: neue Spalten `summary_embedding BLOB`, `embedding_model TEXT` **Reindex-Skript:** `app/reindex_embeddings.py` (Ausführung via `docker exec gwoe-antragspruefer python -m app.reindex_embeddings`). Schreibt v4-Rows parallel zu den v3-Rows, mit 100ms Rate-Limit zwischen Calls (= max 10 req/sec). Bereits mit v4 indexierte Programme werden übersprungen, damit das Skript idempotent ist und nach Abbruch nahtlos fortgesetzt werden kann. **Query-Pfad:** `find_relevant_chunks` filtert jetzt explizit `WHERE model = ?` mit `EMBEDDING_MODEL_READ`. Query-Embeddings werden mit demselben READ-Modell erzeugt (via neuer `model`-Parameter in `create_embedding`), damit Query und Chunks im selben Vektorraum liegen. ## Konsequenzen **Positiv:** - Einheitlicher Vektorraum für Chunks und Assessments → #105, #108, und künftige Ähnlichkeits-Features funktionieren out-of-the-box - Bessere Retrieval-Qualität (MTEB +3.9 Punkte) - Einmaliger Schritt, danach kein Mental-Load für Modell-Drift **Negativ:** - Reindex-Zeit: ~1–2h Wall-Time für alle 69 Programme (rate-limited) - Kurzzeitig doppelter Storage (v3 + v4 Chunks parallel) bis Phase 3 - Assessment-Embedding-Generation adds ~100ms Latenz pro neuer Analyse (ein zusätzlicher API-Call), der aber non-blocking fehlertolerant ist — Backfill zieht später nach **Neutral:** - Die beiden Settings (`write` / `read`) bleiben langfristig im Code bestehen als Infrastruktur für zukünftige Modell-Migrationen (v5, v6, …). Das Pattern ist wiederverwendbar. ## Alternative: "v3 einfrieren" Verworfen, weil v3 kein aktuell unterstütztes Flaggschiff mehr ist und Deprecation wahrscheinlich ist. Besser jetzt migrieren, wenn noch beide Modelle verfügbar sind, als später unter Zeitdruck. ## Alternative: "nur Assessments auf v4" Verworfen wegen der Vektorraum-Fragmentierung (siehe Kontext).