Что такое Pymilvus?
Введение
Pymilvus — это Python SDK, созданный для Milvus и Zilliz Cloud. Это клиент на основе gRPC, который использует общий Milvus protobuf, единый для всех SDK. Для новых и продвинутых пользователей он предоставляет доступ ко всем функциям, предлагаемым Milvus, и является одним из наших самых популярных SDK.
Проблемы, с которыми мы сталкивались
Ключевая идея векторной базы данных Milvus — предоставить пользователям как можно больше рычагов управления, чтобы помочь точно настроить систему под их конкретный сценарий использования. Однако приблизительный поиск по своей сути является приблизительным; универсального алгоритма не существует. Каждый из алгоритмов имеет свои преимущества в соотношении вычислений, скорости и recall/точности. Более того, каждый из алгоритмов можно настроить так, чтобы достичь разного баланса между предыдущими категориями. Например, HNSW против IVF-PQ. IVF-PQ оптимизирован для вычислений и скорости, значительно снижая нагрузку на память и время поиска ценой существенно сниженного recall. HNSW — противоположность; HNSW жертвует вычислениями ради скорости и recall. Интересно то, что их сильные стороны можно менять с помощью конфигурации. Вся эта конфигурация находится только на уровне индекса. На уровне кластера необходимо находить баланс между стоимостью и скоростью, что уникально для каждого пользователя. Некоторым пользователям может быть не важна высокая доступность, и они не хотят репликации. Некоторым пользователям может быть не важна согласованность, и они предпочли бы меньшую согласованность ради преимущества в скорости. Некоторые пользователи могут захотеть назначить TTL своим данным, чтобы снизить затраты на хранение, в то время как другие хотят, чтобы каждая операция резервировалась. Хотя такая настраиваемость отлично подходит для крупных пользователей, где выжимание баланса полезно на наборах данных размером в миллиарды, для небольших пользователей все эти рычаги лишь добавляют слишком много путаницы.
Помимо того, что эти рычаги являются проблемой, на данный момент Zilliz Cloud и Milvus не взаимозаменяемы из-за индексов и параметров подключения.
Что такое MilvusClient
MilvusClient — это попытка упростить API для большинства пользователей. Многие пользователи не хотят иметь дело с подключениями, схемами, индексированием, загрузкой, параметрами и т. д. MilvusClient скрывает все эти аспекты, оборачивая Pymilvus SDK простым API, одинаковым как для Milvus, так и для Zilliz. На данный момент он предлагает:
- insert_data()
- upsert_data()
- search_data()
- query_data()
- get_vectors_by_pk()
- delete_by_pk()
- add_partition()
- remove_partition()
Было решено, что эти функции являются ключевыми функциями, которые понадобятся любому базовому пользователю. В настоящий момент операции предлагаются Pymilvus, но есть много дополнительных вещей, которые необходимо сделать, чтобы убедиться, что они работают корректно.
insert_data:
При использовании MilvusClient нет необходимости создавать схему для коллекции. Вместо этого схема автоматически генерируется из вставляемых данных. Это включает определение необходимой FieldSchema и способа ее организации. Многие пользователи считали создание этой схемы болезненным моментом, поэтому мы делаем это за кулисами. Как только будет поддерживаться динамическая схема, мы сможем изменить реализацию без изменений для пользователя.
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
Для MilvusClient мы хотели придерживаться формата данных, похожего на другие проекты в этой области, — списка словарей. Этот формат прост для понимания и работы и эквивалентен Documents, используемым в LlamaIndex и LangChain. Однако этот формат несовместим с pymilvus, поскольку insert в pymilvus принимает колоночные данные в виде списка списков. Этот колоночный формат данных неудобен в работе, так как требует упорядочивать списки точно в том порядке, в котором была создана схема, и не предлагает никакой гибкости. Кроме того, сообщения об ошибках, получаемые при неправильно отформатированных данных, могли бы быть лучше.
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
]
С учетом всех будущих изменений, связанных со схемой, JSON и т. д., наличие обертки вокруг простой вставки позволит нам выполнять тяжелую работу и оставить пользователю простой API.
upsert_data:
В версии 2.2 upsert в Milvus не существует. Чтобы выполнить upsert, необходимо выполнить delete -> insert. Поскольку многие пользователи ищут эту возможность, мы решили включить ее в клиент. Как только эта функция будет добавлена в pymilvus, мы сможем легко изменить ее, не требуя изменений в коде пользователя.
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:
Ключевыми изменениями в команде поиска стали параметры поиска по умолчанию и преобразование выходных данных в список словарей.
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:
Ключевыми изменениями в команде query стало преобразование выходных данных в список словарей.
get_vectors_by_pk:
Извлечение векторов в pymilvus выполняется через querying. Многие пользователи не знают, что запрос должен выполняться на основе фильтра по первичному ключу. Кроме того, при использовании первичного ключа varchar выражение в запросе должно содержать экранированные кавычки, что является утомительным и неизвестным пользователям.
# 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:
Аналогично get_vectors_by_pk.
add_partition and delete_partition:
Для логики partition пользователям необходимо знать, что изменение partitions требует выгрузки и загрузки collection. Теперь это обрабатывается за кулисами.
Conclusion:
В целом, основная цель этого клиента — добавить простые в использовании операции, которые отсутствуют или не оптимизированы на стороне pymilvus. По мере улучшения pymilvus мы сможем оптимизировать эти операции за кулисами и сохранить простой в использовании API.
Читать далее

3 Easiest Ways to Use Claude Code on Your Mobile Phone
Run Claude Code from your phone with Remote Control, Happy Coder, or SSH + Tailscale. Comparison table, setup steps, and tools for typing, memory, and parallel tasks.

DeepSeek-OCR Explained: Optical Compression for Scalable Long-Context and RAG Systems
Discover how DeepSeek-OCR uses visual tokens and Contexts Optical Compression to boost long-context LLM efficiency and reshape RAG performance.

AI Integration in Video Surveillance Tools: Transforming the Industry with Vector Databases
Discover how AI and vector databases are revolutionizing video surveillance with real-time analysis, faster threat detection, and intelligent search capabilities for enhanced security.



