别一上来就换模型:我现在给 Agent 调优的武器库
别一上来就换模型:我现在给 Agent 调优的武器库
wwxdsg最近在做一类很典型、也很折磨人的 Agent 质量问题。
表面上看,现象是「grain 不准」「business meaning 不稳」「PK 假阳性偏多」;但如果往下拆,就会发现这些问题其实根本不在同一个层面上。
有的是输入信号不够,有的是任务拆法不对,有的是规则层该做的事被硬塞给了 LLM,还有的是其实模型已经答得差不多了,只差一个后处理校验帮它把明显矛盾拦下来。
所以我后来给自己整理了一套更顺手的调优框架:
先别急着换模型,先判断问题到底发生在哪一层。
一张表先把武器库摆清楚
| 作用层 | 手段 | 性价比 | 数据集无关性 |
|---|---|---|---|
| 输入信号 | 给 LLM 看更多、更好的数据 | ⭐⭐⭐ | ✅ |
| 任务拆分 | 把“一次推全部”拆成多步 | ⭐⭐ | ✅ |
| 模型替换 | 换更强的 LLM,如 deepseek-reasoner / GPT-4o |
⭐⭐ | ✅ |
| 后处理校验 | LLM 输出后用规则反查矛盾 | ⭐⭐⭐ | ✅ |
| 规则前置 | 不擅长的交还给规则,LLM 只做语言层 | ⭐⭐⭐ | ⚠️ |
| 多次采样 | 同 prompt 跑 N 次取多数 | ⭐ | ✅ |
| 多 LLM 协作 | Generator + Reviewer 分工 |
⭐⭐ | ✅ |
还有两件我现在基本不会优先考虑的事:
- Fine-tune 模型:周期太长,13 天这种节奏根本不现实。
- 产品端人工干预:这应该留到决赛产品化阶段,而不是当前自动构建阶段。
这个表对我最大的帮助不是“列手段”,而是提醒我:
不同问题要用不同武器,不要一上来就把所有锅都甩给 prompt。
先判断问题落在哪一层
我现在看 Agent 质量问题,通常先问自己三件事:
- LLM 是不是根本没看到足够的结构信号?
- 这个判断到底是不是本来就更适合规则做?
- 模型已经给出一个差不多的答案了,只是缺了一层兜底校验?
如果这三件事没想清楚,就很容易进入一种假忙碌状态:
- prompt 越写越长
- 示例越塞越多
- token 花得越来越快
- 结果还是没有稳定提升
很多时候不是模型不行,而是我们把不该让它承担的任务,硬塞给它了。
问题 A:grain 准确率低,优先补输入和规则
当前这个问题里,我最先盯的是 grain。
因为一旦 grain 判断错了,后面很多描述都会跟着偏:你以为它在解释一张事件表,实际上它把它当成了维表;你以为它在总结“交易粒度”,它却写成了“实体信息表”。
所以 grain 是上游问题,也是最该先处理的问题。
Lever 1:先增强输入信号
目前只给 5 条 sample 和一些 null / unique 比例,其实经常不够。
更有价值的信号包括:
- 行数级别提示:
row_count: 50000比单独几条样本更能说明这是一张大事实表还是大维表。 - 跨表上下文:把
*_id的引用关系摘要塞进 prompt。比如 LLM 一旦看到fact_session.user_id -> dim_user.id,就更容易理解fact_session是 transaction 或 event 粒度。 - 统计学线索:如果表里有
*_at字段,可以补时间分布、增长趋势、大小分位数,这些都会帮助模型判断这是一张行为流还是实体快照。
我现在越来越相信一件事:
很多“推理错误”,本质上只是证据不足。
Lever 5:让规则做 70%,LLM 只做边界情况
grain 这种结构化判断,其实规则层就能覆盖掉很大一部分。
例如:
fact_前缀 + 多个 FK +row_count > 100k,几乎一定是transaction / eventdim_前缀 + 单 PK +row_count < 10k,大概率是dimension
这里最重要的一点不是“把规则写死”,而是:
把规则写成高优先级信号,而不是硬编码真理。
因为不同公司命名并不统一。电商可能用 ods_ / dwd_ / dws_,金融也可能是完全不同的一套体系。
所以规则应该提供强烈提示,但最终仍允许 LLM 覆盖,这样才能避免把系统做成只会识别某一类数据仓库命名习惯的工具。
问题 B:business_meaning 不稳,通常先别单独修
business_meaning 这个字段表面上看是另一个问题,但在我这次实践里,它经常只是 grain 误判的连带伤。
因为语言层面的总结,本来就是 LLM 更擅长的事。
只要它先把这张表的本质看对了,business_meaning 往往会自动跟上。
所以我的顺序不是“同时修两个问题”,而是:
- 先把
grain稳住 - 再看
business_meaning还剩多少问题
如果 grain 已经对了,business_meaning 还不够好,这时候再上 Lever 4 做后处理校验就很划算:
- 检查
business_meaning里是否包含和grain对应的关键词
比如grain = event时,描述里至少要出现“事件 / 行为 / 操作”这类词。 - 检查长度
比如要求< 30字,避免它一展开就像在写报告。 - 检查是否带入数据集特异词
比如一旦出现“电商”“金融”这类词,就应该报警,因为这很可能说明描述已经开始过拟合当前样本数据集。
这个阶段 LLM 不是不会说,而是需要一个更工程化的护栏,帮它把明显不稳的输出裁掉。
问题 C:PK 假阳性,不要再怪 LLM
像 created_at、name 这种字段也被判成 PK,我现在会直接把它归类为:
这不是 LLM 问题,是 dataset ingestor 的规则层问题。
这里最合适的组合是:
Lever 5 规则前置
先加排除规则:- 即使
unique = 1.0 - 但字段名如果命中
*_at / *_time / name / email / description - 就不要直接进入 PK 候选
- 即使
Lever 4 LLM 校验
把规则筛完之后的候选再丢给 LLM,只让它回答一件事:- 这是主键
- 还是“碰巧唯一”
这才是比较健康的分工方式。
规则负责先把明显错的候选过滤掉,LLM 负责处理那些“规则不敢拍板”的剩余情况。
真正执行时,我会分三轮推进
Phase 1:高 ROI、低成本,先上 1 + 4 + 5
第一阶段我最看重的是这三个:
- 输入信号增强
- 后处理校验
- 规则前置
因为这三个都是结构性改进,而且基本不依赖某个具体数据集。
它们做好了,不只是当前这个任务受益,后面别的数据集也会一起吃到提升。
Phase 2:还不够,再上 2 + 3
如果第一轮做完还不够,再考虑:
- 任务拆分:把一次性推
grain + business_meaning + PK,拆成多步生成 - 换更强模型:比如切到
deepseek-reasoner或GPT-4o
我把这两个放到第二阶段,是因为它们更像“针对性加强”,不是第一时间就该动的通用解法。
Phase 3:最后兜底,再上 7 + 6
只有前面都不够时,我才会考虑更贵的方案:
- 多 LLM 协作
Generator -> Reviewer -> Final Rewrite - 多次采样投票
同一个 prompt 跑 3 次,取多数
这两个方案确实有效,但 token 成本基本都会翻倍,甚至更多。
所以在我这里,它们更像“最后的暴力兜底”,不是第一反应。
如果要自审,我会这么拆
如果进入第二轮还不够,我最愿意加的是一个轻量 reviewer:
Generator: 根据 profile 推 grain + business_meaning |
这套模式的好处在于,它不是简单地“多调用一次模型”,而是把一次性生成拆成了:
- 先产出答案
- 再用另一个视角挑错
- 最后基于错误反馈修正
很多原本第一轮就会漏掉的矛盾,在 reviewer 视角下反而很容易被抓出来。
第一轮跑完后,别只看总准确率
我现在越来越不相信单一总分。
如果 grain 准确率低于 60%,我不会马上重写 prompt,而会先按错误类型拆:
dim_*表到底错了多少
看维表是不是总被认成事实表。fact_*表到底错了多少
看事实表是不是总被认成维表。- 复合键表到底错了多少
看桥表、SCD 表这类结构是不是完全没被识别出来。 - 没有
fact_ / dim_前缀的表错了多少
这才是真正检验系统通用性的地方。
因为不同错误,应该用不同武器:
- 全错集中在某类表:优先补输入信号
- 看起来像对了、其实结构不一致:补后处理校验
- 明显结构信号都没用上:上规则前置,把 LLM 退回到边界情况
- 各类都错一点:再考虑换模型
有三件事我现在会坚决不做
- Fine-tune
太慢,太贵,短周期里性价比极低。 - 把规则写成数据集特异硬编码
这直接违背了“数据集无关”的目标。 - 把已知陷阱直接写进 prompt 喂答案
这看起来像优化,实际上是在破坏自动构建的考核意义。
我现在最警惕的一类“优化”,就是那种短期分数会涨,但系统通用性会悄悄塌掉的做法。
最后一个提醒:产品手动测试仍然是最强武器
自动化测试很重要,但它永远不是全部。
哪怕 grain 从 0% 提升到 80%,也还是可能藏着一些自动化测不出来的问题:
fact_subscription的business_meaning写成“订阅信息表”,看着像对,但grain其实仍然错了- KB 工具调用成功了,但返回结果根本没真正影响 system prompt,因为模板里有 bug
search_tables返回了 5 张表,LLM 却选错了去做 JOIN
这些问题只有端到端手测才抓得出来。
所以我现在对“自动化”和“手动测试”的理解是:
- 自动化负责覆盖率、规则一致性、结构正确性
- 产品手测负责端到端可用性和真实任务完成度
它们不是替代关系,而是互补关系。
我的结论:调优先看层,再看招
如果让我把这次经验压缩成一句话,那就是:
Agent 调优最怕的,不是招数不够,而是还没分清问题在哪一层,就开始乱出招。
真正高 ROI 的路径,通常不是第一时间换更大的模型,而是先把:
- 输入信号补够
- 规则边界划清
- 后处理兜底补上
- 再把昂贵的多模型协作和多次采样,留到最后
这样调出来的系统,才更像一个可复用的工程能力,而不是一段只在当前数据集上偶然奏效的 prompt 魔法。