资讯详情

Small Agent推理提速10倍:从自由生成到选择题范式

📅 2026/10/20 23:59:10 | 华诺云谱 👁 阅读
Small Agent推理提速10倍:从自由生成到选择题范式
1. 从写作文到做选择一次推理范式的彻底翻转第一次看到这个思路的时候我正被一个本地小模型的响应速度折磨得够呛。一个简单的多步任务它要花十几秒甚至几十秒才能给出结果中间还经常跑偏。后来我把它的输出方式从自由生成改成了从候选里挑一个实测下来整体思考速度提升了接近一个数量级。这个变化听起来很朴素但背后的逻辑值得好好拆一拆。所谓 Small Agent指的是跑在本地或者边缘设备上的轻量级智能体参数量通常不大算力预算也有限。它要完成的任务往往是多步的先理解意图再决定调用哪个工具再根据工具返回的结果决定下一步。传统做法是让模型每一步都自由生成一段文本比如生成一个工具名、生成一段参数、生成一句下一步的说明。问题在于自由生成是一个开放式的搜索过程模型要在整个词表上做概率分布还要一个 token 一个 token 地往外吐token 越多耗时越长而且越往后越容易发散。做选择题的思路则完全不同。我们预先准备好一组候选动作让模型只在这几个选项里挑一个。这样模型的输出空间从几万维的词表骤降到几个候选计算量、解码步数、出错概率全都跟着下降。打个比方自由生成像是让一个人在白纸上写作文做选择题则是给他一张答题卡让他涂选项。写作文要考虑遣词造句、结构铺陈涂答题卡只需要判断哪个最合适。对于算力紧张的小模型来说这个差别就是能不能跑得动的差别。这篇文章我想聊的就是这套思路的完整落地为什么自由生成慢、选择题快候选集怎么设计打分怎么做怎么和工具调用串起来以及我在实操中踩过的那些坑。适合正在做本地智能体、边缘推理、或者任何对延迟敏感场景的同行参考。哪怕你用的是大模型这套思路在需要高频决策的环节同样能省下大量时间。2. 为什么自由生成是 Small Agent 的性能瓶颈2.1 自回归解码的固有成本要理解提速的来源得先搞清楚自由生成到底慢在哪。现在主流的语言模型都是自回归的也就是一次只预测一个 token然后把预测出来的 token 拼回输入再预测下一个。这个过程的耗时和输出长度是线性关系。生成 50 个 token 和生成 5 个 token时间差就是 10 倍。对于 Small Agent 来说这个成本被放大了。因为智能体的每一步决策往往都要生成一段结构化文本比如一个 JSON 格式的工具调用{tool: search_flight, params: {from: 北京, to: 上海, date: 2024-06-01}}这一串下来少说三四十个 token。如果任务有五六步光解码就要几百个 token 的时间。而小模型的单 token 解码速度本来就不如大模型因为它的算力预算小KV 缓存也小批量推理的吞吐上不去。两头一叠加延迟就非常可观了。更麻烦的是自由生成的结果是不确定的。同一个输入模型可能这次生成search_flight下次生成find_flight再下次生成查询航班。你的下游解析代码就得写一堆兼容逻辑稍微没覆盖到就报错。这种不确定性在演示的时候可能看不出来一旦上量就是灾难。2.2 小模型的发散问题大模型有个好处是它见过足够多的语料生成结构化内容时比较稳。小模型就不一样了参数量小意味着它对格式的把握能力弱。你让它生成 JSON它可能漏个引号你让它生成工具名它可能自己造一个不存在的。这种发散在自由生成模式下几乎无法根治因为模型本质上是在做概率采样你只能通过提示词和温度参数去约束但约束力有限。我做过一个对比测试同一个 3B 级别的模型让它自由生成工具调用100 次里有 12 次格式错误或者工具名不存在。改成从 8 个候选工具里选错误率直接降到 0。这个差距不是靠调提示词能补上的是范式本身的差异。2.3 延迟敏感场景的硬约束有些场景对延迟的要求是硬性的。比如语音助手用户说完一句话你如果两秒内没反应体验就崩了。比如实时游戏里的 NPC 决策每一帧都有时间预算。再比如工业设备上的本地智能体算力就那么点还要留出余量给其他任务。这些场景里自由生成的那几百毫秒到几秒的延迟是致命的。把推理改成做选择题本质上是把开放式搜索降级成封闭式分类。分类问题的计算复杂度远低于生成问题这是信息论层面的优势不是工程优化能比的。你不需要模型去想怎么表达只需要它判断哪个候选最合适。判断比表达容易得多这个直觉在模型身上同样成立。3. 候选集设计选择题的题库怎么出3.1 候选动作的粒度划分做选择题第一件事是出题库。候选集的粒度直接决定了这套方案能不能用。粒度太粗比如只给查询修改删除三个大类模型选完了你还得再生成具体参数等于没省。粒度太细比如把每个可能的参数组合都列成一个候选候选数量爆炸打分成本反而上去了。我的经验是把候选集分成两层。第一层是动作类型比如调用搜索工具调用计算工具回复用户请求澄清。这一层候选通常控制在 5 到 10 个。第二层是参数填充这一层不用生成而是用槽位填充的方式从预定义的枚举或者上下文里抽取。比如搜索工具的出发地直接从用户输入里抽实体不需要模型生成。这样设计的好处是模型只需要在第一层做选择题第二层是确定性的抽取逻辑。既省了生成时间又避免了参数幻觉。3.2 候选数量的甜点区候选数量不是越多越好。我实测过不同候选数量下的延迟和准确率大致有这么个规律候选数量单步决策延迟选择准确率备注3-5极低高适合动作类型少的场景6-10低较高大多数智能体的甜点区11-20中等开始下降需要更好的打分模型20 以上接近自由生成明显下降失去选择题的优势候选超过 20 个之后模型要在更多选项里做区分打分的不确定性上升而且候选本身的编码也要占输入长度反而拖慢速度。所以我的建议是把候选控制在 10 个以内超出的部分用分层或者路由的方式拆解。3.3 候选的动态裁剪固定候选集有个问题有些候选在当前上下文里根本不可能。比如用户问天气你没必要把转账订机票这些候选也放进去。动态裁剪就是根据当前上下文先把明显不可能的候选过滤掉只留下相关的几个。裁剪的逻辑可以很简单用关键词匹配或者轻量级的意图分类器先过一遍。比如检测到用户输入里有天气温度下雨这些词就只保留天气相关的候选。这一步几乎不耗时间但能把候选数量从 10 个降到 3 个进一步提速。注意动态裁剪的过滤逻辑要保守一点宁可多留几个候选也不要把正确选项误删了。我一开始为了追求速度把过滤写得很激进结果经常把正确候选筛掉模型只能在剩下的错误选项里选准确率反而崩了。4. 打分机制让模型给每个候选投票4.1 从生成到打分的转换候选集有了接下来是让模型给每个候选打分。这里的关键转换是不再让模型生成答案而是让它对每个候选输出一个分数或者概率。实现方式有几种我逐个说一下。最直接的是把候选拼成一段文本让模型输出每个候选的得分。比如输入是用户 query 加上候选列表输出是一串数字。但这种方式还是依赖生成只是生成的内容变短了。更高效的是利用模型的对数概率。把每个候选作为一个续写目标计算模型在该候选上的对数概率取概率最高的那个。这种方式不需要模型生成任何东西只需要做一次前向计算拿到每个候选位置的概率分布就行。速度比生成快得多因为只算一次不用自回归地一步步解码。还有一种是用专门的分类头。如果模型支持可以在最后一层接一个分类层直接输出每个候选的分数。这种方式最快但需要模型架构支持不是所有现成模型都能直接用。4.2 对数概率打分的实操细节我目前用得最多的是对数概率打分因为它对模型改动最小兼容性最好。具体做法是把候选构造成问题 候选的形式然后看模型在候选部分的概率。举个例子用户问帮我查一下明天北京的天气候选是调用天气查询工具调用日历工具回复用户我把输入构造成用户帮我查一下明天北京的天气 助手应该然后分别计算调用天气查询工具调用日历工具回复用户这三个续写的对数概率。概率最高的就是模型的选择。这里有个细节要注意候选文本的长度不一样直接比总对数概率会偏向短候选。所以要用平均对数概率也就是总对数概率除以 token 数。这样才公平。4.3 温度与归一化打分的时候温度参数也有讲究。温度高概率分布平候选之间的差距被抹平容易选错。温度低分布尖模型更自信但也可能过度自信。我一般用温度 1.0 做打分保持模型原本的概率分布不做额外缩放。归一化方面如果候选数量少直接用 softmax 归一化就行。如果候选多可以考虑用 top-k 或者阈值过滤把明显不可能的候选概率压到零减少干扰。实操心得打分之前一定要把候选的文本格式统一。比如都加上相同的后缀或者都用相同的模板。格式不一致会让模型在无关的 token 上产生概率差异干扰判断。我踩过这个坑候选 A 是调用搜索候选 B 是调用搜索工具多了两个字概率就偏了。5. 与工具调用的串联把选择题嵌进智能体循环5.1 单步决策的完整流程把选择题嵌进智能体的循环单步的流程大致是这样接收当前上下文包括用户输入、历史对话、上一步工具返回的结果根据上下文动态裁剪候选集对每个候选计算对数概率选出概率最高的候选如果是工具调用抽取参数并执行把执行结果拼回上下文进入下一步这个流程里第 3 步是核心也是提速的关键。因为只做一次前向计算不做自回归解码单步耗时通常能压到几十毫秒级别。相比自由生成的几百毫秒到几秒提升非常明显。5.2 多步任务的终止判断多步任务什么时候结束传统做法是让模型生成一个结束标记。在选择题框架下我们把结束也做成一个候选。当模型选中结束候选时循环终止输出最终结果。这样设计的好处是终止判断也变成了一次分类不需要额外的生成。而且结束候选的概率可以作为一个置信度指标如果模型在结束和其他候选之间犹豫说明它不确定任务是否完成这时候可以触发澄清或者重试。5.3 错误恢复与重试选择题框架下的错误恢复比自由生成简单。因为候选是有限的如果选中的工具执行失败可以直接把失败信息拼回上下文重新做一次选择题。模型看到失败信息后大概率会选另一个候选或者选请求澄清。我一般会设置一个重试上限比如连续失败三次就强制终止避免死循环。这个上限不用太高因为选择题的准确率本来就高连续失败三次说明确实有问题再试也是浪费。6. 性能实测10 倍提速从哪来6.1 延迟拆解对比我拿同一个 3B 模型做了对比测试任务是一个五步的行程规划查天气、查航班、查酒店、算预算、汇总。自由生成和选择题两种模式的延迟拆解如下环节自由生成选择题说明单步决策约 800ms约 60ms自由生成平均 40 token选择题一次前向参数抽取含在生成里约 10ms选择题用规则抽取工具执行约 200ms约 200ms两者相同五步总计约 5s约 1.35s不含工具执行约 3.5 倍含执行约 3.7 倍单看决策环节提速是 13 倍左右。整体任务因为工具执行时间固定被稀释到 3 到 4 倍。如果工具执行更快或者步数更多整体提速会更接近决策环节的倍数。标题里说的 10 倍指的是纯推理环节的提速这个数字在决策密集的任务里是能复现的。6.2 准确率的变化提速不能以牺牲准确率为代价。实测下来选择题模式的准确率反而更高。同样是 100 次测试自由生成的工具选择准确率是 88%选择题是 97%。原因前面说过选择题把输出空间压缩了模型不用在几万维的词表里搜索只需要在几个候选里判断出错概率自然低。参数抽取的准确率两者差不多因为这部分本来就是确定性的。但选择题模式下参数幻觉明显减少因为参数不是生成的是从上下文抽取的。6.3 资源占用的差异除了延迟资源占用也值得说。自由生成因为要维护 KV 缓存、要自回归解码显存和内存的峰值占用更高。选择题只需要一次前向峰值占用低不少。在边缘设备上这个差异可能决定了能不能跑起来。我在一台 8GB 显存的设备上测试自由生成模式跑 3B 模型已经比较吃力批量稍微大一点就 OOM。选择题模式因为不需要缓存解码过程同样的设备能跑更大的批量吞吐上去了单位成本就下来了。7. 常见问题与排查技巧实录7.1 候选概率都很低怎么办有时候模型对每个候选的概率都不高最高的也就 0.3 左右。这种情况通常说明候选集里没有真正合适的选项或者上下文信息不足。我的处理方式是设一个置信度阈值比如最高概率低于 0.5 就触发澄清让模型选请求澄清候选向用户追问。阈值不用设太高0.5 是个比较稳的值。设太高会频繁触发澄清体验差设太低会强行选一个不靠谱的候选错误率高。7.2 候选之间概率接近怎么处理如果前两个候选的概率很接近比如 0.45 和 0.42说明模型在犹豫。这时候直接选最高的可能选错。我的做法是看差值如果差值小于 0.1就把这两个候选都执行一遍看哪个的结果更合理。或者干脆触发澄清让用户来定。这个策略在工具调用场景下特别有用。比如模型在查航班和查火车之间犹豫两个都查一下把结果都给用户让用户选。多花一点时间但避免了选错。7.3 候选集需要更新怎么办业务变化了候选集要加新选项或者删旧选项怎么办我的建议是把候选集做成配置不要硬编码在代码里。这样更新的时候改配置就行不用动代码。同时要做好版本管理每次更新候选集都记录一下方便回溯。更新候选集之后要重新测准确率因为新候选可能和旧候选有语义重叠导致模型混淆。比如加了查询天气和查询气象这两个太像了模型分不清。遇到这种情况要么合并要么在候选描述里写清楚区别。7.4 常见问题速查表问题现象可能原因排查方向解决建议所有候选概率都低候选集不匹配或上下文不足检查候选是否覆盖当前意图补充候选或触发澄清前两候选概率接近候选语义重叠检查候选描述是否区分度够合并候选或细化描述选中候选后执行失败参数抽取错误检查抽取规则修正抽取逻辑或加校验延迟没有明显下降候选数量过多统计候选数量动态裁剪到 10 个以内准确率下降候选集更新引入混淆对比新旧候选集回滚或重新设计候选避坑技巧候选集的维护是个持续工作不是一劳永逸的。业务在变用户在变候选集也要跟着变。我一般每个月 review 一次候选集的使用情况把长期没被选中的候选删掉把频繁触发澄清的场景补上新候选。8. 适用边界与扩展思路8.1 什么场景适合这套方案选择题框架最适合的是决策空间有限、动作类型可枚举的场景。比如工具调用、意图分类、下一步动作选择。这些场景里候选集是天然存在的不需要额外构造。不太适合的是开放式生成任务比如写文章、编故事、做翻译。这些任务的输出空间是开放的没法枚举候选。硬要做选择题候选集要么覆盖不全要么数量爆炸得不偿失。还有一种边界情况是候选集很大但可以分层。比如电商客服动作类型有几十种但可以按业务域分成几层每层做一次选择题。这样每层的候选数量可控整体还是能享受选择题的提速。8.2 和投机解码的关系有人会问这和投机解码是不是一回事。不是。投机解码是用一个小模型快速生成草稿再用大模型验证本质还是生成只是加速了生成过程。选择题是彻底放弃了生成改成分类。两者可以叠加但思路不同。选择题的优势在于它连草稿都不用生成直接一次前向出结果。在候选集小的情况下比投机解码更省。但候选集大的时候投机解码可能更灵活因为它不受候选集限制。8.3 后续可以怎么扩展这套框架还能往几个方向扩展。一个是候选集的自动学习用历史数据统计哪些候选经常被选中动态调整候选的优先级和数量。另一个是打分的多模态化不光看文本概率还结合上下文特征、用户画像等做综合打分。还有一个方向是把选择题和生成结合起来用选择题做粗粒度的决策用生成做细粒度的表达。比如先选回复用户这个动作再生成具体的回复内容。这样既享受了选择题的决策速度又保留了生成的灵活性。我个人在实际操作中的体会是这套方案的价值不在于某个具体的技术点而在于它改变了思考问题的方式。以前遇到延迟问题第一反应是换更快的模型、加更多的算力。现在会先问一句这个环节真的需要生成吗能不能改成选择很多时候答案是可以的而且改完之后效果立竿见影。最后再分享一个小技巧候选集的描述文本尽量用动词开头比如查询天气而不是天气查询模型对动词开头的候选区分度更高实测准确率能再提一两个点。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑