Grundlagen des Retrievals: Wie die RAG-Suche funktioniert
Beherrschen Sie die Grundlagen des Retrievals in RAG-Systemen: Embeddings, vector search, chunking und indexing für relevante Ergebnisse.
Grundlagen des Retrieval : Wie funktioniert die RAG-Suche
Retrieval ist der Herzschlag jedes RAG-Systems (Retrieval-Augmented Generation). Ohne effizientes Retrieval wird selbst das beste LLM der Welt unpassende oder unvollständige Antworten liefern. Dieser Leitfaden führt Sie durch das tiefere Verständnis der Retrieval-Mechanismen, von der Theorie bis zur praktischen Implementierung.
Warum Retrieval in einem RAG-System kritisch ist
Ein RAG-System funktioniert in zwei Schritten: zuerst die relevanten Dokumente abrufen (retrieval), dann eine Antwort basierend auf diesen Dokumenten generieren (generation). Die Qualität der finalen Antwort hängt direkt von der Qualität der abgerufenen Dokumente ab.
Stellen Sie sich einen Assistenten vor, der auf "Was ist Ihre Rückgabepolitik?" antworten soll. Wenn das retrieval Seiten zu Lieferbedingungen statt zur Rückgabepolitik zurückbringt, wird das LLM eine falsche Antwort generieren oder eine fiktive Politik erfinden.
Die drei Säulen des Retrieval
- Repräsentation : Wie Text in mathematische Vektoren transformiert wird
- Indexierung : Wie diese Vektoren für schnelle Suche organisiert werden
- Suche : Wie die relevantesten Dokumente gefunden werden
Embeddings verstehen
Embeddings sind vektorielle Repräsentationen von Text. Jedes Wort, jeder Satz oder jedes Dokument wird in einen Vektor von Zahlen (typischerweise 384 bis 1536 Dimensionen) umgewandelt, der seine semantische Bedeutung einfängt.
Wie Embeddings funktionieren
DEVELOPERpythonfrom sentence_transformers import SentenceTransformer # Charger un modèle d'embedding model = SentenceTransformer('sentence-transformers/all-MiniLM-L6-v2') # Créer des embeddings textes = [ "Comment retourner un produit ?", "Quelle est la politique de remboursement ?", "Horaires d'ouverture du magasin" ] embeddings = model.encode(textes) # Calculer la similarité from sklearn.metrics.pairwise import cosine_similarity similarites = cosine_similarity(embeddings) print("Similarité 'retour' vs 'remboursement':", similarites[0][1]) # ~0.85 print("Similarité 'retour' vs 'horaires':", similarites[0][2]) # ~0.25
Die ersten beiden Sätze sind, obwohl unterschiedlich formuliert, stark ähnlich, da sie dasselbe Thema behandeln. Der dritte ist semantisch weit entfernt.
Modellwahl für Embeddings
| Modèle | Dimensions | Performance | Vitesse | Usage recommandé |
|---|---|---|---|---|
| all-MiniLM-L6-v2 | 384 | Gut | Schnell | Prototyping, große Volumina |
| all-mpnet-base-v2 | 768 | Sehr gut | Mittel | Allgemeine Produktion |
| text-embedding-3-small | 1536 | Ausgezeichnet | Schnell (API) | Produktion mit API-Budget |
| text-embedding-3-large | 3072 | State-of-the-art | Mittel (API) | Kritische Fälle mit hoher Präzision |
| multilingual-e5-large | 1024 | Ausgezeichnet multilingual | Mittel | Inhalte FR/EN/multilingual |
Für ein Projekt in französischer Sprache bevorzugen Sie multilinguale Modelle oder solche, die auf französischen Korpora trainiert wurden:
DEVELOPERpython# Excellent choix pour le français model = SentenceTransformer('intfloat/multilingual-e5-large') # Préfixe requis pour E5 query = "query: Comment fonctionne la garantie ?" documents = ["passage: La garantie couvre les défauts de fabrication pendant 2 ans..."]
Chunking : Dokumente intelligent aufteilen
Chunking ist die Kunst, Dokumente in Stücke angemessener Größe zu unterteilen. Zu groß enthält das Chunk Rauschen. Zu klein geht Kontext verloren.
Chunking-Strategien
1. Chunking mit fester Größe
Die einfachste Methode: alle X Zeichen mit Überlappung aufteilen.
DEVELOPERpythonfrom langchain.text_splitter import RecursiveCharacterTextSplitter splitter = RecursiveCharacterTextSplitter( chunk_size=500, # Taille cible chunk_overlap=50, # Chevauchement pour conserver le contexte separators=["\n\n", "\n", ". ", " ", ""] ) document = """ Politique de retour Vous avez 30 jours pour retourner un produit non utilisé dans son emballage d'origine. Procédure de retour : 1. Connectez-vous à votre espace client 2. Sélectionnez la commande concernée 3. Cliquez sur "Demander un retour" 4. Imprimez l'étiquette de retour Les frais de retour sont à votre charge sauf en cas de produit défectueux. Remboursement Une fois le retour réceptionné et validé, le remboursement est effectué sous 5 jours ouvrés sur le moyen de paiement utilisé lors de l'achat. """ chunks = splitter.split_text(document) for i, chunk in enumerate(chunks): print(f"Chunk {i+1}: {chunk[:100]}...")
2. Semantisches Chunking
Anspruchsvoller: an natürlichen Textgrenzen (Absätze, Abschnitte) aufteilen.
DEVELOPERpythonfrom langchain.text_splitter import MarkdownTextSplitter md_splitter = MarkdownTextSplitter( chunk_size=500, chunk_overlap=0 ) # Respecte la structure Markdown chunks = md_splitter.split_text(markdown_document)
3. Chunking nach Sätzen mit Sliding Window
Ideal für FAQs und kurze Inhalte:
DEVELOPERpythonimport nltk nltk.download('punkt') def chunk_by_sentences(text, sentences_per_chunk=3, overlap=1): sentences = nltk.sent_tokenize(text, language='french') chunks = [] for i in range(0, len(sentences), sentences_per_chunk - overlap): chunk = " ".join(sentences[i:i + sentences_per_chunk]) chunks.append(chunk) return chunks
Vergleichstabelle der Strategien
| Stratégie | Avantages | Inconvénients | Cas d'usage |
|---|---|---|---|
| Taille fixe | Einfach, vorhersehbar | Trennt Ideen mitten im Text | Homogene Dokumente |
| Sémantique | Bewahrt Bedeutung | Komplexer | Strukturierte Dokumentation |
| Par phrase | Feine Genauigkeit | Chunks manchmal zu kurz | FAQ, Support |
| Hiérarchique | Elternkontext bewahrt | Größere Komplexität | Technische Dokumentation |
Indexierung mit Vektordatenbanken
Sobald die Embeddings erstellt sind, müssen sie gespeichert und indexiert werden, um schnelle Suche zu ermöglichen. Vektordatenbanken sind für diese Aufgabe optimiert.
Qdrant : Implementierungsbeispiel
DEVELOPERpythonfrom qdrant_client import QdrantClient from qdrant_client.models import Distance, VectorParams, PointStruct # Connexion client = QdrantClient(host="localhost", port=6333) # Créer une collection client.create_collection( collection_name="knowledge_base", vectors_config=VectorParams( size=384, # Dimension de vos embeddings distance=Distance.COSINE ) ) # Indexer des documents points = [ PointStruct( id=i, vector=embedding.tolist(), payload={ "text": chunk, "source": "politique_retour.md", "category": "support" } ) for i, (embedding, chunk) in enumerate(zip(embeddings, chunks)) ] client.upsert( collection_name="knowledge_base", points=points )
Vektorielle Suche
DEVELOPERpythondef search(query: str, top_k: int = 5): # Encoder la requête query_embedding = model.encode(query) # Rechercher results = client.search( collection_name="knowledge_base", query_vector=query_embedding.tolist(), limit=top_k ) return [ { "text": hit.payload["text"], "score": hit.score, "source": hit.payload["source"] } for hit in results ] # Exemple resultats = search("Comment me faire rembourser ?") for r in resultats: print(f"Score: {r['score']:.3f} - {r['text'][:100]}...")
Similaritätsmetriken
Die Wahl der Metrik beeinflusst die Suchergebnisse.
Cosine similarity
Am häufigsten verwendet. Misst den Winkel zwischen zwei Vektoren, unabhängig von ihrer Magnitude.
DEVELOPERpythonimport numpy as np def cosine_similarity(a, b): return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
Avantages : Unabhängig von der Länge des Originaltexts
Inconvénients : Kann Unterschiede in der Magnitude übersehen
Dot product (Skalarprodukt)
Schneller, aber empfindlich gegenüber der Magnitude der Vektoren.
DEVELOPERpythondef dot_product(a, b): return np.dot(a, b)
Avantages : Schneller zu berechnen
Inconvénients : Erfordert normalisierte Vektoren, um mit Cosine vergleichbar zu sein
Euklidische Distanz
Misst die "Luftlinien"-Distanz zwischen zwei Punkten.
DEVELOPERpythondef euclidean_distance(a, b): return np.linalg.norm(a - b)
Avantages : Geometrisch intuitiv
Inconvénients : Empfindlich gegenüber Ausreißern und hoher Dimensionalität
Retrieval optimieren
1. Query expansion
Die Benutzeranfrage erweitern, um Recall zu verbessern:
DEVELOPERpythondef expand_query(query: str, llm) -> list[str]: prompt = f""" Génère 3 reformulations de cette question pour améliorer la recherche : Question originale : {query} Reformulations : """ expansions = llm.generate(prompt) return [query] + expansions # Rechercher avec toutes les variantes def search_expanded(query: str, top_k: int = 5): queries = expand_query(query, llm) all_results = [] for q in queries: results = search(q, top_k=top_k) all_results.extend(results) # Dédupliquer et re-scorer return deduplicate_and_rerank(all_results)
2. Reranking
Einen Reranking-Modell verwenden, um die Ergebnisse zu verfeinern:
DEVELOPERpythonfrom sentence_transformers import CrossEncoder reranker = CrossEncoder('cross-encoder/ms-marco-MiniLM-L-6-v2') def rerank(query: str, documents: list[str], top_k: int = 3): pairs = [[query, doc] for doc in documents] scores = reranker.predict(pairs) # Trier par score décroissant ranked = sorted(zip(documents, scores), key=lambda x: x[1], reverse=True) return ranked[:top_k] # Pipeline complet def search_with_rerank(query: str): # 1. Recherche initiale (recall élevé) initial_results = search(query, top_k=20) # 2. Reranking (précision élevée) documents = [r["text"] for r in initial_results] reranked = rerank(query, documents, top_k=5) return reranked
3. Filtern mittels Metadaten
Vektorsuche mit klassischen Filtern kombinieren:
DEVELOPERpythonfrom qdrant_client.models import Filter, FieldCondition, MatchValue def search_filtered(query: str, category: str = None, top_k: int = 5): query_embedding = model.encode(query) # Construire le filtre filter_conditions = None if category: filter_conditions = Filter( must=[ FieldCondition( key="category", match=MatchValue(value=category) ) ] ) results = client.search( collection_name="knowledge_base", query_vector=query_embedding.tolist(), query_filter=filter_conditions, limit=top_k ) return results # Rechercher uniquement dans la catégorie "support" resultats = search_filtered("politique retour", category="support")
Die Qualität des Retrieval bewerten
Um die Effizienz Ihres Retrieval-Systems zu messen, verwenden Sie diese Metriken:
Recall@k
Anteil relevanter Dokumente, die unter den k ersten Ergebnissen gefunden wurden.
DEVELOPERpythondef recall_at_k(retrieved: list, relevant: list, k: int) -> float: retrieved_k = set(retrieved[:k]) relevant_set = set(relevant) return len(retrieved_k & relevant_set) / len(relevant_set)
MRR (Mean Reciprocal Rank)
Durchschnittliche Position des ersten relevanten Dokuments.
DEVELOPERpythondef mrr(queries_results: list[tuple[list, list]]) -> float: reciprocal_ranks = [] for retrieved, relevant in queries_results: for i, doc in enumerate(retrieved): if doc in relevant: reciprocal_ranks.append(1 / (i + 1)) break else: reciprocal_ranks.append(0) return sum(reciprocal_ranks) / len(reciprocal_ranks)
NDCG (Normalized Discounted Cumulative Gain)
Berücksichtigt die Reihenfolge der Ergebnisse und Relevanzscores.
DEVELOPERpythonimport numpy as np def ndcg_at_k(relevances: list[float], k: int) -> float: relevances = np.array(relevances[:k]) # DCG discounts = np.log2(np.arange(2, len(relevances) + 2)) dcg = np.sum(relevances / discounts) # IDCG (DCG idéal) ideal_relevances = np.sort(relevances)[::-1] idcg = np.sum(ideal_relevances / discounts) return dcg / idcg if idcg > 0 else 0
Häufige Fallstricke und Lösungen
1. Zu große Chunks
Symptom : Das retrieval liefert vage relevante, aber nicht präzise Dokumente.
Lösung : Die Chunk-Größe reduzieren oder hierarchisches Chunking verwenden.
2. Fachspezifischer Wortschatz
Symptom : Domain-spezifische Begriffe werden von den Embeddings nicht gut erfasst.
Lösung : Das Embedding-Modell fine-tunen oder ein Synonym-Wörterbuch verwenden.
DEVELOPERpythonsynonymes = { "ticket": ["demande", "requête", "incident"], "KB": ["base de connaissances", "knowledge base"], } def expand_with_synonyms(query: str) -> str: for term, syns in synonymes.items(): if term.lower() in query.lower(): query += " " + " ".join(syns) return query
3. Ambigue Anfragen
Symptom : "Problème avec ma commande" liefert zu viele unterschiedliche Ergebnisse.
Lösung : Gesprächskontext nutzen oder um Präzisierungen bitten.
4. Cold start
Symptom : Zu wenig Daten beim Start, retrieval wenig relevant.
Lösung : Mit synthetischen Daten oder generierten FAQs anreichern.
Produktionsarchitektur
Für ein Retrieval-System in Produktion empfehlen wir folgende Architektur:
┌─────────────────────────────────────────────────────────────┐
│ API Gateway │
└─────────────────────┬───────────────────────────────────────┘
│
┌─────────────────────▼───────────────────────────────────────┐
│ Query Processor │
│ - Normalisation │
│ - Détection de langue │
│ - Query expansion │
└─────────────────────┬───────────────────────────────────────┘
│
┌────────────┴────────────┐
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ Dense Search │ │ Sparse Search │
│ (Qdrant) │ │ (BM25) │
└────────┬────────┘ └────────┬────────┘
│ │
└──────────┬─────────────┘
▼
┌─────────────────┐
│ Fusion/Rerank │
└────────┬────────┘
▼
┌─────────────────┐
│ LLM Context │
└─────────────────┘
Nächste Schritte
Jetzt, wo Sie die Grundlagen des Retrieval beherrschen, vertiefen Sie Ihr Wissen mit unseren spezialisierten Guides:
- Dense Retrieval : Recherche sémantique avec embeddings - Tauchen Sie ein in fortgeschrittene Embeddings
- Sparse Retrieval et BM25 - Erfahren Sie, wann lexikalische Suche überlegen ist
- Fusion hybride - Kombinieren Sie das Beste aus beiden Welten
Für einen Gesamtüberblick über RAG lesen Sie unsere Introduction complète au RAG.
Gehen Sie in die Praxis mit Ailog
Ein leistungsfähiges Retrieval-System zu implementieren erfordert Zeit und Expertise. Mit Ailog profitieren Sie von einer schlüsselfertigen RAG-Infrastruktur:
- Intelligentes Chunking optimiert für Ihren Inhaltstyp
- Multilinguale Embedding-Modelle (französisch/englisch nativ)
- Automatisches Reranking für ultra-präzise Ergebnisse
- Souveräner Hosting in Frankreich, DSGVO-konform
Testez gratuitement Ailog und deployen Sie Ihren ersten RAG-Assistenten in 3 Minuten.
Tags
Verwandte Artikel
Hybride RAG-Suche: BM25 + Vektorsuche (2025)
+20–30% RAG-Genauigkeit mit hybrider Suche. Schritt-für-Schritt-Anleitung zum Kombinieren von BM25 und Vektorsuche mit Weaviate, Qdrant oder Pinecone.
Abfrageerweiterung: Relevantere Ergebnisse erhalten
Den Recall um 40 % verbessern: erweitern Sie Nutzeranfragen mit Synonymen, Unterabfragen und von LLM generierten Variationen.
Abruf übergeordneter Dokumente: rauschfreier Kontext
Durchsuchen Sie kleine Fragmente, rufen Sie die vollständigen Dokumente ab: die beste Kombination aus Präzision und Kontext für RAG-Systeme.