Milvus для AI-агентов: масштабируемая векторная БД
🗄️

Milvus для AI-агентов: векторная БД планетарного масштаба

Milvus — облачно-нативная векторная БД, способная индексировать миллиарды векторов. Горизонтальное масштабирование, гибридный поиск, GPU-индексация и глубокая интеграция с AI-фреймворками.

intermediate ⏱ 15 мин
Client SDKs PyMilvus Node.js Java Go Milvus Distributed Core Proxy (LB) Request routing Query Node ×N Search & filter Data Node ×N Insert & index Index Node ×N GPU/CPU index Storage Layer MinIO / S3 etcd (metadata) Pulsar / Kafka Milvus Architecture — Cloud-Native Vector DB for Billion-Scale AI Agents

# 1. Milvus vs Qdrant: когда выбирать Milvus

Milvus — это облачно-нативная векторная БД, созданная для масштаба миллиардов векторов. В отличие от Qdrant (лёгкий, однонодовый по умолчанию), Milvus изначально распределённый: компоненты Proxy, Query Node, Data Node и Index Node масштабируются независимо. Если у вас десятки миллионов документов и нагрузка растёт непредсказуемо — Milvus ваш выбор.

Ключевые фичи: GPU-индексация (построение индексов на GPU в 10x быстрее), IVF-индексы для approximate search на гигантских датасетах, multi-vector поиск (несколько векторов на одну сущность), и нативная потоковая обработка через Pulsar/Kafka. Milvus используют в поисковых системах, рекомендательных движках и AI-агентах с живым обновлением данных.

# Установка Milvus Standalone через Docker Compose
wget https://github.com/milvus-io/milvus/releases/download/v2.4.0/milvus-standalone-docker-compose.yml \
  -O docker-compose.yml
docker compose up -d

# Проверка
docker compose ps
curl http://localhost:9091/healthz

# Установка PyMilvus SDK
pip install pymilvus==2.4.0

# 2. Коллекции, схемы и индексы в Milvus

Milvus требует явного определения схемы коллекции — в отличие от schema-less Qdrant. Вы задаёте поля, их типы (VARCHAR, INT64, FLOAT_VECTOR, etc.) и первичный ключ. Это даёт строгую типизацию и возможность строить индексы не только на векторных, но и на скалярных полях. Для AI-агентов схема обычно включает: id, text, embedding (float_vector), source, timestamp.

Выбор индекса критичен для performance. Для точного поиска — FLAT (brute-force, медленно на больших данных). Для approximate — IVF_FLAT (хороший баланс), IVF_SQ8 (экономия памяти), HNSW (быстрый поиск, дорогой build). Для GPU-ускорения — IVF_GPU. Для миллиардов векторов — DiskANN (поиск с диска).

from pymilvus import MilvusClient, DataType

client = MilvusClient(uri="http://localhost:19530")

# Схема коллекции для RAG-агента
schema = client.create_schema(
    auto_id=False,
    enable_dynamic_field=True,  # для гибких метаданных
    description="AI Agent Knowledge Base"
)

schema.add_field(field_name="id", datatype=DataType.INT64, is_primary=True)
schema.add_field(field_name="text", datatype=DataType.VARCHAR, max_length=65535)
schema.add_field(field_name="embedding", datatype=DataType.FLOAT_VECTOR, dim=1536)
schema.add_field(field_name="source", datatype=DataType.VARCHAR, max_length=512)
schema.add_field(field_name="tenant", datatype=DataType.VARCHAR, max_length=128)

# Создаём коллекцию с IVF_FLAT индексом
index_params = client.prepare_index_params()
index_params.add_index(
    field_name="embedding",
    index_type="IVF_FLAT",
    metric_type="COSINE",
    params={"nlist": 1024}
)

client.create_collection(
    collection_name="agent_knowledge",
    schema=schema,
    index_params=index_params,
    consistency_level="Strong"  # для актуальности данных
)

# 3. Вставка, поиск и гибридный retrieval

Milvus поддерживает batch-вставку (до тысяч записей за вызов) и streaming-вставку для real-time данных. Для поиска доступны: ANN (приближённый), range search (все векторы в радиусе), и hybrid search — комбинация векторного поиска со скалярной фильтрацией. Hybrid search в Milvus выполняет фильтрацию на этапе поиска, а не после, что даёт точные результаты даже на больших данных.

Для поиска с фильтрацией используйте boolean expressions в стиле SQL: tenant == "acme" and timestamp > 1700000000000. Milvus компилирует это в эффективный план выполнения, используя индексы на скалярных полях.

import numpy as np

# Пакетная вставка эмбеддингов
data = [
    {"id": i,
     "text": chunk_text,
     "embedding": embedding.tolist(),
     "source": "docs/api.md",
     "tenant": "acme-corp"}
    for i, (chunk_text, embedding) in enumerate(chunks)
]

client.insert(collection_name="agent_knowledge", data=data)
client.flush(collection_name="agent_knowledge")

# Гибридный поиск: ANN + фильтр по tenant
results = client.search(
    collection_name="agent_knowledge",
    data=[query_embedding.tolist()],
    limit=5,
    filter='tenant == "acme-corp"',
    output_fields=["text", "source"],
    search_params={"metric_type": "COSINE", "params": {"nprobe": 16}}
)

for hits in results:
    for hit in hits:
        print(f"Score: {hit['distance']:.3f}, Source: {hit['entity']['source']}")
        print(f"Text: {hit['entity']['text'][:100]}...")

# 4. Партиции и сегменты для multi-tenant AI-агентов

Milvus поддерживает партиции — логические разделы внутри коллекции. Для multi-tenant AI-агента создайте партицию на каждого клиента. Это даёт изоляцию данных на уровне поиска (запросы в пределах партиции быстрее, чем фильтр по всему набору) и позволяет гибко управлять retention: удалять данные ушедшего клиента одной командой.

Внутри партиций данные делятся на сегменты — это единицы роста и слияния. Когда данные растут (insert), сегменты наполняются; когда достигают порога, Milvus автоматически строит индекс и запечатывает сегмент (sealed). Запечатанные сегменты оптимизированы для чтения и обслуживают основную поисковую нагрузку.

# Создаём партиции для каждого клиента
tenants = ["acme-corp", "globex", "initech"]

for tenant in tenants:
    client.create_partition(
        collection_name="agent_knowledge",
        partition_name=tenant
    )

# Вставка данных в партицию клиента
client.insert(
    collection_name="agent_knowledge",
    data=acme_data,
    partition_name="acme-corp"
)

# Поиск внутри партиции (быстрее, чем фильтр)
results = client.search(
    collection_name="agent_knowledge",
    data=[query_embedding.tolist()],
    partition_names=["acme-corp"],
    limit=5,
    output_fields=["text"]
)

# Удаление данных клиента при расторжении
client.release_partitions(
    collection_name="agent_knowledge",
    partition_names=["globex"]
)
client.drop_partition(
    collection_name="agent_knowledge",
    partition_name="globex"
)

# 5. Интеграция Milvus с LangChain для RAG

LangChain имеет нативную интеграцию с Milvus через langchain_milvus. Вы можете использовать Milvus как векторное хранилище для retrieval-цепочек, с поддержкой фильтрации через search_kwargs. Milvus также поддерживает self-querying retriever: LLM сам генерирует фильтр по метаданным из вопроса пользователя, и Milvus применяет его при поиске.

Для production RAG-агентов используйте Milvus с multi-vector поиском: храните отдельно dense-векторы (семантический поиск) и sparse-векторы (keyword BM25) в одной коллекции. LangChain поддерживает это через MilvusVectorStore с hybrid search конфигурацией.

from langchain_milvus import Milvus
from langchain_openai import OpenAIEmbeddings, ChatOpenAI
from langchain.chains import RetrievalQAWithSourcesChain

embeddings = OpenAIEmbeddings(model="text-embedding-3-small")

# Подключаем существующую коллекцию Milvus
vectorstore = Milvus(
    embedding_function=embeddings,
    collection_name="agent_knowledge",
    connection_args={
        "uri": "http://localhost:19530",
        "token": "root:Milvus"
    },
    primary_field="id",
    text_field="text",
    vector_field="embedding",
)

# Self-querying retriever: LLM сам строит фильтр
retriever = vectorstore.as_retriever(
    search_type="similarity",
    search_kwargs={
        "k": 5,
        "expr": 'tenant == "acme-corp"'
    }
)

# RAG с источниками
chain = RetrievalQAWithSourcesChain.from_chain_type(
    llm=ChatOpenAI(model="gpt-4o", temperature=0),
    chain_type="stuff",
    retriever=retriever,
    return_source_documents=True
)

response = chain.invoke({
    "question": "Как настроить IVF_FLAT индекс в Milvus?"
})
print(response["answer"])
print("Sources:", response["sources"])

# 6. Производительность и продакшен-оптимизации

Для продакшена критически правильно настроить Milvus. Consistency level: Strong для точности, Bounded для скорости, Eventually для максимальной производительности (данные могут отставать на секунды). Load balancing: распределяйте поисковую нагрузку через несколько Query Node. Мониторинг: Milvus экспортирует метрики в Prometheus — отслеживайте latency поиска, размер коллекций, количество sealed/growing сегментов.

Важные подсказки: используйте load_collection() перед поиском, чтобы загрузить индексы в память Query Node (первый поиск без загрузки будет медленным). Включите autoindex для автоматического выбора оптимального индекса. Для GPU-ускорения настройте Index Node с доступом к CUDA — построение индексов ускоряется в 5-10 раз.

# Продакшен-оптимизации Milvus
from pymilvus import MilvusClient

client = MilvusClient(uri="http://localhost:19530")

# 1. Загружаем коллекцию в память перед поиском
client.load_collection("agent_knowledge")

# 2. Проверяем статус загрузки
load_state = client.get_load_state("agent_knowledge")
print(f"Loaded: {load_state['state']}")

# 3. Статистика коллекции
stats = client.get_collection_stats("agent_knowledge")
print(f"Row count: {stats['row_count']}")

# 4. Оптимизированные параметры поиска
results = client.search(
    collection_name="agent_knowledge",
    data=[query_embedding.tolist()],
    limit=10,
    search_params={
        "metric_type": "COSINE",
        "params": {
            "nprobe": 32,        # больше = точнее, но медленнее
            "radius": 0.6,        # минимальный порог сходства
            "range_filter": 0.85  # максимальный порог
        }
    }
)

# 5. Освобождаем память когда коллекция не используется
client.release_collection("agent_knowledge")

📊 Итог: Milvus для AI-агентов

Milvus — правильный выбор когда ваш AI-агент работает с миллионами документов, требует горизонтального масштабирования и строгой типизации данных. Его распределённая архитектура (Proxy, Query/Data/Index Nodes) позволяет масштабировать чтение и запись независимо. Используйте партиции для multi-tenant изоляции, IVF_FLAT для баланса точности и скорости, и GPU-индексацию для ускорения построения индексов. Интеграция с LangChain через langchain_milvus даёт бесшовный RAG-пайплайн. Начните с Milvus Standalone для разработки, переходите на Milvus Distributed когда данные перевалят за 10 миллионов векторов.