Ein Leitfaden für Softwareentwickler: Aufbau hochperformanter semantischer Suchsysteme mit Faiss und Milvus und Best Practices
Moderne Anwendungen müssen in der Lage sein, auf komplexe Benutzeranfragen nicht nur mit Schlüsselwörtern, sondern semantisch zu reagieren. Von Produktempfehlungen über die Dokumentsuche bis hin zu Chatbots und der Inhaltsfilterung geht die semantische Suche über traditionelle Methoden hinaus, um relevantere und reichhaltigere Ergebnisse zu liefern. In diesem Leitfaden werden wir Vektordatenbanken, die Schlüsselwerkzeuge für diese KI-gesteuerten Suchfunktionen, und ihre praktischen Anwendungen untersuchen.
Semantische Suche und Vektordarstellungen
Im Mittelpunkt der semantischen Suche steht die Idee, numerische Darstellungen (Embeddings) von Daten (Text, Bilder, Audio usw.) in hochdimensionalen Vektorräumen zu erstellen. Diese Vektoren erfassen den semantischen Inhalt der Daten; Daten, die semantisch nahe beieinander liegen, haben Vektoren, die sich auch in diesem Raum nahe beieinander befinden. Der Suchprozess beinhaltet die Berechnung der Ähnlichkeit zwischen der Vektordarstellung einer Abfrage und anderen Vektoren in der Datenbank.
Zur Erstellung von Vektordarstellungen werden typischerweise vorab trainierte Deep-Learning-Modelle verwendet. Für Texte stehen Optionen wie SBERT (Sentence-BERT) oder die Embedding-Modelle von OpenAI zur Verfügung. Hier ist ein einfaches SBERT-Embedding-Beispiel mit Python:
from sentence_transformers import SentenceTransformer
import numpy as np
# Ein vortrainiertes SBERT-Modell laden
model = SentenceTransformer('paraphrase-multilingual-MiniLM-L12-v2')
# Beispielsätze
sentences = [
"Wie werden Modelle der künstlichen Intelligenz trainiert?",
"Algorithmen für maschinelles Lernen",
"Architekturen des Deep Learning",
"Wie Computerhardware funktioniert?"
]
# Sätze in Vektoren umwandeln
embeddings = model.encode(sentences)
print("Vektordimension des ersten Satzes:", embeddings[0].shape)
print("Kosinusähnlichkeit zwischen den Vektoren der ersten 2 Sätze:", np.dot(embeddings[0], embeddings[1]) / (np.linalg.norm(embeddings[0]) * np.linalg.norm(embeddings[1])))
Warum Vektordatenbanken?
Traditionelle relationale oder NoSQL-Datenbanken sind nicht darauf ausgelegt, Ähnlichkeitssuchen zwischen hochdimensionalen Vektoren effizient durchzuführen. Das Finden des nächsten Nachbarn (Nearest Neighbor Search - NNS) oder des ungefähr nächsten Nachbarn (Approximate Nearest Neighbor - ANN) unter Millionen oder sogar Milliarden von Vektoren erfordert spezialisierte Algorithmen und Indizierungsstrukturen. Vektordatenbanken bieten optimierte Strukturen, die speziell für diese Herausforderung entwickelt wurden.
Lokale und In-Memory-Lösungen: Faiss
Faiss (Facebook AI Similarity Search) ist eine von Facebook AI entwickelte Bibliothek für hochperformante Ähnlichkeitssuche und Clustering. Sie ist speziell für schnelle Approximate Nearest Neighbor Suchen auf Millionen von Vektoren optimiert. Sie arbeitet In-Memory und ist im Allgemeinen für den Einsatz auf einem einzelnen Server oder clientseitig konzipiert.
Hier ist ein einfaches Beispiel für das Erstellen eines Faiss-Index und das Suchen:
import faiss
# Vektordimension und Anzahl der Datenpunkte
d = embeddings.shape[1] # 384
nb = embeddings.shape[0] # 4 (im Beispiel)
# Die Konvertierung zu Float32 ist eine gängige Anforderung für Faiss
xb = embeddings.astype('float32')
# Einen Faiss-Index erstellen (z.B. einen IndexFlatL2)
# Dieser Index speichert jeden Vektor und führt eine exakte Suche durch (NNS, nicht ANN)
index = faiss.IndexFlatL2(d)
print("Ist der Index trainiert?", index.is_trained) # Sollte True sein, da IndexFlatL2 kein Training benötigt
# Vektoren zum Index hinzufügen
index.add(xb)
print("Anzahl der Vektoren im Index:", index.ntotal)
# Einen Abfragevektor erstellen (z.B. den Vektor des ersten Satzes)
xq = np.array([model.encode("Informationen zum Training künstlicher Intelligenz")])
xq = xq.astype('float32')
# Die 2 nächsten Nachbarn suchen
k = 2
distances, indices = index.search(xq, k)
print("Distanzen der nächsten Nachbarn (L2):", distances)
print("Indizes der nächsten Nachbarn:", indices)
print("Nächste Sätze:", [sentences[i] for i in indices[0]])
Faiss bietet verschiedene Indextypen (IndexFlatL2, IndexIVFFlat, IndexHNSWFlat usw.), mit denen Sie Leistung und Genauigkeit ausbalancieren können. Für größere Datensätze ist die Verwendung von ANN-Algorithmen wie IndexIVFFlat oder IndexHNSWFlat effizienter.
Verteilte und skalierbare Lösungen: Milvus
Wenn Sie mit Milliarden von Vektoren arbeiten müssen oder hohe Verfügbarkeit und Skalierbarkeit in einem verteilten System benötigen, kommen Cloud-native Vektordatenbanken wie Milvus ins Spiel. Milvus ist ein Open-Source-System, das für die Vektorsuche im großen Maßstab entwickelt wurde und auf Plattformen wie Kubernetes bereitgestellt werden kann.
Hier ist ein Beispiel für das Erstellen einer Sammlung, das Hinzufügen von Vektoren und das Suchen mit Milvus (unter der Annahme einer auf Docker laufenden Milvus-Instanz):
from pymilvus import connections, FieldSchema, CollectionSchema, DataType, Collection, utility
import random
# Verbindung zum Milvus-Server herstellen
connections.connect("default", host="localhost", port="19530")
# Das Sammlungsschema definieren
fields = [
FieldSchema(name="id", dtype=DataType.INT64, is_primary=True, auto_id=True),
FieldSchema(name="embedding", dtype=DataType.FLOAT_VECTOR, dim=d), # d = 384 from SBERT
FieldSchema(name="text", dtype=DataType.VARCHAR, max_length=512)
]
schema = CollectionSchema(fields, "Dies ist eine Beispielsammlung für die semantische Suche.")
# Den Sammlungsnamen definieren
collection_name = "semantic_search_collection"
# Falls die Sammlung bereits existiert, löschen (für die Entwicklung)
if utility.has_collection(collection_name):
utility.drop_collection(collection_name)
# Die Sammlung erstellen
collection = Collection(collection_name, schema)
# Vektoren und zugehörigen Text vorbereiten
data = [
model.encode(s).tolist() for s in sentences
]
text_data = sentences
# Daten in Milvus einfügen
mr = collection.insert([data, text_data])
# Auf die Synchronisierung der Daten in Milvus warten
collection.flush()
print("Anzahl der hinzugefügten Vektoren:", collection.num_entities)
# Einen Index erstellen (z.B. IVFFlat)
index_params = {
"metric_type": "L2",
"index_type": "IVF_FLAT",
"params": {"nlist": 128}
}
collection.create_index(field_name="embedding", index_params=index_params)
# Die Sammlung zum Suchen in den Speicher laden
collection.load()
# Den Abfragevektor vorbereiten
search_vector = model.encode("Lernmethoden für künstliche Intelligenz").tolist()
# Suchparameter
search_params = {"metric_type": "L2", "params": {"nprobe": 10}}
# Die Suche durchführen
results = collection.search(
data=[search_vector],
anns_field="embedding",
param=search_params,
limit=2, # Die 2 nächsten Ergebnisse abrufen
expr=None,
output_fields=["text"]
)
print("Suchergebnisse:")
for hit in results[0]:
print(f"Distanz (L2): {hit.distance}, Text: {hit.entity.get('text')}")
# Die Sammlung aus dem Speicher freigeben
collection.release()
Im obigen Beispiel haben wir gesehen, wie man eine semantische Suchsammlung erstellt, Vektoren hinzufügt und abfragt, indem man die Kernfunktionen von Milvus verwendet. Milvus unterstützt verschiedene Indextypen wie FLAT, IVF_FLAT und HNSW und kann dank seiner verteilten Architektur problemlos große Datenmengen und Abfragelasten verwalten.
Best Practices
- Vektordimension und Qualität: Das von Ihnen verwendete Embedding-Modell und damit die Vektordimension haben direkten Einfluss auf die Suchgenauigkeit und -leistung. Wählen Sie das am besten geeignete Modell und die Vektordimension für Ihre Anwendung.
- Auswahl des Indextyps: Die Auswahl des richtigen Faiss- oder Milvus-Indextyps (z. B.
IVFFlat,HNSW) ist entscheidend, basierend auf Ihrer Datengröße und den Anforderungen an Genauigkeit/Geschwindigkeit. - Vorfilterung: Nutzen Sie die Filterfunktionen von Vektordatenbanken (wie den
expr-Parameter von Milvus), um semantische Suchen basierend auf bestimmten Metadaten einzugrenzen. Dies erhöht sowohl die Geschwindigkeit als auch die Relevanz. - Hybride Suche: Manchmal führt eine Kombination aus Stichwort- und semantischer Suche zu den besten Ergebnissen. Sie können hybride Suchfunktionen entwickeln, indem Sie Vektordatenbanken mit traditionellen Suchmaschinen (wie Elasticsearch) integrieren.
- Updates und Löschungen: Für dynamische Datensätze ist es wichtig, die Update- und Löschmechanismen von Vektordatenbanken gründlich zu verstehen und effektiv zu nutzen.
Fazit
Vektordatenbanken sind einer der Eckpfeiler moderner Anwendungen der künstlichen Intelligenz. Sie bieten eine breite Palette von Tools, von lokalen Lösungen wie Faiss bis hin zu verteilten Systemen wie Milvus, die es Entwicklern ermöglichen, skalierbare und intelligente Such-, Empfehlungs- und Datenanalysesysteme zu erstellen. Mit diesem praktischen Leitfaden haben Sie den ersten Schritt zur Stärkung Ihrer eigenen semantischen Suchfunktionen getan. Erkunden Sie weiterhin die Leistungsfähigkeit von Vektordatenbanken in Ihren Anwendungen!
Kommentare (0)
Noch keine Kommentare. Seien Sie der Erste!