Schnellstart mit Milvus Lite
Vektoren, das Ausgabedatenformat von Neuronalen Netzwerkmodellen, können Informationen effektiv kodieren und spielen eine zentrale Rolle in KI-Anwendungen wie Wissensdatenbanken, semantischer Suche, Retrieval Augmented Generation (RAG) und mehr.
Milvus ist eine Open-Source-Vektordatenbank, die sich für KI-Anwendungen jeder Größe eignet, von der Ausführung eines Demo-Chatbots in einem Jupyter-Notebook bis zum Aufbau einer Web-Suche, die Milliarden von Nutzern bedient. In dieser Anleitung zeigen wir Ihnen, wie Sie Milvus innerhalb weniger Minuten lokal einrichten und die Python-Client-Bibliothek zum Erzeugen, Speichern und Durchsuchen von Vektoren verwenden können.
Milvus installieren
In dieser Anleitung verwenden wir Milvus Lite, eine Python-Bibliothek, die in pymilvus
enthalten ist und in die Client-Anwendung eingebettet werden kann. Milvus unterstützt auch die Bereitstellung auf Docker und Kubernetes für Produktionsanwendungen.
Bevor Sie beginnen, stellen Sie sicher, dass Sie Python 3.8+ in der lokalen Umgebung verfügbar haben. Installieren Sie pymilvus
, das sowohl die Python-Client-Bibliothek als auch Milvus Lite enthält:
$ pip install -U pymilvus
Wenn Sie Google Colab verwenden, müssen Sie möglicherweise die Laufzeitumgebung neu starten, um die gerade installierten Abhängigkeiten zu aktivieren. (Klicken Sie auf das Menü "Runtime" am oberen Rand des Bildschirms und wählen Sie "Restart session" aus dem Dropdown-Menü).
Einrichten der Vektordatenbank
Um eine lokale Milvus-Vektordatenbank zu erstellen, richten Sie einfach eine MilvusClient
ein, indem Sie einen Dateinamen angeben, unter dem alle Daten gespeichert werden, z. B. "milvus_demo.db".
from pymilvus import MilvusClient
client = MilvusClient("milvus_demo.db")
Erstellen Sie eine Sammlung
In Milvus benötigen wir eine Sammlung, um Vektoren und ihre zugehörigen Metadaten zu speichern. Sie können sich das wie eine Tabelle in herkömmlichen SQL-Datenbanken vorstellen. Beim Erstellen einer Sammlung können Sie Schema- und Indexparameter definieren, um Vektorspezifikationen wie Dimensionalität, Indextypen und entfernte Metriken zu konfigurieren. Es gibt auch komplexe Konzepte zur Optimierung des Index für die Vektorsuchleistung. Konzentrieren wir uns zunächst auf die Grundlagen und verwenden wir für alles Mögliche die Standardeinstellungen. Zumindest müssen Sie nur den Sammlungsnamen und die Dimension des Vektorfeldes der Sammlung festlegen.
if client.has_collection(collection_name="demo_collection"):
client.drop_collection(collection_name="demo_collection")
client.create_collection(
collection_name="demo_collection",
dimension=768, # The vectors we will use in this demo has 768 dimensions
)
In der obigen Konfiguration,
- Der Primärschlüssel und die Vektorfelder verwenden ihre Standardnamen ("id" und "vector").
- Der metrische Typ (Vektorabstandsdefinition) ist auf den Standardwert(COSINE) eingestellt.
- Das Primärschlüsselfeld akzeptiert ganze Zahlen und wird nicht automatisch inkrementiert (d. h. es wird keine Auto-ID-Funktion verwendet). Alternativ können Sie das Schema der Sammlung formal definieren, indem Sie dieser Anweisung folgen.
Daten vorbereiten
In diesem Leitfaden verwenden wir Vektoren, um eine semantische Suche nach Text durchzuführen. Wir müssen Vektoren für Text generieren, indem wir Einbettungsmodelle herunterladen. Dies lässt sich leicht mit den Dienstprogrammen der Bibliothek pymilvus[model]
bewerkstelligen.
Text mit Vektoren darstellen
Installieren Sie zunächst die Modellbibliothek. Dieses Paket enthält wichtige ML-Tools wie PyTorch. Der Download des Pakets kann einige Zeit in Anspruch nehmen, wenn in Ihrer lokalen Umgebung PyTorch noch nicht installiert ist.
$ pip install "pymilvus[model]"
Erzeugen Sie Vektoreinbettungen mit dem Standardmodell. Milvus erwartet, dass die Daten als eine Liste von Wörterbüchern eingefügt werden, wobei jedes Wörterbuch einen Datensatz darstellt, der als Entität bezeichnet wird.
from pymilvus import model
# If connection to https://huggingface.co/ failed, uncomment the following path
# import os
# os.environ['HF_ENDPOINT'] = 'https://hf-mirror.com'
# This will download a small embedding model "paraphrase-albert-small-v2" (~50MB).
embedding_fn = model.DefaultEmbeddingFunction()
# Text strings to search from.
docs = [
"Artificial intelligence was founded as an academic discipline in 1956.",
"Alan Turing was the first person to conduct substantial research in AI.",
"Born in Maida Vale, London, Turing was raised in southern England.",
]
vectors = embedding_fn.encode_documents(docs)
# The output vector has 768 dimensions, matching the collection that we just created.
print("Dim:", embedding_fn.dim, vectors[0].shape) # Dim: 768 (768,)
# Each entity has id, vector representation, raw text, and a subject label that we use
# to demo metadata filtering later.
data = [
{"id": i, "vector": vectors[i], "text": docs[i], "subject": "history"}
for i in range(len(vectors))
]
print("Data has", len(data), "entities, each with fields: ", data[0].keys())
print("Vector dim:", len(data[0]["vector"]))
Dim: 768 (768,)
Data has 3 entities, each with fields: dict_keys(['id', 'vector', 'text', 'subject'])
Vector dim: 768
[Alternativ] Fake-Darstellung mit zufälligen Vektoren verwenden
Wenn Sie das Modell aufgrund von Netzwerkproblemen nicht herunterladen konnten, können Sie zur Umgehung des Problems Zufallsvektoren zur Darstellung des Textes verwenden und das Beispiel trotzdem beenden. Beachten Sie nur, dass das Suchergebnis die semantische Ähnlichkeit nicht widerspiegelt, da die Vektoren gefälscht sind.
import random
# Text strings to search from.
docs = [
"Artificial intelligence was founded as an academic discipline in 1956.",
"Alan Turing was the first person to conduct substantial research in AI.",
"Born in Maida Vale, London, Turing was raised in southern England.",
]
# Use fake representation with random vectors (768 dimension).
vectors = [[random.uniform(-1, 1) for _ in range(768)] for _ in docs]
data = [
{"id": i, "vector": vectors[i], "text": docs[i], "subject": "history"}
for i in range(len(vectors))
]
print("Data has", len(data), "entities, each with fields: ", data[0].keys())
print("Vector dim:", len(data[0]["vector"]))
Data has 3 entities, each with fields: dict_keys(['id', 'vector', 'text', 'subject'])
Vector dim: 768
Daten einfügen
Fügen wir nun die Daten in die Sammlung ein:
res = client.insert(collection_name="demo_collection", data=data)
print(res)
{'insert_count': 3, 'ids': [0, 1, 2], 'cost': 0}
Semantische Suche
Jetzt können wir semantische Suchen durchführen, indem wir den Text der Suchanfrage als Vektor darstellen und eine Vektorähnlichkeitssuche auf Milvus durchführen.
Vektorielle Suche
Milvus akzeptiert eine oder mehrere Vektorsuchanfragen zur gleichen Zeit. Der Wert der Variable query_vectors ist eine Liste von Vektoren, wobei jeder Vektor ein Array von Fließkommazahlen ist.
query_vectors = embedding_fn.encode_queries(["Who is Alan Turing?"])
# If you don't have the embedding function you can use a fake vector to finish the demo:
# query_vectors = [ [ random.uniform(-1, 1) for _ in range(768) ] ]
res = client.search(
collection_name="demo_collection", # target collection
data=query_vectors, # query vectors
limit=2, # number of returned entities
output_fields=["text", "subject"], # specifies fields to be returned
)
print(res)
data: ["[{'id': 2, 'distance': 0.5859944820404053, 'entity': {'text': 'Born in Maida Vale, London, Turing was raised in southern England.', 'subject': 'history'}}, {'id': 1, 'distance': 0.5118255615234375, 'entity': {'text': 'Alan Turing was the first person to conduct substantial research in AI.', 'subject': 'history'}}]"] , extra_info: {'cost': 0}
Die Ausgabe ist eine Liste von Ergebnissen, die jeweils auf eine Vektorsuchanfrage abgebildet werden. Jede Abfrage enthält eine Liste von Ergebnissen, wobei jedes Ergebnis den Primärschlüssel der Entität, den Abstand zum Abfragevektor und die Entitätsdetails mit dem angegebenen output_fields
enthält.
Vektorsuche mit Metadatenfilterung
Sie können die Vektorsuche auch unter Berücksichtigung der Werte der Metadaten durchführen (in Milvus "skalare" Felder genannt, da sich skalar auf Nicht-Vektordaten bezieht). Dies geschieht mit einem Filterausdruck, der bestimmte Kriterien angibt. Im folgenden Beispiel wird gezeigt, wie man mit dem Feld subject
suchen und filtern kann.
# Insert more docs in another subject.
docs = [
"Machine learning has been used for drug design.",
"Computational synthesis with AI algorithms predicts molecular properties.",
"DDR1 is involved in cancers and fibrosis.",
]
vectors = embedding_fn.encode_documents(docs)
data = [
{"id": 3 + i, "vector": vectors[i], "text": docs[i], "subject": "biology"}
for i in range(len(vectors))
]
client.insert(collection_name="demo_collection", data=data)
# This will exclude any text in "history" subject despite close to the query vector.
res = client.search(
collection_name="demo_collection",
data=embedding_fn.encode_queries(["tell me AI related information"]),
filter="subject == 'biology'",
limit=2,
output_fields=["text", "subject"],
)
print(res)
data: ["[{'id': 4, 'distance': 0.27030569314956665, 'entity': {'text': 'Computational synthesis with AI algorithms predicts molecular properties.', 'subject': 'biology'}}, {'id': 3, 'distance': 0.16425910592079163, 'entity': {'text': 'Machine learning has been used for drug design.', 'subject': 'biology'}}]"] , extra_info: {'cost': 0}
Standardmäßig werden die skalaren Felder nicht indiziert. Wenn Sie eine gefilterte Metadatensuche in großen Datenbeständen durchführen müssen, können Sie die Verwendung eines festen Schemas in Betracht ziehen und auch den Index aktivieren, um die Suchleistung zu verbessern.
Neben der Vektorsuche können Sie auch andere Arten von Suchen durchführen:
Abfrage
Eine Abfrage() ist eine Operation, die alle Entitäten abruft, die einem Kriterium entsprechen, wie z. B. einem Filterausdruck oder einigen IDs.
Zum Beispiel werden alle Entitäten abgefragt, deren Skalarfeld einen bestimmten Wert hat:
res = client.query(
collection_name="demo_collection",
filter="subject == 'history'",
output_fields=["text", "subject"],
)
Direktes Abrufen von Entitäten nach Primärschlüssel:
res = client.query(
collection_name="demo_collection",
ids=[0, 2],
output_fields=["vector", "text", "subject"],
)
Entitäten löschen
Wenn Sie Daten bereinigen möchten, können Sie Entitäten unter Angabe des Primärschlüssels oder alle Entitäten, die einem bestimmten Filterausdruck entsprechen, löschen.
# Delete entities by primary key
res = client.delete(collection_name="demo_collection", ids=[0, 2])
print(res)
# Delete entities by a filter expression
res = client.delete(
collection_name="demo_collection",
filter="subject == 'biology'",
)
print(res)
[0, 2]
[3, 4, 5]
Vorhandene Daten laden
Da alle Daten von Milvus Lite in einer lokalen Datei gespeichert werden, können Sie alle Daten auch nach Beendigung des Programms in den Speicher laden, indem Sie eine MilvusClient
mit der vorhandenen Datei erstellen. Dadurch werden zum Beispiel die Sammlungen aus der Datei "milvus_demo.db" wiederhergestellt und weiterhin Daten in diese Datei geschrieben.
from pymilvus import MilvusClient
client = MilvusClient("milvus_demo.db")
Löschen der Sammlung
Wenn Sie alle Daten in einer Sammlung löschen möchten, können Sie die Sammlung mit
# Drop collection
client.drop_collection(collection_name="demo_collection")
Mehr erfahren
Milvus Lite ist ideal für den Einstieg in ein lokales Python-Programm. Wenn Sie große Datenmengen haben oder Milvus in der Produktion verwenden möchten, können Sie sich über die Bereitstellung von Milvus auf Docker und Kubernetes informieren. Alle Bereitstellungsmodi von Milvus nutzen dieselbe API, sodass sich Ihr clientseitiger Code beim Wechsel zu einem anderen Bereitstellungsmodus nicht großartig ändern muss. Geben Sie einfach die URI und das Token eines Milvus-Servers an, der überall eingesetzt wird:
client = MilvusClient(uri="http://localhost:19530", token="root:Milvus")
Milvus bietet eine REST- und gRPC-API mit Client-Bibliotheken in Sprachen wie Python, Java, Go, C# und Node.js.