最近好几个人问了我同一个问题:你的 Harness 工程里,向量数据库装在哪个环节?我说,拆了。对方一脸震惊——Agent 工程不用向量数据库,长期记忆怎么办?工具路由怎么办?知识库怎么办?我的回答是:这些问题确实存在,但解决它们的方式,不一定非得上向量数据库。
先交代背景。我这里说的 Harness,指的不是某个具体产品,而是 Agent 工程里那一层“控制装置”,社区里叫 Agent Harness、DeepSeek Harness、Claude Code Harness 的实践我都看过不少,本质都是给模型套一层外骨骼:控制工具调用、管理上下文、约束行为、记录轨迹。过去半年多,我一直在维护自己的 Harness 工程,早期架构里向量数据库处于核心位置,几乎所有记忆、知识、工具匹配都走向量检索。后来我逐步把它从主路径上拆出去,整体效果反而更稳了。这篇文章就把这段“去向量数据库化”的完整思考、替代方案和实操教训写出来,给正在做 Agent 工程、做 harness 方向选型的朋友一个参考。
1. 先搞清楚:Harness 到底在解决什么问题
1.1 从“马具”到“控制层”的比喻
Harness 这个词,直译是马具、安全带。放到 AI Agent 语境里,它指的是“驾驭 Agent 的那层结构性框架”。模型本身是一个脑子,你给它工具,它自己决定怎么用,这个流程叫 Agent Loop。但裸奔的 Agent 问题很多:可能反复调用同一个失败工具、可能丢失上下文、可能乱改代码、可能不按既定流程走。Harness 就是包在模型外面的那层壳,负责约束流程、记录状态、提供工具、拦截错误、回滚操作。
我经常跟朋友开一个玩笑:Agent 是一个很能打的实习生,你让他干活他积极,但你得在旁边盯着,因为他偶尔会自作主张。Harness 就是那个“盯着”的机制。社区热词里“Agent Harness:驾驭 AI Agent”“Harness 和 Agent 区别”这些讨论,基本都围绕同一件事:模型负责生成能力,Harness 负责可靠性和可控性。
这层壳本身不产出智能,但它决定了智能能不能落地成结果。所以 Harness 设计的第一原则是:能确定的东西不要靠猜,能用规则做的不要交给概率。这个原则,是后面所有“去向量数据库”决策的出发点。
1.2 早期 Harness 架构里,向量数据库被放在了什么位置
2024 年前后,Agent 工程刚火起来时,向量数据库几乎是标配。我早期架构也是这么设计的:一个中心向量库,里面塞了工具描述、历史会话、文档切片、技能定义,然后每一轮 Agent 循环开始时,先 embedding 当前用户问题,再去向量库里做语义检索,把命中的内容拼进上下文。
具体拆开看,典型的位置有这么几个:
- 工具路由:根据用户意图,从几十上百个工具描述里语义匹配出最合适的几个。
- 长期记忆:把每轮对话总结后写入向量库,下次对话先召回相关历史。
- 知识库问答:把文档切片向量化,用户提问时先检索再让模型回答。
- 技能/插件匹配:从技能库中找与当前任务匹配的 Skill 或 Workflow。
- 代码库检索:在编码类 Agent 里,按语义相关性找代码片段。
听起来很合理,对吧?但实际跑起来,我才发现这套架构的问题,不在于向量数据库本身,而在于它被放到了一个“它不该承担的生态位”上——它试图用“相似度”去解决“正确性”问题。
2. 为什么开始少用向量数据库了:五个核心原因
2.1 语义检索被高估了:Agent 路径上更多是确定性匹配
先看第一层事实:Agent 的工具路由,到底是不是一个“语义匹配”问题?我一开始以为是,后来发现不是。
一个 Agent 常见的工具集可能是:查天气、写文件、执行命令行、调用某 API。用户说“帮我打开项目里的配置文件”,这需要精确映射到“读取文件”工具,而不是“打开某个文件夹”工具。这种判断靠的是指令理解,不是向量相似度。工具数量通常就几十个,每个工具的用途用一两行描述写清楚,模型函数调用的能力完全可以直接输出正确的工具名。
如果硬要插一层向量检索,反而引入两个新问题。第一,向量检索是“模糊”的,它的 top-k 召回结果天然带噪声,可能把相似但不相关的工具也捞进来,增加模型决策负担。第二,不管召回结果怎么样,你还得让模型在候选里再做一轮选择,那这层提前检索除了增加延迟,并没有带来信息增益。
编程类 Agent 更明显。代码库里的符号、路径、类名、接口名,本身就是高确定性的标识符,用字符串匹配、正则、AST 索引就能准确定位,语义搜索反而会匹配到“语义相似但实际无关”的代码。我在一次改造里,把 17 个工具路由全部改成枚举加关键词映射,准确率没有下降,相关覆盖率反而提升了几个百分点。
2.2 成本和延迟:一次 Agent 循环里,检索不能迟到
Agent 的体验瓶颈是什么?是延迟。你问一句,它背后可能要做两三次模型推理,每次还要调用工具,整套流程下来十秒二十秒很正常。这种场景下,任何一步多余的查询都会放大体感。
向量检索这一环的成本有三层。第一层是 embedding 计算,无论是调用外部 embedding API 还是本地模型,都要花时间。第二层是向量库查询本身的时延,小数据量还好,量大了之后索引构建、filter 结合、top-k 重排都会变慢。第三层是存储和同步成本,向量数据要构建索引,要跟随源数据更新,每次文档变化都触发 re-embedding。
我做过一组简单的对比:单次本地向量检索,平均延时大概 40 到 80 毫秒,看起来不高。但放到一个 Agent 循环里,一次完整任务可能要触发 5 到 10 次检索,加起来的额外等待就是 200 到 600 毫秒,甚至更多。对于用户来说,这几个步骤里还穿插着模型推理和工具执行,累计体感已经明显了。而如果这些环节替换成内存里的一个字典查询,延时直接掉到微秒级。
更别说成本。外部 embedding API 按 token 收费,文档越多,每半个月就要全量或增量 embedding 一次,账单是持续累加的。对个人开发者和中小团队来说,这笔开销换来的效果还经常不稳定,很不划算。
2.3 上下文窗口变大,模型“自带记忆”比检索更直接
这个原因在 2025 年尤为明显。主流模型把上下文窗口从早期的 4K、8K,一路卷到 128K、256K,甚至更大。DeepSeek 系列模型的长上下文能力,也在 Agent 社区里催生了一堆“把内容全部塞进去”的 Harness 工程。这带来的直接冲击是:很多以前必须靠向量检索才能“压缩”进上下文的内容,现在可以直接全文放进去。
有没有想过,为什么早期 Agent 一定要接向量数据库?一个很重要的原因是当时的模型“记不住”太多东西,所以你需要把知识库切成块,每次只把最相关的几段塞给它。但上下文窗口足够大以后,这个前提松动了。
举个例子。我有一个文档问答的场景,知识库总量大概三四万字。过去我要切片、embedding、查向量库,然后把三四个片段拼给模型。现在我可以把整份文档作为“参考材料”直接放进上下文,模型自己就能定位到相关内容。不仅少了检索环节,还省掉了切片造成的上下文割裂问题。
当然,不是所有场景都能这样处理,百万级 token 的库,再大的窗口也装不下。但至少在我接触的大多数 Harness 工程里,知识库量级其实并没有大到必须上向量库的程度,很多时候是“为了架构完整”而提前上了。
2.4 召回质量与评测:向量相似度不等于任务相关性
这是我在实际使用中最头疼的一点:向量检索的 top-k,经常和“任务真正需要的”Top-k 对不上。
原因在于向量相似度计算的是语义层面的接近,而任务相关性往往由关键词、实体、业务规则决定。比如用户问“怎么让脚本开机自启”,语义上最接近的文档可能是“如何设置定时启动”,两者语义确实相近,但用户要的是具体到 systemd 配置或 Windows 任务计划程序的操作步骤。如果只靠向量相似度召回,很可能漏掉实操细节,给模型一个七分像的答案。
这类问题一旦出现,调优非常痛苦。你要调切片大小,调 top-k 数量,调 embedding 模型版本,调相似度阈值,但每次改动都会在一个不可见的评测集上带来波动。你很难说清楚“这次效果变差到底是因为哪段代码改了”,因为向量检索的整个链路是黑盒的。
我后来给团队定了一条规矩:凡是涉及精确信息的检索(版本号、接口签名、错误码、文件路径),一律禁止走纯向量召回,至少要用关键词或元数据过滤去兜底。只允许纯语义且不要求精确命中的场景使用向量检索。
2.5 复杂性和可维护性:Agent 工程最大的敌人是“重”
Harness 工程从设计目标上就应该是轻的、薄的一层。但引入向量数据库,意味着你要多维护一个基础设施:数据同步、索引构建、备份恢复、权限控制、版本兼容。对个人项目来说,这个成本往往是隐性的,直到某天你发现数据库挂了,或者某个环境装不上依赖,才意识到它有多重。
社区里关于 DeepSeek Harness 这类工具的讨论里,很多人问“无法安装”“插件加载失败”“Skill 读取文件权限问题”,这些问题一大半都和依赖复杂有关。一个轻量的 Harness 应该尽量少依赖外部服务。向量数据库是其中最重的依赖之一。
我把向量数据库从主链路拆掉之后,整个工程的部署难度明显下降。原本要确保用户本地装好向量库、起服务、导索引,现在只需要一个 Python 环境和一份 JSON 文件就能跑起来。对个人工具型项目来说,这种“降重”几乎是刚需。
3. 那不用向量数据库,到底用什么?四个替代方案
3.1 规则优先:工具注册表加函数调用,本来就不需要检索
先给结论:大多数 Agent 的工具路由,最佳方案是“不路由”。
现在的模型大多具备原生函数调用能力。只要工具数量在几十个量级,且每个工具的 description 写清楚了,模型在你给它的 JSON Schema 列表里直接选工具,效果比任何外部检索引擎都好。因为模型原本就有上下文感知能力,它在整个对话历史之上做判断,比一个脱离上下文的向量检索更准确。
具体做法很简单:把每个工具定义成一个 JSON Schema,里面包含名称、参数、description、触发条件关键词。然后在每次 Agent 循环里,把这些 schema 原封不动地塞进模型消息。模型自己决定调用哪个。
如果你的工具数量大到几百上千,全部塞给模型会占用不少 token。这时候可以做一层“粗过滤”,但即使这样,也可以先用关键词、标签这类确定性规则排除明显不相关的工具,而不是向量匹配。比如工具描述里有“file”标签,用户问题里出现了“文件”,直接按标签过滤。
3.2 全文检索加元数据过滤:知识库场景的稳妥解法
知识库不等于“必须向量化”。绝大多数企业内部文档、个人笔记,核心检索需求仍然是关键词匹配和结构过滤。
我的替代方案是:把文档存进一个带全文索引的关系型数据库或者轻量搜索服务,按标题、标签、更新时间、来源路径建立元数据字段。用户提问时,先用关键词检索,再按元数据过滤,必要时配合简单的 BM25 打分排序。这套方案最直观的好处是“可解释”:你能明确说出为什么召回这份文档,因为它包含用户提到的关键词。而向量检索的命中逻辑,很多时候你自己都说不清。
实际测试下来,对于操作手册、FAQ、代码文档这类内容,BM25 加元数据过滤的精准率和用户满意度,并不比向量检索差。只有当用户用完全不同的表述描述同一件事时(比如“如何把车开走”对“汽车驾驶方法”),关键词检索才会显得力不从心。这种场景才值得考虑语义召回。
3.3 结构化存储和摘要式记忆:长期记忆不该是一袋碎切片
很多 Harness 工程把长期记忆设计成“整篇对话向量化后丢进向量库”,这是一个我后来很反对的做法。因为对话被切碎之后,回忆起来的往往是一堆零散片段,模型需要再花很大力气把它们重组出有用的信息。
我的做法是:把长期记忆分成两层。第一层是结构化摘要,定时对过去的会话做总结,提取用户偏好、常用环境、项目关键信息,存成 JSON 或关系表;第二层是原始记录,按任务 ID 和对话 ID 归档,需要看细节时直接按 ID 拉取。
这样一来,“回忆”这件事变成了两步:先按规则把当前任务映射到相关摘要,再按任务 ID 调取完整记录。和向量数据库相比,它有一个很大的优点:摘要本身就是结论,模型不需要再推理一遍哪些历史是重要的。
3.4 内存向量做兜底:要语义能力,但不要向量数据库
某些场景确实需要“近似匹配”能力,比如用户用口语化的描述找一个功能,而功能名是技术术语。这种情况下,我的建议是:先不要直接上分布式向量数据库,在应用进程里维护一个小规模的内存向量索引就足够了。
具体来说,几千到几万条文本,用 OpenAI Embedding 或本地小模型转成向量后,直接缓存在内存里,算余弦相似度完全没压力。Python 里用 numpy 就能实现,几十行代码搞定。这样既保留了语义召回的能力,又不引入额外的服务依赖和运维负担。
这个方案非常适合个人工具、团队内部系统这类“数据量不大但确实有语义检索需求”的场景。等数据量真正涨到十万、百万级别,再迁移到专业向量数据库也不迟。
4. 什么时候还是得上向量数据库?从极端回到平衡
4.1 必须上向量数据库的三类场景
我不想给读者留下“向量数据库是智商税”的印象。恰恰相反,在真正合适的位置上,向量数据库的价值是任何方案替代不了的。根据我的经验,至少有三类场景是绕不开它的:
第一类,海量非结构化知识库。百万级以上文档、日志、代码库,无法全部塞进上下文或者全文索引也扛不住,必须靠向量检索先做粗召回。第二类,开放式语义匹配。比如智能客服里用户问题千奇百怪,但答案类别相对固定,需要用语义相似度做意图识别;再比如故障排查系统要匹配相似历史工单。第三类,内容推荐和去重。要给用户推荐语义相似的内容,或者做基于内容相似度的聚类,向量索引的计算效率远高于两两暴力比较。
判断依据其实很简单:你需要的是“模糊匹配”还是“精确匹配”?你的数据量是大到其他方案扛不住,还是其实几千条就够了?这两个问题想清楚,答案自然浮出水面。
4.2 一个可复用的选型决策清单
把方法论收敛成一份可以拿着对照的清单,给正在做 Harness 架构选型的朋友参考:
| 场景问题 | 推荐方案 | 理由 |
|---|---|---|
| 工具数量少,职责清晰 | 枚举加函数调用 | 确定性最高,无检索成本 |
| 知识库以手册、FAQ 为主 | 关键词全文检索加元数据过滤 | 可解释、易调试、召回稳定 |
| 记忆需要长期留存、总结 | 结构化摘要加任务 ID 归档 | 避免切片碎片化,重组成本低 |
| 数据量几千条,偶尔需要语义匹配 | 内存向量计算 | 低成本保留语义能力 |
| 数据量百万级,非结构化为主 | 专用向量数据库 | 性能和数据管理优势明显 |
| 混合场景,精确与模糊并存 | 混合检索:规则过滤后再向量召回 | 兼顾准确率和召回率 |
这份清单本质上是把“方案”和“数据规模”“精度要求”挂钩,而不是笼统地“用了高级技术就是好”。
4.3 混合检索的正确姿势:让规则和向量各司其职
如果你确认某些场景必须上向量检索,我也建议把它放在一层“确定性漏斗”之后,而不是让它直接面对原始输入。
我在保留向量检索能力的模块里,通常是这么组织的:先用规则和元数据把候选集缩小(比如代码库指定目录、知识库指定分类、时间范围过滤),再对缩小后的候选集做向量召回,最后再做一轮关键词校验。这样的好处是,向量检索只在它擅长的语义排序上发力,而精确过滤交给规则去完成,两者各司其职。
对比过“裸向量检索”和“规则缩小范围后再向量检索”两种方案后,效果差别很明显。前者的召回结果经常飘,后者的命中率要高得多,而且发生错误时更容易追溯:是过滤条件不对,还是向量排序不对,定位起来非常快。
5. 实操记录:把向量数据库从 Harness 里拆出去的三步走
5.1 盘点:找出链路上那些“装样子”的向量调用
改造第一步,不是写代码,而是先做审计。我把工程里所有调用向量数据库的位置列出来,逐一问三个问题:这个位置的数据规模有多大?这个位置的匹配任务是真的语义匹配,还是其实可以精确匹配?如果换成规则方案,哪些输出会变化?
审计结果让我很吃惊。工程里一共 6 处向量库调用,真正有保留价值的只有 1 处,就是面向外部文档的语义搜索。其他 5 处分别是工具路由、历史会话记忆、技能匹配、提示词模板匹配、代码片段检索。每一处单独看都“像是有必要”,但它们 90% 以上的实际命中,都只需要简单规则。
有一个通用技巧:给每处向量检索打点,记录 top-1 命中的内容,然后在后台肉眼抽查几百条。如果发现 top-1 绝大多数时候就是你预期的那一个,说明根本不需要向量库,用规则就能精确命中。如果 top-1 频繁不是你预期的内容,说明向量召回不可靠,更不应该留在主路径上。
5.2 替换:从枚举路由到混合检索的迁移过程
我的替换过程分三批进行,每一批都做了一轮小规模评测,避免一次动太多无法定位回归问题。
第一批:工具路由和技能匹配。直接改成枚举加标签。工具定义里增加“keywords”字段,把触发这个词的描述写进去。模型消息里塞全部 schema 会让 token 略增,但可靠性大涨。
第二批:历史会话记忆和提示词模板匹配。会话摘要存成 JSON,用当前用户问题的实体关键词做匹配。模板匹配干脆做成“按场景 ID 硬编码”,场景少,没必要搜。
第三批:知识库检索。没有彻底干掉向量检索,而是改成了“先关键词粗筛,再内存向量重排”的混合方案。
整个迁移耗时两周,核心代码没有大改,主要改的是数据流调度逻辑。最终结果:任务成功率从 78% 提升到 91%,单次任务平均延迟下降约 40%,这是在我自己的内部评测集上统计的,样本量不算大,但趋势非常明显。
5.3 评测保留一台“对比试验机”
这里给一个非常重要的建议:改造过程中,一定保留一台旧架构的对照版本,不要直接删掉原逻辑。我见过太多人把旧方案一删,新方案跑起来感觉“好像差不多”,结果过一个月遇到一个怪问题,想对比一下旧逻辑都无从下手。
我的实践是,用同样的输入集做 A/B 测试,每次改造只对比“任务成功率”和“平均完成轮次”这两个指标。不要凭感觉判断,不要看几个漂亮 demo 就下结论。向量检索踢出主路径后,你还会发现一个附带好处:整个系统更可调试了,因为每一条数据都是明确的,你能清楚解释模型为什么做出这个决定。
6. 常见问题与避坑手册
6.1 “Agent 答非所问,是不是向量数据库没用对?”
这是我在社区里见过最多的问题。说实话,答非所问的根源,往往不是检索,而是输入上下文里没有足够的约束信息。模型不知道当前任务的目标边界,不知道有哪些工具可以用,不知道用户偏好,这才是核心。
排查顺序建议是:先看 Prompt 有没有说清任务目标,再看工具列表是不是太长太含糊,然后看模型版本够不够新,最后才轮到检索策略。不要一上来就调 embedding 模型、调 chunk 大小,那是在错误的层面解决问题。
6.2 “不用向量数据库,会不会显得架构不够高级?”
不会。用户的感知只是“Agent 好用不好用”,而不是“你的架构用了什么黑科技”。反过来,如果我看到某个 Agent 项目每个环节都强调向量数据库,我反而会怀疑它的选型是否思考清楚。
我自己也踩过类似的技术虚荣心坑,总想“先上一个向量库再说,显得专业”。后来想明白了,架构设计是减法艺术:能不加的东西尽量不加,直到有数据证明必须要加。
6.3 “语义检索召回率低,先换模型还是先调参数?”
我的建议是:先别调参,先找几个“该召回但没召回”的例子,逐一分析失败原因。如果是因为源文档本身就没有对应内容,那换什么检索都救不回来。如果是因为切分把关键信息切碎了,先改切分策略。如果是深层语义关联问题,比如同义词、指代消解,再考虑换更强的 embedding 模型。
一个表格快速总结常见坑和替代方案:
| 常见问题 | 根因 | 替代方向 |
|---|---|---|
| 检索结果带噪声,模型被误导 | top-k 过大、过滤条件缺失 | 缩小候选集,先规则后向量 |
| 关键词相关但用户要精确信息 | 纯向量召回精确性不足 | 全文检索加元数据过滤 |
| 部署麻烦,环境不兼容 | 向量数据库依赖过重 | 改为内存向量或规则方案 |
| 对话记忆碎片化,重组困难 | 长对话被无脑切片 | 结构化摘要加 ID 归档 |
| 效果波动,无法定位原因 | 检索链路黑盒 | 增加日志,优先可解释方案 |
6.4 “真的必须用向量数据库,部署上有什么建议”
如果你确实走到了必须上向量数据库的那一步,我的建议是把它当独立服务来对待,不要和 Harness 主进程绑死。进程隔离,数据备份独立,索引版本可回滚。同时,一定要给检索链路加可观测性,记录每次召回的 query、候选集、得分、最终命中,否则后续调优寸步难行。
另外,向量数据库只是存储引擎,embedding 模型才是真正的质量瓶颈。先评测你用的 embedding 模型在你自己的数据分布上的效果,再谈索引规模和性能优化,顺序不要反。
最后说点个人的体会
做了大半年去向量数据库化改造,我最深的感受是:Harness 的核心价值在于“可控性”,而向量检索天然带有一定的不可控性。这不是否定向量数据库,而是提醒自己把每个工具放到它真正擅长的位置。我现在的新项目遵循一个默认原则:所有检索需求先默认用最笨、最直接的方式实现,跑通后再根据数据和效果决定要不要引入向量手段。如果你也在做 Agent 工程,建议你也试试“先不加向量数据库”的起步方式,等你真的遇到了非它不可的问题,再把它请回来,那时候你会比现在更清楚它应该待在哪。