首页/新闻资讯/正文详情

Agent技能库实战:注册表设计与两阶段检索提升模型调用准确率

发布时间:2026/9/26 8:32:33 来源:云帆数科 栏目:资讯中心
Agent技能库实战:注册表设计与两阶段检索提升模型调用准确率
做了两年多 AI Agent 相关的开发我发现在这类项目里最容易被人忽略、却又最能决定成败的往往不是模型本身而是你给 Agent 配的那套“技能”。有段时间我一直在做智能客服和自动化流程助手模型从 GPT 系列换到开源模型效果始终差一口气。不是模型不会对话而是它根本不知道该怎么执行任务——你说“帮我查一下上周订单的物流状态”它答得很好但没有任何动作。问题的根源就是缺少一个能让 Agent 稳定、安全、可复用调用外部能力的中层模块也就是我平时说的agent-skills。这篇文章我会把整套思路拆开揉碎从技能库的本质定位、注册表设计、代码实现到性能取舍和真实踩坑完整记录一套可以上手落地的方案。1. 先搞清楚agent-skills到底要解决什么问题1.1 模型不是万能的它需要“外挂”能力先说个基础事实大语言模型本质上是一个概率化文本生成器。你问它“今天天气怎么样”它能凭借训练数据里的知识给出一个泛泛的回答但它真正去读一遍天气API、拿到你所在城市的实时数据这件事它做不到。所以当我们要做真实可用的 Agent 时就必须给模型配一套“手和脚”“手”是各种工具、API、代码执行器“脚”是这些工具的调用规则和编排逻辑。而这套“手和脚”就是 agent-skills。我一开始犯过很典型的错误直接把几十个函数全部塞给模型靠它自己选择调用。结果是模型经常选错函数、传错参数稍微复杂点就完全失控。后来我意识到问题的核心不在于函数数量而在于技能的组织方式——模型需要的是结构化的、带完整解释的、按场景组织的技能集合而不是一堆散落的代码函数。1.2 技能库和普通函数调用差在哪一层很多人会觉得我有函数、有API再让模型去调不就完了实际上agent-skills 和普通函数调用之间差了三层设计上的考量可复用性。函数是一次性的技能是可复用的。一个“获取订单状态”的技能不只服务于客服对话还可以用在主动通知、售后分析、经营报表等场景里。好的技能定义是场景无关的。可发现性。模型尤其是通过 API 调用的大模型需要一个机制来知道“当前有什么技能可用”这就是技能注册和检索。在几十个技能里精准找到用户意图对应那一个这是普通函数列表做不到的。可编排性。单个技能解决单点问题复杂任务要靠多个技能的组合。技能库需要支持“技能与技能之间的组合调用”比如“查询订单”加“生成退款单”加“发消息通知用户”这需要具备规范的输入输出接口才能串联成一条工作流。所以agent-skills 的准确说法是连接用户意图、模型推理和执行动作之间的中间层。它的好坏直接决定 Agent 是“聪明的问答机器”还是“真能干活的工作助理”。2. 内核技能注册表长什么样2.1 给技能写一份“模型能看懂”的使用说明书技能库中每个技能的核心不是背后的实现代码而是它的“说明书”——也就是模型在决定是否调用这个技能时读到的元数据。这个说明书如果写得烂技能实现得再优雅也没用因为模型根本不知道该在什么时候调用它。我常用的技能定义结构包括四块技能名称、技能用途描述、输入参数定义、输出结果说明。下面是一个订单查询技能的标准写法{ name: query_order_status, description: 根据订单号查询订单当前的物流状态和签收时间。适用于用户询问我的订单到哪了东西发没发等场景。, parameters: { type: object, properties: { order_id: { type: string, description: 订单号一般以SO开头例如SO20240613001 } }, required: [order_id] }, returns: { type: object, properties: { status: { type: string, description: 订单状态取值范围pending/shipped/delivered }, tracking_info: { type: string, description: 物流追踪信息 } } } }注意几个细节description 里我不仅写了“它能干什么”还写了“它适合什么场景”甚至附带了查询字符串的示例。不要小看这些“废话”模型是基于语义匹配来决定调用哪个技能的你给的场景上下文越具体匹配准确率越高。参数描述同样重要。参数名要尽量自解释类型要精确npm包的开源库也大多是 JSON Schema 格式我统一用 JSON Schema 来实现。这里不建议用简单字符串拼接去写参数定义因为复杂场景下很容易出错而 JSON Schema 本身就是结构化标准模型对它的理解能力也更稳定。2.2 技能的分类与标签体系决定召回效率当技能数量超过20个之后光靠 name 和 description 的全局匹配会开始出现“技能抢答”的情况——用户问了一个稍微沾边的问题模型调用了好几个不相关的技能。这时候就需要引入分类和标签体系。我习惯把技能分成四类感知类技能获取数据比如查天气、查订单、读文件。操作类技能执行动作比如创建工单、发送邮件、调用接口。检索类技能从知识库或数据库里检索信息比如搜索文档、查历史记录。计算类技能在文本之外做数值计算或逻辑判断不是纯粹的文本生成。在技能注册表里每个技能除了 description还需要挂一个 category 字段和若干 tags 字段。查询时先根据分类过滤一部分候选集再做语义匹配这样既可以减少模型上下文里塞的技能数量也能降低误调用概率。class Skill: def __init__(self, name, description, category, tagsNone, parametersNone, handlerNone): self.name name self.description description self.category category # perception / operation / retrieval / computation self.tags tags or [] self.parameters parameters or {} self.handler handler这个设计现在看起来很简单但当时解决了大问题。有一次我们把技能数量从15个涨到40个模型选择准确率直接从92%掉到70%左右加了 category 过滤后召回准确率重新回到90%以上。3. 从0到1实现一套基础版agent-skills3.1 项目目录怎么搭模块之间怎么解耦先给出一份我用着很顺手的目录结构供参考agent-skills/ ├── skills/ │ ├── __init__.py │ ├── registry.py # 技能注册表 │ ├── base.py # Skill的基类和数据结构 │ └── builtin/ # 内置技能按领域划分 │ ├── order.py │ ├── logistics.py │ └── message.py ├── runtime/ │ ├── executor.py # 技能执行器 │ ├── scheduler.py # 技能编排与调度 │ └── context.py # 会话上下文 ├── llm/ │ ├── client.py # 模型调用封装 │ └── prompts.py # 提示词模板 └── main.py # 入口这里的关键是技能实现与调度逻辑分离。skills 目录里只放技能的声明和具体执行函数不关心模型怎么选它runtime 目录负责技能的调度、执行和上下文管理。这样哪块出问题都能快速定位不至于改一个技能逻辑搞得整个系统崩掉。3.2 技能注册与检索的核心代码直接抄作业下面是一套简化后的核心实现逻辑已经很完整能跑通“技能注册 → 技能检索 → 模型决策 → 技能执行”的全链路。from typing import Callable, Dict, List, Optional class SkillRegistry: 技能注册表集中登记所有技能并提供检索能力 def __init__(self): self._skills: Dict[str, Skill] {} def register(self, skill: Skill) - None: if skill.name in self._skills: raise ValueError(f技能 {skill.name} 已存在) self._skills[skill.name] skill def get(self, name: str) - Optional[Skill]: return self._skills.get(name) def list_skills(self) - List[Skill]: return list(self._skills.values()) def search(self, query: str, category: Optional[str] None) - List[Skill]: 按 query 和 category 过滤技能候选集返回给模型决策 candidates self.list_skills() if category: candidates [s for s in candidates if s.category category] # 这里可以接语义检索embedding简化版先做关键词打分 scored [] for skill in candidates: score 0 if query in skill.description: score 3 for tag in skill.tags: if tag in query: score 2 scored.append((score, skill)) scored.sort(keylambda x: x[0], reverseTrue) return [s for s_score, s in scored if s_score 0][:5]实际项目里我不会只用关键词打分会接一个 embedding 模型做语义检索但思路完全一致先把候选集缩减到5个以内再把这5个技能的完整定义拼进 prompt让大模型选择最终要调用的那一个。这个两阶段策略比把40个技能全塞进上下文效果更好也更省 token。3.3 模型调度时技能列表如何拼写进Prompt调度脚本是模型决策质量的重头戏我把核心 Prompt 固定成这样一个模板SYSTEM_PROMPT 你是一个任务调度助手负责根据用户问题从候选技能中选择需要调用的技能。 候选技能如下 {candidate_skills} 请你从用户的问题中提取出关键参数并以JSON格式输出。 输出格式示例 { selected_skills: [query_order_status], parameters: {query_order_status: {order_id: SO20240613001}} } 如果用户问题与候选技能无关输出 { selected_skills: [], parameters: {} } 每个技能在 candidate_skills 里渲染出来的文本就是我在 2.1 节定义的那个 JSON。这一步做得好不好直接决定大模型能不能“看懂”技能说明所以不要偷懒description 一定要写场景、写样例、写边界。我建议把每次调度的模型输出完整记录下来包括候选技能列表、模型选中的技能和输入的参数。后续排查问题的时候这些日志就是最好的定位证据。4. 实操中的坑我替你先踩一遍4.1 技能描述写不好模型就是“视而不见”这个坑我踩了至少三次。技能实现没问题、注册表没问题但模型就是从不调用它。排查到最后发现全是 description 写得不够具体。举个反面例子。我一开始把“获取企业微信用户信息”这个技能的 description 写成获取企业微信用户详情。看似没毛病但模型在遇到“这个客户的部门是什么”时根本不会联想到这个技能因为“部门”“客户”这些词在 description 里压根没出现。后来我改成根据用户ID获取企业微信通讯录中的用户详细信息包括姓名、部门、职位、手机号、邮箱等。适合在用户询问同事联系方式、组织架构、员工资料时调用。加了“姓名、部门、职位”这些具体字段和“通讯录、组织架构”这些场景词之后调用准确率立刻上去了。所以写描述有个很朴素的检验标准把自己当成完全不了解系统的用户用日常话术描述你会在什么场景下想到用这个技能。如果描述里包含了高频场景词模型大概率也能匹配上。4.2 参数定义不规范轻则报错重则推错流程第二个高频问题是参数 schema 定义。模型在生成参数时非常依赖 schema 的约束。举几个典型问题参数没有写required模型就会在某些情况下漏传关键参数。参数描述没有给示例值模型就可能在枚举值之外生成一个相近但不合法的值。类型定义不严格比如把order_id定义成 number实际值却是SO20240613001这种字母开头的字符串模型就完全会错意。我现在要求所有参数必须类型明确、示例值必填、范围枚举或正则尽量给定。比如订单号可以在 description 里加一条“订单号一般以SO开头由字母和数字组成不要包含空格”。这个小注释对模型理解非常有效。4.3 实际使用后的性能观测与体感数据这一小节说几个真实跑出来的数据方便大家对方案有个体感技能数在10个以内时单次调度的模型延迟约 200ms准确率基本维持在95%以上。技能数增加到40个时如果不做候选集过滤直接全量塞进上下文单次调度 token 消耗约增加 60%准确率下滑到 80% 以下这两个数字都不可接受。引入两阶段“检索 → 决策”之后单次调度的 token 消耗控制在原方案的 40%技能选择准确率回升到 92% 以上。需要说明的是这些数据依赖具体选用的模型和场景不能当通用基准但足够论证一个结论技能库的增长不能靠单纯堆上下文必须配合检索机制。4.4 常见问题速查表为了方便新手排查我把遇到频率最高的几个问题整理成了速查表。现象可能原因排查与解决模型从不调用某个技能description 缺少场景关键词重写 description加入具体字段与典型问题句式模型调用了系统里不该调用的技能候选集过滤不足skill 数量过多引入 category/tags 两阶段检索缩减候选集参数传错如类型不对schema 没有约束类型和格式严格定义 parameters补充示例值技能内部报错但系统没有任何记录缺少调用日志为每次执行打印入参和执行结果建立可观测性同样的问题换个说法模型就不会了description 的表述域太窄增加同义场景描述用多个示例丰富语义边界4.5 一个补充让技能做“减法”学会拒绝最后还想分享一个很容易被忽视的设计思路技能库也要设计“不做什么”。很多技能被误调用的原因不是它描述得不够清楚而是它跟其他技能的边界模糊。我在每个技能 description 里都加了“边界说明”这一项{ name: query_order_status, description: 查询订单物流状态。适用于用户询问订单是否发货、物流到哪里。, not_recommended_for: 退款进度查询请使用 refund_status 技能不要使用本技能。 }这一步看似多余但对降低模型误调用特别有效。模型判断技能归属时是在做推理给它明确的否定边界比正面描述更省心。5. 这套技能体系还能怎么扩展技能库这个结构稳定之后扩展方向其实是很有想象空间的。我自己后续计划里有几个优先级比较高的方向多模态技能。把图像识别、音频转写、文件解析也做成标准技能让 Agent 不只是处理纯文本。技能学习与自动生成。利用大模型自动将一段操作说明转化为结构化技能定义减少人工手写 description 的成本。技能版本与灰度发布。技能也会迭代先让一部分流量用新版本技能跑稳了再全量避免一次大变更导致全员翻车。如果你正在搭自己的 Agent 或自动化系统建议直接从技能注册表两阶段检索这个模式起步它结构简单、效果好而且踩坑空间小。先把10个核心技能跑顺再慢慢扩展这条路我走过稳。我在实际项目里的体会是Agent 的能力上限不在于模型参数有多大而在于你给它配了多少边界清晰的“手艺活”。技能库维护得越细致Agent 在真实场景里就越像个靠谱的同事而不是一个只会聊天的玩具。最后再分享一个小习惯每次新增技能前先在纸上写下“用户会用什么话术触发它”“哪些场景它不该出现”写清楚再动手写代码你会少走很多弯路。

相关推荐

STM32嵌入式开发核心理论:GPIO、PWM、I2C与时钟树实战解析
STM32嵌入式开发核心理论:GPIO、PWM、I2C与时钟树实战解析

1. 从“点灯”到“控世界”:STM32理论到底在讲什么很多人第一次接触STM32,都是从一块F103C8T6最小系统板开始的。板子到手,装好Keil或者STM32CubeIDE,第一件事就是找例程点个LED。灯亮了,心里一阵激动;灯不… · 2026/9/26 8:32:27

华为昇腾Atlas 300V 24G推理加速卡YOLO部署全流程解析
华为昇腾Atlas 300V 24G推理加速卡YOLO部署全流程解析

1. 项目概述与背景1.1 atlas到底是什么先说结论:atlas 在技术圈里通常指代的是华为昇腾(Ascend)AI 处理器家族及其配套的软件栈,尤其是 Atlas 300V 这种推理加速卡。但如果你是在 GitHub 上搜到名为 atlas 的开源项目,… · 2026/9/26 8:32:27

Turbo 节点源码精读:MiniMax-H3-Comfy-NPU 双 flow schedule 采样器与 pruned 底模 LoRA 注入为何巧妙
Turbo 节点源码精读:MiniMax-H3-Comfy-NPU 双 flow schedule 采样器与 pruned 底模 LoRA 注入为何巧妙

Turbo 节点源码精读:MiniMax-H3-Comfy-NPU 双 flow schedule 采样器与 pruned 底模 LoRA 注入为何巧妙 【免费下载链接】MiniMax-H3-Comfy-NPU 项目地址: https://ai.gitcode.com/Ascend-SACT/MiniMax-H3-Comfy-NPU MiniMax-H3-Comfy-NPU 是面向 Ascend NPU… · 2026/9/26 8:32:21

书霸AI期刊避坑|官网www.shubaai.com
书霸AI期刊避坑|官网www.shubaai.com

https://www.shubaai.com写期刊论文时,最容易被忽略的,往往不是“不会写”,而是第一步就选错了方向。打开书霸AI写作的期刊论文功能,可以看到从选择模板、提交论文到生成并下载的流程。页面中还提供地区、学历和院校模板等筛选入口… · 2026/9/26 9:11:17

程序员优秀开源免费软件推荐:TaoToken 统一 Key 接入 Cline 与 CC Switch 配置骨架
程序员优秀开源免费软件推荐:TaoToken 统一 Key 接入 Cline 与 CC Switch 配置骨架

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 9:11:17

Atlas 300V部署YOLO实操:从加速卡选型到模型转换全指南
Atlas 300V部署YOLO实操:从加速卡选型到模型转换全指南

你在搜索引擎里敲下 “atlas” 这个词,大概率会看到两类内容:一类是层出不穷的 atlas 部署 yolo 教程,另一类是 atlas 300v 24g 是运算加速卡吗 这种灵魂拷问。这两类问题其实指向的是同一个东西——华为昇腾的 Atlas 系列 AI 加速产品。很多… · 2026/9/26 9:11:17

自建CRM系统实战:从免费工具到私有部署的完整方案
自建CRM系统实战:从免费工具到私有部署的完整方案

1. 项目缘起:为什么放着现成软件不用,非要搞一套 DeskcommCRM这事得从三年前说起。当时我们团队负责一块涉及几百家长期客户的业务,客户档案散落在 Excel、微信聊天记录、纸质工单和几个同事的脑子里。每次要统计某个客户的历史跟进情况&… · 2026/9/26 9:11:05

DeskcommCRM落地实战:从Excel到团队客户管理全配置指南
DeskcommCRM落地实战:从Excel到团队客户管理全配置指南

原来Excel里那几十个客户名单堆到第三个月就彻底乱套了——谁跟进过、谁成交了、哪个客户该回访,全靠记忆硬撑。后来我干脆搭了一套DeskcommCRM系统,把客户、线索、跟进记录全放进去,销售团队每人一个账号,谁接手了哪个客户、下一… · 2026/9/26 9:11:05

桂花网蓝牙网关多设备连接稳定性设计与实操配置指南
桂花网蓝牙网关多设备连接稳定性设计与实操配置指南

1. 多设备蓝牙连接为什么容易“翻车”做过蓝牙物联网项目的人大概都有这种体会:单台设备连手机调试时稳如老狗,一旦把设备数量拉到几十上百台,问题就全冒出来了——掉线、重连慢、数据丢包、延迟忽高忽低,甚至网关直接“罢工”。这… · 2026/9/26 9:11:05

数据库课后习题答案别硬背:当测试用例集刷,效率翻倍
数据库课后习题答案别硬背:当测试用例集刷,效率翻倍

简介:万常选版《数据库原理与设计》课后习题答案资源,覆盖第2至6章及第9章,适合正在学习关系模型、数据库建模、关系数据理论与模式求精的本科生、自学者作为复习与自测材料。压缩包共7个文件,含3个doc参考答案、2个sql示例脚本、… · 2026/9/26 0:00:21

OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置
OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 0:00:40

向下兼容与向上兼容:接口设计中的兼容性策略与工程实践
向下兼容与向上兼容:接口设计中的兼容性策略与工程实践

一次版本升级事故,是很多团队绕不过去的坎。线上环境里,服务端明明已经上线了新版接口,老的移动端还在照着旧文档传参数。请求一到网关,校验直接拒绝,用户操作失败,客服群炸了锅,开发群里开始互… · 2026/9/26 0:00:46

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码