刚开始做知识库时,模型、分块、向量、数据库和提示词同时出现,很难判断错误发生在哪一步。可以先暂时拿掉模型,用三个手工向量验证“存入、排序、过滤”的行为,再逐步增加真实文档处理。
Qdrant Python 客户端提供本地模式,无需单独启动 Qdrant 服务;可以使用内存模式,也可以选择文件路径持久化。[1] 本文使用内存模式,不调用模型 API,不下载嵌入模型。资料核对日期为 2026 年 10 月 19 日。
先理解示例中的四个对象
官方示例使用 collection 保存 points,并为向量配置维度和距离计算方式;point 可以携带 payload 元数据,再通过条件限制搜索结果。[1][2]
在本文实验中,可以把它们理解为:
对象 | 本文的取值 |
|---|---|
Collection | rag_sandbox |
向量 | 三个手工设计的三维向量 |
Point ID | 1、2、3 |
Payload | 标题和主题分类 |
这些向量由人直接赋值,并没有从标题计算。因此,本文实验只能验证数据操作与排序逻辑,不能证明系统理解中文标题。
安装客户端
在独立 Python 环境中执行:
1python -m pip install qdrant-client
记录实际安装版本,按项目现有方式保存依赖。首次安装需要访问允许的软件包源;本文不要求部署 Docker、建立云账号或填写 API Key。[1]
写入三条合成数据,再查询
保存为 vector_lab.py:
1from qdrant_client import QdrantClient, models23client = QdrantClient(":memory:")4collection = "rag_sandbox"56client.create_collection(7 collection_name=collection,8 vectors_config=models.VectorParams(9 size=3,10 distance=models.Distance.COSINE,11 ),12)1314rows = [15 (1, [1.0, 0.0, 0.0], "部署与运行", "ops"),16 (2, [0.0, 1.0, 0.0], "界面与交互", "ui"),17 (3, [0.0, 0.0, 1.0], "文档与检索", "knowledge"),18]1920client.upsert(21 collection_name=collection,22 wait=True,23 points=[24 models.PointStruct(25 id=point_id,26 vector=vector,27 payload={"title": title, "topic": topic},28 )29 for point_id, vector, title, topic in rows30 ],31)3233result = client.query_points(34 collection_name=collection,35 query=[0.9, 0.1, 0.0],36 limit=2,37 with_payload=True,38)3940for point in result.points:41 print(point.id, round(point.score, 4), point.payload)4243assert result.points[0].id == 1
执行:
1python vector_lab.py
按示例向量与余弦相似度的定义,第一条结果应是 ID 为 1 的点。这里使用断言检查排序,不要求终端输出逐字相同。代码对照官方客户端接口编写,尚未在读者环境实测。[1]
内存模式中的数据随客户端生命周期结束而消失。下一次运行会重新建立实验数据;需要持久保存时,才另行设计独立的数据目录和恢复方式。
加入一个分类过滤条件
在脚本末尾追加下面代码,仍然使用前面创建的客户端与 collection:
1filtered = client.query_points(2 collection_name=collection,3 query=[0.0, 1.0, 0.0],4 query_filter=models.Filter(5 must=[6 models.FieldCondition(7 key="topic",8 match=models.MatchValue(value="ops"),9 )10 ]11 ),12 limit=2,13 with_payload=True,14)1516assert [point.id for point in filtered.points] == [1]17print("过滤结果:", [point.id for point in filtered.points])
这次查询方向指向第二个向量,但过滤条件只允许 topic=ops,所以候选集合只剩 ID 为 1 的点。Qdrant 的条件过滤作用于 payload;它与向量相似度分别承担限制候选和排序的作用。[2]
一个结果排名第一,只表示它在当前候选中最靠前,不能据此断定它已经足够相关。本文建议后续加入“应当无答案”的样例,专门观察系统是否会把不相关内容交给生成模型。
把实验扩展到真实检索时,分步增加能力
本文建议按以下顺序推进:
- 用真实嵌入方法替换手工向量,并记录方法、版本和维度;
- 保存文档标识、版本与片段出处;
- 用查询与期望片段组成小型人工评测集;
- 先检查检索结果,再接入答案生成;
- 加入过滤后,专门验证允许与不允许出现的资料。
这些是实施建议,不是本文已经完成的功能。标题变成向量需要额外步骤,数据库不会因为 payload 中存有文字就自动获得语义向量。
如果后续需要用用户权限过滤资料,还应在应用层建立可信的授权校验,不能只依赖模型自觉传入一个过滤参数。
给 Agent 的最小任务
使用 qdrant-client 的内存模式和三条合成向量,验证写入、相似度排序和 topic 过滤。记录实际版本与断言结果,不连接现有数据库,不下载嵌入模型,不把实验描述为完整 RAG。
先建立这个可以解释每条结果的实验,再换成模型产生的向量,便更容易分清检索逻辑错误与嵌入质量问题。
参考来源
本文为原创整理;三条数据、实验代码、断言和推进顺序为作者设计,不包含检索效果或性能承诺。