大模型在面对实时性问题、数学计算等问题时可能效果不佳。您可以使用 Function Calling 功能,通过引入外部工具,使得大模型可以与外部世界进行交互。
当前支持通义千问的大语言模型。支持的模型为: 建议您优先选择通义千问-Plus,它在效果、速度和成本上相对均衡。 如果您对响应的速度与成本控制有较高要求,商业版模型建议使用通义千问-Turbo系列,开源版模型建议使用Qwen2.5 系列的小参数模型; 如果您对响应的准确率有较高要求,商业版模型建议使用通义千问-Max系列,开源版模型建议使用 qwen2.5-72b-instruct 模型。 如果直接向通义千问 API 提问“阿里云最近有什么新闻?”,大模型并不能准确回答: 如果这个问题需要人类帮助大模型来解决,那么一个有效的操作步骤为: 选择工具 由于问题是关于实时新闻的,打开浏览器工具; 提取参数 由于提问的问题是“阿里云最近有什么新闻?”,用浏览器输入框查询“阿里云新闻”; 运行工具 浏览器返回了许多网页,如“阿里云成为总台《2025年春节联欢晚会》云计算AI独家合作伙伴”等; 将工具的输出提供给大模型 将网页内容输入到提示词对通义千问 API 进行提问:“这是查询到的信息:阿里云成为总台《2025年春节联欢晚会》云计算AI独家合作伙伴......。请总结并回答:阿里云最近有什么新闻?”由于向大模型提供了足够的参考信息,可以得到类似的回复: 大模型此时可以回答关于实时新闻的问题了,然而这个过程需要人的参与(选择工具、提取参数、运行工具),无法实现自动化运行的效果。 Function Calling(工具调用)可以自动化完成以上流程,在接收到提问后可以自动选择工具、提取参数、运行工具并总结工具的输出。效果对比如下所示: 已关闭 function calling 工作流程示意图如下所示:支持的模型
暂不支持通义千问多模态模型。
概述
我无法提供实时信息,因为我的数据只更新到2021年。
阿里云最近的重要新闻是它成为了中央广播电视总台《2025年春节联欢晚会》的云计算AI独家合作伙伴。
...
这些信息表明,阿里云不仅在技术基础设施方面具有优势,而且也在积极探索如何将AI技术应用于大型文化活动中,以创造新的用户体验。
以上组件仅供您参考,并未真实发送请求。
您需要已 获取API Key并 配置API Key到环境变量。如果通过 OpenAI SDK 或 DashScope SDK 进行调用,需要 安装SDK。如果您是子业务空间的成员,请确保超级管理员已为该业务空间进行 模型授权操作。 本部分以 OpenAI 兼容调用方式为例,向您分步骤介绍 Function Calling 的详细用法,备选的工具为天气查询与时间查询。 DashScope OpenAI 兼容 工具是连接大模型与外部世界的桥梁,它是实现 Function Calling 的关键,您首先需要对工具进行定义。 您需要定义两个工具函数:天气查询工具与时间查询工具。 天气查询工具 天气查询工具接收 时间查询工具 时间查询工具不需要输入参数。工具的输出为字符串,格式为: Python Node.js 运行工具后,得到输出: 人类在选择工具之前,需要对工具有全面的了解,包括工具的功能、何时使用以及输入参数等。大模型也需要这些信息才能更准确地选择工具。在使用 Function Calling 时,请根据以下的 JSON 格式提供工具信息。 对于天气查询工具来说,工具描述信息的格式如下: 在发起 Function Calling 前,您需要通过 Python Node.js 与直接向通义千问 API 提问类似,您同样需要维护一个 messages 数组来向大模型传入指令与上下文信息。发起 Function Calling 前,messages 数组需要包含 System Message 与 User Message。 尽管在创建 tools 数组时已经对工具的作用与何时使用工具进行了描述,但在 System Message 中强调何时调用工具通常会提高工具调用的准确率。在当前场景下,我们可以将 System Prompt 设置为: User Message 用于传入用户提问的问题。假设用户提问“上海天气”,此时的 messages 数组为: Python Node.js 在完成 tools 与 messages 的创建后,您可以参考以下代码发起 Function Calling,让大模型“决策”是否需要调用工具,如果需要,大模型会输出需要调用的工具函数与入参信息。 Python Node.js 大模型通过返回对象的 需要注意的是,如果提问的问题被大模型判断为无需使用工具,则不会返回 在Function Calling流程中,运行工具函数是将大模型的决策转化为实际操作的关键步骤。就像在天气查询工具输入“上海”来获取天气一样,您在得到工具函数以及函数的入参后,可以运行工具函数来得到工具的输出。 由于大模型只可以输出字符串格式的内容,因此在运行工具函数前,您需要针对字符串格式的工具函数与入参分别进行解析。 工具函数 您需要建立一个工具函数名称到工具函数实体的映射 入参 Function Calling 返回的入参为 JSON 字符串,您可以使用 JSON 字符串解析工具将其解析为 JSON 对象,提取出入参信息。 Python Node.js 运行以上代码可以得到如下输出: 您可以直接将工具输出作为最终的结果。如果您希望返回结果更符合人类语气,可以参见 大模型总结工具函数输出。 为了提升用户体验和减少等待时间,您可以使用流式输出快速获取所需调用的工具函数名称。其中: 工具函数名称:仅在第一个流式返回的对象中出现。 入参信息:以持续的流式方式输出。 流式输出方式能让您更灵活地处理 Function Calling 的结果。您可以参考以下代码,将发起 Function Calling修改为流式输出方式。 Python Node.js 从第一个返回的流式输出对象可以获得工具函数名称,入参信息则需要您进行拼接,拼接完成后再运行工具函数。 如果您需要使用大模型总结工具函数输出,添加的 Assistant Message 需要符合下方格式。 您需要对以下元素进行替换: 将 将入参信息拼接后,替换 将 上文中的问题“上海天气”只需经过一次工具调用即可得到准确回复,如果输入问题需要调用多次工具,如“四个直辖市的天气如何”或“杭州天气,以及现在几点了”,发起 Function Calling 后只会返回一个工具调用信息,以提问“四个直辖市的天气如何”为例: 返回结果中只有北京市的入参信息。为了解决这一问题,您可以在发起 Function Calling时,将请求参数 Python Node.js 在返回对象的 大模型生成内容具有不确定性,有时会选择错误的工具进行调用。如果您希望对于某一类问题,大模型能够采取制定好的工具选择策略(如强制使用某个工具、强制不使用工具),可以通过修改 强制使用某个工具 如果您希望对于某一类问题,Function Calling 能够强制调用某个工具,可以设定 假设当前场景中只包含天气查询的问题,您可以修改 function_calling 代码为: Python Node.js 无论输入什么问题,返回对象的工具函数都会是 强制不使用工具 如果您希望无论输入什么问题,Function Calling 都不会进行工具调用(返回对象中包含回复内容 假设当前场景中的问题均无需调用工具,您可以修改 function_calling 代码为: Python Node.js 在发起 Function Calling 时,您需要提供 tools 和 messages 参数。输入内容的计费不仅包含 messages 的 Token,还包括 tools 参数中工具描述信息转化后的 Token。 OpenAI兼容 DashScope 您可以通过OpenAI SDK或OpenAI兼容的HTTP方式调用通义千问模型,体验Function Call的功能。 Python Node.js HTTP 当输入: 以下是发起Function Call流程(模型的第一轮调用)时模型的返回信息。当输入“杭州天气”时,模型会返回tool_calls参数;当输入“你好”时,模型判断无需调用工具,模型不会返回tool_calls参数。 输入:杭州天气 输入:你好 如果模型调用失败并返回报错信息,请参见错误信息进行解决。前提条件
如何使用
如果您使用 DashScope SDK,或需要直接获取完整代码,请点击下表的对应位置。
1. 定义工具
1.1. 定义工具函数
arguments
参数,arguments
格式为{"location": "查询的地点"}
。工具的输出为字符串,格式为:“{位置}今天是{天气}。”
。为了便于演示,此处定义的天气查询工具并不真正查询天气,会从晴天、多云、雨天随机选择。在您的实际业务中可以使用如高德天气查询等工具进行替换。
“当前时间:{查询到的时间}。”
。如果您使用 Node.js,请使用以下命令安装获取时间的工具包 date-fns:
npm install date-fns
## 步骤1:定义工具函数# 添加导入random模块import randomfrom datetime import datetime# 模拟天气查询工具。返回结果示例:“北京今天是雨天。”def get_current_weather(arguments): # 定义备选的天气条件列表
weather_conditions = ["晴天", "多云", "雨天"] # 随机选择一个天气条件
random_weather = random.choice(weather_conditions) # 从 JSON 中提取位置信息
location = arguments["location"] # 返回格式化的天气信息
return f"{location}今天是{random_weather}。"# 查询当前时间的工具。返回结果示例:“当前时间:2024-04-15 17:15:18。“def get_current_time(): # 获取当前日期和时间
current_datetime = datetime.now() # 格式化当前日期和时间
formatted_time = current_datetime.strftime('%Y-%m-%d %H:%M:%S') # 返回格式化后的当前时间
return f"当前时间:{formatted_time}。"# 测试工具函数并输出结果,运行后续步骤时可以去掉以下四句测试代码print("测试工具输出:")print(get_current_weather({"location": "上海"}))print(get_current_time())print("\n")
测试工具输出:
上海今天是多云。
当前时间:2025-01-08 20:21:45。
1.2 创建 tools 数组
type
字段固定为"function"
;function
字段为 Object 类型;type
字段固定为"object"
;properties
字段描述了入参的名称、数据类型与描述,为 Object 类型,Key 值为入参的名称,Value 值为入参的数据类型与描述;required
字段指定哪些参数为必填项,为 Array 类型。name
字段为自定义的工具函数名称,建议使用与函数相同的名称,如get_current_weather
或get_current_time
;description
字段是对工具函数功能的描述,大模型会参考该字段来选择是否使用该工具函数。parameters
字段是对工具函数入参的描述,类型是 Object ,大模型会参考该字段来进行入参的提取。如果工具函数不需要输入参数,则无需指定parameters
参数。{
"type": "function",
"function": {
"name": "get_current_weather",
"description": "当你想查询指定城市的天气时非常有用。",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "城市或县区,比如北京市、杭州市、余杭区等。",
}
},
"required": ["location"]
}
}}
tools
参数传入工具的描述信息。tools
为 JSON Array 类型,Array 中的元素为创建好的工具描述信息。tools 参数在发起 Function Calling时进行指定。
# 请将以下代码粘贴到步骤1代码后## 步骤2:创建 tools 数组tools = [
{ "type": "function", "function": { "name": "get_current_time", "description": "当你想知道现在的时间时非常有用。",
}
},
{ "type": "function", "function": { "name": "get_current_weather", "description": "当你想查询指定城市的天气时非常有用。", "parameters": { "type": "object", "properties": { "location": { "type": "string", "description": "城市或县区,比如北京市、杭州市、余杭区等。",
}
}, "required": ["location"]
}
}
}
]
tool_name = [tool["function"]["name"] for tool in tools]print(f"创建了{len(tools)}个工具,为:{tool_name}\n")
2. 创建messages数组
System Message
你是一个很有帮助的助手。如果用户提问关于天气的问题,请调用 ‘get_current_weather’ 函数;
如果用户提问关于时间的问题,请调用‘get_current_time’函数。
请以友好的语气回答问题。
User Message
# 步骤3:创建messages数组# 请将以下代码粘贴到步骤2 代码后messages = [
{ "role": "system", "content": """你是一个很有帮助的助手。如果用户提问关于天气的问题,请调用 ‘get_current_weather’ 函数;
如果用户提问关于时间的问题,请调用‘get_current_time’函数。
请以友好的语气回答问题。""",
},
{ "role": "user", "content": "上海天气"
}
]print("messages 数组创建完成\n")
3. 发起 Function Calling
# 步骤4:发起 function calling# 请将以下代码粘贴到步骤3 代码后from openai import OpenAIimport os
client = OpenAI( # 若没有配置环境变量,请用百炼API Key将下行替换为:api_key="sk-xxx",
api_key=os.getenv("DASHSCOPE_API_KEY"),
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
)def function_calling():
completion = client.chat.completions.create(
model="qwen-plus", # 此处以qwen-plus为例,可按需更换模型名称。模型列表:https://help.aliyun.com/zh/model-studio/getting-started/models
messages=messages,
tools=tools
) print("返回对象:") print(completion.choices[0].message.model_dump_json()) print("\n") return completionprint("正在发起function calling...")
completion = function_calling()
tool_calls
参数,指定需要使用的工具函数名称为:"get_current_weather"
,并指定函数的入参为:"{\"location\": \"上海\"}"
。{
"content": "",
"refusal": null,
"role": "assistant",
"audio": null,
"function_call": null,
"tool_calls": [
{
"id": "call_6596dafa2a6a46f7a217da",
"function": {
"arguments": "{\"location\": \"上海\"}",
"name": "get_current_weather"
},
"type": "function",
"index": 0
}
]}
tool_calls
参数,并会通过content
参数直接进行回复。在输入“你好”时,tool_calls
参数为空,返回对象格式为:{
"content": "你好!有什么可以帮助你的吗?如果你有关于天气或者时间的问题,我特别擅长回答。",
"refusal": null,
"role": "assistant",
"audio": null,
"function_call": null,
"tool_calls": null}
如果没有返回
tool_calls
参数,您的程序可以在此处直接返回 content
字段,无需运行以下步骤。如果您希望每次发起 Function Calling 后大模型都可以选择工具,请参见:强制工具调用。
4. 运行工具函数
运行工具函数的过程由您的计算环境而非大模型来完成。
function_mapper
,将返回的工具函数字符串映射到工具函数实体;# 步骤5:运行工具函数# 请将以下代码粘贴到步骤4 代码后import jsonprint("正在执行工具函数...")# 从返回的结果中获取函数名称和入参function_name = completion.choices[0].message.tool_calls[0].function.name
arguments_string = completion.choices[0].message.tool_calls[0].function.arguments# 使用json模块解析参数字符串arguments = json.loads(arguments_string)# 创建一个函数映射表function_mapper = { "get_current_weather": get_current_weather, "get_current_time": get_current_time
}# 获取函数实体function = function_mapper[function_name]# 如果入参为空,则直接调用函数if arguments == {}:
function_output = function()# 否则,传入参数后调用函数else:
function_output = function(arguments)# 打印工具的输出print(f"工具函数输出:{function_output}\n")
上海今天是多云。
5. 大模型总结工具函数输出(可选)
进阶用法
流式输出
def function_calling():
completion = client.chat.completions.create(
model="qwen-plus",
messages=messages,
tools=tools,
stream=True
) for chunk in completion: print(chunk.model_dump_json())
function_calling()
{"id":"chatcmpl-3f8155c3-e96f-95bc-a2a6-8e48537a0893","choices":[{"delta":{"content":null,"function_call":null,"refusal":null,"role":"assistant","tool_calls":[{"index":0,"id":"call_5507104cabae4f64a0fdd3","function":{"arguments":"{\"location\":","name":"get_current_weather"},"type":"function"}]},"finish_reason":null,"index":0,"logprobs":null}],"created":1736251532,"model":"qwen-plus","object":"chat.completion.chunk","service_tier":null,"system_fingerprint":null,"usage":null}{"id":"chatcmpl-3f8155c3-e96f-95bc-a2a6-8e48537a0893","choices":[{"delta":{"content":null,"function_call":null,"refusal":null,"role":null,"tool_calls":[{"index":0,"id":"","function":{"arguments":" \"上海\"}","name":""},"type":"function"}]},"finish_reason":null,"index":0,"logprobs":null}],"created":1736251532,"model":"qwen-plus","object":"chat.completion.chunk","service_tier":null,"system_fingerprint":null,"usage":null}{"id":"chatcmpl-3f8155c3-e96f-95bc-a2a6-8e48537a0893","choices":[{"delta":{"content":null,"function_call":null,"refusal":null,"role":null,"tool_calls":[{"index":0,"id":"","function":{"arguments":null,"name":null},"type":"function"}]},"finish_reason":"tool_calls","index":0,"logprobs":null}],"created":1736251532,"model":"qwen-plus","object":"chat.completion.chunk","service_tier":null,"system_fingerprint":null,"usage":null}
{
"content": "",
"refusal": None,
"role": "assistant",
"audio": None,
"function_call": None,
"tool_calls": [
{
"id": "call_xxx",
"function": {
"arguments": '{"location": "上海"}',
"name": "get_current_weather",
},
"type": "function",
"index": 0,
}
],}
id
tool_calls
的id
替换为第一个返回的流式输出对象中的choices[0].delta.tool_calls[0].id
;arguments
tool_calls
的arguments
;name
tool_calls
的name
替换为第一个返回的流式输出对象中的choices[0].delta.tool_calls[0].function.name
。指定工具调用方式
并行工具调用
{
"content": "",
"refusal": null,
"role": "assistant",
"audio": null,
"function_call": null,
"tool_calls": [
{
"id": "call_61a2bbd82a8042289f1ff2",
"function": {
"arguments": "{\"location\": \"北京市\"}",
"name": "get_current_weather"
},
"type": "function",
"index": 0
}
]}
parallel_tool_calls
设置为true
,这样返回对象中将包含所有需要调用的工具函数与入参信息。def function_calling():
completion = client.chat.completions.create(
model="qwen-plus", # 模型列表:https://help.aliyun.com/zh/model-studio/getting-started/models
messages=messages,
tools=tools, # 新增参数
parallel_tool_calls=True
) print("返回对象:") print(completion.choices[0].message.model_dump_json()) print("\n") return completionprint("正在发起function calling...")
completion = function_calling()
tool_calls
数组中包含了四个直辖市的入参信息:{
"content": "",
"role": "assistant",
"tool_calls": [
{
"function": {
"name": "get_current_weather",
"arguments": "{\"location\": \"北京市\"}"
},
"index": 0,
"id": "call_c2d8a3a24c4d4929b26ae2",
"type": "function"
},
{
"function": {
"name": "get_current_weather",
"arguments": "{\"location\": \"天津市\"}"
},
"index": 1,
"id": "call_dc7f2f678f1944da9194cd",
"type": "function"
},
{
"function": {
"name": "get_current_weather",
"arguments": "{\"location\": \"上海市\"}"
},
"index": 2,
"id": "call_55c95dd718d94d9789c7c0",
"type": "function"
},
{
"function": {
"name": "get_current_weather",
"arguments": "{\"location\": \"重庆市\"}"
},
"index": 3,
"id": "call_98a0cc7fded64b3ba88251",
"type": "function"
}
]}
强制工具调用
tool_choice
参数来强制指定工具调用的策略。tool_choice
参数的默认值为"auto"
,表示由大模型自主判断如何进行工具调用。如果需要 大模型总结工具函数输出,请在发起总结的请求时将
tool_choice
参数去除,否则大模型 API 仍会返回工具调用信息。tool_choice
参数为{"type": "function", "function": {"name": "the_function_to_call"}}
,大模型将不参与工具的选择,只参与输入参数的选择。def function_calling():
completion = client.chat.completions.create(
model="qwen-plus",
messages=messages,
tools=tools,
tool_choice={"type": "function", "function": {"name": "get_current_weather"}}
) print(completion.model_dump_json())
function_calling()
get_current_weather
。使用该策略前请确保问题与选择的工具相关,否则可能返回不符合预期的结果。
content
而tool_calls
参数为空),可以设定tool_choice
参数为"none"
,或不传入tools
参数,Function Calling 返回的tool_calls
参数将始终为空。def function_calling():
completion = client.chat.completions.create(
model="qwen-plus",
messages=messages,
tools=tools,
tool_choice="none"
) print(completion.model_dump_json())
function_calling()
如何计费
完整代码
示例代码
from openai import OpenAIfrom datetime import datetimeimport jsonimport osimport random
client = OpenAI( # 若没有配置环境变量,请用百炼API Key将下行替换为:api_key="sk-xxx",
api_key=os.getenv("DASHSCOPE_API_KEY"),
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1", # 填写DashScope SDK的base_url)# 定义工具列表,模型在选择使用哪个工具时会参考工具的name和descriptiontools = [ # 工具1 获取当前时刻的时间
{ "type": "function", "function": { "name": "get_current_time", "description": "当你想知道现在的时间时非常有用。", # 因为获取当前时间无需输入参数,因此parameters为空字典
"parameters": {}
}
},
# 工具2 获取指定城市的天气
{ "type": "function", "function": { "name": "get_current_weather", "description": "当你想查询指定城市的天气时非常有用。", "parameters": {
"type": "object", "properties": { # 查询天气时需要提供位置,因此参数设置为location
"location": { "type": "string", "description": "城市或县区,比如北京市、杭州市、余杭区等。"
}
}
}, "required": [ "location"
]
}
}
]# 模拟天气查询工具。返回结果示例:“北京今天是雨天。”def get_current_weather(arguments): # 定义备选的天气条件列表
weather_conditions = ["晴天", "多云", "雨天"] # 随机选择一个天气条件
random_weather = random.choice(weather_conditions) # 从 JSON 中提取位置信息
location = arguments["location"] # 返回格式化的天气信息
return f"{location}今天是{random_weather}。"# 查询当前时间的工具。返回结果示例:“当前时间:2024-04-15 17:15:18。“def get_current_time(): # 获取当前日期和时间
current_datetime = datetime.now() # 格式化当前日期和时间
formatted_time = current_datetime.strftime('%Y-%m-%d %H:%M:%S') # 返回格式化后的当前时间
return f"当前时间:{formatted_time}。"# 封装模型响应函数def get_response(messages):
completion = client.chat.completions.create(
model="qwen-plus", # 模型列表:https://help.aliyun.com/zh/model-studio/getting-started/models
messages=messages,
tools=tools
) return completiondef call_with_messages(): print('\n')
messages = [
{ "content": input('请输入:'), # 提问示例:"现在几点了?" "一个小时后几点" "北京天气如何?"
"role": "user"
}
] print("-"*60) # 模型的第一轮调用
i = 1
first_response = get_response(messages)
assistant_output = first_response.choices[0].message print(f"\n第{i}轮大模型输出信息:{first_response}\n") if assistant_output.content is None:
assistant_output.content = ""
messages.append(assistant_output) # 如果不需要调用工具,则直接返回最终答案
if assistant_output.tool_calls == None: # 如果模型判断无需调用工具,则将assistant的回复直接打印出来,无需进行模型的第二轮调用
print(f"无需调用工具,我可以直接回复:{assistant_output.content}") return
# 如果需要调用工具,则进行模型的多轮调用,直到模型判断无需调用工具
while assistant_output.tool_calls != None: # 如果判断需要调用查询天气工具,则运行查询天气工具
tool_info = {"content": "","role": "tool", "tool_call_id": assistant_output.tool_calls[0].id} if assistant_output.tool_calls[0].function.name == "get_current_weather": # 提取位置参数信息
argumens = json.loads(assistant_output.tool_calls[0].function.arguments)
tool_info["content"] = get_current_weather(argumens) # 如果判断需要调用查询时间工具,则运行查询时间工具
elif assistant_output.tool_calls[0].function.name == 'get_current_time':
tool_info["content"] = get_current_time()
tool_output = tool_info["content"] print(f"工具输出信息:{tool_output}\n") print("-"*60)
messages.append(tool_info)
assistant_output = get_response(messages).choices[0].message if assistant_output.content is None:
assistant_output.content = ""
messages.append(assistant_output)
i += 1
print(f"第{i}轮大模型输出信息:{assistant_output}\n") print(f"最终答案:{assistant_output.content}")if __name__ == '__main__':
call_with_messages()
返回结果
几点了?
时,程序会进行如下输出:{
'id': 'chatcmpl-e2f045fd-2604-9cdb-bb61-37c805ecd15a',
'choices': [
{
'finish_reason': 'tool_calls',
'index': 0,
'logprobs': None,
'message': {
'content': '',
'role': 'assistant',
'function_call': None,
'tool_calls': [
{
'id': 'call_7a33ebc99d5342969f4868',
'function': {
'arguments': '{
"location": "杭州市"
}',
'name': 'get_current_weather' },
'type': 'function',
'index': 0
}
]
}
}
],
'created': 1726049697,
'model': 'qwen-max',
'object': 'chat.completion',
'service_tier': None,
'system_fingerprint': None,
'usage': {
'completion_tokens': 18,
'prompt_tokens': 217,
'total_tokens': 235
}}
错误码