> For the complete documentation index, see [llms.txt](https://docs.clore.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.clore.ai/guides/guides_v2-ru/rag-i-vektornye-bazy-dannykh/milvus.md).

# Milvus

> **Наиболее масштабируемая открытая векторная база данных для AI-приложений — создана для миллиардов векторов**

Milvus — это открытая векторная база данных, специально разработанная для масштабируемого поиска по сходству и AI-приложений. Изначально созданная Zilliz и переданная в LF AI & Data Foundation, Milvus используется в производственных AI-нагрузках в таких компаниях, как NVIDIA, AT\&T, IBM и Salesforce. Это предпочтительный выбор, когда требуется масштабирование до миллиардов векторов.

**GitHub:** [milvus-io/milvus](https://github.com/milvus-io/milvus) — 32K+ ⭐

***

## Milvus vs Qdrant — когда выбирать какую

| Критерии                                       | Milvus                                   | Qdrant              |
| ---------------------------------------------- | ---------------------------------------- | ------------------- |
| Масштаб                                        | Миллиарды векторов                       | Сотни миллионов     |
| Архитектура                                    | Распределённый (несколько сервисов)      | Один бинарный файл  |
| Сложность настройки                            | Выше                                     | Ниже                |
| Поддержка GPU-индексов                         | ✅ Встроенный GPU FAISS                   | Ограничено          |
| Многопользовательская изоляция (Multi-tenancy) | ✅ Разделы (partitions) + псевдонимы      | На основе коллекций |
| Потоковый приём данных                         | ✅ Kafka/Pulsar                           | Ограничено          |
| Гибридный поиск                                | ✅ Плотные + разреженные (dense + sparse) | ✅                   |
| Вариант с управляемым облаком                  | Zilliz Cloud                             | Qdrant Cloud        |

{% hint style="success" %}
**Выберите Milvus, когда:** Вам нужно масштабироваться до миллиардов векторов, требуется индексирование с ускорением на GPU (IVF\_FLAT\_GPU) или нужны корпоративные функции, такие как мультиарендность, потоковый приём данных и управление доступом на основе ролей.
{% endhint %}

***

## Архитектура Milvus

Milvus в автономном режиме (один сервер) включает:

* **milvus** — основной сервис (координаторы proxy, query, data, index)
* **etcd** — хранилище метаданных и обнаружение сервисов
* **MinIO** — объектное хранилище для данных сегментов

В распределённом режиме (кластер) каждый компонент масштабируется независимо.

***

## Требования

* Учетная запись Clore.ai с арендой GPU
* Docker Compose (обычно предустановлен)
* Базовые знания Python
* 16ГБ+ ОЗУ (рекомендуется 32ГБ для продакшена)

***

## Шаг 1 — Арендуйте сервер с GPU на Clore.ai

1. Перейдите на [clore.ai](https://clore.ai) → **Маркетплейс**
2. **Рекомендуемый GPU:** RTX 4090 или A100 для индексирования с ускорением на GPU
3. **Альтернатива на CPU:** Любой сервер с 32ГБ+ ОЗУ для индексирования на CPU

**Минимальные требования:**

* CPU: 8 ядер
* ОЗУ: 16ГБ (рекомендуется 32ГБ)
* Диск: 50ГБ SSD/NVMe
* GPU: опционально (требуется только для типов индексов на GPU)

{% hint style="info" %}
**Типы GPU-индексов в Milvus** (IVF\_FLAT\_GPU, IVFSQ8\_GPU) требуют GPU с поддержкой CUDA и существенно ускоряют построение индексов для больших коллекций. Если вы планируете часто индексировать более 10M векторов, индексирование на GPU быстро окупается.
{% endhint %}

***

## Шаг 2 — Разверните Milvus в автономном режиме

**Docker-образ:**

```
milvusdb/milvus:v2.4.0
```

Для Milvus в автономном режиме требуются etcd и MinIO. Используйте Docker Compose для простейшей настройки.

**Порты:**

```
22
19530
```

* **Порт 19530:** Порт Milvus SDK/gRPC (основной)
* **Порт 9091:** REST API Milvus и проверка здоровья (внутренний)

**Переменные окружения:**

```
NVIDIA_VISIBLE_DEVICES=all
NVIDIA_DRIVER_CAPABILITIES=compute,utility
```

***

## Шаг 3 — Настройка с Docker Compose

Подключитесь по SSH к вашему серверу Clore.ai и создайте файл compose:

```bash
ssh root@<server-ip> -p <ssh-port>

# Установите Docker Compose, если он не установлен
which docker-compose || pip install docker-compose
# Или используйте плагин Docker:
docker compose version

# Создайте директорию проекта
mkdir -p /opt/milvus && cd /opt/milvus

# Скачайте официальный файл compose для Milvus standalone
wget https://github.com/milvus-io/milvus/releases/download/v2.4.0/milvus-standalone-docker-compose.yml \
    -O docker-compose.yml

# Просмотрите файл compose
cat docker-compose.yml
```

### Настройте docker-compose.yml

```yaml
version: '3.5'

services:
  etcd:
    container_name: milvus-etcd
    image: quay.io/coreos/etcd:v3.5.5
    environment:
      - ETCD_AUTO_COMPACTION_MODE=revision
      - ETCD_AUTO_COMPACTION_RETENTION=1000
      - ETCD_QUOTA_BACKEND_BYTES=4294967296
      - ETCD_SNAPSHOT_COUNT=50000
    volumes:
      - /opt/milvus/etcd:/etcd
    command: etcd -advertise-client-urls=http://127.0.0.1:2379 -listen-client-urls http://0.0.0.0:2379 --data-dir /etcd
    healthcheck:
      test: ["CMD", "etcdctl", "endpoint", "health"]
      interval: 30s
      timeout: 20s
      retries: 3

  minio:
    container_name: milvus-minio
    image: minio/minio:RELEASE.2023-03-13T19-46-17Z
    environment:
      MINIO_ACCESS_KEY: minioadmin
      MINIO_SECRET_KEY: minioadmin
    ports:
      - "9001:9001"
      - "9000:9000"
    volumes:
      - /opt/milvus/minio:/minio_data
    command: minio server /minio_data --console-address ":9001"
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
      interval: 30s
      timeout: 20s
      retries: 3

  standalone:
    container_name: milvus-standalone
    image: milvusdb/milvus:v2.4.0
    command: ["milvus", "run", "standalone"]
    security_opt:
      - seccomp:unconfined
    environment:
      ETCD_ENDPOINTS: etcd:2379
      MINIO_ADDRESS: minio:9000
    volumes:
      - /opt/milvus/milvus:/var/lib/milvus
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:9091/healthz"]
      interval: 30s
      start_period: 90s
      timeout: 20s
      retries: 3
    ports:
      - "19530:19530"
      - "9091:9091"
    depends_on:
      - "etcd"
      - "minio"
    deploy:
      resources:
        reservations:
          devices:
            - capabilities: [gpu]  # Включить доступ к GPU
```

### Запустите Milvus

```bash
cd /opt/milvus
docker compose up -d

# Подождите, пока сервисы запустятся (~60 секунд)
sleep 60

# Проверьте, что все сервисы здоровы
docker compose ps

# Проверьте состояние Milvus
curl http://localhost:9091/healthz
# Ожидаемый ответ: {"status":"ok"}

# Просмотр логов
docker compose logs -f standalone --tail 50
```

***

## Шаг 4 — Установите клиент Python

```bash
pip install pymilvus sentence-transformers numpy tqdm

# Проверить соединение
python3 << 'EOF'
from pymilvus import connections, utility

connections.connect("default", host="localhost", port="19530")
print(f"Milvus connected!")
print(f"Version: {utility.get_server_version()}")
EOF
```

***

## Шаг 5 — Создайте коллекцию

В Milvus **collection** похож на таблицу базы данных. У него есть схема с типизированными полями, включая векторные поля.

```python
from pymilvus import (
    connections,
    FieldSchema,
    CollectionSchema,
    DataType,
    Collection,
    utility
)

# Подключиться
connections.connect("default", host="localhost", port="19530")

# Определить схему
fields = [
    FieldSchema(
        name="id",
        dtype=DataType.INT64,
        is_primary=True,
        auto_id=True           # Автогенерация ID
    ),
    FieldSchema(
        name="text",
        dtype=DataType.VARCHAR,
        max_length=2048        # Максимальная длина текста
    ),
    FieldSchema(
        name="source",
        dtype=DataType.VARCHAR,
        max_length=256
    ),
    FieldSchema(
        name="category",
        dtype=DataType.VARCHAR,
        max_length=128
    ),
    FieldSchema(
        name="year",
        dtype=DataType.INT32
    ),
    FieldSchema(
        name="embedding",
        dtype=DataType.FLOAT_VECTOR,
        dim=384                # Размерность вашей модели эмбеддингов
    )
]

schema = CollectionSchema(
    fields=fields,
    description="Эмбеддинги документов для семантического поиска",
    enable_dynamic_field=True  # Разрешить добавление полей, не указанных в схеме
)

# Создать коллекцию
collection_name = "documents"
if utility.has_collection(collection_name):
    utility.drop_collection(collection_name)

collection = Collection(
    name=collection_name,
    schema=schema,
    using="default"
)
print(f"Collection '{collection_name}' created!")
```

***

## Шаг 6 — Создание индекса

Перед загрузкой данных для поиска создайте соответствующий индекс:

```python
from pymilvus import Collection

collection = Collection("documents")

# Индекс HNSW (лучше для большинства случаев, низкая задержка)
hnsw_params = {
    "metric_type": "COSINE",     # COSINE, L2 или IP (скалярное произведение)
    "index_type": "HNSW",
    "params": {
        "M": 16,                 # Связанность графа HNSW (8-64)
        "efConstruction": 200    # Глубина поиска при построении
    }
}

# Индекс IVF_FLAT (CPU, подходит для больших коллекций)
ivf_params = {
    "metric_type": "COSINE",
    "index_type": "IVF_FLAT",
    "params": {
        "nlist": 1024            # Количество кластеров (обычно sqrt от размера данных)
    }
}

# Индекс GPU_IVF_FLAT (требует CUDA GPU — самый быстрый для пакетных запросов)
gpu_ivf_params = {
    "metric_type": "L2",
    "index_type": "GPU_IVF_FLAT",
    "params": {
        "nlist": 1024,
        "cache_dataset_on_device": True
    }
}

# Создать индекс по полю embedding
collection.create_index(
    field_name="embedding",
    index_params=hnsw_params,
    index_name="embedding_idx"
)

# Создать скалярный индекс для фильтруемого поиска
collection.create_index(field_name="category", index_name="category_idx")
collection.create_index(field_name="year", index_name="year_idx")

print("Индексы созданы!")
collection.load()  # Загрузить в память для поиска
```

***

## Шаг 7 — Вставка данных

```python
from pymilvus import Collection
from sentence_transformers import SentenceTransformer
import tqdm

collection = Collection("documents")
model = SentenceTransformer("all-MiniLM-L6-v2", device="cuda")

# Ваши документы
documents = [
    {
        "text": "Milvus — это открытая векторная база данных для масштабируемых AI-приложений.",
        "source": "documentation",
        "category": "database",
        "year": 2024
    },
    {
        "text": "HNSW обеспечивает быстрый приближённый поиск ближайших соседей с высокой полнотой.",
        "source": "research",
        "category": "algorithm",
        "year": 2023
    },
    {
        "text": "Индексирование с ускорением на GPU значительно сокращает время построения для больших векторных коллекций.",
        "source": "blog",
        "category": "performance",
        "year": 2024
    },
    # Добавьте здесь ещё тысячи документов
]

def insert_batch(docs: list, batch_size: int = 1000):
    texts = [d["text"] for d in docs]
    
    # Ускоренное на GPU построение эмбеддингов
    embeddings = model.encode(
        texts,
        batch_size=256,
        show_progress_bar=False,
        normalize_embeddings=True
    )
    
    # Вставка в Milvus
    data = {
        "text": [d["text"] for d in docs],
        "source": [d["source"] for d in docs],
        "category": [d["category"] for d in docs],
        "year": [d["year"] for d in docs],
        "embedding": embeddings.tolist()
    }
    
    result = collection.insert(data)
    return result.insert_count

# Вставка пакетами
BATCH_SIZE = 1000
total_inserted = 0

for i in range(0, len(documents), BATCH_SIZE):
    batch = documents[i:i + BATCH_SIZE]
    count = insert_batch(batch)
    total_inserted += count
    print(f"Inserted {total_inserted}/{len(documents)} documents")

# Флаш, чтобы данные были сохранены и проиндексированы
collection.flush()
print(f"Total inserted and flushed: {total_inserted}")
```

***

## Шаг 8 — Поиск и запросы

### Базовый семантический поиск

```python
from pymilvus import Collection
from sentence_transformers import SentenceTransformer

collection = Collection("documents")
collection.load()

model = SentenceTransformer("all-MiniLM-L6-v2", device="cuda")

def search(query: str, top_k: int = 10):
    query_embedding = model.encode(
        [query],
        normalize_embeddings=True
    )[0].tolist()
    
    results = collection.search(
        data=[query_embedding],
        anns_field="embedding",
        param={
            "metric_type": "COSINE",
            "params": {"ef": 64}    # Параметр HNSW для времени поиска (ef >= top_k)
        },
        limit=top_k,
        output_fields=["text", "source", "category", "year"]
    )
    
    return results[0]

# Поиск
hits = search("how does vector similarity search work")
for hit in hits:
    print(f"Score: {hit.score:.4f}")
    print(f"Text: {hit.entity.get('text')[:100]}")
    print(f"Source: {hit.entity.get('source')}")
    print()
```

### Фильтрованный поиск

```python
from pymilvus import Collection

collection = Collection("documents")

# Поиск с фильтром по метаданным (булево выражение)
results = collection.search(
    data=[query_embedding],
    anns_field="embedding",
    param={"metric_type": "COSINE", "params": {"ef": 64}},
    limit=10,
    expr='category == "database" and year >= 2023',  # Булев фильтр
    output_fields=["text", "category", "year"]
)
```

### Гибридный поиск (плотный + разреженный)

```python
# Milvus 2.4+ поддерживает гибридный dense+sparse поиск
from pymilvus import AnnSearchRequest, WeightedRanker, Collection

collection = Collection("documents")

# Запрос для плотного поиска
dense_req = AnnSearchRequest(
    data=[dense_embedding],
    anns_field="embedding",
    param={"metric_type": "COSINE", "params": {"ef": 64}},
    limit=20
)

# Запрос для разреженного поиска (требуется поле со разреженным вектором)
sparse_req = AnnSearchRequest(
    data=[sparse_embedding],
    anns_field="sparse_embedding",
    param={"metric_type": "IP"},
    limit=20
)

# Комбинировать с Reciprocal Rank Fusion
results = collection.hybrid_search(
    [dense_req, sparse_req],
    rerank=WeightedRanker(0.7, 0.3),  # 70% плотный, 30% разреженный
    limit=10,
    output_fields=["text"]
)
```

***

## Шаг 9 — Постройте RAG-сервис

```bash
pip install fastapi uvicorn openai

cat > /workspace/milvus_rag.py << 'EOF'
from fastapi import FastAPI
from pydantic import BaseModel
from pymilvus import Collection, connections
from sentence_transformers import SentenceTransformer
from openai import OpenAI
import os

app = FastAPI(title="Milvus RAG API")

# Инициализация при старте
connections.connect("default", host="localhost", port="19530")
collection = Collection("documents")
collection.load()
embedder = SentenceTransformer("all-MiniLM-L6-v2", device="cuda")
llm = OpenAI(api_key=os.environ["OPENAI_API_KEY"])

class QueryRequest(BaseModel):
    question: str
    n_results: int = 5

@app.get("/health")
async def health():
    return {"status": "ok", "vectors": collection.num_entities}

@app.post("/search")
async def semantic_search(req: QueryRequest):
    embedding = embedder.encode(
        [req.question],
        normalize_embeddings=True
    )[0].tolist()
    
    results = collection.search(
        data=[embedding],
        anns_field="embedding",
        param={"metric_type": "COSINE", "params": {"ef": 64}},
        limit=req.n_results,
        output_fields=["text", "source", "category"]
    )
    
    return {
        "results": [
            {
                "text": hit.entity.get("text"),
                "source": hit.entity.get("source"),
                "score": hit.score
            }
            for hit in results[0]
        ]
    }

@app.post("/rag")
async def rag(req: QueryRequest):
    embedding = embedder.encode([req.question], normalize_embeddings=True)[0].tolist()
    
    hits = collection.search(
        data=[embedding],
        anns_field="embedding",
        param={"metric_type": "COSINE", "params": {"ef": 64}},
        limit=req.n_results,
        output_fields=["text", "source"]
    )[0]
    
    context = "\n\n".join([
        f"[{hit.entity.get('source')}]: {hit.entity.get('text')}"
        for hit in hits if hit.score > 0.4
    ])
    
    response = llm.chat.completions.create(
        model="gpt-4o-mini",
        messages=[
            {"role": "system", "content": "Answer based on context. Be concise."},
            {"role": "user", "content": f"Context:\n{context}\n\nQuestion: {req.question}"}
        ]
    )
    
    return {"answer": response.choices[0].message.content, "context_used": len(hits)}

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)
EOF

python3 /workspace/milvus_rag.py
```

***

## Шаг 10 — Мониторинг и управление

```python
from pymilvus import connections, utility, Collection

connections.connect("default", host="localhost", port="19530")

# Список всех коллекций
print("Collections:", utility.list_collections())

# Статистика по коллекции
col = Collection("documents")
print(f"Entity count: {col.num_entities:,}")
print(f"Schema: {col.schema}")

# Управление разделами (partitions)
col.create_partition("2024_docs")
col.create_partition("2023_docs")

# Вставка с указанием раздела
col.insert(data, partition_name="2024_docs")

# Поиск в конкретном разделе
results = col.search(
    data=[query_vec],
    anns_field="embedding",
    param={"metric_type": "COSINE", "params": {"ef": 64}},
    limit=10,
    partition_names=["2024_docs"]  # Поиск только в этом разделе
)
```

***

## Устранение неполадок

### Сервисы не запускаются

```bash
# Проверьте логи контейнеров
docker compose logs etcd
docker compose logs minio
docker compose logs standalone

# Проверьте место на диске
df -h /opt/milvus

# Перезапустите сервисы
docker compose restart
```

### Connection Refused на 19530

```bash
# Убедитесь, что Milvus прослушивает порт
netstat -tlnp | grep 19530

# Проверить состояние
curl http://localhost:9091/healthz

# Дайте время на старт (90 секунд)
docker compose logs standalone | tail -20
```

### Таймаут построения индекса для больших коллекций

```python
# Увеличьте таймаут для крупных построений индекса
from pymilvus import Collection

collection = Collection("documents")
collection.create_index(
    field_name="embedding",
    index_params=hnsw_params,
    timeout=3600  # таймаут 1 час
)
```

### Высокое использование памяти

```bash
# Настройте лимиты памяти Milvus в docker-compose.yml
# Добавьте в сервис standalone:
deploy:
  resources:
    limits:
      memory: 16g
```

***

## Руководство по выбору типа индекса

| Тип индекса    | Лучше всего для             | Память           | Скорость     | Требуется GPU |
| -------------- | --------------------------- | ---------------- | ------------ | ------------- |
| FLAT           | Малые (<1M), точный поиск   | Высокая          | Медленно     | Нет           |
| IVF\_FLAT      | Средние (1M–10M)            | Средне           | Хорошо       | Нет           |
| HNSW           | Низкая задержка, <100M      | Высокая          | Отлично      | Нет           |
| IVF\_SQ8       | Сжатый, для больших объёмов | Низкая           | Хорошо       | Нет           |
| GPU\_IVF\_FLAT | Быстрые пакетные запросы    | GPU+ОЗУ          | Лучший выбор | Да            |
| DISKANN        | Для миллиардных объёмов     | Низко (на диске) | Хорошо       | Нет           |

***

## Тесты производительности

| Размер коллекции | Индекс         | GPU      | QPS      |
| ---------------- | -------------- | -------- | -------- |
| 1M векторов      | HNSW           | RTX 3090 | \~8,000  |
| 10M векторов     | IVF\_FLAT      | RTX 4090 | \~2,500  |
| 10M векторов     | GPU\_IVF\_FLAT | A100     | \~12,000 |
| 100M векторов    | DISKANN        | A100     | \~1,200  |

***

## Дополнительные ресурсы

* [Документация Milvus](https://milvus.io/docs)
* [Milvus на GitHub](https://github.com/milvus-io/milvus)
* [Документация PyMilvus](https://milvus.io/api-reference/pymilvus/v2.4.x/About.md)
* [Milvus Bootcamp](https://github.com/milvus-io/bootcamp) — Примеры приложений
* [Zilliz Cloud](https://cloud.zilliz.com/) — Управляемый Milvus
* [Сравнение векторных баз данных](https://milvus.io/docs/benchmark.md)
* [Attu GUI](https://github.com/zilliztech/attu) — Веб-интерфейс для управления Milvus

***

*Milvus на Clore.ai — идеальное решение для AI-приложений, которым нужно масштабироваться за пределы сотен миллионов векторов. В сочетании с генерацией эмбеддингов с ускорением на GPU вы можете создавать первоклассные системы семантического поиска и RAG при доле затрат управляемого облака.*

***

## Рекомендации Clore.ai по GPU

| Сценарий использования                   | Рекомендуемый GPU | Примерная стоимость на Clore.ai |
| ---------------------------------------- | ----------------- | ------------------------------- |
| Разработка/Тестирование                  | RTX 3090 (24GB)   | \~$0.12/gpu/hr                  |
| Производственный векторный поиск         | RTX 3090 (24GB)   | \~$0.12/gpu/hr                  |
| Высокопропускная способность эмбеддингов | RTX 4090 (24GB)   | \~$0.70/gpu/hr                  |

> 💡 Все примеры в этом руководстве можно развернуть на [Clore.ai](https://clore.ai/marketplace) GPU-серверах. Просматривайте доступные GPU и арендуйте по часам — без обязательств, с полным root-доступом.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.clore.ai/guides/guides_v2-ru/rag-i-vektornye-bazy-dannykh/milvus.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
