【大模型实战篇】基于大模型GLM的Function Call实践

1. 背景

        大模型的函数调用功能能够提升模型的推理能力,并支持执行多种外部操作场景,如信息检索、数据库查询、知识图谱搜索与推理,以及调用操作系统工具等。这一功能实现了模型与外部函数库的联动。函数调用依赖于内容生成API中的一个可选参数 tools,用于向模型提供函数定义。通过 tools 参数,模型可以根据提供的规范生成相应的函数调用参数。然而,API本身并不实际执行这些函数调用,而是返回供调用所需的参数。开发者可根据模型输出的参数,在具体应用中完成函数调用的执行。我们将会使用chat completion接口向模型描述外部函数,并与模型交互,触发模型对函数的调用,进而使用模型生成的结果调用外部函数。

特别关注:chat.completions 提供了一种支持模型推理与外部功能交互的能力。通过指定functions 参数,开发者可以定义一组函数接口,包括函数的名称、输入参数和规范。模型根据上下文生成符合这些定义的参数,chat.completions 本身并不实际执行这些函数,而是返回所需的调用参数。

2. 描述外部函数

        假设需要创建一个具备查询学生信息的机器人,定义两个外部函数供模型选择调用:

  1. 查询班级中身高最高的同学姓名:get_student_num(class_id:str, feature:str)

  2. 查询某学生的某门课程期末成绩: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.arguments
        function_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 json

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.arguments
        function_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:函数调用

<think>嗯,用户现在问的是“大模型 function call”,也就是大模型如何调用函数。首先我需要理解“大模型”在这里指的是像GPT-4、PaLM这类大型语言模型。Function call可能指的是让这些模型在生成文本的过程中调用外部函数或工具,以完成更复杂的任务,比如获取实数据、进行计算或者访问数据库等。 接下来,我要回顾之前的对话历史。用户之前询问过DeepSeek Prompt,是关于如何优化提示工程来提升模型输出的。现在这个问题可能是在探索如何让大模型不仅仅是生成文本,还能与外部系统交互,执行具体功能。这可能涉及到模型的功能扩展和应用场景的拓展。 需要确定用户的具体需求。他们可能想知道大模型如何调用函数,比如在开发聊天机器人,让模型在回答用户问题调用天气API获取实数据。或者,他们可能对实现这种调用的技术细节感兴趣,比如API设计、模型训练方法等。 接下来,我应该分几个部分来介绍:首先定义什么是大模型function call,然后说明其工作原理,应用场景,常用方法,挑战与解决方案,最后结合实际例子,比如OpenAI的Function Calling功能,或者DeepSeek的可能实现方式。 需要注意的是,用户可能对技术细节有一定了解,但需要更系统的解释。因此,解释需要平衡技术术语和通俗语言,确保不同背景的读者都能理解。同,要避免过于冗长,但又要覆盖关键点,比如模型如何决定何调用函数、如何传递参数、如何处理返回结果等。 另外,用户可能关心实际应用中的问题,比如安全性、效率、错误处理等,这些也应该在回答中提到。例如,模型调用外部API的权限管理,错误回退机制,以及如何保证调用的准确性和可靠性。 最后,检查是否有遗漏的重要点,比如现有的框架或工具支持,如LangChain等库如何处理function call,或者企业级解决方案中的最佳实践。确保回答全面且结构清晰,帮助用户全面理解大模型function call的概念和应用。</think>以下是关于**大模型 Function Call函数调用)**的详细介绍: --- ### **1. 核心概念** **大模型 Function Call** 指大型语言模型(如GPT-4、PaLM等)通过调用外部函数或工具,完成文本生成之外的复杂任务(如计算、数据查询、API交互等)。其本质是让模型具备**“决策+调用”**能力,即: - **理解用户需求** → **决定是否需要调用函数** → **生成调用参数** → **整合外部结果生成最终回复**。 --- ### **2. 工作原理** 1. **任务识别**:模型分析用户输入,判断是否需要调用函数(例如“北京天气如何?”需调用天气API)。 2. **参数生成**:模型根据需求生成函数调用所需的参数(如间、地点、格式等)。 3. **执行函数**:系统调用外部工具或API,获取结果(如实天气数据)。 4. **结果整合**:模型将外部结果与自身生成内容结合,输出最终回答。 --- ### **3. 典型应用场景** - **实数据查询**:调用天气、股票、新闻等API。 - **复杂计算**:使用计算器、数据库或专业工具(如数学求解器)。 - **多模态扩展**:生成图像调用文生图模型(如DALL·E),或处理语音调用ASR(语音识别)。 - **自动化流程**:通过调用函数实现邮件发送、日程管理等功能。 --- ### **4. 实现方法** #### **a. 基于提示工程(Prompting)** - **显式指令**:要求模型返回函数调用格式(如JSON)。 ``` 用户:计算3的平方根。 系统:请以 { "function": "math_sqrt", "input": 3 } 格式返回调用需求。 ``` - **示例引导**:通过Few-Shot示例教会模型如何调用函数。 #### **b. 微调(Fine-tuning)** - 在训练数据中加入函数调用示例,让模型学习何调用、如何传参。 - 例如:OpenAI的Function Calling功能通过微调模型识别调用需求。 #### **c. 框架支持** - **LangChain**:通过`Tools`模块将大模型与外部函数连接。 - **OpenAI Function Calling**:直接通过API定义函数,模型自动生成调用请求。 ```python # OpenAI示例:定义函数并调用 functions = [{ "name": "get_current_weather", "parameters": {"location": {"type": "string"}} }] response = openai.ChatCompletion.create( model="gpt-3.5-turbo", messages=[{"role": "user", "content": "北京天气如何?"}], functions=functions ) ``` --- ### **5. 技术挑战与解决方案** | **挑战** | **解决方案** | |-------------------------|-----------------------------------------------------------------------------| | 模型误判调用需求 | 设置置信度阈值,或提供备用回复逻辑(如“是否需要查询实数据?”)。 | | 参数格式错误 | 后置校验逻辑(如JSON语法检查),或要求模型重新生成参数。 | | 外部工具响应延迟或失败 | 超重试机制,或返回降级结果(如“暂无法获取数据,以下是历史信息”)。 | | 安全风险(如敏感API调用)| 权限分级控制,仅允许白名单函数被调用。 | --- ### **6. 实例说明** **用户提问**: “帮我预订明天从北京到上海的高铁,下午出发。” **模型Function Call流程**: 1. **识别意图** → 调用“订票系统API”。 2. **生成参数** → `{出发地: "北京", 目的地: "上海", 日期: "2023-10-25", 段: "下午"}`。 3. **API返回结果** → 获取车次列表(如G123、G456)。 4. **整合回复** → “找到以下车次:G123(14:00)、G456(15:30),是否需要预订?” --- ### **7. 与提示工程的关系** - **互补性**:Function Call依赖提示工程引导模型生成调用请求,同扩展了模型能力边界。 - **差异**: - **提示工程**:优化模型自身的文本生成逻辑。 - **Function Call**:连接模型与外部工具,突破纯文本生成的局限。 --- ### **8. 企业级应用(如DeepSeek)** 若涉及特定厂商(如深度求索的DeepSeek-R1模型),其Function Call可能支持: - **私有化工具集成**:对接企业内部数据库或工具链。 - **领域定制化**:针对金融、医疗等场景预置专用函数库。 - **低代码配置**:通过可视化界面定义函数与调用规则。 --- 通过Function Call大模型从“文本生成器”升级为“智能代理”,成为连接用户需求与现实世界的桥梁。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

源泉的小广场

感谢大佬的支持和鼓励!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值