体验向量数据库 qdrant

作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢!


背景

为了早点搞懂公司的百万行 C# 的祖传代码,我想在缺乏文档、缺乏帮手的情况下,先建立一个 企业知识库 来快速帮我理清头绪。

一开始,我是打算以 weaviate 来作为向量数据库,然后把已有的文档和代码信息都写入向量数据库中;

最后,配合本地的大模型来写提示词进行 AI 总结就行了。

第一期,我先整理了文档,并写入 weaviate。

并且打算也做一个拟人化的 AI 问答助手。

终于在上周,实现了这个问答助手。长这样:

(这个形象一看就给人一种聪明绝顶的感觉......)

实际使用者发现 AI 汇总功能执行得非常慢,且结果也差强人意。

通过思考过程发现,codex 使用了 BM25(Best Matching 25)来在 weaviate 中检索。这也难怪,我为了导入方便,直接把整个文档导入到了 weaviate,没有先为文档计算向量。

于是,我尝试使用了 qdrant 向量数据库。

直观的感受上,查询速度和查询结果都好了很多。

下面是我部署的细节:

Cooking 搞起

qdrant 服务器

docker 命令如下:

bash 复制代码
docker run -it --rm \
  --name qdrant \
  -p 6333:6333 \
  -p 6334:6334 \
  -v "/Users/ahfu/Downloads/temp/2026/qdrant_storage:/qdrant/storage" \
  -e QDRANT__SERVICE__API_KEY='my-secret-key' \
  qdrant/qdrant:v1.15.4
  • 6333 是 http 端口
  • 6334 是 grpc 端口
  • QDRANT__SERVICE__API_KEY 来为服务器设置一个 api key

但是,这个服务器并不提供 MCP 的接口,为了方便文档导入 + AI 检索,还需要再部署 MCP 服务器。

mcp-server-qdrant

官方提供的 MCP 服务器没有提供镜像,需要自己 clone 仓库并自己进行 docker build.

仓库地址是:https://github.com/qdrant/mcp-server-qdrant

此外,还需要一个对中文友好的用于对文件计算向量值的工具。mcp-server-qdrant 内置了 FastEmbed 运行环境,可以在启动时下载 BAAI/bge-small-zh-v1.5 模型来做向量计算。

启动方法如下:

bash 复制代码
docker build -t mcp-server-qdrant .
docker run -it --rm \
  --name mcp-server-qdrant  \
  -p 8098:8080 \
  -e QDRANT_URL=http://host.docker.internal:8099 \
  -e QDRANT_API_KEY=my-super-secret-key \
  -e FASTMCP_SERVER_HOST="0.0.0.0" \
  -e FASTMCP_SERVER_PORT="8080" \
  -e EMBEDDING_MODEL="BAAI/bge-small-zh-v1.5" \
  -e QDRANT_READ_ONLY=false \
  -e QDRANT_CREATE_COLLECTION=true \
  mcp-server-qdrant \
    uvx mcp-server-qdrant --transport streamable-http

测试一下:

bash 复制代码
curl -i \
  -X POST \
  http://127.0.0.1:8098/mcp/ \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "initialize",
    "params": {
      "protocolVersion": "2025-06-18",
      "capabilities": {},
      "clientInfo": {
        "name": "curl",
        "version": "1.0"
      }
    }
  }'

但是, MCP 服务有两个问题:

  1. MCP 服务不提供 API KEY 的校验,部署后直接通过 qdrant 的 key 访问到后端,直接就裸奔了;
  2. 每次启动都要花时间去下载模型,提早打包在镜像内更好

因此,我 folk 了这个仓库,增加了上述功能。地址在:https://github.com/ahfuzhang/mcp-server-qdrant/tree/dev

也可以直接使用我构建好的镜像:https://hub.docker.com/repository/docker/ahfuzhang/mcp-server-qdrant/tags

增加 MCP API KEY 校验方法的启动方式为:

bash 复制代码
docker run -d --rm \
		--name mcp-server-qdrant  \
		-p 8098:8080 \
		-e QDRANT_URL=http://host.docker.internal:6333 \
		-e QDRANT_API_KEY=my-secret-key \
		-e FASTMCP_SERVER_HOST="0.0.0.0" \
		-e FASTMCP_SERVER_PORT="8080" \
		-e EMBEDDING_MODEL="BAAI/bge-small-zh-v1.5" \
		-e QDRANT_READ_ONLY=false \
		-e QDRANT_CREATE_COLLECTION=true \
		-e MCP_API_KEY="ahfu_mcp_key" \
		ahfuzhang/mcp-server-qdrant:v0.1.0 \
			mcp-server-qdrant --transport streamable-http

在 K8s 中部署

可以使用 sidecar 的方式,把 qdrant 和 mcp-server-qdrant 部署在一个 stateful set 之中:

yaml 复制代码
apiVersion: v1
kind: Secret
metadata:
  name: qdrant-secrets
  namespace: our-team
type: Opaque
stringData:
  QDRANT_API_KEY: "my-secret-key"
  MCP_API_KEY: "ahfu_mcp_key"

----

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: qdrant-0
  labels:
    app: qdrant
  namespace: our-team
spec:
  serviceName: qdrant-headless
  replicas: 1
  podManagementPolicy: Parallel
  selector:
    matchLabels:
      app: qdrant
  template:
    metadata:
      labels:
        app: qdrant
    spec:
      containers:
        - name: qdrant
          image: qdrant/qdrant:v1.15.4
          imagePullPolicy: IfNotPresent
          ports:
            - name: http
              containerPort: 6333
            - name: grpc
              containerPort: 6334
          env:
            - name: QDRANT__SERVICE__API_KEY
              valueFrom:
                secretKeyRef:
                  name: qdrant-secrets
                  key: QDRANT_API_KEY
          readinessProbe:
            httpGet:
              path: /readyz
              port: 6333
            initialDelaySeconds: 10
            periodSeconds: 10
          livenessProbe:
            httpGet:
              path: /livez
              port: 6333
            initialDelaySeconds: 30
            periodSeconds: 20
          resources:
            limits:
              cpu: "8"
              memory: 8Gi
            requests:
              cpu: "8"
              memory: 8Gi
          volumeMounts:
            - name: qdrant-data
              mountPath: /qdrant/storage
        - name: mcp-server-qdrant
          image: ahfuzhang/mcp-server-qdrant:v0.1.0
          imagePullPolicy: IfNotPresent
          command:
            - mcp-server-qdrant
            - --transport
            - streamable-http
          ports:
            - name: mcp-http
              containerPort: 8080
          env:
            - name: QDRANT_URL
              value: "http://localhost:6333"
            - name: QDRANT_API_KEY
              valueFrom:
                secretKeyRef:
                  name: qdrant-secrets
                  key: QDRANT_API_KEY
            - name: MCP_API_KEY
              valueFrom:
                secretKeyRef:
                  name: qdrant-secrets
                  key: MCP_API_KEY
            - name: FASTMCP_SERVER_HOST
              value: "0.0.0.0"
            - name: FASTMCP_SERVER_PORT
              value: "8080"
            - name: EMBEDDING_MODEL
              value: "BAAI/bge-small-zh-v1.5"
            - name: QDRANT_READ_ONLY
              value: "false"
            - name: QDRANT_CREATE_COLLECTION
              value: "true"
          resources:
            limits:
              cpu: "2"
              memory: 2Gi
            requests:
              cpu: "1"
              memory: 1Gi
  volumeClaimTemplates:
    - metadata:
        name: qdrant-data
      spec:
        accessModes: ["ReadWriteOnce"]
        storageClassName: alicloud-disk
        resources:
          requests:
            storage: 20Gi
----
apiVersion: v1
kind: Service
metadata:
  name: qdrant-headless
  namespace: our-team
  labels:
    app: qdrant
spec:
  clusterIP: None
  publishNotReadyAddresses: true
  selector:
    app: qdrant
  ports:
    - name: http
      port: 6333
    - name: grpc
      port: 6334

----

apiVersion: v1
kind: Service
metadata:
  name: qdrant
  namespace: our-team
  labels:
    app: qdrant
spec:
  type: NodePort
  selector:
    app: qdrant
  ports:
    - name: mcp-http
      protocol: TCP
      port: 8080
      targetPort: 8080
      nodePort: 30313

配置到 codex

在 $CODEX_HOME 的 config.toml 中增加:

toml 复制代码
[mcp_servers.qdrant]
url = "http://10.105.xx.xx:30313/mcp"
bearer_token_env_var = "MCP_API_KEY"

然后 shell 中增加:

bash 复制代码
export MCP_API_KEY=ahfu_mcp_key

提示词中指明需要使用向量数据库:

text 复制代码
回答下面的问题时,必须优先查询 MCP 中的企业知识库。

 步骤:
 1. 查看可用 collection。
 2. 找到包含企业文档/代码知识的 collection。
 3. 使用 qdrant_qdrant-find 搜索相关内容。(支持向量搜索)
 4. 如果第一次结果不足,修改关键词再次搜索。
 5. 基于检索到的内容回答。
 6. 告诉我答案依据了哪些文件/path/document。
 7. 如果查不到就返回查不到,不要做猜测

 问题:

 /GetUserInfo 这条接口,有哪些请求参数?

实在是太爽了,如果自己亲手去找,不知道要找多久!

总结

本文简单的尝试了一下 qdrant 数据库,初步的感觉是好于 weaviate 数据库的,只是部署和使用上比 weaviate 稍麻烦一些。

  • 导入到 qdrant 中的文档,先经过 MCP 服务器内的 BAAI/bge-small-zh-v1.5 模型来为中文文本计算向量值
  • 支持向量值的搜索,其速度和质量比 BM25(Best Matching 25) 算法更好。

Have Fun.

😃