通过高德天气接口这个具体案例,直观地对比原生 Function Calling(“手搓”模式)与 Qwen-Agent(框架模式)在实现上的巨大差异。

核心结论先行

  • Function Calling 是底层能力:你需要手动定义 JSON Schema、手动解析模型回复、手动运行代码、手动拼接历史记录再次请求模型。
  • Qwen-Agent 是集成框架:它封装了上述所有过程。你只需要写好工具函数(Python代码),框架自动完成“定义-调用-反馈-总结”的全闭环。

场景背景

  • 目标:查询北京的天气(adcode: 110000)。
  • APIhttps://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)
原生模式的痛点
  1. Schema 编写累:必须手写详细的 JSON 结构,容易写错。
  2. 流程控制复杂:需要写 if 判断、解析 JSON、手动维护 messages 列表(添加 tool 角色的消息)。
  3. 无状态:每次对话都要把之前的历史记录完整传回去。

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)你想吃什么,剩下的所有环节框架自动搞定,直接给你送到面前。

在这里插入图片描述

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐