Кристи Бергман: почему я присоединилась к 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.
Читать далее
Stop Building AI Data Infra for the Wrong Stage
Learn how AI data infrastructure should evolve from prototype to enterprise scale, and when Vector Lakebase becomes the right architecture for AI apps.

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.

Selecting the Right ETL Tools for Unstructured Data to Prepare for AI
Learn the right ETL tools for unstructured data to power AI. Explore key challenges, tool comparisons, and integrations with Milvus for vector search.



