第十六章:工具(Tools)与技能(Skills)
学习目标
- 理解工具(Tools)的类型和作用
- 掌握Function Calling的工作原理
- 理解技能(Skills)的概念和特点
- 区分工具与技能的关系
前置要求
建议先学习第十五章:AI智能体(Agent),了解Agent的基本概念,因为工具和技能是Agent执行任务的核心手段。
什么是工具(Tools)?
工具(Tools)是Agent可以调用的外部功能模块,用于扩展Agent的能力边界。LLM本身只能处理文本,但通过工具,Agent可以搜索网络、执行计算、操作文件、调用API等。
为什么需要工具?
LLM有三大天然局限:知识有截止日期(无法获取最新信息)、无法执行操作(只能生成文本)、计算能力有限(复杂计算容易出错)。工具弥补了这些不足,让Agent成为真正的"全能助手"。
常见工具类型
| 工具类型 | 功能 | 示例 |
|---|---|---|
| 搜索工具 | 搜索互联网获取信息 | Google Search、Bing Search、DuckDuckGo |
| 计算工具 | 执行数学计算 | Python REPL、Wolfram Alpha、Calculator |
| 文件工具 | 读写文件、管理目录 | 文件读写、PDF解析、Excel操作 |
| API工具 | 调用外部服务API | 天气API、地图API、数据库查询 |
| 代码工具 | 编写和执行代码 | Python解释器、Shell命令 |
| 浏览器工具 | 浏览网页、提取信息 | Web Browser、HTML Parser |
Function Calling流程
工具注册
向系统注册可用工具的名称、描述和参数
用户请求
用户发送需要工具辅助的问题
LLM决策
LLM判断需要调用哪个工具,生成调用参数
执行与返回
系统执行工具调用,将结果返回给LLM
生成回答
LLM基于工具结果生成最终回答
什么是技能(Skills)?
技能(Skills)是为Agent预配置的专业能力模块,是一组工具、知识和提示词的组合。如果说工具是"扳手、锤子"这样的单个工具,技能就是"修水管、修电路"这样的完整技能包。
类比理解
工具就像厨师的"菜刀、锅、灶台"——是执行具体操作的基本工具。
技能就像厨师的"炒菜技能、烘焙技能"——是完成特定任务的完整能力,包含了工具使用方法、经验和知识。
技能的特点
- 组合性:一个技能通常包含多个工具的配合使用
- 专业性:每个技能针对特定领域优化
- 可复用:技能可以在不同Agent之间共享
- 可扩展:可以不断添加新的技能来增强Agent能力
常见技能类型
| 技能类型 | 功能 | 包含的工具 |
|---|---|---|
| 搜索技能 | 搜索和整理信息 | 搜索引擎、网页解析、摘要生成 |
| 编程技能 | 编写和调试代码 | 代码编辑器、运行环境、调试工具 |
| 数据分析技能 | 处理和分析数据 | 数据处理、可视化、统计分析 |
| 文档处理技能 | 创建和编辑文档 | 文档读写、格式转换、摘要提取 |
| 图像处理技能 | 生成和处理图像 | 图像生成、编辑、OCR识别 |
技能 vs 工具
工具是原子化的功能单元(如"搜索"),技能是面向任务的组合方案(如"信息调研")。一个技能通常包含多个工具的使用策略和领域知识。工具回答"怎么做",技能回答"做什么"。
代码实践
以下代码模拟了Function Calling的核心机制:工具注册、意图识别和自动调用。这帮助你理解AI Agent如何与外部工具交互。
import json
import re
from datetime import datetime
# ========== 工具注册表 ==========
class ToolRegistry:
def __init__(self):
self.tools = {}
def register(self, name, description, func, params=None):
self.tools[name] = {
"description": description,
"function": func,
"params": params or {}
}
def get_tool(self, name):
return self.tools.get(name)
def list_tools(self):
return {k: v["description"] for k, v in self.tools.items()}
# ========== 模拟的"AI决策"函数 ==========
def ai_decide(user_input, available_tools):
"""模拟LLM的Function Calling决策过程"""
user_input = user_input.lower()
# 简单的关键词匹配(实际LLM用语义理解)
if any(w in user_input for w in ["天气", "温度", "下雨"]):
return "get_weather", {"city": re.search(r'([\u4e00-\u9fa5]{2,10})', user_input)}
elif any(w in user_input for w in ["时间", "几点", "日期"]):
return "get_time", {}
elif any(w in user_input for w in ["计算", "加", "减", "乘", "除"]):
nums = re.findall(r'\d+', user_input)
if len(nums) >= 2:
return "calculator", {"a": int(nums[0]), "b": int(nums[1]), "op": "+"}
elif any(w in user_input for w in ["搜索", "查一下", "什么是"]):
query = user_input.replace("搜索", "").replace("查一下", "").strip()
return "web_search", {"query": query}
return None, {}
# ========== 具体工具实现 ==========
def get_weather(city="北京"):
"""模拟天气查询"""
mock_data = {
"北京": {"temp": 22, "condition": "晴"},
"上海": {"temp": 25, "condition": "多云"},
"广州": {"temp": 30, "condition": "小雨"},
}
data = mock_data.get(city, {"temp": 20, "condition": "未知"})
return f"{city}当前天气:{data['condition']},温度 {data['temp']}°C"
def get_time():
"""获取当前时间"""
now = datetime.now()
return f"当前时间:{now.strftime('%Y年%m月%d日 %H:%M:%S')}"
def calculator(a, b, op="+"):
"""简单计算器"""
if op == "+":
return f"{a} + {b} = {a + b}"
elif op == "-":
return f"{a} - {b} = {a - b}"
elif op == "*":
return f"{a} × {b} = {a * b}"
elif op == "/":
return f"{a} ÷ {b} = {a / b:.2f}" if b != 0 else "错误:除数不能为0"
return "不支持的操作"
def web_search(query):
"""模拟网络搜索"""
return f"搜索结果:找到关于'{query}'的约 1,234,567 条结果(模拟数据)"
# ========== 主程序 ==========
if __name__ == "__main__":
# 1. 注册工具
registry = ToolRegistry()
registry.register("get_weather", "查询指定城市的天气", get_weather)
registry.register("get_time", "获取当前时间", get_time)
registry.register("calculator", "进行数学计算", calculator)
registry.register("web_search", "搜索网络信息", web_search)
print("📋 已注册工具:")
for name, desc in registry.list_tools().items():
print(f" • {name}: {desc}")
# 2. 模拟用户请求
test_inputs = [
"北京今天天气怎么样?",
"现在几点了?",
"帮我计算 15 加 27",
"搜索一下人工智能",
]
print("\n" + "=" * 50)
for user_input in test_inputs:
print(f"\n👤 用户:{user_input}")
# 3. AI决策(识别意图)
tool_name, params = ai_decide(user_input, registry.list_tools())
if tool_name:
# 4. 执行工具
tool = registry.get_tool(tool_name)
result = tool["function"](**params)
print(f"🤖 AI决定调用工具:{tool_name}")
print(f"📤 工具返回:{result}")
else:
print("🤖 AI:我不确定如何帮你,请尝试其他说法。")
运行结果
📋 已注册工具:
• get_weather: 查询指定城市的天气
• get_time: 获取当前时间
• calculator: 进行数学计算
• web_search: 搜索网络信息
==================================================
👤 用户:北京今天天气怎么样?
🤖 AI决定调用工具:get_weather
📤 工具返回:北京当前天气:晴,温度 22°C
👤 用户:现在几点了?
🤖 AI决定调用工具:get_time
📤 工具返回:当前时间:2024年01月15日 14:32:18
👤 用户:帮我计算 15 加 27
🤖 AI决定调用工具:calculator
📤 工具返回:15 + 27 = 42
👤 用户:搜索一下人工智能
🤖 AI决定调用工具:web_search
📤 工具返回:搜索结果:找到关于'人工智能'的约 1,234,567 条结果(模拟数据)
这个示例展示了Function Calling的四个核心步骤:
- 工具注册:将可用工具注册到系统中,附带描述信息
- 意图识别:AI分析用户输入,决定是否需要调用工具
- 参数提取:从用户输入中提取工具所需的参数
- 执行返回:调用工具函数,将结果返回给用户
实际的大模型(如GPT-4)使用更复杂的语义理解来做意图识别,但核心流程与此相同。
本章小结
- 工具(Tools)是Agent调用外部功能的基本单元,弥补了LLM在获取实时信息、执行操作和复杂计算方面的不足。
- Function Calling是LLM调用工具的标准机制,通过工具注册→用户请求→LLM决策→执行返回→生成回答的流程实现。
- 技能(Skills)是工具、知识和提示词的组合,是面向特定任务的完整能力模块,比单个工具更高级、更专业。
- 工具是"扳手、锤子",技能是"修水管、修电路"——工具是原子化功能,技能是面向任务的组合方案。
练习题
-
以下哪项最适合作为Agent的"工具"而非"技能"?
A. 信息调研能力
B. Google搜索API
C. 数据分析能力
D. 文档写作能力答案:B。Google搜索API是一个具体的、原子化的功能单元,属于"工具"。其他选项都是面向任务的组合能力,属于"技能"。
-
Function Calling流程的正确顺序是什么?
A. 用户请求→工具注册→LLM决策→执行与返回→生成回答
B. 工具注册→用户请求→LLM决策→执行与返回→生成回答
C. LLM决策→工具注册→用户请求→执行与返回→生成回答
D. 用户请求→LLM决策→工具注册→执行与返回→生成回答答案:B。Function Calling的正确流程是:先注册可用工具,然后接收用户请求,LLM根据工具描述决策调用哪个工具,系统执行后返回结果,LLM基于结果生成最终回答。
-
技能与工具的核心区别是什么?
A. 技能比工具更简单
B. 技能是工具、知识和提示词的组合,面向特定任务
C. 工具只能用于搜索,技能可以用于任何场景
D. 技能和工具是完全相同的概念答案:B。技能是面向特定任务的完整能力模块,包含多个工具的使用策略和领域知识;工具是原子化的功能单元。