Fortgeschritten 11 Min.Optimierung

Hybride Suche: BM25 + vectoriel

Direkte Antwort

Die hybride Suche führt parallel eine Stichwortsuche (BM25) und eine Vektorsuche für dieselbe Frage aus und führt anschließend die beiden Ranglisten zusammen, meist mittels Reciprocal Rank Fusion (RRF). Sie gleicht Fälle aus, in denen das Embedding versagt (Kennungen, Eigennamen, seltene Begriffe), ohne das Verständnis von Paraphrasen einzubüßen. Qdrant, Weaviate und Elasticsearch unterstützen sie nativ; mit ChromaDB lässt sie sich in dreißig Zeilen Python implementieren.

Eine Vektordatenbank findet Bedeutungen, keine exakten Zeichenfolgen: Eine Referenz wie „RG/2024-117“ oder eine Ticketnummer entgeht ihr. Umgekehrt versteht die Stichwortsuche nicht, dass „automobile“ und „voiture“ dasselbe bezeichnen. Dieser Leitfaden zeigt, wie sich beide Ansätze kombinieren lassen, welche Fusionsmethode zu wählen ist, was Qdrant und Weaviate tun und welche Falle bei der Tokenisierung französischer Texte den BM25-Teil unbemerkt ruiniert.

Von Mohamed Meguedmi·Aktualisierung 2026-09-30·Unter Windows, macOS und Linux getestet

#Warum rein vektorbasierte Suche bei manchen Fragen scheitert

Die Vektorsuche wandelt jede Textpassage in einen Vektor um, der ihren allgemeinen Sinn zusammenfasst, und gibt dann die Passagen zurück, deren Vektoren dem Vektor der Frage am nächsten liegen. Diese Kompression funktioniert sehr gut bei Paraphrasen, aber schlecht bei allem, was wortgetreu gefunden werden muss: einer Kennung, einem Fehlercode, einem Personennamen, einem internen Kürzel. Beim Embedding ähneln sich „PROD-4817“ und „PROD-4871“, sodass ein unpassendes Ticket vor dem richtigen erscheinen kann. Die hybride Suche begegnet diesem Problem: Sie ergänzt eine zweite Rangfolge, die auf dem exakten Vorkommen der Wörter beruht, und führt beide zusammen, sodass jede Methode die blinden Flecken der anderen ausgleicht.

Identifikatoren und Referenzen
Ticketnummern, Aktennummern, Vertragsnummern, SKU, Fehlercodes: Sie sind Zeichenketten, die ein Embedding nicht zuverlässig speichert und die BM25 sofort wiederfindet, sobald sie im Abschnitt vorkommen.
Seltene Fachbegriffe
Seltene medizinische, juristische oder technische Begriffe: Ein seltenes Wort hat in BM25 ein hohes Gewicht, während sein Embedding unscharf sein kann.
Sehr kurze Anfragen
Zwei Wörter wie „Rechnung 2024“ liefern wenig Material für ein Embedding; Schlüsselwörter hingegen werden unverändert miteinander verglichen.
Paraphrasen und Umformulierungen
Der umgekehrte Fall: „befristeter Arbeitsvertrag“ und „CDD“ oder „Auto“ und „Automobil“ haben kein Wort gemeinsam; nur die Vektorsuche stellt eine Verbindung zwischen ihnen her.
i
Ein typisches Beispiel
In einer Ticket-Datenbank liefert die Anfrage „PROD-4817“ bei rein vektorbasierter Suche Tickets mit ähnlichem Inhalt zurück, während die Stichwortsuche sofort das einzige Ticket mit dieser Nummer herausfiltert.

#BM25: Was die Stichwortsuche leistet

Das RAG-Local-Kit

Ihre Dokumente, Ihre KI: ein zuverlässiges lokales RAG für Ihre PDFs, Notizen und E-Mails – ohne Daten in die Cloud zu senden.

  • Lebenslanger Online-Zugang
  • PDF + Dateien
  • Erstattung binnen 30 Tagen

BM25 ist die lexikalische Rankingfunktion, die Lucene, Elasticsearch und OpenSearch verwenden und die SQLite in seinem FTS5-Modul anbietet (die Dokumentation beschreibt die Funktion bm25() als eine Funktion, die einen Wert zurückgibt, der angibt, wie gut die Zeile zur Suchanfrage passt). Sie beruht auf drei Ideen: Ein seltenes Wort hat mehr Gewicht als ein häufiges, ein wiederholtes Wort zählt ab einer bestimmten Anzahl von Vorkommen immer weniger, und eine lange Passage wird gegenüber einer kurzen leicht benachteiligt. Der Parameter k1 steuert diese Sättigung: Laut der Beschreibung von Elastic begrenzt er den Einfluss, den ein einzelner Begriff der Suchanfrage auf den Score eines Dokuments haben kann.

Stärken
Seltene Begriffe, Kennungen, kurze Suchanfragen, Fachvokabular, kein Modell, das geladen oder trainiert werden muss, kompakter Index, nachvollziehbares Ergebnis (man weiß, welches Wort den betreffenden Abschnitt in den Suchergebnissen nach oben gebracht hat).
Schwächen
Synonyme, Umformulierungen, Paraphrasen, Tippfehler; ohne Lemmatisierung sind „signé“ und „signature“ zwei verschiedene Wörter.
Voraussetzungen
Eine sorgfältige Tokenisierung: Umwandlung in Kleinbuchstaben, Entfernung von Akzenten, gegebenenfalls Stammformreduktion (Stemming). Genau hier machen die meisten selbst entwickelten Implementierungen Fehler, siehe unten.

#Hybride Suche: das Prinzip

Beide Suchen werden für dieselbe Frage ausgeführt. Jede liefert ihre Liste von Kandidaten (20 bis 50 Passagen), anschließend werden die beiden Listen zu einer einzigen Rangliste zusammengeführt. Der Vorteil ergibt sich aus einer einfachen Beobachtung: Passagen, die in beiden Listen erscheinen, sind fast immer relevant, und jede Methode liefert zusätzlich Passagen, die die andere übersehen hat. Weaviate definiert die hybride Suche so: Sie kombiniert die Ergebnisse einer Vektorsuche und einer Stichwortsuche, indem sie die beiden Ergebnismengen zusammenführt, wobei sich die Fusionsmethode und die relativen Gewichtungen konfigurieren lassen. Der messbare Vorteil hängt vom Korpus und den Fragen ab: Keine allgemeine Zahl ist verlässlich, und Sie müssen den Vorteil anhand Ihrer eigenen Dokumente messen (siehe unten).

#Ohne Normalisierung fusionieren: Reciprocal Rank Fusion

Der klassische Fehler besteht darin, die Rohwerte der Scores zu addieren. Ein BM25-Score ist eine positive Zahl ohne obere Grenze; ein Score für Vektorähnlichkeit ist eine Distanz oder ein Kosinuswert in einem begrenzten Wertebereich: Die beiden Skalen sind nicht vergleichbar, und schon die kleinste Änderung am Korpus verschiebt sie. Reciprocal Rank Fusion umgeht das Problem, indem sie ausschließlich die Rangpositionen verwendet. Die Elasticsearch-Dokumentation beschreibt sie als eine Methode, die keinerlei Abstimmung erfordert und deren Relevanzmaße nicht miteinander in Beziehung stehen müssen.

RRF-Formel
score(doc) = somme, sur chaque liste i où le doc apparaît, de 1 / (k + rang_i(doc))

k = 60 par défaut (valeur par défaut d'Elasticsearch)
rang_i = 1 pour le premier de la liste, 2 pour le deuxième, etc.
Un doc absent d'une liste n'ajoute rien pour cette liste.

Eine Textpassage, die bei BM25 auf Platz eins und bei der Vektorsuche auf Platz fünf steht, erhält 1/61 + 1/65, also etwa 0,0318; eine Textpassage auf Platz fünfzehn in beiden Listen erhält 2/75, also etwa 0,0267. Die Konstante k schwächt den Vorteil des allerersten Rangs ab: Je größer sie ist, desto stärker zählen weiter hinten liegende Ränge. Elasticsearch dokumentiert diese Konstante unter dem Namen rank_constant mit einem Standardwert von 60 sowie eine Fenstergröße (rank_window_size), die die Länge jeder Liste vor der Zusammenführung festlegt. Ein größeres Fenster verbessert die Relevanz auf Kosten der Performance, erläutert die Dokumentation.

#Und die Score-Fusion?

Einige Suchsysteme bieten eine Alternative: die Scores jeder Liste normalisieren und anschließend gewichtet zusammenführen. Weaviate dokumentiert beide Methoden, eine rangbasierte Zusammenführung und eine Zusammenführung anhand relativer Scores. Letztere ist seit Version 1.24 die Standardmethode; sie ist erforderlich, um autocut mit dem Hybridoperator zu verwenden. Qdrant bietet RRF und DBSF an. Letztere behält die Rohscores bei, normalisiert jedoch vor der Zusammenführung deren Verteilung (Mittelwert und Standardabweichung). Die rangbasierte Zusammenführung ist robuster, wenn die Verteilung der Scores unbekannt ist; die Zusammenführung anhand von Scores ermöglicht eine feinere Abstimmung, wenn Messungen möglich sind.

#Welches Tool: Suchmaschinen mit nativer Unterstützung für hybride Suche

Hybride Suche je nach Tool (offizielle Dokumentation, September 2026)
ToolNative hybride SucheFusionEinstellung der Gewichtung
QdrantJa, über die Query-API (seit Version 1.10 verfügbar)RRF oder DBSFGewichtung pro Abfrage und Konstante k in neueren Versionen einstellbar
WeaviateJa, mit dem Operator hybridRelative Ränge oder Scores (Standard ab Version 1.24)Parameter alpha: 1 = rein vektorbasiert, 0 = rein schlüsselwortbasiert
ElasticsearchJa, rrf-RetrieverRRFrank_constant (Standardwert: 60) und rank_window_size
SQLite FTS5 + VektorerweiterungMuss zusammengesetzt werdenNoch zu schreibenLiegt bei Ihnen
ChromaDB + rank_bm25In Python zusammenzustellenZu schreiben (RRF in 6 Zeilen)Liegt bei Ihnen

Der grundlegende Unterschied liegt nicht in der Zusammenführung selbst, die sich mit wenigen Codezeilen umsetzen lässt, sondern im Index: Eine Suchengine mit nativer Unterstützung hält beide Indizes gemeinsam aktuell, während eine selbst gebaute Lösung den BM25-Index im Arbeitsspeicher hält und ihn bei jedem neu hinzugefügten Dokument neu aufbauen muss. Für ein Korpus mit einigen Tausend Textabschnitten, das sich selten ändert, reicht die selbst gebaute Lösung völlig aus. Bei größeren Korpora oder sobald sich die Dokumente täglich ändern, vermeidet eine Suchengine mit nativer Unterstützung Inkonsistenzen zwischen den beiden Indizes. Die Anleitung zu Weaviate stellt dieses Tool ausführlich vor.

#Eigenentwicklung: ChromaDB, rank_bm25 und RRF

Der folgende Code kombiniert die drei Bausteine. Er behebt einen häufigen Fehler in Beispielen: Die Normalisierungsfunktion muss vor dem Filtern die diakritischen Zeichen entfernen, sonst teilt jeder akzentuierte Buchstabe ein Wort in zwei Teile.

Hybrid: BM25 + ChromaDB mit RRF
import re, unicodedata
import chromadb
from rank_bm25 import BM25Okapi

def normalize(txt):
    txt = unicodedata.normalize("NFKD", txt.lower())
    txt = "".join(c for c in txt if not unicodedata.combining(c))  # retire les accents
    return re.findall(r"[a-z0-9]+", txt)

# Indexation BM25 (en mémoire) : l'indice de la liste = l'identifiant du passage
all_docs = [d["text"] for d in load_docs()]
bm25 = BM25Okapi([normalize(d) for d in all_docs])

# ChromaDB : les ids doivent être les mêmes, sous forme de chaînes "0", "1", ...
coll = chromadb.PersistentClient("./chroma_db").get_collection("docs")

def rrf_fuse(rankings, weights=None, k=60):
    weights = weights or [1.0] * len(rankings)
    scores = {}
    for ranking, w in zip(rankings, weights):
        for rank, doc_id in enumerate(ranking, start=1):
            scores[doc_id] = scores.get(doc_id, 0) + w / (k + rank)
    return sorted(scores, key=scores.get, reverse=True)

def hybrid_search(question, top_k=5, n_candidates=20):
    s = bm25.get_scores(normalize(question))
    bm25_top = sorted(range(len(all_docs)), key=lambda i: -s[i])[:n_candidates]
    bm25_ranking = [str(i) for i in bm25_top]
    vec_ranking = coll.query(query_texts=[question], n_results=n_candidates)["ids"][0]
    fused = rrf_fuse([bm25_ranking, vec_ranking])
    return [all_docs[int(i)] for i in fused[:top_k]]
!
Stolperfalle bei der Tokenisierung französischer Texte
Bei der üblichen Normalisierung „NFKD, dann alles, was weder a-z noch eine Ziffer ist, durch ein Leerzeichen ersetzen“ wird „référence“ zu „re fe rence“: Jeder Akzent hinterlässt ein kombinierendes Zeichen, das durch ein Leerzeichen ersetzt wird. Der BM25-Teil funktioniert weiterhin für Identifikatoren, verfehlt aber sämtliche Wörter mit Akzenten. Testen Sie normalize an drei Sätzen, bevor Sie indexieren.

Zwei praktische Vorsichtsmaßnahmen. Erstens müssen die Kennungen in beiden Indizes identisch sein: Hier dient der Listenindex, in eine Zeichenkette umgewandelt, als Chroma-Kennung. Zweitens geht der BM25-Index im Arbeitsspeicher beim Beenden des Programms verloren: Bauen Sie ihn beim Start neu auf, was bei Zehntausenden von Textpassagen einige Sekunden dauert, oder speichern Sie die Dokumentenliste neben der Datenbank.

#Das Verhältnis zwischen BM25 und Vektorsuche einstellen

Standardmäßig gewichtet RRF beide Listen gleich. Wenn Ihr Korpus viele Referenzen enthält (Rechtsprechung, Tickets, Kataloge), geben Sie BM25 mehr Gewicht; wenn die Fragen dialogorientiert sind, behalten Sie die gleiche Gewichtung bei oder bevorzugen Sie die Vektorsuche. In der vorherigen Funktion genügt es, weights=[0.6, 0.4] zu übergeben, um BM25 mit 60 % zu gewichten. Qdrant ermöglicht dieselbe Einstellung: Laut Dokumentation beträgt das Gewicht jeder Abfrage standardmäßig 1, wodurch sich wieder die ursprüngliche RRF-Formel ergibt, und die Konstante k lässt sich in neueren Versionen einstellen. In Weaviate stellt man alpha ein: 1 entspricht einer reinen Vektorsuche, 0 einer reinen Schlüsselwortsuche.

Ausgangspunkt je nach Korpustyp
Korpus und FragenAnfangsgewichtung BM25 / VektorsucheWas Sie beobachten
Referenzen, Nummern, Eigennamen (Recht, Tickets, Kataloge)60 / 40Werden Fragen nach Identifikator zuerst zurückgegeben?
Ausformulierte Dokumentation, Fragen in natürlicher Sprache40 / 60Wird bei paraphrasierten Anfragen der richtige Abschnitt gefunden?
Gemischtes oder unbekanntes Korpus50 / 50Recall@5 bei 30 bis 50 echten Fragen
Abkürzungen und Fachbegriffe55 / 45, mit einem Synonymwörterbuch für BM25Finden die Abkürzung und die ausgeschriebene Form dieselbe Passage?
→
Vor dem Einstellen messen
Diese Werte sind Ausgangspunkte, keine gemessenen Ergebnisse. Stellen Sie 30 bis 50 echte Fragen mit der jeweils erwarteten Textpassage zusammen, berechnen Sie den Recall unter den ersten 5 Ergebnissen zunächst für BM25 allein, dann für die rein vektorbasierte und schließlich für die hybride Suche, und behalten Sie die hybride Suche nur bei, wenn sie bei Ihren Dokumenten besser abschneidet.

#Nach der Fusion: Reranker hinzufügen

Die Fusion liefert eine vielfältigere Kandidatenmenge als jede Methode allein. Ein Reranker kann diese Menge anschließend sortieren, indem er jeden Abschnitt zusammen mit der Frage liest: Die beiden Techniken lassen sich kombinieren. Der übliche Ablauf ist die hybride Suche, dann die Fusion, dann ein Reranker für die ersten 20 bis 50 Ergebnisse und schließlich die Aufnahme der 3 bis 5 besten Abschnitte in den Prompt. Der Leitfaden zum Reranker erläutert diesen letzten Schritt im Detail, und der Leitfaden zum Chunking erklärt, warum die Länge der Abschnitte sowohl BM25 als auch die Embeddings so stark beeinflusst.

#Häufige Fragen zu hybrider Suche

FAQ
Was ist die hybride Suche in einem RAG?+
Dabei werden zwei Suchverfahren für dieselbe Frage kombiniert: eine Vektorsuche, die Passagen mit ähnlicher Bedeutung findet, und eine Stichwortsuche (BM25), die Passagen mit denselben Begriffen findet. Die beiden Ranglisten werden zu einer einzigen zusammengeführt, meist mittels Reciprocal Rank Fusion, bevor die besten Passagen an das Modell übermittelt werden.
Sollten BM25- und Vektor-Scores vor der Addition normalisiert werden?+
Bei RRF ist das nicht nötig, da RRF nur die Rangpositionen verwendet. Genau darum geht es: Die beiden Skalen sind nicht vergleichbar. Wenn Sie lieber die Scores kombinieren möchten, müssen Sie diese zunächst normalisieren, wie es die Fusion anhand relativer Scores von Weaviate oder DBSF von Qdrant tut, und prüfen, ob das Ergebnis bei Änderungen am Korpus stabil bleibt.
Welchen Wert für k sollte man bei RRF wählen?+
Behalten Sie 60, den Standardwert von Elasticsearch, bei, solange Sie keinen Grund haben, etwas anderes zu wählen. Ein kleinerer Wert bevorzugt die allerersten Rangplätze stärker, ein größerer gibt weiter hinten liegenden Rangplätzen mehr Einfluss. Diese Einstellung hat im Vergleich zur Qualität der Tokenisierung und zur Anzahl der Kandidaten in jeder Liste wenig Einfluss.
Kann man mit ChromaDB eine hybride Suche durchführen?+
Ja, indem Sie die Vektorsuche von Chroma, einen BM25-Index in Python (mit der Bibliothek rank_bm25) und eine RRF-Fusion mit wenigen Zeilen Code kombinieren. Achten Sie darauf, in beiden Indizes dieselben Kennungen zu verwenden und bei der Tokenisierung die Akzentzeichen zu entfernen. Bei einem Korpus, das sich häufig ändert, erspart Ihnen eine Suchmaschine mit nativer Unterstützung für hybride Suche wie Qdrant oder Weaviate die Pflege zweier Indizes.
Verlangsamt die hybride Suche die Abfragen erheblich?+
Im Allgemeinen nur sehr wenig: BM25 auf einem Index im Arbeitsspeicher ist sehr schnell, und die Vektorsuche findet ohnehin bereits statt. Der eigentliche Aufwand entsteht durch einen eventuell nachgeschalteten Reranker und den Speicherbedarf des lexikalischen Index. Messen Sie die Zeit vom Anfang bis zum Ende Ihrer Abfragen, nicht die Dauer jedes einzelnen Schritts isoliert.
Wie kann man entscheiden, ob der hybride Ansatz für meine Dokumente sinnvoll ist?+
Vergleichen Sie bei 30 bis 50 echten Fragen, bei denen Sie den erwarteten Abschnitt kennen, die Trefferquote in den ersten 5 Ergebnissen von BM25 allein, dem Vektoransatz allein und der hybriden Methode. Wenn die hybride Methode keinen Vorteil bringt, ist Ihr Korpus möglicherweise rein konversationell und der Vektoransatz reicht aus. Wenn sie vor allem bei Identifikatoren gewinnt, erhöhen Sie das Gewicht von BM25.
Hat Ihnen dieser Guide geholfen?

Haben Sie Feedback, einen Fehler entdeckt oder möchten Sie etwas präzisieren? Geben Sie uns Bescheid – so wird der Guide für alle besser.