# Hybride Suche

HINWEIS

Dieser Leitfaden gilt nur für die DB-Version 1.5.0 oder höher.

Dieser Leitfaden erläutert, wie man eine hybride Volltext- und Vektorsuche in MyScale durchführt.

Sowohl die Volltextsuche als auch die Vektorsuche haben ihre eigenen Stärken und Schwächen. Die Volltextsuche eignet sich für grundlegende Stichwortsuche und Textabgleich, während die Vektorsuche sich durch die semantische Übereinstimmung zwischen Dokumenten und ein tiefes Verständnis der Semantik auszeichnet, aber möglicherweise bei kurzen Textabfragen an Effizienz verliert. Um die Vorteile beider Ansätze zu nutzen, wurde die hybride Suche entwickelt. Durch die Kombination von Volltextindizierung und Vektorsuche kann sie verschiedene Anforderungen an die Textsuche effektiv erfüllen, die Genauigkeit und Geschwindigkeit bei der Suche nach Texten verbessern und die Erwartungen der Benutzer an präzise Ergebnisse effizient erfüllen.

# Übersicht über das Tutorial

Dieses Dokument führt Sie durch drei Suchexperimente:

Vektorsuche in MyScale durchführen

Alle Dokument- und Abfragetexte verwenden das all-MiniLM-L6-v2 (opens new window)-Modell zur Vektorengenerierung und den Kosinusabstand zur Ähnlichkeitsmessung.

Textsuche in MyScale durchführen

MyScale integriert die Tantivy (opens new window)-Bibliothek, um die BM25-Indizierung für die Volltextsuche (FTS) zu ermöglichen. Durch die Indizierung aller Textdaten in der Tabelle ermöglicht die FTS-Fähigkeit von MyScale, Suchergebnisse basierend auf BM25-Werten zu rangieren und so relevantere und genauere Suchergebnisse zu liefern.

Verschmelzen von Vektor- und Textsuchergebnissen mit der RRF-Strategie

Wir verwenden die weit verbreitete Python-Bibliothek ranx (opens new window), um Vektor- und Textsuchergebnisse zu kombinieren. Diese Fusion verbessert die Anpassungsfähigkeit von Textsuchen in verschiedenen Szenarien und letztendlich die Suchgenauigkeit.

Illustration der hybriden Suche in MyScale

Bevor Sie beginnen, stellen Sie sicher, dass Sie einen MyScale-Cluster eingerichtet haben. Für Anweisungen zur Einrichtung verweisen wir auf unseren Schnellstart-Leitfaden (opens new window).

# Datensatz

Für das Experiment wurde der Wikipedia-Abstract-Datensatz (opens new window) von RediSearch verwendet, der 5.622.309 Dokumenteinträge umfasst. Der Text wurde mit dem all-MiniLM-L6-v2 (opens new window)-Modell verarbeitet, um 384-dimensionale Vektoren zu erstellen, die in der Spalte body_vector gespeichert sind. Die Ähnlichkeit zwischen den Vektoren wurde mit dem Kosinusabstand berechnet.

TIP

Weitere Informationen zur Verwendung von all-MiniLM-L6-v2 finden Sie in der Dokumentation von HuggingFace.

Der Datensatz wiki_abstract_with_vector.parquet (opens new window) hat eine Größe von 8,2 GB. Sie können den Inhalt unten vorab anzeigen, ohne ihn lokal herunterladen zu müssen, da wir ihn in den nachfolgenden Experimenten direkt über S3 in MyScale importieren werden.

id body title url body_vector
... ... ... ... ...
77 Jake Rodkin is an American .... and Puzzle Agent. Jake Rodkin https://en.wikipedia.org/wiki/Jake_Rodkin (opens new window) [-0.081793934,....,-0.01105572]
78 Friedlandpreis der Heimkehrer is ... of Germany. Friedlandpreis der Heimkehrer https://en.wikipedia.org/wiki/Friedlandpreis_der_Heimkehrer (opens new window) [0.018285718,...,0.03049711]
... ... ... ... ...

# Erstellung der Tabelle und Import der Daten

Um die Tabelle wiki_abstract_5m im SQL-Arbeitsbereich von MyScale zu erstellen, führen Sie den folgenden SQL-Befehl aus:

CREATE TABLE default.wiki_abstract_5m(
    `id` UInt64,
    `body` String,
    `title` String,
    `url` String,
    `body_vector` Array(Float32),
    CONSTRAINT check_length CHECK length(body_vector) = 384
)
ENGINE = MergeTree
ORDER BY id
SETTINGS index_granularity = 128;

Importieren Sie die Daten aus S3 in die Tabelle. Bitte haben Sie Geduld während des Datenimportprozesses.

INSERT INTO default.wiki_abstract_5m
SELECT * FROM s3('https://myscale-datasets.s3.ap-southeast-1.amazonaws.com/wiki_abstract_with_vector.parquet', 'Parquet');

Hinweis

Die geschätzte Zeit für den Datenimport beträgt etwa 10 Minuten.

Überprüfen Sie, ob es 5.622.309 Zeilen Daten in der Tabelle gibt, indem Sie diese Abfrage ausführen:

SELECT count(*) FROM default.wiki_abstract_5m;

Ausgabe:

count()
5622309

Um die Tabelle zu optimieren und die Leistung der Vektorsuche zu verbessern, indem die Daten in einen Teil zusammengeführt werden (optional), führen Sie diesen SQL-Befehl in Ihrem SQL-Arbeitsbereich aus:

OPTIMIZE TABLE default.wiki_abstract_5m FINAL;

Dieser Optimierungsschritt kann einige Zeit in Anspruch nehmen.

Überprüfen Sie mit dieser Abfrage, ob die Datenteile dieser Tabelle zu einem einzigen Teil komprimiert wurden:

SELECT COUNT(*) FROM system.parts WHERE table='wiki_abstract_5m' AND active=1;

Wenn erfolgreich, sehen Sie:

count()
1

# Index erstellen

# FTS-Index erstellen

TIP

Weitere Informationen zum Erstellen eines FTS-Index finden Sie in der Dokumentation zum FTS-Index.

Bei der Einrichtung eines FTS-Index haben Benutzer die Möglichkeit, den Tokenizer anzupassen. In diesem Beispiel wird der stem-Tokenizer zusammen mit der Anwendung von stop words verwendet. Der stem-Tokenizer kann Wortformen im Text übersehen, um präzisere Suchergebnisse zu erzielen. Durch die Verwendung von stop words werden häufige Wörter wie "a", "an", "of" und "in" herausgefiltert, um die Suchgenauigkeit zu verbessern.

ALTER TABLE default.wiki_abstract_5m
ADD INDEX body_idx (body)
TYPE fts('{"body":{"tokenizer":{"type":"stem", "stop_word_filters":["english"]}}}');

Materialisieren Sie den Index:

ALTER TABLE default.wiki_abstract_5m MATERIALIZE INDEX body_idx;

# Vektorindex erstellen

TIP

Erfahren Sie mehr über den MSTG-Vektorindex in der Dokumentation zur Vektorsuche.

Um den MSTG-Vektorindex mit Kosinus als Berechnungsmethode für den body_vec_idx in der Tabelle default.wiki_abstract_5m zu erstellen, führen Sie diesen SQL-Befehl aus:

ALTER TABLE default.wiki_abstract_5m
ADD VECTOR INDEX body_vec_idx body_vector
TYPE MSTG('metric_type=Cosine');

Der Aufbau eines Vektorindex kann zeitaufwändig sein. Um den Fortschritt zu überwachen, führen Sie diese SQL-Abfrage aus. Wenn die Spalte "status" "Built" anzeigt, bedeutet dies, dass der Index erfolgreich erstellt wurde. Während des Fortschritts sollte "InProgress" angezeigt werden.

SELECT * FROM system.vector_indices;

# Hybride Suche durchführen

# Vorbereitungen

Um den Abfragetext in Vektoren umzuwandeln, verwenden wir das all-MiniLM-L6-v2 (opens new window)-Modell.

Installieren Sie zunächst die Bibliothek sentence-transformers, indem Sie Folgendes ausführen:

pip install -U sentence-transformers

Für die Fusion verwenden wir die Bibliothek ranx (opens new window). Installieren Sie sie mit:

pip install -U ranx

Die hybride Suche wird in einer Python-Datei implementiert. Bevor Sie mit dieser Übung fortfahren, stellen Sie sicher, dass Sie Ihre MyScale-Cluster-Informationen in den bereitgestellten Beispielcode eingeben.

TIP

Die Verbindungsdetails für einen MyScale-Cluster finden Sie in der Webkonsole.

import clickhouse_connect
from numba import NumbaTypeSafetyWarning
from prettytable import PrettyTable
from ranx import Run, fuse
from ranx.normalization import rank_norm
from sentence_transformers import SentenceTransformer
import warnings
warnings.filterwarnings('ignore', category=NumbaTypeSafetyWarning)
# Verwenden Sie das Modell all-MiniLM-L6-v2
model = SentenceTransformer('sentence-transformers/all-MiniLM-L6-v2')
# MyScale-Informationen
host = "Ihr Cluster-Endpunkt"
port = 443
username = "Ihr Benutzername"
password = "Ihr Passwort"
database = "default"
table = "wiki_abstract_5m"
# Initialisieren Sie den MyScale-Client
client = clickhouse_connect.get_client(host=host, port=port,
                                       username=username, password=password)
# Verwenden Sie eine Tabelle, um Ihren Inhalt auszugeben
def print_results(result_rows, field_names):
    x = PrettyTable()
    x.field_names = field_names
    for row in result_rows:
        x.add_row(row)
    print(x)

# Vektorsuche durchführen

TIP

Die British Graham Land Expedition (BGLE) war eine britische Expedition. Detaillierte Informationen finden Sie in Wikipedia (opens new window).

Unser Ziel ist es, die von der BGLE-Expedition in diesem Datensatz besuchten und kartierten Orte zu identifizieren. Dazu verwenden wir "Charted by BGLE" als Suchzeichenfolge bei einer Vektorsuchabfrage.

TIP

Fügen Sie den in dieser Nachricht bereitgestellten Beispielcode in die zuvor erstellte Python-Datei ein, um eine reibungslose Ausführung des Programms zu gewährleisten. Stellen Sie außerdem sicher, dass Sie die anderen Schritte in ähnlicher Weise behandeln.

terms = "Charted by BGLE"
terms_embedding = model.encode([terms])[0]
vector_search = f"SELECT id, title, body, distance('alpha=3')" \
                f"(body_vector,{list(terms_embedding)}) AS distance FROM {database}.{table} " \
                f"ORDER BY distance ASC LIMIT 100"
vector_search_res = client.query(query=vector_search)
print("\nErgebnisse der Vektorsuche:")
print_results(vector_search_res.result_rows[:10], ["ID", "Titel", "Text", "Abstand"])

Die über die Vektorsuche abgerufenen Dokumente enthalten keine Informationen zu "Charted by BGLE" in den ersten 10 Ergebnissen, da die Vektorsuche für kurze Textabfragen tendenziell schlecht abschneidet.

ID Titel Text Abstand
1177089 B.G. discography Dies ist die Diskografie von B.G. 0.44516414403915405
2710950 Ruy Blas and the Blasé Roué Ruy Blas and the Blasé Roué ist eine Burleske von A. C. 0.4736078381538391
4571962 BLL BLL kann sich beziehen auf: 0.48070353269577026
3797998 Bles Bles kann sich beziehen auf: 0.4849556088447571
4558187 The Complete Blam Blam Blam The Complete Blam Blam Bam ist eine Kompilation LP von Blam Blam Blam. Sie wurde im November 1992 veröffentlicht. 0.4863016605377197
5556733 BLG BLG kann sich beziehen auf: 0.49544525146484375
4591273 Blagg Blagg kann sich beziehen auf: 0.5007722973823547
3087541 Paul Bley discography Dies ist die Diskografie des kanadischen Jazzmusikers Paul Bley. 0.5030192136764526
3389086 Blot (album) Blot ist das vierte Studioalbum der norwegischen Black-/Viking-Metal-Band Einherjer. Es wurde am 21. November 2003 von Tabu Recordings veröffentlicht. 0.5040180087089539
1876940 Blåljus! Blåljus! ist eine sechsbändige Taschenbuchserie von Romanen von Margit Sandemo und wurde von der schwedischen Tochtergesellschaft Boknöje AB der norwegischen Veröffentlichung Bladkompaniet im Jahr 2004 veröffentlicht. 0.5080643892288208

# Textsuche durchführen

Wir verwenden die TextSearch()-Funktion von MyScale, um eine Reihe relevanter Ergebnisse zusammen mit BM25-Werten abzurufen. Um die spätere Ergebnisfusion zu erleichtern, müssen wir diese Dokumentendaten vorübergehend speichern.

text_search = f"SELECT id, title, body, TextSearch(body, '{terms}') AS score " \
              f"FROM {database}.{table} " \
              f"ORDER BY score DESC LIMIT 100"
text_search_res = client.query(query=text_search)
# Suchergebnisse vorübergehend speichern.
stored_data = {}
for row in vector_search_res.result_rows:
    stored_data[str(row[0])] = {"title": row[1], "body": row[2]}
for row in text_search_res.result_rows:
    if str(row[0]) not in stored_data:
        stored_data[str(row[0])] = {"title": row[1], "body": row[2]}

# Verwenden der RRF-Strategie zur Verschmelzung von Vektor- und Textsuchergebnissen

Wir verwenden die ranx (opens new window)-Bibliothek, um Vektor- und Textsuchergebnisse zu kombinieren und die RRF-Fusionsstrategie (Reciprocal Rank Fusion) zur Verbesserung der Suchgenauigkeit zu implementieren. Für alternative Fusionsstrategien können Sie ranx/fusion (opens new window) konsultieren.

# ID und Score aus den Abfrageergebnissen extrahieren.
bm25_dict = {"query-0": {str(row[0]): float(row[3]) for row in text_search_res.result_rows}}
# Für die ranx-Bibliothek wird erwartet, dass ein höherer Score eine größere Relevanz anzeigt,
# daher ist eine Vorverarbeitung für Vektordistanzberechnungsmethoden wie Kosinus und L2 erforderlich.
max_value = max(float(row[3]) for row in vector_search_res.result_rows)
vector_dict = {"query-0": {str(row[0]): max_value - float(row[3]) for row in vector_search_res.result_rows}}
# Score der Abfrageergebnisse normalisieren.
vector_run = rank_norm(Run(vector_dict, name="vector"))
bm25_run = rank_norm(Run(bm25_dict, name="bm25"))
# Fusion der Abfrageergebnisse mit RRF.
combined_run = fuse(
    runs=[vector_run, bm25_run],
    method="rrf",
    params={'k': 10}
)
print("\nFusions-Ergebnisse:")
pretty_results = []
for id_, score in combined_run.get_doc_ids_and_scores()[0].items():
    if id_ in stored_data:
        pretty_results.append([id_, stored_data[id_]["title"], stored_data[id_]["body"], score])
print_results(pretty_results[:10], ["ID", "Titel", "Text", "Score"])

Die Ergebnisse der Fusionsabfrage lauten wie folgt: Die hybride Suche hat fünf Artikel genau den Orten zugeordnet, die von der BGLE-Expedition kartiert wurden, und zeigt damit die Vorteile der hybriden Suche bei der Verarbeitung von kurzen Textabfragen.

ID Title Body Score
200245 Salmon Island Salmon Island () is the westernmost of the Fish Islands, lying off the west coast of Graham Land. Charted by the British Graham Land Expedition (BGLE) under Rymill, 1934-37. 0.09090909090909091
1177089 B.G. discography This is the discography of B.G. 0.09090909090909091
5024941 Woozle Hill Woozle Hill () is a hill near the center of Galindez Island, in the Argentine Islands in the Wilhelm Archipelago. First charted by the British Graham Land Expedition (BGLE) under Rymill, 1934-37. 0.08333333333333333
2710950 Ruy Blas and the Blasé Roué Ruy Blas and the Blasé Roué is a burlesque written by A. C. 0.08333333333333333
4571962 BLL BLL may refer to: 0.07692307692307693
4426976 Symington Islands Symington Islands () is a group of small islands lying west-northwest of Lahille Island, in the Biscoe Islands. Charted by the British Graham Land Expedition (BGLE) under Rymill, 1934-37. 0.07692307692307693
3797998 Bles Bles may refer to: 0.07142857142857142
197443 Tadpole Island Tadpole Island () is an island just north of Ferin Head, off the west coast of Graham Land. Charted by the British Graham Land Expedition (BGLE) under Rymill, 1934-37. 0.07142857142857142
202128 Sohm Glacier Sohm Glacier () is a glacier flowing into Bilgeri Glacier on Velingrad Peninsula, the west coast of Graham Land. Charted by the British Graham Land Expedition (BGLE) under Rymill, 1934-37. 0.06666666666666667
4558187 The Complete Blam Blam Blam The Complete Blam Blam Bam is a compilation LP by Blam Blam Blam. It was released on November, 1992. 0.06666666666666667

# Fazit

Dieses Dokument gibt Einblicke in die Verwendung der hybriden Suche von MyScale in Szenarien der Textsuche und konzentriert sich auf Methoden und Techniken zur Suche in unstrukturierten Textdaten. In der praktischen Übung haben wir ein Beispiel mit Wikipedia-Abstracts entwickelt. Die Durchführung einer hybriden Suche ist mit den fortschrittlichen Volltext- und Vektorsuchfunktionen von MyScale einfach und liefert durch die Kombination von Stichwort- und semantischen Informationen genauere Ergebnisse.

Last Updated: Tue May 07 2024 02:28:12 GMT+0000