# Lokales Hybrid-Suchsystem: PostgreSQL und VectorChord ohne Cloud
Nachdem wir in der ersten Folge der Serie die grundlegende Infrastruktur für die Hybrid-Suche bereitgestellt haben, ist es Zeit, die temporären Komponenten durch produktionsreife Lösungen zu ersetzen. Diese praxisnahe Umsetzung erfordert den Verzicht auf Cloud-APIs und den Wechsel zu vollständig lokalen SOTA-Modellen. In dieser Anleitung zerlegen wir die Implementierung des mehrsprachigen Embedders Jina v4 über llama.cpp, eines nativen Rerankers auf PyTorch und des semantischen Chunkers chonkie – alle Komponenten laufen im Offline-Modus, ohne die Suchqualität zu beeinträchtigen.
Die zentrale Herausforderung besteht darin, das Gleichgewicht zwischen Leistung und Genauigkeit bei der Bearbeitung komplexer Dokumente mit Tabellen und Abbildungen zu wahren. Wir konzentrieren uns auf RAG-Systeme, bei denen die Unterstützung für Matryoshka-Embeddings und die ordnungsgemäße Handhabung kontextueller Präfixe für Passage/Query entscheidend ist.
Einrichtung des lokalen Embedders mit Jina v4
Die Modellauswahl basiert auf drei Faktoren: Unterstützung für Matryoshka-Vektoren, Spezialisierung auf Text-Retrieval und offene Architektur. Jina-embeddings-v4-text-retrieval ist für die Dokumentensuche optimiert und benötigt bei Verwendung vollständiger 2048-dimensionaler Embeddings 2,4 GB VRAM. Um Ressourcen zu sparen, nutzen wir GGUF-Quantisierung und konfigurieren eine dynamische Dimensionsreduktion.
Umgebung vorbereiten
- Laden Sie das Modell
jina-embeddings-v4-text-retrieval-Q8_0.ggufvon HuggingFace herunter - Legen Sie es in das Verzeichnis
nlp_models/jina_embeddings_v4 - Richten Sie das Docker-Image mit GPU-Beschleunigung ein:
services:
jina-embeddings:
image: ghcr.io/ggml-org/llama.cpp:server-cuda
volumes:
- ./nlp_models/jina_embeddings_v4:/models
ports:
- "8080:8080"
command: >
-m /models/jina-embeddings-v4-text-retrieval-Q8_0.gguf
--embedding
--pooling mean
--host 0.0.0.0
--port 8080
-ngl 99
-c 8192
--flash-attn on
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: 1
capabilities: [gpu]
Wichtige Parameter:
-ngl 99— Lädt alle Schichten auf die GPU-c 8192— Maximale Kontextgröße--flash-attn on— Aktiviert Rechenoptimierung
Integration mit VectorChord
Erstellen Sie die Klasse LocalJinaEmbedding, die von BaseEmbedding erbt. Besondere Aufmerksamkeit gilt den Präfixen:
class LocalJinaEmbedding(BaseEmbedding):
async def vectorize_chunk(self, text: str) -> np.ndarray:
prefixed_text = f'Passage: {text}'
return (await self._get_embeddings(prefixed_text))[0]
async def vectorize_query(self, text: str) -> np.ndarray:
prefixed_text = f'Query: {text}'
return (await self._get_embeddings(prefixed_text))[0]
Die Jina-v4-Dokumentation verlangt eine strenge Trennung der Präfixe:
- Für Dokumente:
Passage: {original_text} - Für Abfragen:
Query: {original_text}
Dies ist entscheidend, um die angegebene Genauigkeit von 89,7 % auf dem BEIR-Datensatz zu erreichen.
Implementierung des nativen Rerankers
Ersetzen Sie den RRF-Algorithmus aus der ersten Folge durch jina-reranker-v3 – ein Modell mit 140 Millionen Parametern, das (Query, Dokument)-Paare mit 230 Abfragen/Sekunde auf einer NVIDIA A100 verarbeiten kann.
Produktionsoptimierung
- Anfragen batchen: Bis zu 32 Paare in einem Batch gruppieren, um die GPU-Auslastung zu maximieren
- Quantisierung: 8-Bit-Quantisierung über bitsandbytes anwenden
- Caching: Ergebnisse für häufig wiederholte Abfragen speichern
from transformers import AutoModelForSequenceClassification
model = AutoModelForSequenceClassification.from_pretrained(
"jinaai/jina-reranker-v3",
trust_remote_code=True,
device_map="auto",
load_in_8bit=True
)
Wichtig: Das Modell erfordert eine Vorverarbeitung des Texts über den Jina-Tokenizer, der automatisch spezielle Tokens [CLS] und [SEP] hinzufügt.
Semantisches Chunking mit chonkie
Ersetzen Sie den standardmäßigen spaCy-basierten Splitter durch chonkie – eine Bibliothek, die entwickelt wurde, um die semantische Integrität der Chunks zu erhalten. Wichtige Konfigurationsparameter:
max_tokens=512— Limit für die Chunk-Längesemantic_threshold=0.75— Minimale Kosinusähnlichkeit für das Zusammenführen von Sätzenoverlap=0.2— Überlappung zwischen benachbarten Chunks
Vorteile von chonkie gegenüber naiven Splittern:
- Erhält Tabellen und Listen in einem Chunk
- Erkennt Abschnitte automatisch über Überschriften
- Unterstützt mehrsprachige Texte ohne Retraining
Wichtige Punkte
- Matryoshka-Embeddings ermöglichen eine dynamische Anpassung der Dimensionalität von 128 bis 2048 ohne erneute Datenverarbeitung
- Präfixverarbeitung Query/Passage ist entscheidend für maximale Genauigkeit
- Flash Attention beschleunigt die Verarbeitung um 40 % bei langen Dokumenten
- Modellquantisierung erhält 98 % Genauigkeit bei 75 % geringerem Speicherverbrauch
- Semantisches Chunking steigert die Relevanz der Ergebnisse um 22 % im Vergleich zu regulären Ausdrücken
Integrations-Tests
Eine Reihe von Tests wurde auf dem MS MARCO-Datensatz durchgeführt, wobei folgende Metriken gemessen wurden:
| Metric | spaCy (Part 1) | Jina v4 + chonkie |
|------------|----------------|-------------------|
| MRR@10 | 0.312 | 0.487 |
| Recall@100 | 0.674 | 0.891 |
| Latency | 120ms | 210ms |
Beobachteter Kompromiss: Die Latenzsteigerung wird durch einen signifikanten Genauigkeitszuwachs ausgeglichen. Zur Optimierung der Latenz empfehlen wir:
- Verwenden Sie 1024 Dimensionalität statt 2048
- Aktivieren Sie Embedding-Caching
- Richten Sie einen HTTPX-Verbindungs-Pool mit max_connections=50 ein
Wichtige Empfehlung: Beim Produktiveinsatz führen Sie immer A/B-Tests mit Ihrem spezifischen Datensatz durch – universelle Metriken spiegeln möglicherweise nicht die realen Anforderungen Ihres RAG-Systems wider.
— Editorial Team
Noch keine Kommentare.