> 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

> **Самая масштабируемая open-source векторная база данных для ИИ-приложений — рассчитана на миллиарды векторов**

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

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

***

## Milvus против Qdrant — когда что выбирать

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

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

***

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

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

* **milvus** — основной сервис (proxy, query, data, index coordinators)
* **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 и значительно ускоряют построение индекса для больших коллекций. Если вы планируете часто индексировать более 10 млн векторов, индексация на 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
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"Версия: {utility.get_server_version()}")
EOF
```

***

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

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

```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_name}' создана!")
```

***

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

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

```python
from pymilvus import Collection

collection = Collection("documents")

# Индекс HNSW (лучше для большинства сценариев, низкая задержка)
hnsw_params = {
    "metric_type": "COSINE",     # COSINE, L2 или IP (Inner Product)
    "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            # Количество кластеров (обычно берут корень из размера данных)
    }
}

# Индекс 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 — это open-source векторная база данных для масштабируемых ИИ-приложений.",
        "source": "documentation",
        "category": "database",
        "year": 2024
    },
    {
        "text": "HNSW обеспечивает быстрый приближённый поиск ближайших соседей с высоким recall.",
        "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"Вставлено {total_inserted}/{len(documents)} документов")

# Выполните flush, чтобы гарантировать сохранение и индексацию данных
collection.flush()
print(f"Всего вставлено и зафиксировано: {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("как работает поиск по сходству векторов")
for hit in hits:
    print(f"Оценка: {hit.score:.4f}")
    print(f"Текст: {hit.entity.get('text')[:100]}")
    print(f"Источник: {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+ поддерживает гибридный поиск плотных+разреженных векторов
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 vector)
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="API Milvus RAG")

# Инициализация при запуске
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": "Отвечайте на основе контекста. Будьте кратки."},
            {"role": "user", "content": f"Контекст:\n{context}\n\nВопрос: {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"Количество сущностей: {col.num_entities:,}")
print(f"Схема: {col.schema}")

# Управление разделами
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
```

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

***

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

| Размер коллекции | Индекс         | GPU      | QPS      |
| ---------------- | -------------- | -------- | -------- |
| 1 млн векторов   | HNSW           | RTX 3090 | \~8,000  |
| 10 млн векторов  | IVF\_FLAT      | RTX 4090 | \~2,500  |
| 10 млн векторов  | GPU\_IVF\_FLAT | A100     | \~12,000 |
| 100 млн векторов | 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)
* [Bootcamp Milvus](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 — идеальное решение для приложений ИИ, которым нужно масштабироваться до сотен миллионов векторов. В сочетании с генерацией эмбеддингов с ускорением на GPU вы можете создавать первоклассные системы семантического поиска и RAG за долю стоимости управляемых облачных сервисов.*

***

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

| Сценарий использования                                  | Рекомендуемый GPU | Оценочная стоимость на Clore.ai |
| ------------------------------------------------------- | ----------------- | ------------------------------- |
| Разработка/тестирование                                 | RTX 3090 (24 ГБ)  | $0.07–0.21/гпу/ч                |
| Продакшен-векторный поиск                               | RTX 3090 (24 ГБ)  | $0.07–0.21/гпу/ч                |
| Генерация эмбеддингов с высокой пропускной способностью | RTX 4090 (24 ГБ)  | $0.14–0.42/гпу/ч                |

> 💡 Все примеры в этом руководстве можно развернуть на [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.
