Qdrant

Qdrant 是独立向量数据库(Rust),以 HTTP 6333(REST / Dashboard)和 6334(gRPC)对外服务。适合需要 payload 过滤、多客户端、之后做混合检索的项目。文档:qdrant.tech/documentation

本机开发仍可先用 Chroma;已有 Postgres 用 pgvector


Docker 启动

需要本机 Docker。官方 Quickstart 会映射两个端口,并挂卷保存数据。

docker pull qdrant/qdrant
docker run -p 6333:6333 -p 6334:6334 \
  -v "$(pwd)/qdrant_storage:/qdrant/storage:z" \
  qdrant/qdrant
docker pull qdrant/qdrant
docker run -p 6333:6333 -p 6334:6334 `
  -v "${PWD}/qdrant_storage:/qdrant/storage" `
  qdrant/qdrant

浏览器打开 http://localhost:6333/dashboard。健康检查:

curl http://localhost:6333/readyz
Invoke-RestMethod http://localhost:6333/readyz

只映射 6333 时,部分 Python 客户端若走 gRPC 会连不上 6334,两个端口都映射更省事。Docker 基础见本站 Docker 教程


Python 客户端:建表、upsert、检索

pip install qdrant-client
from qdrant_client import QdrantClient
from qdrant_client.models import Distance, PointStruct, VectorParams

client = QdrantClient(url="http://localhost:6333")

client.create_collection(
    collection_name="faq",
    vectors_config=VectorParams(size=1536, distance=Distance.COSINE),
)

vec = [0.0] * 1536  # 换成 embeddings 章的真实向量
vec[0] = 0.12
client.upsert(
    collection_name="faq",
    wait=True,
    points=[
        PointStruct(
            id=1,
            vector=vec,
            payload={"source": "refund.md", "dept": "hr", "text": "退款须在到货 7 日内申请。"},
        )
    ],
)

hits = client.query_points(
    collection_name="faq",
    query=vec,
    limit=3,
    with_payload=True,
).points
print([(h.id, h.payload) for h in hits])

upsert = 插入或覆盖同一 id。旧文档里的 client.search(...) 与现在的 query_points 都是「按向量找近邻」;新代码请跟官方 Quickstart 用 query_pointssize 必须等于嵌入维数(OpenAI small = 1536,bge-m3 ≈ 1024)。


Payload 过滤

from qdrant_client.models import FieldCondition, Filter, MatchValue

hits = client.query_points(
    collection_name="faq",
    query=vec,
    query_filter=Filter(
        must=[FieldCondition(key="dept", match=MatchValue(value="hr"))]
    ),
    limit=5,
    with_payload=True,
).points

这就是「混合」的第一层:语义近邻 部门 / 语言 / 时间符合条件。完整 FAQ + 过滤见 实战案例 案例 3。


混合检索预告(dense + sparse)

Qdrant 可在同一 collection 里存 dense 向量和 sparse(BM25 类)向量,再用 Reciprocal Rank Fusion 合并。教学上先把 dense + filter 做稳,再加稀疏通道:

from qdrant_client.models import Fusion, FusionQuery, Prefetch

# 示意:collection 需先配置 named vectors "dense" 与 "sparse"
# hits = client.query_points(
#     collection_name="faq",
#     prefetch=[
#         Prefetch(query=dense_vec, using="dense", limit=20),
#         Prefetch(query=sparse_vec, using="sparse", limit=20),
#     ],
#     query=FusionQuery(fusion=Fusion.RRF),
# ).points

专有名词、条款号往往稀疏通道更稳;同义改写靠 dense。两者一起上之前,先用 评估 的 hit@k 对比「只 dense」和「dense+filter」。


下一步

评论