> 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-zh/rag-yu-xiang-liang-shu-ju-ku/qdrant.md).

# Qdrant

> **用于语义搜索和 RAG 应用的高性能向量数据库 — GPU 加速索引**

Qdrant 是一款用 Rust 编写的开源、可直接用于生产的向量数据库。它通过高级过滤、载荷索引和多向量支持，在数十亿个向量中提供快速的近似最近邻（ANN）搜索。它是许多生产级 RAG（检索增强生成）管道和语义搜索应用的基础。

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

***

## 为什么选择 Qdrant？

| 功能          | Qdrant  | Pinecone | Weaviate | Chroma   |
| ----------- | ------- | -------- | -------- | -------- |
| 开源          | ✅       | ❌        | ✅        | ✅        |
| Rust 性能     | ✅       | —        | ❌ Go     | ❌ Python |
| 查询时过滤       | ✅ 高级    | ✅ 基础     | ✅        | ✅ 基础     |
| 多向量         | ✅       | ❌        | ✅        | ❌        |
| 基于磁盘的 HNSW  | ✅       | ✅        | ✅        | ❌        |
| 载荷索引        | ✅       | 有限       | ✅        | 有限       |
| gRPC + REST | ✅ 两者都支持 | ✅ REST   | ✅        | REST     |
| 自托管         | ✅       | ❌ 仅云端    | ✅        | ✅        |

{% hint style="success" %}
**Qdrant 采用 Rust 编写** — 在保证内存安全的同时提供 C 级性能。基准测试表明，Qdrant 的表现始终 **快 1.5–3 倍** 在高负载场景下优于基于 Python 的替代方案，如 Chroma。
{% endhint %}

***

## 主要用例

* **RAG（检索增强生成）** — 为 LLM 提示词查找相关上下文
* **语义搜索** — 按语义搜索，而不只是关键词
* **推荐系统** — 通过嵌入相似性查找相似项目
* **重复检测** — 识别近似重复内容
* **异常检测** — 查找远离聚类中心的向量
* **图像/音频相似性搜索** — 多模态检索

***

## 前提条件

* 带 GPU 租赁的 Clore.ai 账户
* 对 REST API 或 Python 有基本了解
* 你选择的嵌入模型（OpenAI、SentenceTransformers 等）

***

## 步骤 1 — 在 Clore.ai 上租用服务器

Qdrant 在提供服务时主要受 CPU/RAM 限制，但在以下情况会受益于 GPU：

* 在提供服务的同时生成嵌入（嵌入模型运行在同一台服务器上）
* 大规模批量索引操作

1. 前往 [clore.ai](https://clore.ai) → **市场**
2. 用于 **嵌入 + 服务组合：** 配备 32GB+ 内存的 RTX 3090/4090
3. 用于 **仅提供服务：** 配备高速 NVMe 存储的 CPU 优化服务器

{% hint style="info" %}
**内存规划：**

* 每个 1536 维的 float32 向量 = 6KB
* 100 万个向量 = 约 6GB 内存
* 1000 万个向量 = 约 60GB 内存
* 对于非常大的集合，请启用磁盘存储
  {% endhint %}

***

## 步骤 2 — 部署 Qdrant 容器

**Docker 镜像：**

```
qdrant/qdrant:latest
```

**端口：**

```
22
6333
6334
```

* **端口 6333：** REST API（HTTP）
* **端口 6334：** gRPC API（适合批量操作，性能更高）

**环境变量：**

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

**卷/持久化存储：** 挂载 `/qdrant/storage` 用于数据持久化。如果不这样做，容器重启后数据将丢失。

***

## 步骤 3 — 验证 Qdrant 是否正在运行

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

# 检查 Qdrant 是否正在运行
curl http://localhost:6333/

# 预期响应：
# {"title":"qdrant - 向量搜索引擎","version":"..."}

# 检查健康状态
curl http://localhost:6333/healthz

# 检查集群信息
curl http://localhost:6333/cluster
```

***

## 步骤 4 — 安装 Python 客户端

```bash
# 安装 Qdrant Python 客户端和嵌入工具
pip install qdrant-client sentence-transformers openai numpy

# 验证连接
python3 << 'EOF'
from qdrant_client import QdrantClient

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

***

## 步骤 5 — 创建集合

集合是具有固定维度的命名向量组。

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

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

# 为 OpenAI text-embedding-3-small 创建集合（1536 维）
client.create_collection(
    collection_name="documents",
    vectors_config=VectorParams(
        size=1536,           # 向量维度（与您的嵌入模型匹配）
        distance=Distance.COSINE,  # 可选：COSINE、EUCLID、DOT
        on_disk=False        # 对于非常大的集合设置为 True
    ),
    hnsw_config=HnswConfigDiff(
        m=16,                # HNSW 图连接度（越高 = 召回率越好，内存占用越大）
        ef_construct=100,    # 构建时搜索深度（越高 = 质量越好，索引越慢）
        full_scan_threshold=10000  # 低于此数量时使用暴力搜索
    ),
    optimizers_config=OptimizersConfigDiff(
        indexing_threshold=20000  # 在达到这么多向量后开始 HNSW 索引
    ),
    quantization_config=QuantizationConfig(
        scalar=ScalarQuantizationConfig(
            type=ScalarType.INT8,  # 将向量压缩为 INT8（内存减少 4 倍）
            quantile=0.99,
            always_ram=True        # 将量化索引保留在内存中
        )
    )
)

print("集合已创建！")
print(client.get_collection("documents"))
```

### SentenceTransformers 的集合（384 维）

```python
client.create_collection(
    collection_name="embeddings_384",
    vectors_config=VectorParams(
        size=384,              # all-MiniLM-L6-v2 输出大小
        distance=Distance.COSINE
    )
)
```

***

## 步骤 6 — 索引文档

### 使用 OpenAI 嵌入

```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="your-openai-api-key")

def get_embeddings(texts: list[str], batch_size: int = 100) -> list[list[float]]:
    """批量生成嵌入。"""
    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 = [
    {
        "id": str(uuid.uuid4()),
        "text": "Qdrant 是一个用 Rust 构建的高性能向量数据库。",
        "source": "documentation",
        "category": "database",
        "year": 2024
    },
    {
        "id": str(uuid.uuid4()),
        "text": "机器学习模型将文本转换为稠密向量表示。",
        "source": "article",
        "category": "ml",
        "year": 2023
    },
    # 添加更多文档...
]

# 生成嵌入
texts = [doc["text"] for doc in documents]
embeddings = get_embeddings(texts)

# 上载到 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  # 等待索引完成
)

print(f"已索引 {len(points)} 篇文档！")
```

### 使用 SentenceTransformers（本地，GPU 加速）

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

# 在 GPU 上加载嵌入模型
model = SentenceTransformer("all-MiniLM-L6-v2", device="cuda")

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

documents = [
    {"text": "如何在 GPU 服务器上设置 Qdrant？", "tag": "setup"},
    {"text": "向量数据库存储高维嵌入用于相似性搜索。", "tag": "concept"},
    {"text": "HNSW 算法提供近似最近邻搜索。", "tag": "algorithm"},
    # ... 更多文档
]

# GPU 加速批量编码
texts = [doc["text"] for doc in documents]
embeddings = model.encode(
    texts,
    batch_size=256,       # GPU 效率更高的大批量大小
    show_progress_bar=True,
    normalize_embeddings=True  # 为余弦相似度进行归一化
)

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

# 批量上载（更高效）
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"已索引 {min(i + BATCH_SIZE, len(points))}/{len(points)}")
```

***

## 步骤 7 — 搜索与查询

### 基础语义搜索

```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"):
    # 生成查询嵌入
    query_vector = model.encode(query, normalize_embeddings=True).tolist()
    
    # 搜索
    results = client.search(
        collection_name=collection,
        query_vector=query_vector,
        limit=limit,
        with_payload=True,
        with_vectors=False    # 不返回向量（节省带宽）
    )
    
    return results

# 测试搜索
results = search("向量数据库性能")
for r in results:
    print(f"得分：{r.score:.4f} | {r.payload['text'][:100]}")
```

### 过滤搜索（元数据 + 向量）

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

# 使用元数据过滤进行搜索
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)  # 年份 >= 2023
            )
        ]
    ),
    limit=10,
    with_payload=True
)
```

### 批量/多查询搜索

```python
from qdrant_client.models import SearchRequest

queries = [
    "如何安装向量数据库",
    "机器学习推理优化",
    "RAG 管道架构"
]

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

# 批量搜索（一次 API 调用处理所有查询）
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"\n查询：{query}")
    for r in res:
        print(f"  {r.score:.3f}: {r.payload['text'][:80]}")
```

***

## 步骤 8 — 构建 RAG 管道

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

# 初始化客户端
qdrant = QdrantClient("localhost", port=6333)
embedder = SentenceTransformer("all-MiniLM-L6-v2", device="cuda")
llm = OpenAI(api_key="your-openai-key")

def rag_query(question: str, n_context: int = 5) -> str:
    # 第 1 步：对问题进行嵌入
    query_vector = embedder.encode(question, normalize_embeddings=True).tolist()
    
    # 第 2 步：从 Qdrant 中检索相关上下文
    search_results = qdrant.search(
        collection_name="documents",
        query_vector=query_vector,
        limit=n_context,
        with_payload=True
    )
    
    # 第 3 步：构建上下文字符串
    context = "\n\n".join([
        f"[来源: {r.payload.get('source', 'unknown')}]\n{r.payload['text']}"
        for r in search_results
        if r.score > 0.5  # 过滤低置信度结果
    ])
    
    # 第 4 步：使用 LLM 生成答案
    response = llm.chat.completions.create(
        model="gpt-4o-mini",
        messages=[
            {
                "role": "system",
                "content": "根据提供的上下文回答问题。保持简洁准确。"
            },
            {
                "role": "user",
                "content": f"上下文：\n{context}\n\n问题：{question}"
            }
        ],
        temperature=0.1
    )
    
    return response.choices[0].message.content

# 测试 RAG 管道
answer = rag_query("Qdrant 是什么，它是如何工作的？")
print(answer)
```

***

## 步骤 9 — 监控和管理集合

```python
# 集合统计信息
info = client.get_collection("documents")
print(f"向量数量：{info.vectors_count:,}")
print(f"点数量：{info.points_count:,}")
print(f"已索引向量：{info.indexed_vectors_count:,}")
print(f"状态：{info.status}")
print(f"磁盘使用量：{info.disk_data_size / 1024 / 1024:.1f} MB")

# 列出所有集合
collections = client.get_collections()
for c in collections.collections:
    print(f" - {c.name}")

# 按过滤条件删除点
client.delete(
    collection_name="documents",
    points_selector=Filter(
        must=[FieldCondition(key="source", match=MatchValue(value="old_source"))]
    )
)

# 优化集合（强制构建索引）
client.update_collection(
    collection_name="documents",
    optimizer_config=OptimizersConfigDiff(indexing_threshold=0)  # 强制立即索引
)
```

***

## 故障排查

### 连接被拒绝

```bash
# 检查 Qdrant 是否正在运行
docker ps | grep qdrant
# 或检查进程
ps aux | grep qdrant

# 检查端口是否开放
curl http://localhost:6333/
netstat -tlnp | grep 6333
```

### 搜索性能缓慢

```python
# 优化 HNSW 参数以提高召回率
client.update_collection(
    collection_name="documents",
    hnsw_config=HnswConfigDiff(ef=128)  # 增大搜索时的 ef（默认 100）
)

# 使用 INT8 量化以在内存中容纳更多向量
```

### 高内存使用

```python
# 为大型集合启用磁盘存储
client.create_collection(
    collection_name="large_collection",
    vectors_config=VectorParams(
        size=1536,
        distance=Distance.COSINE,
        on_disk=True  # 将向量存储在磁盘而不是内存中
    )
)
```

***

## REST API 快速参考

```bash
# 列出集合
curl http://localhost:6333/collections

# 创建集合
curl -X PUT http://localhost:6333/collections/my_collection \
    -H "Content-Type: application/json" \\
    -d '{"vectors": {"size": 384, "distance": "Cosine"}}'

# 统计点数量
curl http://localhost:6333/collections/my_collection/points/count

# 搜索
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
    }'

# 删除集合
curl -X DELETE http://localhost:6333/collections/my_collection
```

***

## Clore.ai 成本估算

| 配置     | 服务器              | 月成本          | 容量          |
| ------ | ---------------- | ------------ | ----------- |
| 小型 RAG | RTX 3090，32GB 内存 | 约 60–80 美元   | 约 500 万个向量  |
| 中等规模搜索 | RTX 4090，64GB 内存 | 约 120–150 美元 | 约 1500 万个向量 |
| 大规模    | A100，128GB 内存    | 约 250–350 美元 | 约 3000 万个向量 |

***

## 更多资源

* [Qdrant 文档](https://qdrant.tech/documentation/)
* [Qdrant GitHub](https://github.com/qdrant/qdrant)
* [Qdrant Python 客户端](https://github.com/qdrant/qdrant-client)
* [Qdrant 示例](https://github.com/qdrant/examples)
* [向量数据库基准测试](https://qdrant.tech/benchmarks/)
* [Sentence Transformers](https://www.sbert.net/)

***

*Qdrant 在 Clore.ai 上为你提供自托管、高性能的向量数据库，无需承担 Pinecone 或 Weaviate Cloud 的按查询计费成本。非常适合处理数百万文档的 RAG 流水线。*

***

## Clore.ai GPU 推荐

| 使用场景    | 推荐 GPU         | Clore.ai 预计成本     |
| ------- | -------------- | ----------------- |
| 开发/测试   | RTX 3090（24GB） | $0.07–0.21/gpu/hr |
| 生产级向量搜索 | RTX 3090（24GB） | $0.07–0.21/gpu/hr |
| 高吞吐量嵌入  | RTX 4090（24GB） | $0.14–0.42/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-zh/rag-yu-xiang-liang-shu-ju-ku/qdrant.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.
