对比原生 Function Calling(手搓)与Qwen-Agent(框架模式)在实现上的差异
·
通过高德天气接口这个具体案例,直观地对比原生 Function Calling(“手搓”模式)与 Qwen-Agent(框架模式)在实现上的巨大差异。
核心结论先行:
- Function Calling 是底层能力:你需要手动定义 JSON Schema、手动解析模型回复、手动运行代码、手动拼接历史记录再次请求模型。
- Qwen-Agent 是集成框架:它封装了上述所有过程。你只需要写好工具函数(Python代码),框架自动完成“定义-调用-反馈-总结”的全闭环。
场景背景
- 目标:查询北京的天气(adcode: 110000)。
- API:
https://restapi.amap.com/v3/weather/weatherInfo?city=110000&key=YOUR_KEY
1. 方式一:原生 Function Calling (手动挡)
在原生模式下,开发者是“保姆”,需要负责模型与外部世界交互的每一步。
代码实现逻辑
import json
import requests
from openai import OpenAI # 假设使用兼容 OpenAI 协议的 Qwen API
# 1. 【繁琐】手动定义工具的 JSON Schema
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "查询特定城市的天气情况",
"parameters": {
"type": "object",
"properties": {
"city_adcode": {
"type": "string",
"description": "城市编码,例如北京是110000"
}
},
"required": ["city_adcode"]
}
}
}
]
# 2. 编写实际执行函数
def get_weather(city_adcode):
key = "你的高德Key"
url = f"https://restapi.amap.com/v3/weather/weatherInfo?city={city_adcode}&key={key}"
resp = requests.get(url).json()
return json.dumps(resp)
# 3. 【繁琐】第一轮交互:发送请求
messages = [{"role": "user", "content": "帮我查一下北京的天气"}]
client = OpenAI(api_key="...", base_url="...")
response = client.chat.completions.create(
model="qwen-max",
messages=messages,
tools=tools
)
msg = response.choices[0].message
# 4. 【繁琐】手动解析与路由
if msg.tool_calls:
# 提取函数名和参数
func_name = msg.tool_calls[0].function.name
args = json.loads(msg.tool_calls[0].function.arguments)
if func_name == "get_weather":
# 5. 【繁琐】执行代码
tool_result = get_weather(args["city_adcode"])
# 6. 【繁琐】维护上下文:必须把中间步骤拼回去
messages.append(msg) # 添加模型的 tool_calls 消息
messages.append({ # 添加工具执行结果消息
"role": "tool",
"content": tool_result,
"tool_call_id": msg.tool_calls[0].id
})
# 7. 【繁琐】第二轮交互:将结果发回给模型生成最终答案
final_response = client.chat.completions.create(
model="qwen-max",
messages=messages,
tools=tools
)
print(final_response.choices[0].message.content)
原生模式的痛点
- Schema 编写累:必须手写详细的 JSON 结构,容易写错。
- 流程控制复杂:需要写
if判断、解析 JSON、手动维护messages列表(添加tool角色的消息)。 - 无状态:每次对话都要把之前的历史记录完整传回去。
2. 方式二:Qwen-Agent 实现 (自动挡)
Qwen-Agent 框架将“思考-执行-反馈”的循环(ReAct Loop)封装在内部。
代码实现逻辑
import urllib.parse
import requests
from qwen_agent.agents import Assistant
from qwen_agent.tools.base import BaseTool, register_tool
# 1. 【简化】定义工具类
# Qwen-Agent 会自动读取类名、docstring 和 parameters 生成 Schema
@register_tool('get_weather')
class AmapWeather(BaseTool):
description = '查询特定城市的天气情况'
parameters = [{
'name': 'city_adcode',
'type': 'string',
'description': '城市编码,例如北京是110000',
'required': True
}]
def call(self, params: str, **kwargs):
# 框架自动处理了参数解析,这里直接写业务逻辑
import json
params = json.loads(params)
city_adcode = params['city_adcode']
key = "你的高德Key"
url = f"https://restapi.amap.com/v3/weather/weatherInfo?city={city_adcode}&key={key}"
resp = requests.get(url).json()
return resp
# 2. 【简化】初始化 Agent
bot = Assistant(
llm={'model': 'qwen-max'},
function_list=['get_weather'], # 直接注册工具
name='天气助手'
)
# 3. 【简化】一键运行
# 框架自动完成:调用模型 -> 发现需要工具 -> 执行 call -> 结果回传 -> 生成最终回复
messages = [{'role': 'user', 'content': '帮我查一下北京的天气'}]
for response in bot.run(messages=messages):
print(response)
3. 详细对比:Qwen-Agent 到底简化了什么?
| 维度 | 原生 Function Calling (手动挡) | Qwen-Agent (自动挡) | Qwen-Agent 简化的具体内容 |
|---|---|---|---|
| 工具定义 (Schema) | 手动编写 JSON 开发者必须精通 JSON Schema 规范,且与执行代码分离,容易不一致。 |
Python 类/函数映射 通过 Python 类属性、Type Hint 或 Docstring 自动生成 JSON Schema。 |
自动生成 Schema:将 Python 代码逻辑直接转化为模型能懂的定义。 |
| 执行流程 (Execution) | 手动闭环 (While Loop) 请求 -> 解析 -> 执行 -> 拼接 -> 再请求。开发者要写死循环来处理多步调用。 |
全自动闭环bot.run() 内部自动处理多轮对话和工具调用。 |
托管 ReAct 循环:隐藏了“模型调用工具”到“工具返回结果”中间的复杂握手过程。 |
| 结果解析 (Parsing) | 手动解析字符串 需要处理 msg.tool_calls,从 JSON 字符串中 json.loads 参数,还要处理解析报错。 |
自动注入参数 框架解析好参数后,直接传给 call 方法的变量。 |
自动参数绑定:不需要写代码去提取 JSON 里的字段。 |
| 历史管理 (Memory) | 手动拼接 必须严格按照 user -> assistant(tool_calls) -> tool 的顺序维护消息列表。 |
自动维护 Agent 内部维护 Session,自动记录工具的调用历史和结果。 |
上下文托管:不需要开发者操心消息列表的拼接顺序和格式。 |
总结
- Function Calling 像是在买菜:你要自己挑选食材(写Schema),自己洗菜切菜(解析参数),自己炒菜(执行代码),最后自己端上桌(拼接消息)。
- Qwen-Agent 像是点外卖:你只需要提供餐厅菜单(定义工具类),然后告诉骑手(Agent)你想吃什么,剩下的所有环节框架自动搞定,直接给你送到面前。

更多推荐



所有评论(0)