> 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-fr/rag-et-bases-de-donnees-vectorielles/milvus.md).

# Milvus

> **La base de données vectorielle open-source la plus évolutive pour les applications IA — conçue pour des milliards de vecteurs**

Milvus est une base de données vectorielle open-source conçue pour la recherche de similarité évolutive et les applications d'IA. Initialement créée par Zilliz puis donnée à la LF AI & Data Foundation, Milvus alimente des charges de travail IA en production dans des entreprises telles que NVIDIA, AT\&T, IBM et Salesforce. C'est le choix de référence lorsque vous devez monter à l'échelle jusqu'à des milliards de vecteurs.

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

***

## Milvus vs Qdrant — Quand choisir lequel

| Critères                    | Milvus                         | Qdrant                   |
| --------------------------- | ------------------------------ | ------------------------ |
| Échelle                     | Milliards de vecteurs          | Centaines de millions    |
| Architecture                | Distribué (plusieurs services) | Binaire unique           |
| Complexité d'installation   | Plus élevée                    | Plus faible              |
| Prise en charge d'index GPU | ✅ FAISS GPU natif              | Limité                   |
| Multi-tenant                | ✅ Partitions + alias           | Basé sur des collections |
| Ingestion en streaming      | ✅ Kafka/Pulsar                 | Limité                   |
| Recherche hybride           | ✅ Dense + sparse               | ✅                        |
| Option gérée dans le cloud  | Zilliz Cloud                   | Qdrant Cloud             |

{% hint style="success" %}
**Choisissez Milvus lorsque :** Vous devez monter à l'échelle jusqu'à des milliards de vecteurs, avez besoin d'un indexage accéléré par GPU (IVF\_FLAT\_GPU), ou nécessitez des fonctionnalités d'entreprise comme le multi-tenant, l'ingestion en streaming et le contrôle d'accès basé sur les rôles.
{% endhint %}

***

## Architecture de Milvus

Milvus en mode autonome (serveur unique) inclut :

* **milvus** — le service principal (coordonnateurs proxy, query, data, index)
* **etcd** — stockage des métadonnées et découverte de services
* **MinIO** — stockage d'objets pour les données de segments

En mode distribué (cluster), chaque composant s'échelonne indépendamment.

***

## Prérequis

* Compte Clore.ai avec location de GPU
* Docker Compose (généralement préinstallé)
* Connaissances Python de base
* 16 Go+ RAM (32 Go recommandés pour la production)

***

## Étape 1 — Louer un serveur GPU sur Clore.ai

1. Aller à [clore.ai](https://clore.ai) → **Place de marché**
2. **GPU recommandé :** RTX 4090 ou A100 pour l'indexation accélérée par GPU
3. **Alternative CPU :** Tout serveur avec 32 Go+ de RAM pour l'indexation basée sur CPU

**Configuration minimale :**

* CPU : 8 cœurs
* RAM : 16 Go (32 Go recommandés)
* Disque : SSD/NVMe 50 Go
* GPU : Optionnel (nécessaire uniquement pour les types d'index GPU)

{% hint style="info" %}
**Types d'index GPU dans Milvus** (IVF\_FLAT\_GPU, IVFSQ8\_GPU) nécessitent des GPU compatibles CUDA et accélèrent considérablement la construction d'index pour de grandes collections. Si vous prévoyez d'indexer fréquemment plus de 10M de vecteurs, l'indexation GPU s'amortit rapidement.
{% endhint %}

***

## Étape 2 — Déployer Milvus en mode autonome

**Image Docker :**

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

Milvus en mode autonome nécessite etcd et MinIO. Utilisez Docker Compose pour l'installation la plus simple.

**Ports :**

```
22
19530
```

* **Port 19530 :** Port SDK/gRPC de Milvus (principal)
* **Port 9091 :** API REST de Milvus et vérification de santé (interne)

**Variables d’environnement :**

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

***

## Étape 3 — Configurer avec Docker Compose

Connectez-vous en SSH à votre serveur Clore.ai et créez le fichier compose :

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

# Installer Docker Compose si absent
which docker-compose || pip install docker-compose
# Ou utiliser le plugin Docker :
docker compose version

# Créer le répertoire du projet
mkdir -p /opt/milvus && cd /opt/milvus

# Télécharger le fichier compose officiel Milvus standalone
wget https://github.com/milvus-io/milvus/releases/download/v2.4.0/milvus-standalone-docker-compose.yml \
    -O docker-compose.yml

# Examiner le fichier compose
cat docker-compose.yml
```

### Personnaliser 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"]
      intervalle : 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"]
      intervalle : 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"]
      intervalle : 30s
      start_period : 90s
      timeout : 20s
      retries : 3
    ports:
      - "19530:19530"
      - "9091:9091"
    depends_on:
      - "etcd"
      - "minio"
    deploy:
      resources:
        reservations:
          devices:
            - capabilities: [gpu]  # Activer l'accès GPU
```

### Démarrer Milvus

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

# Attendre le démarrage des services (~60 secondes)
sleep 60

# Vérifier que tous les services sont sains
docker compose ps

# Vérifier la santé de Milvus
curl http://localhost:9091/healthz
# Attendu : {"status":"ok"}

# Voir les logs
docker compose logs -f standalone --tail 50
```

***

## Étape 4 — Installer le client Python

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

# Vérifier la connexion
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
```

***

## Étape 5 — Créer une collection

Dans Milvus, une **collection** est similaire à une table de base de données. Elle a un schéma avec des champs typés incluant des champs vecteurs.

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

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

# Définir le schéma
fields = [
    FieldSchema(
        name="id",
        dtype=DataType.INT64,
        is_primary=True,
        auto_id=True           # Générer automatiquement les IDs
    ),
    FieldSchema(
        name="text",
        dtype=DataType.VARCHAR,
        max_length=2048        # Longueur maximale du texte
    ),
    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                # Dimension de votre modèle d'embedding
    )
]

schema = CollectionSchema(
    fields=fields,
    description="Embeddings de documents pour la recherche sémantique",
    enable_dynamic_field=True  # Permet d'ajouter des champs non présents dans le schéma
)

# Créer une collection
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!")
```

***

## Étape 6 — Créer l'index

Avant de charger des données pour la recherche, créez un index approprié :

```python
from pymilvus import Collection

collection = Collection("documents")

# Index HNSW (meilleur pour la plupart des cas d'utilisation, faible latence)
hnsw_params = {
    "metric_type": "COSINE",     # COSINE, L2 ou IP (Inner Product)
    "index_type": "HNSW",
    "params": {
        "M": 16,                 # Connectivité du graphe HNSW (8–64)
        "efConstruction": 200    # Profondeur de recherche au moment de la construction
    }
}

# Index IVF_FLAT (CPU, bon pour grandes collections)
ivf_params = {
    "metric_type": "COSINE",
    "index_type": "IVF_FLAT",
    "params": {
        "nlist": 1024            # Nombre de clusters (la racine carrée de la taille des données est typique)
    }
}

# Index GPU_IVF_FLAT (requiert GPU CUDA — le plus rapide pour les requêtes par lots)
gpu_ivf_params = {
    "metric_type": "L2",
    "index_type": "GPU_IVF_FLAT",
    "params": {
        "nlist": 1024,
        "cache_dataset_on_device": True
    }
}

# Créer l'index sur le champ d'embedding
collection.create_index(
    field_name="embedding",
    index_params=hnsw_params,
    index_name="embedding_idx"
)

# Créer un index scalaire pour la recherche filtrée
collection.create_index(field_name="category", index_name="category_idx")
collection.create_index(field_name="year", index_name="year_idx")

print("Indexes created!")
collection.load()  # Charger en mémoire pour la recherche
```

***

## Étape 7 — Insérer des données

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

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

# Vos documents
documents = [
    {
        "text": "Milvus est une base de données vectorielle open-source pour des applications IA évolutives.",
        "source": "documentation",
        "category": "database",
        "year": 2024
    },
    {
        "text": "HNSW offre une recherche approximative de plus proches voisins rapide avec un rappel élevé.",
        "source": "research",
        "category": "algorithm",
        "year": 2023
    },
    {
        "text": "L'indexation accélérée par GPU réduit considérablement le temps de construction pour de grandes collections de vecteurs.",
        "source": "blog",
        "category": "performance",
        "year": 2024
    },
    # Ajouter des milliers d'autres documents ici
]

def insert_batch(docs: list, batch_size: int = 1000):
    texts = [d["text"] for d in docs]
    
    # Embedding accéléré par GPU
    embeddings = model.encode(
        texts,
        batch_size=256,
        show_progress_bar=False,
        normalize_embeddings=True
    )
    
    # Insérer dans 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

# Insérer par lots
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")

# Flusher pour s'assurer que les données sont persistées et indexées
collection.flush()
print(f"Total inserted and flushed: {total_inserted}")
```

***

## Étape 8 — Recherche et requêtes

### Recherche sémantique basique

```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}    # Paramètre HNSW au temps de recherche (ef >= top_k)
        },
        limit=top_k,
        output_fields=["text", "source", "category", "year"]
    )
    
    return results[0]

# Recherche
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()
```

### Recherche filtrée

```python
from pymilvus import Collection

collection = Collection("documents")

# Recherche avec filtre de métadonnées (expression booléenne)
results = collection.search(
    data=[query_embedding],
    anns_field="embedding",
    param={"metric_type": "COSINE", "params": {"ef": 64}},
    limit=10,
    expr='category == "database" and year >= 2023',  # Filtre booléen
    output_fields=["text", "category", "year"]
)
```

### Recherche hybride (Dense + Sparse)

```python
# Milvus 2.4+ prend en charge la recherche hybride dense+sparse
from pymilvus import AnnSearchRequest, WeightedRanker, Collection

collection = Collection("documents")

# Requête de recherche dense
dense_req = AnnSearchRequest(
    data=[dense_embedding],
    anns_field="embedding",
    param={"metric_type": "COSINE", "params": {"ef": 64}},
    limit=20
)

# Requête de recherche sparse (nécessite un champ de vecteur sparse)
sparse_req = AnnSearchRequest(
    data=[sparse_embedding],
    anns_field="sparse_embedding",
    param={"metric_type": "IP"},
    limit=20
)

# Combiner avec Reciprocal Rank Fusion
results = collection.hybrid_search(
    [dense_req, sparse_req],
    rerank=WeightedRanker(0.7, 0.3),  # 70% dense, 30% sparse
    limit=10,
    output_fields=["text"]
)
```

***

## Étape 9 — Construire un service 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")

# Initialiser au démarrage
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": "Répondre en se basant sur le contexte. Soyez concis."},
            {"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
```

***

## Étape 10 — Surveiller et gérer

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

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

# Lister toutes les collections
print("Collections:", utility.list_collections())

# Statistiques de la collection
col = Collection("documents")
print(f"Entity count: {col.num_entities:,}")
print(f"Schema: {col.schema}")

# Gestion des partitions
col.create_partition("2024_docs")
col.create_partition("2023_docs")

# Insertion avec partition
col.insert(data, partition_name="2024_docs")

# Rechercher une partition spécifique
results = col.search(
    data=[query_vec],
    anns_field="embedding",
    param={"metric_type": "COSINE", "params": {"ef": 64}},
    limit=10,
    partition_names=["2024_docs"]  # Ne rechercher que dans cette partition
)
```

***

## Dépannage

### Services ne démarrent pas

```bash
# Vérifiez les logs du conteneur
docker compose logs etcd
docker compose logs minio
docker compose logs standalone

# Vérifier l'espace disque
df -h /opt/milvus

# Redémarrer les services
docker compose restart
```

### Connexion refusée sur 19530

```bash
# Vérifier que Milvus écoute
netstat -tlnp | grep 19530

# Vérifier la santé
curl http://localhost:9091/healthz

# Laisser le temps au démarrage (90 secondes)
docker compose logs standalone | tail -20
```

### Timeout de construction d'index pour les grandes collections

```python
# Augmenter le timeout pour les grosses constructions d'index
from pymilvus import Collection

collection = Collection("documents")
collection.create_index(
    field_name="embedding",
    index_params=hnsw_params,
    timeout=3600  # timeout d'1 heure
)
```

### Usage élevé de la mémoire

```bash
# Configurer les limites de mémoire de Milvus dans docker-compose.yml
# Ajouter au service standalone :
deploy:
  resources:
    limits :
      memory : 16g
```

***

## Guide de sélection du type d'index

| Type d'index   | Idéal pour                    | Mémoire         | Vitesse    | GPU requis |
| -------------- | ----------------------------- | --------------- | ---------- | ---------- |
| FLAT           | Petit (<1M), recherche exacte | Élevée          | Lent       | Non        |
| IVF\_FLAT      | Moyen (1M–10M)                | Moyen           | Bonne      | Non        |
| HNSW           | Faible latence, <100M         | Élevée          | Excellente | Non        |
| IVF\_SQ8       | Compressé, grand              | Faible          | Bonne      | Non        |
| GPU\_IVF\_FLAT | Requêtes par lots rapides     | GPU+RAM         | Meilleur   | Oui        |
| DISKANN        | À l'échelle du milliard       | Faible (disque) | Bonne      | Non        |

***

## Benchmarks de performance

| Taille de la collection | Index          | GPU      | QPS      |
| ----------------------- | -------------- | -------- | -------- |
| 1M de vecteurs          | HNSW           | RTX 3090 | \~8,000  |
| 10M de vecteurs         | IVF\_FLAT      | RTX 4090 | \~2,500  |
| 10M de vecteurs         | GPU\_IVF\_FLAT | A100     | \~12,000 |
| 100M de vecteurs        | DISKANN        | A100     | \~1,200  |

***

## Ressources supplémentaires

* [Documentation Milvus](https://milvus.io/docs)
* [GitHub Milvus](https://github.com/milvus-io/milvus)
* [Documentation PyMilvus](https://milvus.io/api-reference/pymilvus/v2.4.x/About.md)
* [Milvus Bootcamp](https://github.com/milvus-io/bootcamp) — Applications exemple
* [Zilliz Cloud](https://cloud.zilliz.com/) — Milvus géré
* [Comparaison de bases de données vectorielles](https://milvus.io/docs/benchmark.md)
* [Attu GUI](https://github.com/zilliztech/attu) — Interface web pour la gestion de Milvus

***

*Milvus sur Clore.ai est la solution idéale pour les applications IA qui doivent dépasser les centaines de millions de vecteurs. Combiné à la génération d'embeddings accélérée par GPU, vous pouvez construire des systèmes de recherche sémantique et de RAG de classe mondiale à une fraction du coût des solutions cloud managées.*

***

## Recommandations GPU Clore.ai

| Cas d’utilisation                   | GPU recommandé  | Coût estimé sur Clore.ai |
| ----------------------------------- | --------------- | ------------------------ |
| Développement/Test                  | RTX 3090 (24GB) | \~$0.12/gpu/hr           |
| Recherche vectorielle en production | RTX 3090 (24GB) | \~$0.12/gpu/hr           |
| Embeddings à haut débit             | RTX 4090 (24GB) | \~$0.70/gpu/hr           |

> 💡 Tous les exemples de ce guide peuvent être déployés sur [Clore.ai](https://clore.ai/marketplace) serveurs GPU. Parcourez les GPU disponibles et louez à l’heure — sans engagement, avec accès root complet.


---

# 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:

```
GET https://docs.clore.ai/guides/guides_v2-fr/rag-et-bases-de-donnees-vectorielles/milvus.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
