通义千问的 Function Call - demo学习

1、理解 Function Call

让大模型能调用外部工具、函数,而非仅靠自身知识库回答问题。

2、流程步骤:

用户提问→模型判断调用函数→执行自定义函数→模型基于函数结果生成回答

第一调用模型

让模型分析用户问题,判断是否需要调用函数,并返回调用函数指令

第二次调用模型

把自定义函数执行的结果传给模型,模型基于真实数据生成自然语言回答(比如 "大连当前温度 10 摄氏度,晴天,微风")

3、代码

python 复制代码
# 导入JSON模块:用于序列化/反序列化函数参数和返回结果
import json
# 导入操作系统模块:读取环境变量中的API密钥
import os
# 导入通义千问SDK核心模块
import dashscope

# 从环境变量读取API密钥并配置
dashscope.api_key = os.environ.get('DASHSCOPE_API_KEY')

# 定义天气查询函数:模拟返回指定城市的天气(核心业务函数)
def get_current_weather(location, unit="摄氏度"):
    # 初始化温度(默认-1表示未匹配城市)
    temperature = -1
    # 按城市匹配模拟温度
    if '大连' in location: temperature = 10
    if '上海' in location: temperature = 36
    if '深圳' in location: temperature = 37
    # 构造天气信息字典并转为JSON字符串返回(符合Function Call格式要求)
    return json.dumps({
        "location": location,
        "temperature": temperature,
        "unit": unit,
        "forecast": ["晴天", "微风"]
    })

# 封装模型调用函数
def call_qwen(messages):
    try:
        # 调用通义千问qwen-max模型,指定函数列表和返回格式
        return dashscope.Generation.call(
            model='qwen-max',
            messages=messages,
            functions=functions,
            result_format='message'  # 结构化消息格式,便于解析函数调用
        )
    except Exception as e:
        # 捕获异常并打印,返回None标识调用失败
        print(f"API调用异常: {str(e)}")
        return None

# 核心对话逻辑:实现"提问→判断调用函数→执行函数→生成最终回答"
def weather_qa():
    # 1. 初始化用户问题和消息上下文(大模型对话必须的格式:role+content)
    messages = [{"role": "user", "content": "大连的天气怎样"}]
    
    # 2. 第一次调用模型:判断是否需要调用函数
    response = call_qwen(messages)

    # 校验响应有效性,失败则直接返回
    if not response or not response.output:
        return "模型响应失败"

    # 提取模型返回的核心消息
    assistant_msg = response.output.choices[0].message

    # 将模型消息加入上下文(保证对话连贯性)
    messages.append(assistant_msg)

    # 3. 判断模型是否要求调用函数
    if hasattr(assistant_msg, 'function_call') and assistant_msg.function_call:
        # 解析函数调用参数(JSON字符串转字典)
        args = json.loads(assistant_msg.function_call['arguments'])
        # 执行天气查询函数,获取结果
        weather_result = get_current_weather(
            location=args.get('location'),
            unit=args.get('unit', '摄氏度')  # 设默认值,避免参数缺失
        )

        # 构造函数调用结果消息(必须按role=function格式)
        function_msg = {
            "role": "function",
            "name": assistant_msg.function_call['name'],
            "content": weather_result
        }
        # 将函数结果加入上下文
        messages.append(function_msg)
        
        # 4. 第二次调用模型:基于函数结果生成最终回答
        final_response = call_qwen(messages)
        if final_response and final_response.output:
            return final_response.output.choices[0].message.content
    
    # 若无需调用函数,直接返回模型初始回答
    return assistant_msg.content

# 定义函数调用描述(核心:告诉模型可调用的函数及参数规则)
functions = [{
    'name': 'get_current_weather',  # 必须和自定义函数名一致
    'description': '获取指定城市的当前天气',  # 改为中文描述,更适配中文提问
    'parameters': {
        'type': 'object',
        'properties': {
            'location': {
                'type': 'string',
                'description': '城市名称,例如:大连、上海'  # 中文示例更直观
            },
            'unit': {'type': 'string', 'enum': ['摄氏度', '华氏度']}  # 改为中文枚举值
        },
        'required': ['location']  # 必填参数:location
    }
}]

# 主程序入口
if __name__ == "__main__":
    # 执行问答逻辑并打印最终结果
    print("最终回答:", weather_qa())
相关推荐
KEEN的创享空间20 小时前
AI编程从0到1之10X提效(Vibe Coding 氛围式编码 )09篇
openai·ai编程
GPUStack20 小时前
Token 不再焦虑:用 GPUStack + OpenClaw 搭一个“无限用”的本地 AI 助手
ai·模型推理·gpustack·openclaw
AlienZHOU21 小时前
为 AI Agent 编写高质量 Skill:Claude 官方指南
agent·ai编程·claude
恋猫de小郭21 小时前
移动端开发稳了?AI 目前还无法取代客户端开发,小红书的论文告诉你数据
前端·flutter·ai编程
KaneLogger1 天前
【翻译】打造 Agent Skills 的最佳实践
agent·ai编程·claude
王小酱1 天前
Everything Claude Code 文档
openai·ai编程·aiops
雮尘1 天前
如何在非 Claude IDE (TARE、 Cursor、Antigravity 等)下使用 Agent Skills
前端·agent·ai编程
刘贺同学1 天前
Day12-龙虾哥打工日记:OpenClaw 子 Agent 到底看到了什么?
aigc·ai编程
程序员鱼皮1 天前
离大谱,我竟然在 VS Code 里做了个视频!
github·aigc·ai编程