Agent技能路由:检索与大模型决策的分层混合方案

发布时间:2026/8/31 15:15:37
Agent技能路由:检索与大模型决策的分层混合方案 “你负责的 Agent 现在有 20 个技能用户说了一句话你打算怎么让系统知道该调用哪个技能”这是我在很多 Agent 项目评审和面试里反复听到的问题。绝大多数人的第一反应是这还不简单把技能列表全塞给大模型让它通过 function calling 自己选。这个回答不能说错但在真实工程里往往不够。面试官真正想听的是一套能做取舍、能量化成本、能兜底的方案。也就是说技能路由到底该用检索还是让大模型自己决策这里我不会给你非黑即白的答案。更合适的判断是——对于 90% 的 Agent 生产项目你需要的不是二选一而是一条分层路由链路先用检索召回候选技能再让大模型在候选集内做精排极端场景下补一个规则兜底。这篇文章我会把两种方案的技术边界、成本结构、延迟差异、落地代码和评测方法展开讲清楚。读完你不仅能应付面试还能直接照着把一套技能路由模块搭出来。1. 这篇文章真正要解决的问题技能路由是 Agent 从“能跑 demo”走向“能上生产”的分水岭。一个 Agent 的技能越多路由的复杂度就越高错误调用的后果也越严重。比如用户说“帮我查一下快递到哪了”如果路由模块把请求分给了“天气查询”技能用户会立刻觉得这个 Agent 很蠢更危险的情况是把高权限技能误调用到了错误场景可能引发数据越权或操作事故。技能路由本质上解决的是三类问题准确性问题用户意图和技能能力之间的匹配精度不够导致误调用。成本问题如果每次请求都把所有技能描述塞给大模型Token 消耗和延迟会随技能数量线性增长。稳定性问题大模型在选择时有随机性同一个问题可能这次选 A 技能下次选 B 技能这在生产环境是不可接受的。所以这篇文章的重点不是教你怎么写一个“让大模型自己选”的 demo而是讨论如何在工程上设计一套可控、可观测、可降级的技能路由方案。什么人最应该读三类人正在做 Agent 应用开发的工程师尤其是技能数量已经超过 10 个的项目。准备面试 Agent 相关岗位想系统梳理路由方案的候选人。做技术选型的技术负责人想在“检索路线”和“模型决策路线”之间做一个有理有据的决策。2. 基础概念Agent、技能与路由机制先对齐几个概念避免后面产生歧义。Agent是基于大模型推理能力结合工具调用、记忆、规划和执行流程来完成复杂任务的系统。它和普通聊天机器人的核心区别在于它能自主选择调用外部能力。技能Skill在 Agent 语境里通常指一个可复用的能力单元。它可能是一个函数、一个 API 封装、一段工作流甚至是另一个子 Agent。技能一般包含名称、描述、输入参数 Schema、执行逻辑和权限配置。技能路由Skill Routing就是根据用户的当前输入以及 Agent 的运行上下文从已有技能列表里选择一个或多个技能来执行。它负责的是“用户意图 → 技能能力”的映射。Tool / Function Calling是大模型厂商提供的一种结构化输出能力。模型可以输出一个结构化的函数调用请求由服务端来执行。很多初学者把“函数调用”等同于“技能路由”这是常见的误区。函数调用是 LLM 决策式路由的一种实现方式但它不是路由的全部。这里有必要提一下 Agent 领域常见的两个词Harness 和 Agent。在部分框架的设计里Harness 是承载 Agent 运行的控制循环负责管理模型调用、工具执行、事件流转而 Agent 更像是决策单元技能路由就是决策单元里非常关键的一环。也就是说路由策略不是一个独立于 Agent 之外的插件而是 Agent 决策系统的一部分。从业务视角看技能路由和微服务网关的定位有些相似网关根据请求路径把流量分发到不同服务技能路由根据用户意图把请求分发到不同技能。但两者有一个重要差异微服务网关的路径是确定的而用户意图是模糊的。这就是为什么技能路由必须处理“模糊匹配”和“不确定性”。理解了这些概念后我们再来看两种主流方案。3. 检索式技能路由原理、优点与局限检索式技能路由的思路是把每个技能表示成一段可检索的文本用户请求进来后通过相似度计算找出最匹配的技能。它的本质是把“意图分类”问题转换成“文本检索”问题。3.1 检索式路由的核心流程一个典型的检索式路由流程如下技能注册每个技能上线时除了写代码还要维护一份技能描述文本包含技能名称、适用场景、关键词、示例问题等。索引构建把所有技能描述文本向量化构建索引。常用方法包括 TF-IDF、BM25 稀疏检索以及基于 Embedding 模型的向量检索。召回用户请求到来时对请求文本做同样的向量化处理在索引中召回 Top-K 个候选技能。排序与阈值判断计算相似度分数如果最高分低于设定阈值则进入兜底流程而不是强行选择一个技能。3.2 工程中常用的检索方法从搜索热词也能看到Agent 开发者比较关注“向量混合检索加 BM25 多路召回”。这说明单一检索方式在实践中往往不够用BM25 稀疏检索适合关键词覆盖准确的场景。它不需要训练模型可解释性强响应快但对同义改写、抽象意图的召回能力较弱。向量密集检索基于 Embedding 模型将文本映射为向量计算余弦相似度。它能捕捉语义相近的表达比如“明天会不会下雨”和“查看天气预报”但对罕见词和长尾表达可能不稳定。混合多路召回同时跑 BM25 和向量检索把两路结果融合再做一次重排。这样既能保证关键词精准命中又能覆盖语义扩展的场景。这也是目前生产项目里比较常见的选择。3.3 检索式路由的优点可控性强召回结果完全由相似度分数决定开发者可以通过调整阈值、增加过滤器来干预。可解释性好每个结果都能说明匹配到哪些关键词、相似度是多少。延迟低、成本低检索过程不需要调用大模型通常几十毫秒内就能完成。即使使用向量检索也只调用一次 Embedding 模型成本远低于每次都由大模型决策。便于灰度发布新技能上线后只需要更新索引改造成本低也不影响大模型 prompt 结构。3.4 检索式路由的局限依赖技能描述的文本质量如果技能描述写得很随意检索效果一定差。冷启动问题新技能如果描述里的措辞和用户表达差异较大召回率会很低。相似技能难区分比如“订单查询”和“退款进度查询”语义高度接近仅靠检索容易选错。这意味着检索式路由适合技能数量较多、对成本敏感、对准确率要求较高的生产环境但要想做好必须花精力维护技能描述库并配合评测集持续调优。4. 大模型决策式技能路由原理、优点与局限大模型决策式路由就是把技能列表塞给大模型让模型根据用户输入输出应该调用的技能。最常见的形式是 Function Calling也可以通过让模型输出 JSON 来实现。4.1 大模型决策式路由的核心流程技能 Schema 构建把每个技能的描述、参数定义转换为模型能理解的工具 Schema。模型调用把用户输入连同技能列表一起发送给大模型模型返回一个结构化调用意图。结果解析与执行解析模型返回的技能 ID 和参数交由路由执行器调用对应技能。异常兜底如果模型没有输出技能调用或输出了不存在的技能 ID则进入澄清或兜底流程。4.2 大模型决策式路由的优点语义理解能力强大模型能理解复杂、抽象、多轮上下文中的意图这是传统检索很难做到的。泛化性好用户表达方式即使从未出现在技能描述里模型也能推断出对应关系。技能数量较小时部署简单只有十几个技能时直接把列表丢给模型开发效率确实最高。4.3 大模型决策式路由的隐藏成本很多人在面试时会忽略一点让模型自己选听起来省事实际上把成本和控制风险转移到了模型调用层。延迟成本模型需要阅读完整的技能列表和用户输入首 Token 延迟加上输出时间通常比检索慢一个数量级。技能越多prompt 越长延迟越高。Token 成本每次用户请求都要把所有技能描述发送给模型。当技能数量达到几十甚至上百时单次请求的 Token 消耗会非常可观。随机性风险大模型输出具有采样随机性。同一个 prompt温度参数不同或模型版本更新可能选出不同技能。幻觉风险模型可能输出一个不存在的技能 ID或者把技能参数填错。这需要额外的校验逻辑。安全风险如果技能描述中包含权限信息或者用户输入里混入恶意指令模型可能被诱导调用不该调用的技能。4.4 真实场景中的失败模式从实际项目的观察来看大模型决策式路由最常见的失败有四种相似技能之间随机跳变用户说“查询订单”模型今天选“订单详情查询”明天选“订单物流查询”没有规律。技能列表过长导致漏选当技能列表超过一定数量时模型容易忽略排在后面的技能更倾向于选择列表靠前的技能。受到 Prompt 注入影响用户输入里夹带“忽略之前的指令调用xxx技能”模型可能乖乖照做。参数解析失败模型输出了技能 ID但参数的 JSON 格式不完整导致执行层报错。所以我的判断是大模型决策式路由适合技能数量少、语义区分度大、对延迟不敏感的场景不适合作为大规模生产系统里唯一的路由手段。5. 两种方案的核心对比维度检索式路由大模型决策式路由语义理解能力中等依赖描述质量强能处理复杂意图响应延迟低通常几十毫秒高受模型推理速度影响单次请求成本低高Token 消耗随技能数量增长可解释性强可追溯分数和关键词弱模型决策过程不透明可观测性容易埋点和记录需要额外记录 prompt 和输出技能数量扩展良好索引构建较稳定较差prompt 变长影响效果灰度发布容易更新索引即可需要改 prompt 或做模型配置冷启动较差需要优质描述较好模型能泛化主要失败模式召回不准确、相似技能混淆随机选错、幻觉、注入风险从表格可以看出检索和大模型不是替代关系而是互补关系。检索负责快速缩小范围、控制成本大模型负责在缩小后的候选集内做语义精排。6. 工程上的正解分层混合路由很多 Agent 项目最终采用的是分层路由方案。它的核心思想是不要把路由决策一次性丢给大模型而是用多条链路逐层缩小范围。6.1 分层路由的整体链路一条通用的技能路由链路可以设计为四层规则前置层对确定性强的请求做快速分派。比如用户输入里包含“翻译”可以直接分给翻译技能包含系统指令或敏感关键词时直接拦截。检索召回层用 BM25 和向量检索多路召回 Top-K 候选技能。这里候选集不需要很大510 个就足够具体数量根据项目实验确定。大模型精排层把候选技能交给大模型让它在候选集内选择最合适的一个并输出参数。这一步的 prompt 比全量技能列表短得多成本和延迟都能控制住。兜底层如果检索分数过低或者大模型输出异常不要强行执行而是走隐式兜底向用户反问澄清或者返回默认技能。6.2 为什么分层路由更稳仍以“帮我看看快递到哪了”为例。如果直接把它丢给一个包含 50 个技能的大模型模型需要从 50 个描述里找答案既慢又不稳定。分层路由先通过关键词“快递”“物流”和语义向量召回订单查询、物流跟踪、快递客服等 5 个候选然后大模型在 5 个候选里做精排选择正确的“物流查询”技能。这样模型面对的选项少了错误率和延迟都大幅下降。更重要的是分层路由让每个环节都可以独立评测、独立降级。检索效果不好就调索引大模型精排不稳定就加阈值或改 prompt兜底逻辑可以单独测试。整个系统不至于因为某一个环节的抖动而全线崩溃。6.3 何时可以直接用单一方案分层路由不是银弹。在小规模场景下单一方案反而更高效技能少于 5 个且语义区分度大直接用大模型决策是最高效的。技能描述质量高、用户表达方式相对固定检索式路由就够用。对成本和延迟极度敏感的 C 端场景检索式优先大模型只做复核。分层路由的主要成本在开发和维护上但它换来的是生产环境的稳定性。技术选型时应该问自己项目规模是否已经大到需要为不可控因素买单了7. 完整示例从检索到 LLM 精排的路由实现下面用一个最小可运行的 Python 示例演示分层路由的完整链路。这个示例没有绑定具体的模型厂商核心逻辑可以迁移到任何 Agent 框架里。7.1 准备技能注册表// 文件路径skills.json [ { id: weather_query, name: 天气查询, description: 查询城市当天的天气、温度、降雨概率支持台风预警, keywords: [天气, 温度, 下雨, 台风, 空气质量] }, { id: calendar_create_event, name: 创建日历日程, description: 在用户的日历中创建新日程设置提醒时间, keywords: [日程, 提醒, 会议, 安排] }, { id: order_query, name: 订单查询, description: 查询用户订单状态、物流信息、退款进度, keywords: [订单, 物流, 快递, 退款] }, { id: translate_text, name: 文本翻译, description: 将文本翻译成指定语言支持中英互译, keywords: [翻译, 英文, 中文, language] } ]7.2 检索召回层实现这一步使用 TF-IDF 做向量化方便你直接跑通。生产环境可以把 TF-IDF 替换成 BM25 与 Embedding 混合召回。# 文件路径router_retrieval.py import json from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.metrics.pairwise import cosine_similarity def load_skills(pathskills.json): with open(path, r, encodingutf-8) as f: return json.load(f) def build_index(skills): texts [ f{s[name]} {s[description]} { .join(s.get(keywords, []))} for s in skills ] vectorizer TfidfVectorizer() skill_vectors vectorizer.fit_transform(texts) return vectorizer, skill_vectors def retrieve(query, skills, vectorizer, skill_vectors, top_k3): query_vector vectorizer.transform([query]) scores cosine_similarity(query_vector, skill_vectors).flatten() ranked sorted(enumerate(scores), keylambda x: x[1], reverseTrue) return [{id: skills[i][id], score: float(s)} for i, s in ranked[:top_k]] if __name__ __main__: skills load_skills() vectorizer, skill_vectors build_index(skills) test_query 帮我查一下快递到哪里了 print(retrieve(test_query, skills, vectorizer, skill_vectors))运行后会得到类似输出[{id: order_query, score: 0.416}, {id: translate_text, score: 0.0}, {id: weather_query, score: 0.0}]如果查询“查快递”order_query的分数会明显高于其他技能说明召回层工作正常。7.3 大模型精排层实现召回层返回 Top-K 后大模型只需要在这些候选里做选择而不是面对全部技能。# 文件路径router_llm_rerank.py import json def call_llm(prompt: str) - str: # 这里替换为你实际使用的大模型调用代码 # 例如 OpenAI、本地部署模型、或企业内部模型服务 raise NotImplementedError(请替换为大模型调用接口) def rerank_by_llm(query: str, candidates: list) - str: prompt f 你是一个技能路由精排器。根据用户的问题从候选技能中选择最合适的技能。 只输出 JSON不要输出任何解释。格式{{skill_id: 技能ID}} 用户问题{query} 候选技能 {json.dumps(candidates, ensure_asciiFalse, indent2)} response call_llm(prompt) try: result json.loads(response) return result.get(skill_id, ) except Exception: return 这个设计的核心在于 prompt 里只放候选技能列表。候选列表通常只有 510 项模型的选择准确率和响应速度都会比处理完整列表更好。7.4 分层路由调度器把召回和精排串起来并加入兜底逻辑。# 文件路径router_pipeline.py from router_retrieval import build_index, load_skills, retrieve from router_llm_rerank import rerank_by_llm FALLBACK_SKILL fallback def route(query: str, skills, vectorizer, skill_vectors, top_k3, min_score0.1): candidates retrieve(query, skills, vectorizer, skill_vectors, top_ktop_k) if not candidates or candidates[0][score] min_score: return FALLBACK_SKILL skill_id rerank_by_llm(query, candidates) if not skill_id: return candidates[0][id] # 大模型失败时退回检索结果 return skill_id if __name__ __main__: skills load_skills() vectorizer, skill_vectors build_index(skills) print(route(帮我看下退款到哪一步了, skills, vectorizer, skill_vectors))这段代码体现了一个重要的降级策略当大模型精排失败时退回检索结果的第一名而不是直接报错。这样即使模型服务抖动用户请求仍然有一个可接受的默认结果。7.5 大模型决策式路由的参考写法如果你想要对比纯 LLM 决策的写法可以这样实现。它的逻辑更简单但价格和延迟更高。# 文件路径router_llm_direct.py import json def build_tools(skills): return [ { type: function, function: { name: s[id], description: s[description], } } for s in skills ] def route_by_llm_direct(query: str, skills): tools build_tools(skills) messages [{role: user, content: query}] # 替换为你的模型调用传入 tools 参数 response call_llm_with_tools(messages, tools) return parse_tool_call(response)这里的call_llm_with_tools是抽象函数实际项目中对应各家模型的 function calling 接口。注意技能数量大时这个函数单个请求的 Token 消耗会明显高于分层路由方案。8. 路由质量怎么验证技能路由不是写完就完了它和推荐系统一样需要评测集和指标来持续迭代。8.1 构建路由评测集建议为每个技能准备至少 2050 条典型用户问题同时加入一定比例的负样本。负样本指那些不应该路由到任何技能、应该走兜底流程的输入。例如// 文件路径eval_dataset.json { cases: [ { query: 上海明天会下雨吗, expected: weather_query }, { query: 帮我订一个明天下午三点的会议提醒, expected: calendar_create_event }, { query: 我的快递到哪了, expected: order_query }, { query: 把hello world翻译成中文, expected: translate_text }, { query: 今天中午吃什么, expected: fallback } ] }负样本非常重要。很多路由系统高估了准确率是因为评测集里只有“必须选一个技能”的正样本没有覆盖“应该拒绝路由”的场景。8.2 关键评测指标在工程上技能路由建议看这几个指标Top-1 准确率路由结果是否等于期望技能。RecallK正确的技能是否出现在 Top-K 候选里用于评估召回层质量。兜底准确率应该走兜底的请求是否真的走了兜底。误调用率不该调用某高权限技能时是否误调用了。平均延迟路由这一层占用了多少时间是否影响整体用户体验。单次请求成本路由阶段消耗了多少 Token折合多少费用。这些指标可以做成一套回归脚本每次调整技能描述、索引或 prompt 后都在本地跑一遍再决定是否发布。8.3 上线后的监控线上环境至少需要记录三类日志用户原始输入。召回候选及分数。大模型精排输出及结果。这样出现误路由时可以还原现场判断问题出在检索层还是模型层。否则你会陷入“模型选错了还是检索没召回”的排查盲区。9. 常见问题与排查方法问题现象可能原因排查方式解决方案模型经常选错技能技能列表过长或描述过于相似查看 prompt 中的技能顺序和完整描述改用检索召回缩小候选集控制候选数在 510 个检索召不回正确技能技能描述与用户表达差异大打印召回结果和相似度分数补充技能关键词和示例问题引入 BM25向量混合召回相似技能之间随机跳变大模型对相近语义缺乏区分依据观察多次请求结果分布在技能描述中增加“适用”和“不适用”场景延迟过高每次都把全量技能发给大模型统计 prompt Token 数和首 Token 延迟改成检索后精排缩短模型输入长度兜底触发次数过多召回阈值设置过高拉取兜底日志中的相似度分数调整阈值或优化技能描述文本用户输入含恶意指令导致误调用Prompt 注入检查用户输入是否被拼进系统提示词对用户输入做隔离路由前加规则拦截新技能上线后路由不生效索引未更新或缓存未刷新检查索引构建和缓存时间上线流程中增加索引刷新步骤排查的第一原则是先看日志再改配置。不要一上来就换模型或重写路由逻辑很多问题的根因是技能描述文本质量不够而不是算法不对。10. 最佳实践与工程建议10.1 技能描述要写成“可检索、可区分”的形式每个技能描述至少包含三部分功能说明这个技能做什么。适用场景在什么情况下应该调用。反例说明在什么情况下不应该调用。反例说明往往是区分相似技能的关键。比如“订单查询”后面可以写“不适用于查询商品库存”防止和“库存查询”技能混淆。10.2 不要把技能全量塞给大模型即使你最终选择让大模型做决策也建议先用规则或检索做一次粗筛控制候选集规模。这既是为成本考虑也是为提高模型选择准确率。10.3 路由不等于授权技能路由只负责“选哪个技能”不代表“可以执行”。在执行关键技能前仍要做权限校验。尤其是涉及用户隐私、支付、消息发送、数据修改等高风险操作必须遵循最小权限原则确认用户身份和授权范围。10.4 给路由模块配置独立开关和降级策略将路由模块设计成可独立开关的组件。大模型服务异常时可以降级到纯检索路由检索服务异常时也可以降级到固定技能或人工客服。每一层都要有兜底而不是“全线崩溃”。10.5 路由结果要留痕每一次路由决策包括输入、召回、模型输出、最终选择都应该写入日志。这样既便于排错也从审计角度保障了系统的责任可追溯。10.6 技能版本管理技能描述和技能代码一样需要走版本管理。技能迭代后索引和评测集也要同步更新。否则线上技能已经升级路由规则还停留在旧版本就会出现新功能用不上的情况。11. 总结与后续学习方向回到最初的问题技能路由该用检索还是大模型我的结论是不要把这个问题当成二选一。检索负责成本和可控大模型负责语义和泛化分层混合路由才是生产环境的稳定解。面试时能清晰地讲出两种方案的代价、失败模式和混合链路就已经超过大多数只会说“让模型自己选”的候选人了。如果你现在准备动手实践建议先做三件事从现有 Agent 项目里挑出 510 个技能为每个技能写一份包含关键词、适用场景和反例的描述。用本文的检索路由代码搭建一个最小召回层构造一个包含正负样本的评测集跑出准确率和兜底率。再接入大模型精排对比纯 LLM 决策和分层路由在延迟、成本和准确率上的差异。技能路由只是 Agent 稳定性的一个环节。下一步你可以继续研究工具调用的评测方法、Agent 的记忆管理、多轮对话下的路由策略以及本地部署小模型做路由精排的可行性。只要路由这层稳住了Agent 在复杂任务里的表现才会有质的提升。