在强调数据隐私、离线可用和成本可控的场景中,将 Ollama 与 Qdrant 组合起来,可以快速搭建一套完全运行于本地的向量检索服务。Ollama 负责把文本转换为向量,Qdrant 负责存储、检索向量并依据 Payload 过滤业务数据,适合内部知识库、文档搜索和本地 RAG 等应用。🔍
一、整体架构与数据流
这套服务的核心流程可以概括为:文档切分、生成向量、写入 Qdrant、查询向量化、条件过滤、返回相似结果。一次典型检索中,应用先把用户问题发送给 Ollama 的嵌入接口,再将获得的查询向量提交给 Qdrant,同时附带部门、文档类型、权限或时间范围等过滤条件。
Ollama 提供用于生成文本向量的 /api/embed 接口,既可接收单条文本,也可批量接收文本数组。建立索引和执行查询时必须使用同一个嵌入模型,否则向量空间不一致,检索结果将失去意义。模型选择、批量调用方式及接口字段可参考 Ollama Embeddings 文档。
二、启动 Ollama 与 Qdrant
先在本机安装 Ollama,然后拉取适合语义检索的嵌入模型。Qdrant 可以通过 Docker 启动,并将服务端口和数据目录映射到宿主机。默认情况下,Ollama API 常使用 11434 端口,Qdrant HTTP API 常使用 6333 端口。实际部署时应绑定可信网卡,并避免把未配置认证的服务直接暴露到公网。🛡️
应用侧可以安装 ollama 与 qdrant-client 两个 Python 包,分别连接本地模型服务和向量数据库。Qdrant 官方也提供了 Ollama 集成示例,展示了生成嵌入、创建集合和写入 Point 的基本方法,详见 Ollama 与 Qdrant 集成指南。
三、创建集合并写入向量
首次调用 Ollama 生成一条测试向量后,应读取返回数组的实际长度,并将其作为 Qdrant 集合的向量维度,而不是凭经验写死。距离算法可优先选用余弦距离。若后续更换嵌入模型,应创建新集合并重新生成全部文档向量,不能直接把不同维度或不同模型产生的向量混入原集合。
Qdrant 中每条 Point 通常包含唯一 ID、向量和 Payload。建议将 Payload 设计为稳定的结构,例如 document_id、chunk_id、tenant_id、department、category、created_at、permission_level 和 text。其中 text 用于展示原文,其余字段用于权限控制、结果聚合和精确过滤。
文档切分不宜只按固定字符数粗暴截断。更稳妥的做法是优先沿标题、段落和列表边界切分,再保留适量上下文重叠。写入时采用批量嵌入和批量 upsert,可以减少网络往返;若任务中断,则利用稳定的 document_id 与 chunk_id 重新写入,实现幂等更新。⚙️
四、使用 Payload 缩小检索范围
向量相似度只能表达语义接近程度,无法可靠表示用户权限、租户隔离、文件状态或发布时间。因此,业务约束应放在 Payload 过滤器中,而不是拼进查询文本。例如检索“报销标准”时,可以要求 tenant_id 等于当前租户、department 属于财务部门、status 等于 published,并限制 created_at 的范围。
Qdrant 支持使用 must、should 和 must_not 组合过滤条件,分别对应必须满足、至少满足一项和必须排除。对于同一字段的多个候选值,优先使用一次 match any,而不是堆叠大量 should 条件。嵌套字段、数值范围和日期范围等写法可查看 Qdrant Filtering 文档。
权限过滤必须由服务端根据当前身份生成,不能直接信任客户端提交的 tenant_id 或 permission_level,否则可能出现跨租户检索和越权读取。
五、Payload 索引优化实践
Payload 能否存储与是否适合高频过滤是两个问题。对于 tenant_id、department、category、status 等精确匹配字段,可建立 keyword 索引;对版本号、等级等整数使用 integer 索引;对 created_at 使用 datetime 索引。Qdrant 的 Payload 索引既能加速条件匹配,也能帮助查询规划器估算过滤结果规模,相关机制见 Payload Index 官方说明。
索引并非越多越好,因为每个索引都会消耗内存、磁盘和构建资源。应优先索引查询频率高、过滤选择性强、结构稳定的字段,而 text、摘要等主要用于返回展示的长文本通常无需建立普通关键字索引。官方建议在导入数据之前创建计划使用的 Payload 索引,以避免大量数据写入后再集中构建所产生的额外压力。
- 控制候选集:先用 tenant_id、权限和状态字段排除无关数据,再进行向量相似度计算。
- 限制返回内容:仅返回需要的 Payload 字段,较长正文可通过 document_id 再次读取。
- 分批写入:批次大小依据本机内存、模型速度和文本长度逐步调整,不盲目追求大批量。
- 记录指标:分别观察嵌入耗时、检索耗时、过滤后候选量、结果数量和失败率。
六、常见问题与排查思路
- 集合维度报错:检查当前模型返回的向量长度是否与集合配置一致。
- 结果相关性较差:确认索引和查询使用同一模型,并检查文本切分是否破坏完整语义。
- 过滤结果为空:核对 Payload 字段名、数据类型和大小写,数值范围不能用于字符串字段。
- 首次请求较慢:模型可能需要加载到内存,可通过预热请求降低正式查询的首次等待。
- 过滤延迟明显:检查高频过滤字段是否建立了对应类型的 Payload 索引。
总结
Ollama 与 Qdrant 的组合实现简单,但要真正形成稳定的本地检索服务,关键不只是“把向量存进去”。嵌入模型一致性、合理的文档切分、清晰的 Payload 结构、服务端权限过滤以及有选择地建立索引,都会直接影响准确性、安全性和响应效率。建议先用小规模真实文档验证召回效果,再依据查询日志优化字段和索引,让系统逐步从可运行走向可维护、可扩展。🚀