Lässt es sich mit cremefarbenem Papier, einer Tönung, mehr Kontrast oder größerer Schrift besser lesen? Wählen Sie Ihre Farben und Ihre Schrift, einmalig für alle Seiten.

Kostenlose Lektion

Hybride Suche mit BM25 und Vektoren

Nach dieser Lektion: Ich kann Stichwort- und Bedeutungssuche zu einer Rangliste verbinden und sagen, wann welche gewinnt.

Lektion, 65 Min.5 BefehleLab für KI-Coding-Agenten: mit opencode Code erklären und reparieren lassen und die Arbeit prüfen

Zwei Suchen, zwei blinde Flecken

Die hybride Suche startet eine Stichwortsuche und eine Bedeutungssuche und verschmilzt die beiden Ranglisten. Sie ist wichtig, weil jede Suche verpasst, was die andere findet.

Jemand tippt „Benutzername vergessen“. Keine Hilfeseite enthält „Benutzername“, also findet die Stichwortsuche nichts. Eine andere Person tippt „Bestellnummer 4417“. Die Bedeutungssuche weiß nicht, was 4417 ist.

Das Ziel dieser Lektion

Notiz

Ich kann Stichwort- und Bedeutungssuche zu einer Rangliste verbinden und sagen, wann welche gewinnt.

Schlüsselwörter

BegriffWas er bedeutet
BM25ein Stichwortwert, der seltene Wörter und kurze Seiten belohnt
Termhäufigkeitwie oft ein Wort in einem Dokument vorkommt
Inverse Dokumenthäufigkeitein hohes Gewicht für Wörter, die wenige Dokumente enthalten
Rangder Platz eines Ergebnisses in einer Liste, ab 1 gezählt
Reziproke RangverschmelzungListen verbinden, indem man 1 durch k plus Rang addiert
Lexikalische Sucheeine Suche, die die Wörter selbst vergleicht

Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.

BM25 bewertet die Wörter selbst

Eine Stichwortsuche zählt die Wörter der Anfrage in jedem Dokument. BM25 verbessert diese einfache Zählung auf drei Arten. Ein Wort zählt mehr, wenn nur wenige Dokumente es enthalten. Jede Wiederholung hilft weniger. Ein kurzes Dokument schlägt ein langes mit gleicher Zählung.

Das Ergebnis ist exakt: Ein fehlendes Wort bringt nichts. Das ist Stärke und blinder Fleck zugleich.

Die Bedeutungssuche vergleicht Vektoren

Beim Thema Embeddings wurde Text zu Vektoren, und es wurde deren Richtung verglichen. Hier hat jede Hilfeseite drei erfundene Zahlen: wie sehr sie von Konto, Lieferung und Geld handelt.

Die Anfrage erhält eigene Zahlen, und die nächsten Seiten gewinnen. „Benutzername vergessen“ handelt vor allem vom Konto. Kontoseiten kommen also zuerst, ohne ein gemeinsames Wort. Ein echtes System bekommt seine Vektoren aus einem Embedding-Modell mit Hunderten Zahlen.

Verschmelzen Sie Ränge, nie Werte

BM25-Werte reichen von 0 bis zehn oder mehr. Kosinus-Werte bleiben zwischen 0 und 1. Würde man sie addieren, übertönte eine Liste die andere.

Die reziproke Rangverschmelzung ignoriert Werte und nutzt Ränge. Ein Element erhält aus jeder Liste, die es enthält, 1 / (60 + Rang), und die Punkte werden addiert. Ein Element, das beide Listen mögen, schlägt eines, das nur eine mag.

Durchgerechnetes Beispiel: Bestellnummer 4417

SeiteRang nach WörternRang nach BedeutungVerschmolzene Punkte
d4 Paket verfolgen130,0323
d3 Erstattungkeiner10,0164
d5 Bezahlenkeiner20,0161

Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.

Ein häufiger Fehler

Warnung

Viele glauben, hybride Suche bedeute, die beiden Werte zu addieren. Die Skalen unterscheiden sich, also gewinnt immer dieselbe Liste. Addieren Sie stattdessen Ränge mit 1 / (k + Rang), dann haben beide Listen gleiches Gewicht.

Die hybride Suche schreiben, Teil 1

Befehl
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const seiten = [' '  { id: \"d1\", text: \"Passwort über die Anmeldeseite zurücksetzen\", v: [9, 0, 1] },' '  { id: \"d2\", text: \"E-Mail-Adresse Ihres Kontos ändern\", v: [8, 1, 0] },' '  { id: \"d3\", text: \"Erstattung für zurückgeschickte Pakete\", v: [1, 5, 8] },' '  { id: \"d4\", text: \"Paket mit der Bestellnummer verfolgen\", v: [0, 9, 1] },' '  { id: \"d5\", text: \"Mit Karte oder Überweisung bezahlen\", v: [1, 1, 9] },' '  { id: \"d6\", text: \"Konto und Daten löschen\", v: [7, 0, 2] },' '];' 'const K1 = 1.5, B = 0.75;' 'function woerter(t) { return t.toLowerCase().split(\" \"); }' 'const mittel = seiten.reduce(function (s, d) { return s + woerter(d.text).length; }, 0) / seiten.length;' > hybrid1.js"

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Die hybride Suche schreiben, Teil 2

Befehl
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function bm25(anfrage, seite) {' '  let punkte = 0;' '  woerter(anfrage).forEach(function (w) {' '    const n = seiten.filter(function (d) { return woerter(d.text).includes(w); }).length;' '    if (n === 0) return;' '    const idf = Math.log(1 + (seiten.length - n + 0.5) / (n + 0.5));' '    const f = woerter(seite.text).filter(function (x) { return x === w; }).length;' '    const laenge = woerter(seite.text).length;' '    punkte += idf * f * (K1 + 1) / (f + K1 * (1 - B + B * laenge / mittel));' '  });' '  return punkte;' '}' >> hybrid1.js"

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Die hybride Suche schreiben, Teil 3

Befehl
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function kosinus(a, b) {' '  let prod = 0, sa = 0, sb = 0;' '  for (let i = 0; i < a.length; i++) { prod += a[i] * b[i]; sa += a[i] * a[i]; sb += b[i] * b[i]; }' '  return prod / Math.sqrt(sa * sb);' '}' 'function rangliste(werte) {' '  return seiten.map(function (d, i) { return { id: d.id, s: werte[i] }; })' '    .filter(function (x) { return x.s > 0.01; })' '    .sort(function (x, y) { return y.s - x.s; })' '    .map(function (x) { return x.id; });' '}' 'function verschmelzen(listen) {' '  const summe = {};' '  listen.forEach(function (liste) {' '    liste.forEach(function (id, stelle) { summe[id] = (summe[id] || 0) + 1 / (60 + stelle + 1); });' '  });' '  return Object.keys(summe).sort(function (x, y) { return summe[y] - summe[x]; });' '}' >> hybrid1.js"

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Die hybride Suche schreiben, Teil 4

Befehl
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const anfragen = [' '  { text: \"Benutzername vergessen\", v: [9, 0, 0] },' '  { text: \"Bestellnummer 4417\", v: [2, 3, 3] },' '];' 'anfragen.forEach(function (q) {' '  const a = rangliste(seiten.map(function (d) { return bm25(q.text, d); }));' '  const b = rangliste(seiten.map(function (d) { return kosinus(q.v, d.v); })).slice(0, 3);' '  console.log(q.text);' '  console.log(\"  Wörter:\", a.join(\" \") || \"nichts\");' '  console.log(\"  Bedeutung:\", b.join(\" \"));' '  console.log(\"  verschmolzen:\", verschmelzen([a, b]).join(\" \"));' '});' >> hybrid1.js"

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Starten und die Listen vergleichen

Befehl
docker exec -w /home/node/project agent node hybrid1.js

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Das ist ein Platzhalter

Der Run ruft kein Modell auf. Die Vektoren sind drei erfundene Zahlen, und sechs Seiten stehen für einen Index. Ein echtes System enthält Millionen Seiten und holt seine Vektoren aus einem Embedding-Modell.

Die Form bleibt gleich: zwei Ranglisten, dann eine verschmolzene Liste.

Was der Run ausgibt

AnfrageWörterBedeutungVerschmolzen
Benutzername vergessennichtsd1 d2 d6d1 d2 d6
Bestellnummer 4417d4d3 d5 d4d4 d3 d5

Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.

Über dieses Lab und seinen Quellcode: Lab für KI-Coding-Agenten: mit opencode Code erklären und reparieren lassen und die Arbeit prüfen

Sie unterrichten eine Gruppe? Weisen Sie dieses Modul Ihren Studierenden zu, mit Handbuch für Lehrende, automatisch geprüften Aufgaben und einem Lab für jede Person.