> 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 d’IA — conçue pour des milliards de vecteurs**

Milvus est une base de données vectorielle open source conçue spécialement pour la recherche de similarité à grande échelle et les applications d’IA. Créé à l’origine par Zilliz et donné à la LF AI & Data Foundation, Milvus alimente des charges de travail d’IA en production chez des entreprises telles que NVIDIA, AT\&T, IBM et Salesforce. C’est le choix de référence lorsque vous devez passer à l’échelle de milliards de vecteurs.

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

***

## Milvus contre Qdrant — Quand choisir l’un ou l’autre

| Critères                       | Milvus                         | Qdrant                    |
| ------------------------------ | ------------------------------ | ------------------------- |
| Échelle                        | Des milliards de vecteurs      | Des centaines de millions |
| Architecture                   | Distribué (plusieurs services) | Binaire unique            |
| Complexité de configuration    | Plus élevée                    | Réduisez                  |
| Prise en charge de l’index GPU | ✅ FAISS GPU natif              | Limité                    |
| Multi-tenant                   | ✅ Partitions + alias           | Basé sur les collections  |
| Ingestion en flux              | ✅ Kafka/Pulsar                 | Limité                    |
| Recherche hybride              | ✅ Dense + clairsemé            | ✅                         |
| Option gérée dans le cloud     | Zilliz Cloud                   | Qdrant Cloud              |

{% hint style="success" %}
**Choisissez Milvus lorsque :** Vous devez passer à l’échelle de milliards de vecteurs, avez besoin d’une indexation accélérée par GPU (IVF\_FLAT\_GPU) ou de fonctionnalités d’entreprise comme le multi-tenant, l’ingestion en flux et le contrôle d’accès basé sur les rôles.
{% endhint %}

***

## Architecture de Milvus

Milvus en mode autonome (serveur unique) comprend :

* **milvus** — le service principal (proxy, coordonnateurs de requêtes, de données et d’index)
* **etcd** — stockage des métadonnées et découverte de services
* **MinIO** — stockage d’objets pour les données de segment

En mode distribué (cluster), chaque composant évolue indépendamment.

***

## Prérequis

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

***

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

1. Accédez à [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 :** N’importe quel serveur avec 32 Go+ de RAM pour l’indexation sur CPU

**Exigences minimales :**

* CPU : 8 cœurs
* RAM : 16 Go (32 Go recommandés)
* Disque : SSD/NVMe de 50 Go
* GPU : facultatif (requis 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 des index pour les grandes collections. Si vous prévoyez d’indexer fréquemment plus de 10 millions de vecteurs, l’indexation GPU est rapidement rentabilisée.
{% 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 la configuration la plus simple.

**Ports :**

```
22
19530
```

* **Port 19530 :** Port SDK/gRPC de Milvus (principal)
* **Port 9091 :** API REST 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 s’il n’est pas présent
which docker-compose || pip install docker-compose
# Ou utilisez 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 de Milvus en mode autonome
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
```

### Personnalisez 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]  # 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 l’état de santé de Milvus
curl http://localhost:9091/healthz
# Attendu : {"status":"ok"}

# Afficher les journaux
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 connecté !")
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 possède un schéma avec des champs typés, y compris des champs vectoriels.

```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 ID
    ),
    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’encodage
    )
]

schema = CollectionSchema(
    fields=fields,
    description="Vecteurs de documents pour la recherche sémantique",
    enable_dynamic_field=True  # Autoriser l’ajout de champs absents du schéma
)

# Créer la 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}' créée !")
```

***

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

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

```python
from pymilvus import Collection

collection = Collection("documents")

# Index HNSW (le meilleur pour la plupart des cas d’usage, faible latence)
hnsw_params = {
    "metric_type": "COSINE",     # COSINE, L2 ou IP (produit intérieur)
    "index_type": "HNSW",
    "params": {
        "M": 16,                 # Connectivité du graphe HNSW (8-64)
        "efConstruction": 200    # Profondeur de recherche à la construction
    }
}

# Index IVF_FLAT (CPU, adapté aux 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 (nécessite un 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 un index sur le champ 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 créés !")
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 d’IA évolutives.",
        "source": "documentation",
        "category": "database",
        "year": 2024
    },
    {
        "text": "HNSW offre une recherche rapide approximative des plus proches voisins avec un fort rappel.",
        "source": "research",
        "category": "algorithm",
        "year": 2023
    },
    {
        "text": "L’indexation accélérée par GPU réduit considérablement le temps de construction pour les grandes collections de vecteurs.",
        "source": "blog",
        "category": "performance",
        "year": 2024
    },
    # Ajoutez ici des milliers d’autres documents
]

def insert_batch(docs: list, batch_size: int = 1000):
    texts = [d["text"] for d in docs]
    
    # Encodage 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

# Insertion 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"Inséré {total_inserted}/{len(documents)} documents")

# Vider pour s’assurer que les données sont persistées et indexées
collection.flush()
print(f"Total inséré et synchronisé : {total_inserted}")
```

***

## Étape 8 — Rechercher et interroger

### Recherche sémantique de base

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

# Recherche
comment fonctionne la recherche de similarité vectorielle
for hit in hits:
    print(f"Score : {hit.score:.4f}")
    print(f"Texte : {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 sur les 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 + clairsemé)

```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 clairsemé)
sparse_req = AnnSearchRequest(
    data=[sparse_embedding],
    anns_field="sparse_embedding",
    param={"metric_type": "IP"},
    limit=20
)

# Combiner avec la fusion de rang réciproque
results = collection.hybrid_search(
    [dense_req, sparse_req],
    rerank=WeightedRanker(0.7, 0.3),  # 70 % dense, 30 % clairsemé
    limit=10,
    output_fields=["text"]
)
```

***

## Étape 9 — Créer 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="API RAG Milvus")

# 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épondez en vous basant sur le contexte. Soyez concis."},
            {"role": "user", "content": f"Contexte:\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"Nombre d'entités : {col.num_entities:,}")
print(f"Schéma : {col.schema}")

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

# Insérer 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"]  # Rechercher uniquement dans cette partition
)
```

***

## Dépannage

### Les services ne démarrent pas

```bash
# Vérifier les journaux 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 est à l'écoute
netstat -tlnp | grep 19530

# Vérifier l'état de santé
curl http://localhost:9091/healthz

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

### Délai de création d'index dépassé pour les grandes collections

```python
# Augmenter le délai pour les grandes créations d'index
from pymilvus import Collection

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

### Utilisation élevée de la mémoire

```bash
# Configurer les limites 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           | Bon        | Non        |
| HNSW           | Faible latence, <100M         | Élevée          | Excellente | Non        |
| IVF\_SQ8       | Compressé, volumineux         | Faible          | Bon        | Non        |
| GPU\_IVF\_FLAT | Requêtes par lot rapides      | GPU+RAM         | Meilleur   | Oui        |
| DISKANN        | À l'échelle du milliard       | Faible (disque) | Bon        | Non        |

***

## Benchmarks de performance

| Taille de la collection  | Index          | GPU      | QPS      |
| ------------------------ | -------------- | -------- | -------- |
| 1 million de vecteurs    | HNSW           | RTX 3090 | \~8,000  |
| 10 millions de vecteurs  | IVF\_FLAT      | RTX 4090 | \~2,500  |
| 10 millions de vecteurs  | GPU\_IVF\_FLAT | A100     | \~12,000 |
| 100 millions 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)
* [Bootcamp Milvus](https://github.com/milvus-io/bootcamp) — Applications d'exemple
* [Zilliz Cloud](https://cloud.zilliz.com/) — Milvus géré
* [Comparaison des bases de données vectorielles](https://milvus.io/docs/benchmark.md)
* [Interface graphique Attu](https://github.com/zilliztech/attu) — Interface web pour la gestion de Milvus

***

*Milvus sur Clore.ai est la solution idéale pour les applications d'IA qui doivent passer à l'échelle au-delà de centaines de millions de vecteurs. Associée à 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 services cloud gérés.*

***

## Recommandations GPU Clore.ai

| Cas d’utilisation                   | GPU recommandé   | Coût estimé sur Clore.ai |
| ----------------------------------- | ---------------- | ------------------------ |
| Développement/Test                  | RTX 3090 (24 Go) | 0,07–0,21 $/gpu/h        |
| Recherche vectorielle de production | RTX 3090 (24 Go) | 0,07–0,21 $/gpu/h        |
| Embeddings à haut débit             | RTX 4090 (24 Go) | 0,14–0,42 $/gpu/h        |

> 💡 Tous les exemples de ce guide peuvent être déployés sur [Clore.ai](https://clore.ai/marketplace) des serveurs GPU. Parcourez les GPU disponibles et louez à l'heure — sans engagement, 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, and the optional `goal` query parameter:

```
GET https://docs.clore.ai/guides/guides_v2-fr/rag-et-bases-de-donnees-vectorielles/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.
