Che cos'è Pymilvus?
Introduzione
Pymilvus è l'SDK Python creato per Milvus e Zilliz Cloud. È un client basato su gRPC che utilizza un protobuf Milvus comune condiviso tra tutti gli SDK. Sia per i nuovi utenti sia per quelli avanzati, fornisce accesso a tutte le funzionalità offerte da Milvus ed è uno dei nostri SDK più popolari.
Problemi che stavamo riscontrando
L'idea chiave alla base del database vettoriale Milvus è dare agli utenti il maggior numero possibile di leve per aiutarli a perfezionare il sistema in base al loro caso d'uso specifico. Tuttavia, la ricerca approssimata è, nella sua essenza, approssimata; non esiste un algoritmo valido per tutti. Ciascuno degli algoritmi eccelle in termini di calcolo vs. velocità vs. recall/accuratezza. Inoltre, ciascuno degli algoritmi può essere configurato per ottenere un diverso equilibrio tra le categorie precedenti. Ad esempio, HNSW vs. IVF-PQ. IVF-PQ è ottimizzato per calcolo e velocità, riducendo significativamente il carico di memoria e i tempi di ricerca al costo di un recall significativamente ridotto. HNSW è l'opposto; HNSW sacrifica il calcolo a favore di velocità e recall. L'aspetto interessante è che i loro punti di forza possono essere scambiati tramite configurazione. Tutta questa configurazione è solo a livello di indice. A livello di cluster, ci sono equilibri da trovare in termini di costo vs velocità, il che è unico per ciascun utente. Alcuni utenti potrebbero non preoccuparsi dell'alta disponibilità e non volere la replica. Alcuni utenti potrebbero non preoccuparsi della coerenza e preferire essere meno coerenti a vantaggio della velocità. Alcuni utenti potrebbero voler associare un TTL ai propri dati per ridurre i costi di storage, mentre altri desiderano che ogni operazione sia sottoposta a backup. Sebbene questa personalizzazione sia eccellente per i grandi utenti, per i quali trovare il giusto equilibrio è vantaggioso su dataset dell'ordine dei miliardi, per gli utenti più piccoli tutte queste leve aggiungono semplicemente troppa confusione.
Oltre al fatto che queste leve rappresentano un problema, al momento Zilliz Cloud e Milvus non sono intercambiabili a causa degli indici e dei parametri di connessione.
Cos'è MilvusClient
MilvusClient è un tentativo di semplificare l'API per la maggior parte degli utenti. Molti utenti non vogliono gestire connessioni, schemi, indicizzazione, caricamento, parametri, ecc. MilvusClient nasconde tutti questi aspetti racchiudendo l'SDK Pymilvus in un'API semplice che è identica sia per Milvus sia per Zilliz. Al momento, offre:
- insert_data()
- upsert_data()
- search_data()
- query_data()
- get_vectors_by_pk()
- delete_by_pk()
- add_partition()
- remove_partition()
Queste funzioni sono state scelte come le funzioni chiave di cui qualsiasi utente di base avrebbe bisogno. Al momento attuale, le operazioni sono offerte da Pymilvus, ma ci sono molte cose extra che devono essere fatte per garantire che funzionino correttamente.
insert_data:
Usando MilvusClient, non è necessario creare uno schema per una collection. Invece, lo schema viene generato automaticamente dai dati inseriti. Questo comporta la determinazione del FieldSchema richiesto e di come organizzarlo. Molti utenti hanno trovato la creazione di questo schema un punto critico, ed è per questo che lo facciamo dietro le quinte. Una volta supportato lo schema dinamico, potremo modificare l'implementazione senza cambiamenti per l'utente.
def _infer_fields(self, data):
"""Infer all the fields based on the input data."""
# TODO: Assuming ordered dict for 3.7
fields = {}
# Figure out each datatype of the input.
for key, value in data.items():
# Infer the corresponding datatype of the metadata
dtype = infer_dtype_bydata(value)
# Datatype isnt compatible
if dtype in (DataType.UNKNOWN, DataType.NONE):
logger.error(
"Failed to parse schema for collection %s, unrecognized dtype for key: %s",
self.collection_name,
key,
)
raise ValueError(f"Unrecognized datatype for {key}.")
# Create an entry under the field name
fields[key] = {}
fields[key]["name"] = key
fields[key]["dtype"] = dtype
# Area for attaching kwargs for certain datatypes
if dtype == DataType.VARCHAR:
fields[key]["max_length"] = 65_535
return fields
Per MilvusClient, volevamo attenerci a un formato di dati simile a quello di altri progetti del settore: un elenco di dizionari. Questo formato è facile da comprendere e utilizzare ed è equivalente ai Documents presenti in LlamaIndex e LangChain. Tuttavia, questo formato è incompatibile con pymilvus, poiché l'inserimento di pymilvus accetta dati colonnari come elenco di elenchi. Questo formato di dati colonnare non è facile da usare, poiché comporta l'ordinamento degli elenchi nell'esatto ordine in cui è stato definito lo schema e non offre alcuna flessibilità. Inoltre, i messaggi di errore ricevuti per dati formattati in modo errato potrebbero essere migliori.
for k in data:
for key, value in k.items():
if key in self.fields:
insert_dict.setdefault(key, []).append(value)
for i in self.tqdm(range(0, len(data), batch_size), disable=not progress_bar):
# Convert dict to list of lists batch for insertion
try:
insert_batch = [
insert_dict[key][i : i + batch_size]
for key in self.fields
if key != ignore_pk
]
Con tutte le modifiche future in arrivo per schema, JSON, ecc., avere un wrapper attorno a un semplice inserimento ci permetterà di occuparci del lavoro più complesso e lasciare all'utente una API semplice.
upsert_data:
Nella versione 2.2, upsert non esiste in Milvus. Per eseguire un upsert, è necessario eseguire un delete -> insert. Poiché molti utenti cercano questa funzionalità, abbiamo deciso di includerla nel client. Una volta che la funzionalità sarà aggiunta a pymilvus, saremo in grado di modificarla facilmente senza richiedere cambiamenti nel codice dell'utente.
pks = [x[self.pk_field] for x in data]
self.delete_by_pk(pks, timeout)
ret = self.insert_data(
data=data,
timeout=timeout,
batch_size=batch_size,
partition=partition,
progress_bar=progress_bar,
)
search_data:
Le modifiche principali al comando search sono state i parametri di ricerca predefiniti e la conversione degli output in un elenco di dizionari.
ret = []
for hits in res:
query_result = []
for hit in hits:
ret_dict = {x: hit.entity.get(x) for x in return_fields}
query_result.append({"score": hit.score, "data": ret_dict})
ret.append(query_result)
query_data:
Le modifiche principali al comando query sono state la conversione degli output in un elenco di dizionari.
get_vectors_by_pk:
L'estrazione dei vettori in pymilvus viene eseguita tramite query. Ciò che molti utenti non sanno è che la query deve essere eseguita in base a un filtro sulla chiave primaria. Oltre a questo, se si utilizza una chiave primaria varchar, l'espressione nella query dovrà contenere virgolette con escape, qualcosa di noioso e sconosciuto agli utenti.
# Varchar pks need double quotes around the values
if self.fields[self.pk_field] == DataType.VARCHAR:
ids = ['"' + str(entry) + '"' for entry in pks]
expr = f"""{self.pk_field} in [{','.join(ids)}]"""
else:
ids = [str(entry) for entry in pks]
expr = f"{self.pk_field} in [{','.join(ids)}]"
delete_by_pk:
Simile a get_vectors_by_pk.
add_partition e delete_partition:
Per la logica delle partizioni, gli utenti devono sapere che la modifica delle partizioni richiede lo scaricamento e il caricamento di una collection. Questo ora viene gestito dietro le quinte.
Conclusione:
Nel complesso, l'obiettivo principale di questo client è aggiungere operazioni facili da usare che non esistono o non sono ottimizzate dal lato pymilvus. Man mano che pymilvus migliorerà, saremo in grado di ottimizzare queste operazioni dietro le quinte e mantenere una API semplice da usare.
Continua a leggere

How to Install and Run OpenClaw (Previously Clawdbot/Moltbot) on Mac
Turn your Mac into an AI gateway for WhatsApp, Telegram, Discord, iMessage, and more — in under 5 minutes.

How Zilliz Saw the Future of Vector Databases—and Built for Production
An inside look at how Zilliz built vector databases for real-world use, focusing on scalability, stability, and running them reliably at scale.

Why AI Databases Don't Need SQL
Whether you like it or not, here's the truth: SQL is destined for decline in the era of AI.



