Missverständnisse über die Geschwindigkeit der Dateneinfügung in Milvus aufklären
Viele Nutzer, die sich wegen der praktischen und kürzeren API-Schritte auf LangChain oder LlamaIndex verlassen, könnten denken: „Das Einfügen von Daten in Milvus ist langsam.“ Diese Wahrnehmung entsteht jedoch oft dadurch, dass die detaillierten Prozessschritte übergangen werden.
Die verborgenen Schritte
Bei der Verwendung von LangChain oder LlamaIndex wandeln diese Bibliotheken unstrukturierte Daten (wie Texte, Bilder oder Geräusche) mithilfe von Embedding-Modellen in Vektoren um. Anschließend fügen sie diese Vektoren in Milvus Lite ein. Die Bibliotheken vereinfachen diesen komplexen Prozess, indem sie mehrere Schritte im Hintergrund für Sie übernehmen.
Diese Abstraktion kann den Eindruck erwecken, dass der Dateneinfügeprozess lange dauert.
Der Zeitfresser: Embedding-Erzeugung
Die durchschnittliche Zeit, die für die Erzeugung von Embeddings aus unstrukturierten Daten aufgewendet wird, ist deutlich länger als die Zeit, die zum Einfügen von Daten in Milvus erforderlich ist. Die wahrgenommene Langsamkeit ist oft auf den rechenintensiven Prozess der Umwandlung der Daten in Vektordarstellungen zurückzuführen und nicht auf den Schritt des Dateneinfügens.
Um den Unterschied zwischen den Zeiten für Embedding-Erzeugung und Dateneinfügung zu veranschaulichen, zeige ich in diesem Blog ein Beispiel, bei dem die durchschnittliche Embedding-Zeit etwa 5 Sekunden beträgt. Im Gegensatz dazu beträgt die durchschnittliche Einfügezeit in die Milvus-Vektordatenbank nur etwa eine Zehntelsekunde. Der vollständige Code befindet sich auf meinem GitHub.
Mit anderen Worten: Rund 97 % der in LangChain oder LlamaIndex beobachteten „Milvus insert“-Zeit werden für die Embedding-Erzeugung aufgewendet, während etwa 3 % auf den eigentlichen Datenbank-Einfügeschritt entfallen.
Ich habe in einem früheren Blog gezeigt, wie man entweder mit LlamaIndex oder LangChain eine Verbindung zu Milvus Lite herstellt.
In den folgenden Abschnitten behandle ich:
Beispiel für LlamaIndex-Code zum Einfügen von Daten in Milvus
Beispiel für LangChain-Code zum Einfügen von Daten in Milvus
Beispiel für Pymilvus-API-Code zum Einfügen von Daten in Milvus
Beispiel für LlamaIndex-Code zum Einfügen von Daten in Milvus
Hier ist ein Beispielcode in LlamaIndex.
from llama_index.core import (
ServiceContext,
StorageContext,
VectorStoreIndex,
)
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from llama_index.vector_stores.milvus import MilvusVectorStore
import time
# Define the embedding model.
service_context = ServiceContext.from_defaults(
# LlamaIndex local: translates to the same location as default HF cache.
embed_model="local:BAAI/bge-large-en-v1.5",
)
# Create a Milvus collection from the documents and embeddings.
EMBEDDING_DIM = 1024
vectorstore = MilvusVectorStore(
uri="./milvus_llamaindex.db",
dim=EMBEDDING_DIM,
# Override LlamaIndex default values for Milvus.
consistency_level="Eventually",
drop_old=True,
index_params = {
"metric_type": "COSINE",
"index_type": "AUTOINDEX",
"params": {},}
)
storage_context = StorageContext.from_defaults(
vector_store=vectorstore
)
llamaindex = VectorStoreIndex.from_documents(
lli_docs[:1],
storage_context=storage_context,
service_context=service_context
)
Beispiel für LangChain-Code zum Einfügen von Daten in Milvus
Hier ist ein Beispielcode in LangChain.
from langchain_milvus import Milvus
from langchain_huggingface import HuggingFaceEmbeddings
from langchain.text_splitter import RecursiveCharacterTextSplitter
import time
# Define the embedding model.
model_name = "BAAI/bge-large-en-v1.5"
model_kwargs = {'device': 'cpu'}
encode_kwargs = {'normalize_embeddings': True}
embed_model = HuggingFaceEmbeddings(
model_name=model_name,
model_kwargs=model_kwargs,
encode_kwargs=encode_kwargs
)
EMBEDDING_DIM = embed_model.dict()['client'].get_sentence_embedding_dimension()
# Define the chunking strategy.
text_splitter = RecursiveCharacterTextSplitter(chunk_size=512, chunk_overlap=51)
# Create a Milvus collection from the documents with chunking and embeddings.
start_time = time.time()
docs = text_splitter.split_documents(docs)
vectorstore = Milvus.from_documents(
documents=docs,
embedding=embed_model,
connection_args={"uri": "./milvus_demo.db"},
# Override LangChain default values for Milvus.
consistency_level="Eventually",
drop_old=True,
index_params = {
"metric_type": "COSINE",
"index_type": "AUTOINDEX",
"params": {},}
)
Beispiel für Pymilvus-API-Code zum Einfügen von Daten in Milvus
Lassen Sie uns anhand direkter Pymilvus-API-Aufrufe zeigen, was tatsächlich hinter den Kulissen dieser kurzen, praktischen LangChain- und LlamaIndex-Codes geschieht.
Die obigen Beispiele verwendeten Milvus-Dokumentationswebseiten, die direkt aus dem Internet heruntergeladen wurden. Um den Unterschied zwischen Einbettungszeiten und Einfügezeiten zu zeigen, verwende ich unten ein Open-Source-multimodales Einbettungsmodell, um 1) sowohl Bilder als auch Texte einzubetten und 2) die dichten Vektoren in Milvus einzufügen.
import pymilvus
import requests
from io import BytesIO
# Run this in small batches to avoid memory issues.
BATCH_SIZE = 10
# Batch embed text and images and insert data into Milvus.
batch_embedding_times = []
batch_insert_times = []
for i in range(0, 300, BATCH_SIZE):
batch_images = []
batch_texts = []
batch_urls = []
for j in range(BATCH_SIZE):
if i + j < len(image_texts):
text = image_texts[i + j]
url = image_urls[i + j]
with Image.open(f"./images/{url}.jpg") as img:
batch_images.append(img.copy())
batch_texts.append(text)
batch_urls.append(url)
# STEP 1. EMBEDDING INFERENCE FOR TEXT AND IMAGES.
start_time = time.time()
image_embeddings, text_embeddings = embedding_model(
batch_images=batch_images,
batch_texts=batch_texts)
end_time = time.time()
# print(f"Embedding time for batch size {len(batch_images)}: ", end="")
# print(f"{np.round(end_time - start_time, 2)} seconds")
batch_embedding_times.append(end_time - start_time)
# STEP 2. INSERT CHUNK LIST INTO MILVUS OR ZILLIZ.
chunk_dict_list = []
# Create chunk dict_list.
for chunk, img_url, img_embed, text_embed in zip(
batch_texts,
batch_urls,
image_embeddings, text_embeddings):
chunk_dict = {
'chunk': chunk,
'image_filepath': img_url,
'text_vector': text_embed,
'image_vector': img_embed
}
chunk_dict_list.append(chunk_dict)
start_time = time.time()
try:
col.insert(data=chunk_dict_list)
except:
print(f"Insert error: {img_url}")
end_time = time.time()
# print(f"Insert time for {len(chunk_dict_list)} vectors: ", end="")
# print(f"{np.round(end_time - start_time, 4)} seconds")
batch_insert_times.append(end_time - start_time)
col.flush()
# Calculate the average embedding time.
average_time = np.mean(batch_embedding_times)
print(f"Average embedding time: {round(average_time,2)} seconds")
# Calculate the average insert time.
average_time = np.mean(batch_insert_times)
print(f"Average insert time: {round(average_time,2)} seconds")
Hier ist die Ausgabe der Batch-Einbettungszeiten.
Hier ist die Ausgabe der Zeiten für das Einfügen von Batch-Daten in Milvus.
Die durchschnittliche Embedding-Zeit betrug ~5 Sekunden, und die durchschnittliche Einfügezeit in die Milvus-Vektordatenbank lag bei etwa einer Zehntelsekunde. Das bedeutet, dass etwa 97 % der Gesamtzeit für die Embedding-Generierung aufgewendet wurden, während etwa 3 % für das Einfügen in die Datenbank benötigt wurden.
Wie Sie sehen können, dauert der Embedding-Schritt am längsten!
Ressourcen und weiterführende Lektüre
Weiterlesen

Zilliz Cloud Now Available in AWS Europe (Ireland)
Zilliz Cloud launches in AWS eu-west-1 (Ireland) — bringing low-latency vector search, EU data residency, and full GDPR-ready infrastructure to European AI teams. Now live across 30 regions on five cloud providers.

Announcing the General Availability of Zilliz Cloud BYOC on Google Cloud Platform
Zilliz Cloud BYOC on GCP offers enterprise vector search with full data sovereignty and seamless integration.

Vector Databases vs. Key-Value Databases
Use a vector database for AI-powered similarity search; use a key-value database for high-throughput, low-latency simple data lookups.



