kimi API进阶-Function Calling打造专属你的“支小宝”AI生活管家
❝大家好,我是小智。支付宝近日推出App“支小宝”,依托百灵大模型,定位为AI生活管家。用户可通过对话享受公共出行、订票、点餐等服务,实现“你说我办”。它还能解答问题、推荐攻略、提供灵感、查询账单。利用场景感知,它可根据生活习惯及时间空间推荐专属服务。同时,“支小宝”也能畅聊新闻资讯、百科知识。

❝大模型最显著的特点是其理解和处理自然语言的能力。引入大模型可以显著提升用户体验。对于开发者而言,通过提示词调用大模型可以减少复杂逻辑代码的编写成本。实现类似“支小宝”这样的“AI生活助手”并不难,主要在于整合各类生活服务接口。通过解析用户提示词中的指令,提取请求参数,并调用相应的服务 API,就可以实现功能(如图所示)。

❝重难点在于如何让大模型在理解用户意图后有效调用外部 API。开发者在使用 API 调用大模型时常遇到的问题是,大模型无法利用外部工具或数据,从而限制了其推理能力的发挥。例如,我们希望大模型获取某城市未来几天的天气并根据此提出出行、穿衣或携带雨伞的建议。但由于大模型本身无法直接访问外部资源,它无法获取天气数据进行建议。

本文将以 Kimi 为例,探讨如何通过 API 的 tool_calls 特性来解决这些问题。
Function Calling是什么用一句话概括:方法(函数)调用!!
❝就是字面意思,调用大模型之外的API,从而赋予了大模型更多的能力。在请求大模型的时候同时携带一个函数列表,告诉大模型都有哪些函数可以调用。大模型在理解提示词的时候,会根据函数列表中每个函数的描述,判断需要调用哪些函数,再根据函数的请求参数描述返回正确的结构化数据。用户在拿到大模型返回的结果后,调用对应的函数并把结果添加到上下文中再次请求大模型。

Function Calling解决了哪些问题
-
获取实时性数据:通过调用有联网能力的外部函数,可以实现大模型获取实时性函数; -
与开发者已有的系统进行更紧密的集成:开发者提供函数列表,大模型判断使用哪个函数; -
稳定的返回结构化数据:通过函数入参参数描述,大模型可以稳定返回约定好的结构化数据。
Function Calling能力再升级
❝OpenAI 在 2023 年提供了 functions 参数以开启函数调用(即 function_call)功能。经过功能迭代,OpenAI 后续推出了工具调用(即 tool_calls)功能,并将 functions 参数标记为已废弃(deprecated),这意味着在后续的 API 迭代中,functions 参数随时可能被移除。
❝Kimi API 兼容了 OpenAI 的接口规范,我们可以使用 OpenAI 提供的 Python 或 NodeJS SDK 来调用和使用 Kimi 大模型。完整支持了工具调用(即 tool_calls)的能力,同时,由于 functions 已被废弃,Kimi API 不支持使用 functions 参数执行函数调用。
特性 | tool_calls | function_call |
---|---|---|
并行调用支持 | 支持并行调用,Kimi 大模型可以一次返回多个 tool_calls |
不支持并行调用,每次只能返回一个 function_call |
调用方式 | 可以使用并发的方式同时调用多个 tool_calls |
只能顺序调用,每次调用一个 function_call |
时间消耗 | 并行调用可以减少总体时间消耗 | 顺序调用可能导致总体时间消耗较高 |
Tokens 消耗 | 对于没有依赖关系的 tool_calls ,可能降低 Tokens 消耗 |
顺序调用可能会导致较高的 Tokens 消耗 |
实战(出行建议为例)接下来,我们以AI生活管家中的天气查询服务为例,实战tool_calls的使用。定义工具集
❝首先我们需要定义工具集,这个工具集用来告诉大模型我们都有哪些方法可以提供调用。以提示词“接下来一周我要去天津出差,查询天津接下来一周的天气信息,给我相关的出行建议”为例:
❝首先,提示词中并未提及具体是什么时间,而是“接下来一周”这么一个时间范围,由于大模型无法获取当前时间,所以我们首先需要定义一个方法为“get_now”用来获取当前时间。其次,我们拿到时间范围和地点后,再调用“get_weather”方法就可以获取天气信息了,最后把这些数据统一交给大模型,就可以获取用户想要获取的数据了。
如图:

❝其中每一个工具定义的“type”字段用来标明这个工具的类型是一个函数,目前为固定填写“function”。在“function”字段中,使用“name”定义函数的名称,“description”描述调用该函数的条件。函数定义的 parameters 部分应使用JSON Schema 描述。如果模型生成函数调用,它将使用此信息根据你提供的schema生成参数。
tools = [
{
"type": "function", # 约定的字段 type,目前支持 function 作为值
"function": { # 当 type 为 function 时,使用 function 字段定义具体的函数内容
"name": "get_now", # 函数的名称,请使用英文大小写字母、数据加上减号和下划线作为函数名称
"description": """
获取当前时间,当用户的提示词当中出现时间范围的词时,需要调用该方法用来获取当前的时间,
当用户输入要查询天气信息的时候,如果提示词中出现时间范围的信息,且没有指明具体的时间信息,调用该方法获取当前时间,
""", # 函数的介绍,在这里写上函数的具体作用以及使用场景,以便 Kimi 大模型能正确地选择使用哪些函数
}
},
{
"type": "function",
"function": {
"name": "get_weather",
"description": """
当用户查询天气信息的时候,如果提示词中出现了具体的地点,调用该方法,获取天气信息。
""",
"parameters": {
"type": "object",
"properties": {
"start_time": {
"type": "string",
"description": "查询天气的开始时间,格式应为 'YYYY-MM-DDTHH:MM:SS'。"
},
"end_time": {
"type": "string",
"description": "查询天气的结束时间,格式应为 'YYYY-MM-DDTHH:MM:SS'。"
},
"location": {
"type": "string",
"description": "查询天气的地点,例如:上海"
}
},
"required": ["start_time", "end_time"]
}
}
}
]
注册工具集在请求参数中添加“tools”参数。completion = client.chat.completions.create(
model="moonshot-v1-8k",
messages=messages,
temperature=0.3,
tools=tools, # <-- 我们通过 tools 参数,将定义好的 tools 提交给 Kimi 大模型
)
执行工具完整的代码如下:import json
from openai import OpenAI
client = OpenAI(
api_key="密钥",
base_url="https://api.moonshot.cn/v1",
)
tools = [
{
"type": "function", # 约定的字段 type,目前支持 function 作为值
"function": { # 当 type 为 function 时,使用 function 字段定义具体的函数内容
"name": "get_now", # 函数的名称,请使用英文大小写字母、数据加上减号和下划线作为函数名称
"description": """
获取当前时间,当用户的提示词当中出现时间范围的词时,需要调用该方法用来获取当前的时间,
当用户输入要查询天气信息的时候,如果提示词中出现时间范围的信息,且没有指明具体的时间信息,调用该方法获取当前时间,
""", # 函数的介绍,在这里写上函数的具体作用以及使用场景,以便 Kimi 大模型能正确地选择使用哪些函数
}
},
{
"type": "function",
"function": {
"name": "get_weather",
"description": """
当用户查询天气信息的时候,如果提示词中出现了具体的地点,调用该方法,获取天气信息。
""",
"parameters": {
"type": "object",
"properties": {
"start_time": {
"type": "string",
"description": "查询天气的开始时间,格式应为 'YYYY-MM-DDTHH:MM:SS'。"
},
"end_time": {
"type": "string",
"description": "查询天气的结束时间,格式应为 'YYYY-MM-DDTHH:MM:SS'。"
},
"location": {
"type": "string",
"description": "查询天气的地点,例如:上海"
}
},
"required": ["start_time", "end_time"]
}
}
}
]
def get_now(args):
# 返回格式化的当前时间
return datetime.now().strftime("%Y-%m-%d %H:%M:%S")
from datetime import datetime, timedelta
import random
def get_weather(query):
# 模拟调用天气 API,这里生成随机天气和温度。
weather_list = []
# 获取查询的时间范围和地点
start_time_str = query.get("start_time")
end_time_str = query.get("end_time")
location = query.get("location")
# 将时间字符串转换为 datetime 对象
start_time = datetime.fromisoformat(start_time_str)
end_time = datetime.fromisoformat(end_time_str)
current_time = start_time
# 定义天气类型和温度范围
weather_types = ["晴天", "多云", "阴天", "小雨", "大雨"]
temperature_range = (15, 35) # 温度范围从15°C到35°C
while current_time <= end_time:
weather_list.append({
"date": current_time.strftime("%Y-%m-%d"),
"location": location, # 包含地点信息
"weather": random.choice(weather_types),
"temperature": f"{random.randint(*temperature_range)}°C",
})
# 增加一天
current_time += timedelta(days=1)
return weather_list
tool_map = {
"get_now": get_now,
"get_weather": get_weather,
}
messages = [
{"role": "system",
"content": "你是 Kimi,由 Moonshot AI 提供的人工智能助手,你更擅长中文和英文的对话。你会为用户提供安全,有帮助,准确的回答。同时,你会拒绝一切涉及恐怖主义,种族歧视,黄色暴力等问题的回答。Moonshot AI 为专有名词,不可翻译成其他语言。"},
{"role": "user",
"content": '接下来一周我要去天津出差,查询天津接下来一周的天气信息,给我相关的出行建议'}
]
finish_reason = None
while finish_reason is None or finish_reason == "tool_calls":
completion = client.chat.completions.create(
model="moonshot-v1-8k",
messages=messages,
temperature=0.3,
tools=tools, # <-- 我们通过 tools 参数,将定义好的 tools 提交给 Kimi 大模型
)
print(completion.choices[0])
choice = completion.choices[0]
finish_reason = choice.finish_reason
if finish_reason == "tool_calls": # <-- 判断当前返回内容是否包含 tool_calls
messages.append(choice.message) # <-- 我们将 Kimi 大模型返回给我们的 assistant 消息也添加到上下文中,以便于下次请求时 Kimi 大模型能理解我们的诉求
for tool_call in choice.message.tool_calls: # <-- tool_calls 可能是多个,因此我们使用循环逐个执行
tool_call_name = tool_call.function.name
tool_call_arguments = json.loads(
tool_call.function.arguments) # <-- arguments 是序列化后的 JSON Object,我们需要使用 json.loads 反序列化一下
tool_function = tool_map[tool_call_name] # <-- 通过 tool_map 快速找到需要执行哪个函数
tool_result = tool_function(tool_call_arguments)
# 使用函数执行结果构造一个 role=tool 的 message,以此来向模型展示工具调用的结果;
# 注意,我们需要在 message 中提供 tool_call_id 和 name 字段,以便 Kimi 大模型
# 能正确匹配到对应的 tool_call。
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"name": tool_call_name,
"content": json.dumps(tool_result), # <-- 我们约定使用字符串格式向 Kimi 大模型提交工具调用结果,因此在这里使用 json.dumps 将执行结果序列化成字符串
})
else:
print(choice.message.content) # <-- 在这里,我们才将模型生成的回复返回给用户
执行结果:Choice(finish_reason='tool_calls', index=0, logprobs=None, message=ChatCompletionMessage(content='', refusal=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='get_now:0', function=Function(arguments='{}', name='get_now'), type='function', index=0)]))
Choice(finish_reason='tool_calls', index=0, logprobs=None, message=ChatCompletionMessage(content='', refusal=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='get_weather:0', function=Function(arguments='{
"start_time": "2024-09-08T00:00:00",
"end_time": "2024-09-15T00:00:00",
"location": "天津"
}', name='get_weather'), type='function', index=0)]))
Choice(finish_reason='stop', index=0, logprobs=None, message=ChatCompletionMessage(content='根据查询结果,天津接下来一周的天气情况如下:
- 2024年9月8日:多云,气温33°C
- 2024年9月9日:大雨,气温22°C
- 2024年9月10日:大雨,气温31°C
- 2024年9月11日:阴天,气温22°C
- 2024年9月12日:阴天,气温33°C
- 2024年9月13日:多云,气温19°C
- 2024年9月14日:晴天,气温35°C
- 2024年9月15日:晴天,气温21°C
出行建议:
1. 由于有几天会有大雨,建议携带雨具,如雨衣和雨伞。
2. 天气变化较大,建议携带适合不同天气的衣物,如雨衣、薄外套等。
3. 由于气温较高,注意防晒和补水,可以携带防晒霜和水杯。
4. 由于天气预报可能会有变化,建议出行前再次查看最新的天气预报。', refusal=None, role='assistant', function_call=None, tool_calls=None))
根据查询结果,天津接下来一周的天气情况如下:
- 2024年9月8日:多云,气温33°C
- 2024年9月9日:大雨,气温22°C
- 2024年9月10日:大雨,气温31°C
- 2024年9月11日:阴天,气温22°C
- 2024年9月12日:阴天,气温33°C
- 2024年9月13日:多云,气温19°C
- 2024年9月14日:晴天,气温35°C
- 2024年9月15日:晴天,气温21°C
出行建议:
1. 由于有几天会有大雨,建议携带雨具,如雨衣和雨伞。
2. 天气变化较大,建议携带适合不同天气的衣物,如雨衣、薄外套等。
3. 由于气温较高,注意防晒和补水,可以携带防晒霜和水杯。
4. 由于天气预报可能会有变化,建议出行前再次查看最新的天气预报。
总结
❝在本文中,我们通过讨论支付宝新推出的AI智能管家App的实现原理,探讨了如何利用Kimi API 的 tool_calls特性来解决大模型在理解用户意图后有效调用外部 API 的问题。相信通过阅读本文,你已经对API调用大模型有了更加深入的理解。希望今天的分享能为大家在AI路上赋能,觉得我的文章对你有帮助的话,请不要吝啬你的点赞、在看和转发。欢迎大家关注我的公众号小智AI指南。