> 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/qdrant.md).

# Qdrant

> **Base de données vectorielle haute performance pour la recherche sémantique et les applications RAG — indexation accélérée par GPU**

Qdrant est une base de données vectorielle open source prête pour la production, écrite en Rust. Elle offre une recherche d'approx nearest neighbor (ANN) rapide sur des milliards de vecteurs avec filtrage avancé, indexation des payloads et prise en charge multi-vecteurs. C'est l'épine dorsale de nombreux pipelines RAG (Retrieval-Augmented Generation) en production et d'applications de recherche sémantique.

**GitHub :** [qdrant/qdrant](https://github.com/qdrant/qdrant) — 22K+ ⭐

***

## Pourquoi Qdrant ?

| Fonctionnalité                   | Qdrant     | Pinecone           | Weaviate | Chroma    |
| -------------------------------- | ---------- | ------------------ | -------- | --------- |
| Open source                      | ✅          | ❌                  | ✅        | ✅         |
| Performance Rust                 | ✅          | —                  | ❌ Go     | ❌ Python  |
| Filtrage au moment de la requête | ✅ Avancé   | ✅ Basique          | ✅        | ✅ Basique |
| Multi-vecteur                    | ✅          | ❌                  | ✅        | ❌         |
| HNSW basé sur disque             | ✅          | ✅                  | ✅        | ❌         |
| Indexation de payload            | ✅          | Limité             | ✅        | Limité    |
| gRPC + REST                      | ✅ Les deux | ✅ REST             | ✅        | REST      |
| Auto-hébergé                     | ✅          | ❌ Cloud uniquement | ✅        | ✅         |

{% hint style="success" %}
**Qdrant est écrit en Rust** — offrant des performances de niveau C avec sécurité mémoire. Les tests de benchmark montrent que Qdrant est constamment **1,5–3x plus rapide** que des alternatives basées sur Python comme Chroma dans des scénarios à forte charge.
{% endhint %}

***

## Cas d'utilisation clés

* **RAG (Retrieval-Augmented Generation)** — trouver un contexte pertinent pour les prompts LLM
* **Recherche sémantique** — rechercher par sens, pas seulement par mots-clés
* **Systèmes de recommandation** — trouver des éléments similaires par similarité d'embeddings
* **Détection de doublons** — identifier un contenu presque dupliqué
* **Détection d'anomalies** — trouver des vecteurs éloignés des centres de clusters
* **Recherche de similarité image/audio** — récupération multimodale

***

## Prérequis

* Compte Clore.ai avec location de GPU
* Familiarité de base avec les API REST ou Python
* Votre modèle d'embeddings préféré (OpenAI, SentenceTransformers, etc.)

***

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

Qdrant dépend principalement du CPU/RAM pour le service, mais bénéficie du GPU lorsque :

* Génération d'embeddings en parallèle du service (modèle d'embeddings sur le même serveur)
* Opérations d'indexation en lots à grande échelle

1. Aller à [clore.ai](https://clore.ai) → **Place de marché**
2. Pour **combinaison embeddings + service :** RTX 3090/4090 avec 32 Go+ de RAM
3. Pour **service uniquement :** Serveur optimisé CPU avec stockage NVMe rapide

{% hint style="info" %}
**Planification mémoire :**

* Chaque vecteur float32 de 1536 dimensions = 6 Ko
* 1 million de vecteurs = \~6 Go de RAM
* 10 millions de vecteurs = \~60 Go de RAM
* Activer le stockage sur disque pour des collections très volumineuses
  {% endhint %}

***

## Étape 2 — Déployer le conteneur Qdrant

**Image Docker :**

```
qdrant/qdrant:latest
```

**Ports :**

```
22
6333
6334
```

* **Port 6333 :** API REST (HTTP)
* **Port 6334 :** API gRPC (meilleure performance pour les opérations en masse)

**Variables d’environnement :**

```
QDRANT__SERVICE__HTTP_PORT=6333
QDRANT__SERVICE__GRPC_PORT=6334
QDRANT__LOG_LEVEL=INFO
QDRANT__STORAGE__STORAGE_PATH=/qdrant/storage
```

**Volume/Stockage persistant :** Monter `/qdrant/storage` pour la persistance des données. Sans cela, les données sont perdues au redémarrage du conteneur.

***

## Étape 3 — Vérifier que Qdrant fonctionne

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

# Vérifier que Qdrant fonctionne
curl http://localhost:6333/

# Réponse attendue :
# {"title":"qdrant - vector search engine","version":"..."}

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

# Vérifier les infos du cluster
curl http://localhost:6333/cluster
```

***

## Étape 4 — Installer le client Python

```bash
# Installer le client Python Qdrant et les outils d'embeddings
pip install qdrant-client sentence-transformers openai numpy

# Vérifier la connexion
python3 << 'EOF'
from qdrant_client import QdrantClient

client = QdrantClient("localhost", port=6333)
print(f"Qdrant connecté : {client.get_collections()}")
EOF
```

***

## Étape 5 — Créer une collection

Une collection est un groupe nommé de vecteurs avec une dimension fixe.

```python
from qdrant_client import QdrantClient
from qdrant_client.models import (
    Distance,
    VectorParams,
    HnswConfigDiff,
    OptimizersConfigDiff,
    QuantizationConfig,
    ScalarQuantizationConfig,
    ScalarType
)

client = QdrantClient("localhost", port=6333)

# Créer une collection pour OpenAI text-embedding-3-small (1536 dims)
client.create_collection(
    collection_name="documents",
    vectors_config=VectorParams(
        size=1536,           # Dimension du vecteur (correspond à votre modèle d'embeddings)
        distance=Distance.COSINE,  # Options : COSINE, EUCLID, DOT
        on_disk=False        # Mettre True pour des collections très volumineuses
    ),
    hnsw_config=HnswConfigDiff(
        m=16,                # Connectivité du graphe HNSW (plus élevé = meilleur rappel, plus de RAM)
        ef_construct=100,    # Profondeur de recherche au moment de la construction (plus élevé = meilleure qualité, indexation plus lente)
        full_scan_threshold=10000  # Utiliser la force brute sous ce seuil
    ),
    optimizers_config=OptimizersConfigDiff(
        indexing_threshold=20000  # Démarrer l'indexation HNSW après autant de vecteurs
    ),
    quantization_config=QuantizationConfig(
        scalar=ScalarQuantizationConfig(
            type=ScalarType.INT8,  # Compresser les vecteurs en INT8 (réduction mémoire 4x)
            quantile=0.99,
            always_ram=True        # Garder l'index quantifié en RAM
        )
    )
)

print("Collection créée !")
print(client.get_collection("documents"))
```

### Collection pour SentenceTransformers (384 dims)

```python
client.create_collection(
    collection_name="embeddings_384",
    vectors_config=VectorParams(
        size=384,              # taille de sortie de all-MiniLM-L6-v2
        distance=Distance.COSINE
    )
)
```

***

## Étape 6 — Indexer des documents

### Avec OpenAI Embeddings

```python
from qdrant_client import QdrantClient
from qdrant_client.models import PointStruct
from openai import OpenAI
import uuid

client = QdrantClient("localhost", port=6333)
openai_client = OpenAI(api_key="votre-cle-openai")

def get_embeddings(texts: list[str], batch_size: int = 100) -> list[list[float]]:
    """Générer des embeddings par lots."""
    all_embeddings = []
    for i in range(0, len(texts), batch_size):
        batch = texts[i:i + batch_size]
        response = openai_client.embeddings.create(
            model="text-embedding-3-small",
            input=batch
        )
        all_embeddings.extend([e.embedding for e in response.data])
    return all_embeddings

# Documents d'exemple
documents = [
    {
        "id": str(uuid.uuid4()),
        "text": "Qdrant est une base de données vectorielle construite en Rust pour des performances élevées.",
        "source": "documentation",
        "category": "database",
        "year": 2024
    },
    {
        "id": str(uuid.uuid4()),
        "text": "Les modèles d'apprentissage automatique convertissent le texte en représentations vectorielles denses.",
        "source": "article",
        "category": "ml",
        "year": 2023
    },
    # Ajouter plus de documents...
]

# Générer des embeddings
texts = [doc["text"] for doc in documents]
embeddings = get_embeddings(texts)

# Upsert dans Qdrant
points = [
    PointStruct(
        id=str(uuid.uuid4()),
        vector=embedding,
        payload={
            "text": doc["text"],
            "source": doc["source"],
            "category": doc["category"],
            "year": doc["year"]
        }
    )
    for doc, embedding in zip(documents, embeddings)
]

client.upsert(
    collection_name="documents",
    points=points,
    wait=True  # Attendre que l'indexation soit terminée
)

print(f"Indexé {len(points)} documents !")
```

### Avec SentenceTransformers (local, accéléré par GPU)

```python
from sentence_transformers import SentenceTransformer
from qdrant_client import QdrantClient
from qdrant_client.models import PointStruct
import torch
import uuid

# Charger le modèle d'embeddings sur GPU
model = SentenceTransformer("all-MiniLM-L6-v2", device="cuda")

client = QdrantClient("localhost", port=6333)

documents = [
    {"text": "Comment configurer Qdrant sur un serveur GPU ?", "tag": "setup"},
    {"text": "Les bases de données vectorielles stockent des embeddings haute dimension pour la recherche par similarité.", "tag": "concept"},
    {"text": "L'algorithme HNSW fournit une recherche approximative des plus proches voisins.", "tag": "algorithm"},
    # ... plus de documents
]

# Encodage par lots accéléré GPU
texts = [doc["text"] for doc in documents]
embeddings = model.encode(
    texts,
    batch_size=256,       # Grande taille de lot pour l'efficacité GPU
    show_progress_bar=True,
    normalize_embeddings=True  # Normaliser pour la similarité cosinus
)

# Indexer dans Qdrant
points = [
    PointStruct(
        id=str(uuid.uuid4()),
        vector=embedding.tolist(),
        payload=doc
    )
    for doc, embedding in zip(documents, embeddings)
]

# Upsert par lots (plus efficace)
BATCH_SIZE = 1000
for i in range(0, len(points), BATCH_SIZE):
    batch = points[i:i + BATCH_SIZE]
    client.upsert(collection_name="embeddings_384", points=batch)
    print(f"Indexé {min(i + BATCH_SIZE, len(points))}/{len(points)}")
```

***

## Étape 7 — Recherche et requête

### Recherche sémantique basique

```python
from qdrant_client import QdrantClient
from sentence_transformers import SentenceTransformer

client = QdrantClient("localhost", port=6333)
model = SentenceTransformer("all-MiniLM-L6-v2", device="cuda")

def search(query: str, limit: int = 5, collection: str = "embeddings_384"):
    # Générer l'embedding de la requête
    query_vector = model.encode(query, normalize_embeddings=True).tolist()
    
    # Recherche
    results = client.search(
        collection_name=collection,
        query_vector=query_vector,
        limit=limit,
        with_payload=True,
        with_vectors=False    # Ne pas retourner les vecteurs (économise la bande passante)
    )
    
    return results

# Tester la recherche
results = search("performance des bases de données vectorielles")
for r in results:
    print(f"Score: {r.score:.4f} | {r.payload['text'][:100]}")
```

### Recherche filtrée (métadonnées + vecteur)

```python
from qdrant_client.models import Filter, FieldCondition, MatchValue, Range

# Recherche avec filtres metadata
results = client.search(
    collection_name="documents",
    query_vector=query_vector,
    query_filter=Filter(
        must=[
            FieldCondition(
                key="category",
                match=MatchValue(value="database")
            ),
            FieldCondition(
                key="year",
                range=Range(gte=2023)  # Année >= 2023
            )
        ]
    ),
    limit=10,
    with_payload=True
)
```

### Recherche par lots/multi-requête

```python
from qdrant_client.models import SearchRequest

queries = [
    "comment installer une base de données vectorielle",
    "optimisation de l'inférence en machine learning",
    "architecture de pipeline RAG"
]

query_vectors = model.encode(queries, normalize_embeddings=True)

# Recherche par lots (un appel API pour toutes les requêtes)
results = client.search_batch(
    collection_name="embeddings_384",
    requests=[
        SearchRequest(
            vector=vec.tolist(),
            limit=5,
            with_payload=True
        )
        for vec in query_vectors
    ]
)

for query, res in zip(queries, results):
    print(f"\nRequête : {query}")
    for r in res:
        print(f"  {r.score:.3f} : {r.payload['text'][:80]}")
```

***

## Étape 8 — Construire un pipeline RAG

```python
from qdrant_client import QdrantClient
from sentence_transformers import SentenceTransformer
from openai import OpenAI

# Initialiser les clients
qdrant = QdrantClient("localhost", port=6333)
embedder = SentenceTransformer("all-MiniLM-L6-v2", device="cuda")
llm = OpenAI(api_key="votre-cle-openai")

def rag_query(question: str, n_context: int = 5) -> str:
    # Étape 1 : Encoder la question
    query_vector = embedder.encode(question, normalize_embeddings=True).tolist()
    
    # Étape 2 : Récupérer le contexte pertinent depuis Qdrant
    search_results = qdrant.search(
        collection_name="documents",
        query_vector=query_vector,
        limit=n_context,
        with_payload=True
    )
    
    # Étape 3 : Construire la chaîne de contexte
    context = "\n\n".join([
        f"[Source : {r.payload.get('source', 'inconnue')}]\n{r.payload['text']}"
        for r in search_results
        if r.score > 0.5  # Filtrer les résultats à faible confiance
    ])
    
    # Étape 4 : Générer la réponse avec le LLM
    response = llm.chat.completions.create(
        model="gpt-4o-mini",
        messages=[
            {
                "role": "system",
                "content": "Répondre aux questions en se basant sur le contexte fourni. Être concis et précis."
            },
            {
                "role": "user",
                "content": f"Contexte:\n{context}\n\nQuestion : {question}"
            }
        ],
        temperature=0.1
    )
    
    return response.choices[0].message.content

# Tester le pipeline RAG
answer = rag_query("Qu'est-ce que Qdrant et comment fonctionne-t-il ?")
print(answer)
```

***

## Étape 9 — Surveiller et gérer les collections

```python
# Statistiques de la collection
info = client.get_collection("documents")
print(f"Nombre de vecteurs : {info.vectors_count:,}")
print(f"Nombre de points : {info.points_count:,}")
print(f"Vecteurs indexés : {info.indexed_vectors_count:,}")
print(f"Statut : {info.status}")
print(f"Utilisation disque : {info.disk_data_size / 1024 / 1024:.1f} MB")

# Lister toutes les collections
collections = client.get_collections()
for c in collections.collections:
    print(f" - {c.name}")

# Supprimer des points par filtre
client.delete(
    collection_name="documents",
    points_selector=Filter(
        must=[FieldCondition(key="source", match=MatchValue(value="old_source"))]
    )
)

# Optimiser la collection (forcer la construction de l'index)
client.update_collection(
    collection_name="documents",
    optimizer_config=OptimizersConfigDiff(indexing_threshold=0)  # Forcer l'indexation immédiate
)
```

***

## Dépannage

### Connexion refusée

```bash
# Vérifier que Qdrant fonctionne
docker ps | grep qdrant
# Ou vérifier le processus
ps aux | grep qdrant

# Vérifier que les ports sont ouverts
curl http://localhost:6333/
netstat -tlnp | grep 6333
```

### Performance de recherche lente

```python
# Optimiser les paramètres HNSW pour un meilleur rappel
client.update_collection(
    collection_name="documents",
    hnsw_config=HnswConfigDiff(ef=128)  # Augmenter ef de temps de recherche (par défaut 100)
)

# Utiliser la quantification INT8 pour faire tenir plus de vecteurs en RAM
```

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

```python
# Activer le stockage sur disque pour les grandes collections
client.create_collection(
    collection_name="large_collection",
    vectors_config=VectorParams(
        size=1536,
        distance=Distance.COSINE,
        on_disk=True  # Stocker les vecteurs sur disque plutôt qu'en RAM
    )
)
```

***

## Référence rapide de l'API REST

```bash
# Lister les collections
curl http://localhost:6333/collections

# Créer une collection
curl -X PUT http://localhost:6333/collections/my_collection \
    -H "Content-Type: application/json" \
    -d '{"vectors": {"size": 384, "distance": "Cosine"}}'

# Compter les points
curl http://localhost:6333/collections/my_collection/points/count

# Recherche
curl -X POST http://localhost:6333/collections/my_collection/points/search \
    -H "Content-Type: application/json" \
    -d '{
        "vector": [0.1, 0.2, ...],
        "limit": 5,
        "with_payload": true
    }'

# Supprimer une collection
curl -X DELETE http://localhost:6333/collections/my_collection
```

***

## Estimation des coûts sur Clore.ai

| Configuration     | Serveur             | Coût mensuel | Capacité       |
| ----------------- | ------------------- | ------------ | -------------- |
| Petit RAG         | RTX 3090, 32 Go RAM | \~60–80 $    | \~5M vecteurs  |
| Recherche moyenne | RTX 4090, 64 Go RAM | \~120–150 $  | \~15M vecteurs |
| Grande échelle    | A100, 128 Go RAM    | \~250–350 $  | \~30M vecteurs |

***

## Ressources supplémentaires

* [Documentation Qdrant](https://qdrant.tech/documentation/)
* [GitHub Qdrant](https://github.com/qdrant/qdrant)
* [Client Python Qdrant](https://github.com/qdrant/qdrant-client)
* [Exemples Qdrant](https://github.com/qdrant/examples)
* [Benchmarks de bases de données vectorielles](https://qdrant.tech/benchmarks/)
* [Sentence Transformers](https://www.sbert.net/)

***

*Qdrant sur Clore.ai vous offre une base de données vectorielle auto-hébergée et haute performance sans les coûts par requête de Pinecone ou Weaviate Cloud. Parfait pour les pipelines RAG traitant des millions de documents.*

***

## 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/qdrant.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.
