Christy Bergman: Por que entrei para a Zilliz
Meu nome é Christy Bergman, e recentemente entrei para a Zilliz como Developer Advocate baseada em São Francisco. Vou organizar, participar e palestrar em eventos, escrever blogs e tutoriais de código, melhorar a documentação e, em geral, ajudar pessoas (como você, espero!) a aprender como usar o Milvus, o banco de dados vetorial open-source mais popular do mundo (medido por estrelas no GitHub).
Antes da Zilliz, fui Developer Advocate na Anyscale, criadora do Ray open-source, que torna a computação distribuída fácil para todos os desenvolvedores. Antes disso, fui AWS AI/ML Specialist Solutions Architect focada em previsão com deep learning.
Então, por que escolhi entrar para a Zilliz? Tudo começou com minha curiosidade sobre como melhorar as respostas de chat do ChatGPT injetando contexto no prompt. Depois comecei uma jornada para experimentar embeddings e, a partir daí, passei a procurar um banco de dados vetorial rápido e fácil de usar. Neste post do blog, vou mostrar a você as etapas que me trouxeram até aqui.
A dúvida: eu realmente preciso de um banco de dados vetorial?
No início, questionei se um banco de dados vetorial era mesmo necessário. No entanto, algumas tentativas de incorporar texto em uma variável Python, fazer pickle e unpickle, me fizeram acreditar que embeddings devem ser armazenados em cache ou persistidos em algum lugar melhor do que pickle.
Milvus é um banco de dados completo criado desde o início especificamente para vetores. Milhares de desenvolvedores no mundo todo usam Milvus, que inclui suporte a muitos algoritmos diferentes de busca vetorial, métricas de distância em espaço vetorial e outros recursos como Insert/upsert, TopK e Range Search, suporte a GPU e muito mais. A versão comercial se chama Zilliz Cloud e tem disponibilidade SLA de 99,9%, auto-scaling, roda na AWS e no GCP (Azure em breve), e você pode executar na sua conta de cloud com total conformidade SOC2.
Explorando as opções: testando diferentes bancos de dados vetoriais
Para colocar embeddings em um banco de dados vetorial, você precisa de: 1) dados não estruturados, 2) um plano de como dividir esses dados em chunks, 3) um modelo de embedding e 4) um banco de dados vetorial.
Para os dados, usei o IMDB large movie review dataset do Stanford AI Lab. É um conjunto de dados convenientemente processado com 50.000 itens (proporção amostrada 50:50 de avaliações Positivas/Negativas). Esses dados têm as colunas: movie_index, texto bruto da avaliação e classificação do filme.
Para o chunking, escolhi manter as avaliações de filmes inteiras, a menos que fossem muito longas. Para avaliações muito longas, usei os chunks típicos padrão de comprimento 512. Isso significa que avaliações longas foram divididas em várias partes de 512 caracteres. No jargão de LLM, isso é chamado de “chunk size”.
Para o modelo de embedding, experimentei vários modelos, incluindo os onipresentes embeddings da OpenAI. Até perceber que o mais fácil era simplesmente selecionar o alvo sempre em movimento do menor modelo, mais bem classificado na aba Retriever, no leaderboard MTEB do HuggingFace. Na época, fiquei com “e5-base-v2”. Na verdade, é uma coisa boa que a escolha do modelo de embedding seja independente do próprio banco de dados vetorial.
Para os bancos de dados, testei FAISS, Qdrant, Chroma, Weaviate, Pinecone e, claro, Milvus. Submeti todos aos mesmos testes: 1) Quão fácil e rápido é carregar diretamente do pandas para o banco de dados vetorial? 2) Quão fácil, rápido e ajustável é obter bons resultados de consulta do banco de dados vetorial? 3) Quão fácil e ajustável é realizar RAG usando LangChain (futuro post do blog!).
Milvus se destaca
Entre todos os bancos de dados que explorei, o Milvus chamou minha atenção por vários motivos. Primeiro, ele ofereceu uma experiência fácil de usar, especialmente ao inserir dados diretamente do pandas com metadados, já que esta é a primeira abordagem que um Cientista de Dados poderia tentar.
O Milvus também chamou minha atenção por causa de sua velocidade ao carregar vetores e realizar consultas. O Milvus foi visivelmente mais ágil do que outras abordagens, algumas das quais eram lentas, mesmo nesta pequena escala. Também observei os recursos e escolhi as configurações padrão para outros bancos de dados (busca exaustiva IVF-flat com métrica L2), embora o Milvus ofereça suporte a outras opções.
Abaixo está um gist para inserir um data frame do pandas no Milvus. O código completo está no meu GitHub.
# Complete code is at: https://github.com/christy/ZillizDemos/blob/main/milvus_onboarding/hello_world_milvus.ipynb
###########
# 1. Download to use locally, a sentence transformer from 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")
# Get the model parameters and save for later.
MAX_SEQ_LENGTH = retriever.get_max_seq_length()
HF_EOS_TOKEN_LENGTH = 1
EMBEDDING_LENGTH = retriever.get_sentence_embedding_dimension()
###########
# 2. Choose a chunking function from LangChain for convenience.
###########
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. Manipulate a pandas dataframe.
# Download: https://ai.stanford.edu/~amaas/data/sentiment/aclImdb_v1.tar.gz
###########
# 1. Batch of data from pandas DataFrame.
batch = df.head(100).copy()
# 2. Change primary key type to string.
batch["movie_index"] = batch["movie_index"].apply(lambda x: str(x))
# 3. Truncate reviews to 512 characters.
batch['chunk'] = batch['text'].apply(chunk_text)
batch = batch.explode('chunk', ignore_index=True)
# 4. Add embeddings as new column in df.
review_embeddings = torch.tensor(retriever.encode(batch['chunk']))
# Normalize embeddings to unit length.
review_embeddings = F.normalize(review_embeddings, p=2, dim=1)
# 5. Convert embeddings to list of `numpy.ndarray`, each containing `numpy.float32` numbers.
converted_values = list(map(np.float32, review_embeddings))
batch['embeddings'] = converted_values
# 6. Reorder columns for conveneince, so index first, labels at end.
new_order = ["movie_index", "text", "chunk", "embeddings", "label_int", "label"]
batch = batch[new_order]
###########
# 4. Install and import milvus.
###########
!pip install milvus pymilvus
import milvus, pymilvus
###########
# 5. Define schema for data loading into Milvus.
###########
# Set the Milvus collection name.
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. Inicie um servidor Milvus local (lite).
###########
default_server.start()
connections.connect(host='127.0.0.1',
port=default_server.listen_port,
show_startup_banner=True)
###########
# 7. Insira dados no Milvus.
###########
# Mostrando como alterar os parâmetros do índice, em vez de usar os padrões.
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)
# Depois que a entidade final for inserida, chame flush para interromper segmentos em crescimento deixados na memória.
mc.flush()
###########
# 8. Consulte o banco de dados.
###########
# Antes de realizar uma busca ou uma consulta, você precisa carregar os dados na memória.
mc.load()
# Defina uma pergunta de exemplo sobre seus dados.
query = "I'm a medical doctor, what movie should I watch?"
# Faça o embedding da consulta usando o mesmo modelo de embedding usado para criar a coleção Milvus.
query_embeddings = torch.tensor(retriever.encode([query]))
# Normalize os embeddings para comprimento unitário.
query_embeddings = torch.nn.functional.normalize(query_embeddings, p=2, dim=1)
# Converta os embeddings para uma lista de listas de np.float32.
query_embeddings = list(map(np.float32, query_embeddings))
# Execute uma busca vetorial com índice 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"
)
Após meus testes (rápidos e não oficiais), preenchi um formulário online para me candidatar a uma vaga de Developer Advocate na Zilliz. Depois que tive minha última entrevista, a equipe da Zilliz foi rápida em me fazer uma oferta. Então, sem hesitar, aceitei!
Tenho colegas de trabalho fabulosos. Veja os blogs de Yujian Tang e Frank Liu sobre por que eles se juntaram à Zilliz. Minha chefe, Chris Churilo, é a cola secreta que explica por que todos trabalhamos juntos com tanta eficiência. Ela usa seu conhecimento e experiência para fazer todos nós brilharmos. Meu colega Filip Haltmayer é excepcionalmente paciente e bom em me explicar tudo sobre Milvus e Zilliz durante meu onboarding. Nosso CEO, Charles Xie, teve a visão original em 2017 de criar um banco de dados especialmente para dados não estruturados.
O que vem a seguir
À medida que começo a fazer trabalho de evangelismo para o Milvus, estou ansiosa para conhecer todos vocês na comunidade de desenvolvedores de IA! Vou organizar o Meetup Unstructured Data em San Francisco, onde estou sempre procurando ótimos palestrantes, locais e coanfitriões (por favor, entrem em contato comigo!). Vou escrever mais no blog e palestrar mais (por favor, entrem em contato!). Se você quiser experimentar o Milvus open-source em seu projeto de dados não estruturados, por favor me diga como posso ajudar!
Estou envolvida com várias organizações de ciência de dados para o bem, incluindo DataKind, Women in Data Science e as San Francisco Civil Hack nights da Code for America (que me apresentaram à minha organização local Sonoma Safe Agriculture, onde criei um mapa interativo de pesticidas). Por favor, junte-se a mim enquanto levo meus novos aprendizados sobre bancos de dados vetoriais também para a comunidade mais ampla de ciência de dados para o bem.
Continue lendo

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.

Zilliz Cloud Update: Tiered Storage, Business Critical Plan, Cross-Region Backup, and Pricing Changes
This release offers a rebuilt tiered storage with lower costs, a new Business Critical plan for enhanced security, and pricing updates, among other features.

Proactive Monitoring for Vector Database: Zilliz Cloud Integrates with Datadog
we're excited to announce Zilliz Cloud's integration with Datadog, enabling comprehensive monitoring and observability for your vectorDB deployments.



