Кристи Бергман: почему я присоединилась к Zilliz
Меня зовут Кристи Бергман, и недавно я присоединилась к Zilliz в качестве Developer Advocate в Сан-Франциско. Я буду организовывать, посещать мероприятия и выступать на них, писать блоги и руководства по коду, улучшать документацию и в целом помогать людям (надеюсь, таким как вы!) учиться использовать Milvus, самую популярную в мире векторную базу данных с открытым исходным кодом (по количеству звёзд на GitHub).
До Zilliz я была Developer Advocate в Anyscale, создателе open-source Ray, который делает распределённые вычисления простыми для всех разработчиков. До этого я была AWS AI/ML Specialist Solutions Architect, специализируясь на прогнозировании с помощью глубокого обучения.
Так почему же я решила присоединиться к Zilliz? Всё началось с моего любопытства по поводу улучшения ответов в чате ChatGPT путём добавления контекста в промпт. Затем я начала исследовать embeddings, а оттуда стала искать простую в использовании и быструю векторную базу данных. В этой публикации блога я проведу вас через шаги, которые привели меня сюда.
Сомнение: действительно ли мне нужна векторная база данных?
Вначале я сомневалась, действительно ли векторная база данных необходима. Однако несколько попыток поместить embedding текста в переменную Python, сериализовать и десериализовать его с помощью pickle убедили меня, что embeddings должны кэшироваться или сохраняться где-то лучше, чем в pickle.
Milvus — это полноценная база данных, изначально созданная специально для векторов. Тысячи разработчиков по всему миру используют Milvus, который включает поддержку множества различных алгоритмов векторного поиска, метрик расстояния в векторном пространстве и других функций, таких как Insert/upsert, TopK и Range Search, поддержка GPU и многое другое. Коммерческая версия называется Zilliz Cloud и имеет доступность по SLA 99,9%, автоматическое масштабирование, работает на AWS и GCP (Azure скоро появится), и вы можете запускать её в своём облачном аккаунте с полным соответствием SOC2.
Изучение вариантов: пробую разные векторные базы данных
Чтобы поместить embeddings в векторную базу данных, вам нужны: 1) неструктурированные данные, 2) план того, как разбить эти данные на фрагменты, 3) модель embedding и 4) векторная база данных.
Для данных я использовала большой набор данных рецензий на фильмы IMDB из Stanford AI Lab. Это удобно обработанный набор данных из 50 000 записей (соотношение выборки позитивных/негативных рецензий 50:50). В этих данных есть столбцы: movie_index, исходный текст рецензии и рейтинг фильма.
Для разбиения на фрагменты я решила сохранять рецензии на фильмы целиком, если только они не были очень длинными. Для очень длинных рецензий я использовала типичные фрагменты длиной по умолчанию 512. Это означает, что длинные рецензии разбивались на несколько фрагментов длиной 512 символов. На языке LLM это называется «размер фрагмента».
Для модели embedding я пробовала различные модели, включая повсеместно используемые embeddings OpenAI. Пока не поняла, что проще всего просто выбрать постоянно меняющуюся цель — самую маленькую модель с высоким рейтингом на вкладке Retriever в таблице лидеров MTEB HuggingFace. На тот момент я остановилась на «e5-base-v2». На самом деле хорошо, что выбор модели embedding независим от самой векторной базы данных.
Что касается баз данных, я пробовала FAISS, Qdrant, Chroma, Weaviate, Pinecone и, конечно, Milvus. Я проверяла их все по одним и тем же критериям: 1) Насколько легко и быстро можно загрузить данные напрямую из pandas в векторную базу данных? 2) Насколько легко, быстро и настраиваемо можно получать хорошие результаты запросов из векторной базы данных? 3) Насколько легко и гибко можно выполнять RAG с использованием LangChain (будущая публикация в блоге!).
Milvus выделяется
Среди всех баз данных, которые я изучила, Milvus привлекла мое внимание по нескольким причинам. Во-первых, она предлагала удобный пользовательский опыт, особенно при вставке данных напрямую из pandas с метаданными, поскольку это первый подход, который может попробовать Data Scientist.
Milvus также привлекла мое внимание своей скоростью загрузки векторов и выполнения запросов. Milvus была заметно более шустрой, чем другие подходы, некоторые из которых были медленными даже в таком небольшом масштабе. Я также обратила внимание на функции и выбрала настройки по умолчанию для других баз данных (IVF-flat exhaustive search с L2-metric), хотя Milvus поддерживает и другие варианты.
Ниже приведен gist для вставки pandas data frame в Milvus. Полный код находится на моем GitHub.
# Полный код находится по адресу: https://github.com/christy/ZillizDemos/blob/main/milvus_onboarding/hello_world_milvus.ipynb
###########
# 1. Загрузите для локального использования sentence transformer из HuggingFace Hub.
###########
import os
from dotenv import load_dotenv, find_dotenv
from huggingface_hub import login
_ = load_dotenv(find_dotenv())
hub_token = os.getenv("HUGGINGFACEHUB_API_TOKEN")
login(token=hub_token);
from sentence_transformers import SentenceTransformer
model_name = "BAAI/bge-base-en-v1.5"
retriever = SentenceTransformer(model_name, device="cuda")
# Получите параметры модели и сохраните их на потом.
MAX_SEQ_LENGTH = retriever.get_max_seq_length()
HF_EOS_TOKEN_LENGTH = 1
EMBEDDING_LENGTH = retriever.get_sentence_embedding_dimension()
###########
# 2. Выберите функцию разбиения на чанки из LangChain для удобства.
###########
from langchain.text_splitter import RecursiveCharacterTextSplitter
chunk_size = MAX_SEQ_LENGTH - HF_TOKEN_EOS_LENGTH
chunk_overlap = np.round(chunk_size * 0.10, 0)
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=chunk_size,
chunk_overlap=chunk_overlap,
length_function=len,
)
def chunk_text(text):
chunks = text_splitter.split_text(text)
return [chunk for chunk in chunks if chunk]
###########
# 3. Манипулируйте pandas dataframe.
# Скачать: https://ai.stanford.edu/~amaas/data/sentiment/aclImdb_v1.tar.gz
###########
# 1. Пакет данных из pandas DataFrame.
batch = df.head(100).copy()
# 2. Измените тип первичного ключа на string.
batch["movie_index"] = batch["movie_index"].apply(lambda x: str(x))
# 3. Обрежьте отзывы до 512 символов.
batch['chunk'] = batch['text'].apply(chunk_text)
batch = batch.explode('chunk', ignore_index=True)
# 4. Добавьте embeddings как новый столбец в df.
review_embeddings = torch.tensor(retriever.encode(batch['chunk']))
# Нормализуйте embeddings до единичной длины.
review_embeddings = F.normalize(review_embeddings, p=2, dim=1)
# 5. Преобразуйте embeddings в список `numpy.ndarray`, каждый из которых содержит числа `numpy.float32`.
converted_values = list(map(np.float32, review_embeddings))
batch['embeddings'] = converted_values
# 6. Переупорядочьте столбцы для удобства, чтобы index был первым, а labels — в конце.
new_order = ["movie_index", "text", "chunk", "embeddings", "label_int", "label"]
batch = batch[new_order]
###########
# 4. Установите и импортируйте milvus.
###########
!pip install milvus pymilvus
import milvus, pymilvus
###########
# 5. Определите schema для загрузки данных в Milvus.
###########
# Задайте имя коллекции Milvus.
COLLECTION_NAME = "movies"
fields = [
FieldSchema(name="pk", dtype=DataType.INT64, is_primary=True, auto_id=True),
FieldSchema(name="movie_index", dtype=DataType.VARCHAR, max_length=8),
FieldSchema(name="chunk", dtype=DataType.VARCHAR, max_length=MAX_SEQ_LENGTH),
FieldSchema(name="embeddings", dtype=DataType.FLOAT_VECTOR, dim=EMBEDDING_LENGTH),
FieldSchema(name="label_int", dtype=DataType.INT64),
FieldSchema(name="label", dtype=DataType.VARCHAR, max_length=8),
]
schema = CollectionSchema(fields, "Search imdb movie reviews")
mc = Collection(COLLECTION_NAME, schema, consistency_level="Eventually")
###########
6. Запустите локальный сервер Milvus (lite).
###########
default_server.start()
connections.connect(host='127.0.0.1',
port=default_server.listen_port,
show_startup_banner=True)
###########
# 7. Вставьте данные в Milvus.
###########
# Показываем, как изменить параметры индекса вместо использования значений по умолчанию.
index_params = {
"index_type": "HNSW",
"metric_type": "COSINE",
"params": {'M': 16, # int. 4~64, num_layers
"efConstruction": 32} # int. 8~512, num_nearest_neighbors
}
mc.create_index("embeddings", index_params)
insert_result = mc.insert(batch)
# После вставки последней сущности вызовите flush, чтобы остановить растущие сегменты, оставшиеся в памяти.
mc.flush()
###########
# 8. Выполните запрос к базе данных.
###########
# Перед выполнением поиска или запроса необходимо загрузить данные в память.
mc.load()
# Определите пример вопроса о ваших данных.
query = "I'm a medical doctor, what movie should I watch?"
# Создайте embedding запроса с помощью той же embedding-модели, которая использовалась для создания коллекции Milvus.
query_embeddings = torch.tensor(retriever.encode([query]))
# Нормализуйте embeddings до единичной длины.
query_embeddings = torch.nn.functional.normalize(query_embeddings, p=2, dim=1)
# Преобразуйте embeddings в список списков np.float32.
query_embeddings = list(map(np.float32, query_embeddings))
# Выполните векторный поиск с индексом HNSW.
TOP_K = 3
search_params = {
"M": 16,
"ef": 32,
}
results = mc.search(
data=query_embeddings,
anns_field="embeddings",
param=search_params,
output_fields=["movie_index", "chunk", "label"],
limit=TOP_K,
consistency_level="Eventually"
)
После моего (быстрого, неофициального) тестирования я заполнила онлайн-форму, чтобы подать заявку на вакансию Developer Advocate в Zilliz. После последнего собеседования команда Zilliz быстро сделала мне предложение. Поэтому, не раздумывая, я согласилась!
У меня потрясающие коллеги. Посмотрите блоги Yujian Tang и Frank Liu о том, почему они присоединились к Zilliz. Моя руководительница, Chris Churilo, — тот самый секретный клей, благодаря которому мы все так эффективно работаем вместе. Она использует свои знания и опыт, чтобы помочь каждому из нас проявить себя. Мой коллега Filip Haltmayer исключительно терпелив и отлично объясняет мне всё, что касается Milvus и Zilliz, во время моего onboarding. У нашего CEO, Charles Xie, еще в 2017 году появилось исходное видение — создать базу данных специально для неструктурированных данных.
Что дальше
Когда я начинаю заниматься evangelism для Milvus, я с нетерпением жду возможности познакомиться со всеми вами в сообществе AI-разработчиков! Я буду организовывать Meetup Unstructured Data в Сан-Франциско, где я всегда ищу отличных спикеров, площадки и соведущих (пожалуйста, напишите мне!). Я буду больше писать в блог и выступать (пожалуйста, свяжитесь со мной!). Если вы хотите попробовать open-source Milvus в своем проекте с неструктурированными данными, пожалуйста, дайте мне знать, чем я могу помочь!
Я участвую в нескольких организациях data science for good, включая DataKind, Women in Data Science и San Francisco Civil Hack nights от Code for America (которые познакомили меня с моей местной организацией Sonoma Safe Agriculture, где я создала интерактивную карту пестицидов). Пожалуйста, присоединяйтесь ко мне, когда я буду делиться своими новыми знаниями о векторных базах данных с более широким сообществом data-science-for-good.
Читать далее

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.

Zilliz Cloud Update: Smarter Autoscaling for Cost Savings, Stronger Compliance with Audit Logs, and More
What's new in Zilliz Cloud? Smarter autoscaling with scale-down, audit logs GA, enhanced SSO, and Milvus 2.6 in Private Preview.

How to Use Anthropic MCP Server with Milvus
MCP + Milvus: Streamline AI agent development with standardized data access, eliminating integration hassles while enhancing context and flexibility.



