【大模型实战篇】基于大模型GLM的Function Call实践
1. 背景
大模型的函数调用功能能够提升模型的推理能力,并支持执行多种外部操作场景,如信息检索、数据库查询、知识图谱搜索与推理,以及调用操作系统工具等。这一功能实现了模型与外部函数库的联动。函数调用依赖于内容生成API中的一个可选参数 tools
,用于向模型提供函数定义。通过 tools
参数,模型可以根据提供的规范生成相应的函数调用参数。然而,API本身并不实际执行这些函数调用,而是返回供调用所需的参数。开发者可根据模型输出的参数,在具体应用中完成函数调用的执行。我们将会使用chat completion接口向模型描述外部函数,并与模型交互,触发模型对函数的调用,进而使用模型生成的结果调用外部函数。
特别关注:chat.completions
提供了一种支持模型推理与外部功能交互的能力。通过指定functions
参数,开发者可以定义一组函数接口,包括函数的名称、输入参数和规范。模型根据上下文生成符合这些定义的参数,chat.completions
本身并不实际执行这些函数,而是返回所需的调用参数。
2. 描述外部函数
假设需要创建一个具备查询学生信息的机器人,定义两个外部函数供模型选择调用:
查询班级中身高最高的同学姓名:get_student_num(class_id:str, feature:str)
查询某学生的某门课程期末成绩:get_student_grade(student_id:str, course:str)
为了向模型描述外部函数库,需要向 tools 字段传入可以调用的函数列表。参数如下表:
description :说明函数方法的用途。
type :定义 JSON 数据的数据类型约束。
properties:一个Object,其中的每个属性代表要定义的 JSON 数据中的一个键。
required:指定哪些属性在数据中必须被包含。
enum:如果一个属性是枚举类型,则此字段应当设置为枚举值的数组。
完整的tools字段设置为:
tools = [{"type": "function","function": {"name": "get_student_num","description": "根据班级id和特征描述,查找对应信息的学生姓名","parameters": {"type": "object","properties": {"class_id": {"description": "班级id","type": "string"},"feature": {"description": "学生特征","type": "string"}},"required": ["class_id", "feature"]},} },{"type": "function","function": {"name": "get_student_grade","description": "根据学生id和对应课程信息,查找该生对应课程的成绩","parameters": {"type": "object","properties": {"student_id": {"description": "学生id","type": "string"},"course": {"description": "课程","type": "string"}},"required": ["student_id", "course"]},} }, ]
在 tools 参数中,如果填写了 functions 参数,则默认情况下模型将决定何时使用其中一个函数。
3. Function Call 流程实践
以具备查询学生信息功能的聊天机器人完成函数调用。
初始化函数定义和client:
from zhipuai import ZhipuAI
client = ZhipuAI(api_key="") # 替换成你自己的api_key
messages = []
tools = [{"type": "function","function": {"name": "get_student_num","description": "根据班级id和特征描述,查找对应信息的学生姓名","parameters": {"type": "object","properties": {"class_id": {"description": "班级id","type": "string"},"feature": {"description": "学生特征","type": "string"}},"required": ["class_id", "feature"]},} },{"type": "function","function": {"name": "get_student_grade","description": "根据学生id和对应课程信息,查找该生对应课程的成绩","parameters": {"type": "object","properties": {"student_id": {"description": "学生id","type": "string"},"course": {"description": "课程","type": "string"}},"required": ["student_id", "course"]},} },
]
查询班级id为12345的班级女生的数量。向模型提供这个信息:
messages = []
messages.append({"role": "user", "content": "帮我查询班级id为12345的班级中女生的数量"})
response = client.chat.completions.create(model="glm-4", # 填写需要调用的模型名称messages=messages,tools=tools,)
print(response.choices[0].message)
messages.append(response.choices[0].message.model_dump())
查询学生id为s58523的语文成绩:
messages.append({"role": "user", "content": "帮我查询学生id为s58523的语文成绩"})
response = client.chat.completions.create(model="glm-4", # 填写需要调用的模型名称messages=messages,tools=tools,
)
print(response.choices[0].message)
messages.append(response.choices[0].message.model_dump())
定义parse_function_call(response, messages)
def get_student_num(class_id:str, feature:str):class_student_info = {"12345":{"女生" : "28","男生" : "22",},"254313":{"女生" : "20","男生" : "30",}}return { "student":class_student_info[class_id][feature] }def get_student_grade(student_id:str , course:str):course_grade_info = {"s58292":{"数学" : "149","语文" : "125",},"s58523":{"数学" : "123","语文" : "140",}}return { "grade":course_grade_info[student_id][course] }def parse_function_call(model_response,messages):# 处理函数调用结果,根据模型返回参数,调用对应的函数。# 调用函数返回结果后构造tool message,再次调用模型,将函数结果输入模型# 模型会将函数调用结果以自然语言格式返回给用户。if model_response.choices[0].message.tool_calls:tool_call = model_response.choices[0].message.tool_calls[0]args = tool_call.function.argumentsfunction_result = {}if tool_call.function.name == "get_student_num":function_result = get_student_num(**json.loads(args))if tool_call.function.name == "get_student_grade":function_result = get_student_grade(**json.loads(args))messages.append({"role": "tool","content": f"{json.dumps(function_result)}","tool_call_id":tool_call.id})response = client.chat.completions.create(model="glm-4", # 填写需要调用的模型名称messages=messages,tools=tools,)print(response.choices[0].message)messages.append(response.choices[0].message.model_dump())
完整代码:
from zhipuai import ZhipuAI
import jsondef get_student_num(class_id:str, feature:str):class_student_info = {"12345":{"女生" : "28","男生" : "22",},"254313":{"女生" : "20","男生" : "30",}}return { "student":class_student_info[class_id][feature] }def get_student_grade(student_id:str , course:str):course_grade_info = {"s58292":{"数学" : "149","语文" : "125",},"s58523":{"数学" : "123","语文" : "140",}}return { "grade":course_grade_info[student_id][course] }def parse_function_call(model_response,messages):# 处理函数调用结果,根据模型返回参数,调用对应的函数。# 调用函数返回结果后构造tool message,再次调用模型,将函数结果输入模型# 模型会将函数调用结果以自然语言格式返回给用户。if model_response.choices[0].message.tool_calls:tool_call = model_response.choices[0].message.tool_calls[0]args = tool_call.function.argumentsfunction_result = {}if tool_call.function.name == "get_student_num":function_result = get_student_num(**json.loads(args))if tool_call.function.name == "get_student_grade":function_result = get_student_grade(**json.loads(args))messages.append({"role": "tool","content": f"{json.dumps(function_result)}","tool_call_id":tool_call.id})response = client.chat.completions.create(model="glm-4", # 填写需要调用的模型名称messages=messages,tools=tools,)print(response.choices[0].message)messages.append(response.choices[0].message.model_dump())client = ZhipuAI(api_key="")
tools = [{"type": "function","function": {"name": "get_student_num","description": "根据班级id和特征描述,查找对应的学生数量","parameters": {"type": "object","properties": {"class_id": {"description": "班级id","type": "string"},"feature": {"description": "学生特征","type": "string"}},"required": ["class_id", "feature"]},}},{"type": "function","function": {"name": "get_student_grade","description": "根据学生id和对应课程信息,查找该生对应课程的成绩","parameters": {"type": "object","properties": {"student_id": {"description": "学生id","type": "string"},"course": {"description": "课程","type": "string"}},"required": ["student_id", "course"]},}},
]messages = []
messages.append({"role": "user", "content": "帮我查询班级id为12345的班级中女生的数量"})
response = client.chat.completions.create(model="glm-4",messages=messages,tools=tools,)
print(response.choices[0].message)
messages.append(response.choices[0].message.model_dump())parse_function_call(response, messages)messages.append({"role": "user", "content": "帮我查询学生id为s58523的语文成绩"})
response = client.chat.completions.create(model="glm-4",messages=messages,tools=tools,
)
print(response.choices[0].message)
messages.append(response.choices[0].message.model_dump())parse_function_call(response, messages)
输出结果:
扩展阅读:
《全方位解读大模型》
4. 参考材料
【1】bigmodel:函数调用