共计 1896 个字符,预计需要花费 5 分钟才能阅读完成。
什么是 Agent Skill?
Agent Skill(智能体技能)是对话系统中的功能模块,它能理解用户的自然语言输入,执行特定任务并返回结构化响应。比如天气查询、订餐、日程提醒等,每个独立功能都可以封装成一个 Skill。它的核心价值在于:

- 模块化:不同技能可独立开发和部署
- 可复用:一个技能能被多个对话机器人调用
- 易扩展:新增功能只需添加新技能
新手开发的三大痛点
-
意图识别不准:用户说 ” 明天会下雨吗 ” 和 ” 天气预报 ” 其实都是查询天气,但 NLU 模型可能识别为不同意图
-
上下文断裂:多轮对话时(如先问 ” 北京天气 ” 再问 ” 上海呢 ”),技能容易丢失之前的对话记忆
-
异常处理缺失:当 API 调用失败或用户输入模糊时,没有友好的降级方案
实战:天气查询 Skill 开发
1. 技能注册框架(Python)
from typing import Dict, Any
class WeatherSkill:
def __init__(self):
self.skill_id = "weather_v1"
def can_handle(self, intent: str) -> bool:
return intent == "query_weather"
async def execute(self, params: Dict[str, Any]) -> Dict[str, Any]:
# 核心逻辑在下文实现
pass
2. 意图定义(Dialogflow 格式)
{
"intents": [
{
"name": "query_weather",
"trainingPhrases": ["{city}天气怎么样",
"{city}会下雨吗",
"查 {city} 的天气预报"
],
"parameters": [
{
"name": "city",
"entityType": "@sys.city"
}
]
}
]
}
3. 完整实现(含 API 调用)
import aiohttp
from datetime import datetime
async def execute(self, params):
city = params.get('city', '北京') # 默认城市
try:
async with aiohttp.ClientSession() as session:
# 示例 API,实际需替换为真实天气接口
url = f"https://api.weather.com/v1?city={city}"
async with session.get(url) as resp:
data = await resp.json()
# 构造自然语言响应
temp = data['temperature']
return {"text": f"{city}今天气温{temp}℃,{self._get_weather_desc(temp)}",
"data": data # 原始数据供后续技能使用
}
except Exception as e:
return {"text": "暂时无法获取天气数据,请稍后再试"}
def _get_weather_desc(self, temp):
if temp > 30: return "记得防晒哦"
elif temp < 10: return "建议穿厚外套"
else: return "天气舒适宜人"
调试三大最佳实践
- 意图测试工具:
- 使用 Dialogflow 或 Rasa 的测试控制台
-
重点验证边界案例(如 ” 后天下午纽约的体感温度 ”)
-
日志埋点:
print(f"[DEBUG] {datetime.now()} 收到参数: {params}") - 记录原始请求和最终响应
-
标记处理耗时超过 500ms 的调用
-
单元测试模板:
async def test_weather_skill(): skill = WeatherSkill() result = await skill.execute({"city": "上海"}) assert "上海" in result["text"] assert "气温" in result["text"]
性能监控方案
- 关键指标:
- 意图识别准确率(通过标注测试集计算)
- API 平均响应时间(grafana 监控)
-
异常请求占比(Sentry 报警)
-
实现示例:
# 在 execute 方法开头添加 start_time = time.time() # 在返回前添加 statsd.timing(f'skill.{self.skill_id}.latency', (time.time()-start_time)*1000)
扩展思考
- 如何让技能记住用户上次查询的城市,实现 ” 再查一次 ” 这种省略提问?
- 当用户同时询问 ” 天气和限行 ” 时,如何协调多个技能的输出?
开发第一个技能就像学骑自行车——开始可能摇摇晃晃,但掌握核心要领后,很快就能自由骑行。建议从这个小天气案例出发,逐步尝试更复杂的场景处理。
正文完