# Plan: SentencePiece-Tokenizer-Support für multilinguales Embedding-Modell ## Ziel `paraphrase-multilingual-MiniLM-L12-v2` als alternatives Embedding-Modell ermöglichen, indem der `EmbeddingService` neben WordPiece (BERT) auch SentencePiece (XLM-RoBERTa) Tokenizer unterstützt. ## Hintergrund - Aktuell: `all-MiniLM-L6-v2` (BERT, WordPiece, `vocab.txt`, 384 Dims) - Ziel-Modell: `paraphrase-multilingual-MiniLM-L12-v2` (XLM-RoBERTa, SentencePiece, `sentencepiece.bpe.model`, 384 Dims) - Problem: Unser Tokenizer ist hardcoded auf WordPiece – Special Tokens (`[CLS]`/`[SEP]`), `token_type_ids`, `vocab.txt` ## Unterschiede zwischen den Tokenizern | Aspekt | WordPiece (BERT) | SentencePiece (XLM-R) | |---|---|---| | Vocab-Datei | `vocab.txt` | `sentencepiece.bpe.model` | | Special Tokens | `[CLS]`=101, `[SEP]`=102, `[PAD]`=0 | ``=0, ``=2, ``=1 | | token_type_ids | Required (alle 0) | Nicht verwendet | | Subword-Prefix | `##` | `▁` (U+2581) | | Vocab-Groesse | ~30.522 | ~250.002 | --- ## Schritte ### Schritt 1: NuGet-Paket hinzufuegen - `Microsoft.ML.Tokenizers.SentencePieceBpe` oder `SentencePieceSharp` evaluieren - Kriterien: .NET 10 Kompatibilitaet, kein native-Dependency-Problem auf Linux, Lizenz - Paket zu `gott.csproj` hinzufuegen ### Schritt 2: Tokenizer-Abstraktion in `EmbeddingService.cs` - Interface oder Strategie-Pattern: `ITextTokenizer` mit Methode `Tokenize(string text, int maxLen) -> (long[] inputIds, long[] attentionMask, long[]? tokenTypeIds)` - `WordPieceTokenizer` – bestehende Logik extrahieren (Zeilen 127-161) - `SentencePieceTokenizer` – neue Implementierung - Constructor-Logik: Wenn `vocab.txt` existiert -> WordPiece; wenn `sentencepiece.bpe.model` existiert -> SentencePiece - Property `TokenizerType` fuer Debug/Logging ### Schritt 3: ONNX-Session Input anpassen - WordPiece: 3 Inputs (`input_ids`, `attention_mask`, `token_type_ids`) - SentencePiece: 2 Inputs (`input_ids`, `attention_mask`) – kein `token_type_ids` - `GenerateEmbedding()` muss dynamisch die richtigen Inputs erstellen basierend auf Tokenizer-Typ - ONNX Input-Names aus dem Modell lesen statt hardcoded (robuster) ### Schritt 4: Special Token IDs konfigurierbar machen - `[CLS]`/`[SEP]` IDs vs. ``/`` IDs - Am besten aus `special_tokens_map.json` oder `tokenizer_config.json` lesen, falls vorhanden - Fallback: Hardcoded Mapping pro Tokenizer-Typ ### Schritt 5: Modell-Dateien bereitstellen - Von HuggingFace herunterladen: - `model.onnx` (ONNX-Export des Modells) - `sentencepiece.bpe.model` - Ablegen in `data/models/paraphrase-multilingual-MiniLM-L12-v2/` - Server-Setting `EmbeddingModelDir` auf den neuen Ordner setzen ### Schritt 6: Re-Embed-Kompatibilitaet - Dimensionen sind identisch (384) -> Keine DB-Schema-Aenderung noetig - Re-Embed-Endpoint muss weiterhin funktionieren - Beim Modell-Wechsel: **Alle** Embeddings muessen neu berechnet werden (altes Modell-Vektoren sind inkompatibel mit neuem Modell) - Warnung im Admin-UI wenn Modell gewechselt wurde aber Re-Embed noch nicht gelaufen ist ### Schritt 7: Tests & Verifikation - Embedding-Debug-Page nutzen: Gleiche Queries mit altem vs. neuem Modell vergleichen - Testcases: - Deutsche Query -> deutsche Messages ("weisst du was zum thema autocontext") - Englische Query -> englische Messages ("skills") - Gemischt -> gemischte Messages ("otter karten") - Pruefen ob Scores sich verbessern (besonders fuer deutsche Queries) --- ## Betroffene Dateien 1. `gott.csproj` – NuGet-Paket 2. `Services/EmbeddingService.cs` – Tokenizer-Abstraktion, SentencePiece-Support 3. `wwwroot/js/embedding-debug.js` – ggf. Anzeige des aktiven Modells/Tokenizers ## Risiken - **SentencePiece NuGet auf Linux**: Native Dependencies koennten Probleme machen -> vorher testen - **Re-Embed Dauer**: 14k Messages mit 256 Tokens -> je nach CPU 5-30 Minuten - **Dimensionen-Mismatch**: Falls ein zukuenftiges Modell andere Dims hat -> DB-Migration noetig (aktuell nicht, beide 384) ## Aufwand - Geschaetzt: ~2-3 Stunden Implementierung - Groesster Block: Tokenizer-Abstraktion sauber bauen