一、什么是Function Call

2023年6月13日OpenAI公布了FunctionCall(函数调用)功能,该功能指的是在语言模型中集成外部功能或API的调用能力,这意味着模型可以在生成文本的过程中调用外部函数或服务,获取额外的数据或执行特定的任务

Function Call简化流程如下图所示

在这里插入图片描述

Function Call可以解决大模型什么问题?

在这里插入图片描述

当没有函数调用(funciton call)时候,我们调用GPT构建AI应用的模式非常简单。

主要步骤:

  1. 用户(Client)发请求给我们的服务(Chat Server)
  2. 我们的服务(ChatServer)给GPT提示词
  3. 重复执行

这里需要注意的是,当前场景下,用户并不是和GPT交互,而是和我们的Chat Server进行交互(Chat Server可以是企业开发的APP,内嵌了大模型,如内嵌了GPT)
在这里插入图片描述
当有函数调用(funciton call)时候,我们调用GPT构建AI应用的模式比之前要复杂一些。

主要步骤:

  1. 用户(Client)发请求prompt给我们的服务(ChatServer)
  2. 我们的服务(ChatServer)不仅会将用户(Client)的请求prompt发给大模型,还会将其能够提供的函数列表functions给大模型
  3. GPT模型根据用户的prompt,判断是用普通文本还是函数调用的格式响应我们的服务(Chat Server)
  4. 如果是函数调用格式,那么Chat Server就会执行这个函数,并且将结果返回给GPT
  5. 然后模型使用提供的数据,用连贯的文本响应。
    在这里插入图片描述

二、在coze中使用Function Call

2.1 coze插件简介

从程序员的视角Function Call是函数列表,而在coze种则是以插件对待。

模型会通过阅读插件的描述来决定是否调用该插件,所以对于插件的描述至关重要。
在这里插入图片描述

coze插件生态一览

在这里插入图片描述

2.2 旅游助手示例

我们设置了如下的提示词:其中用到了四个Function Call
在这里插入图片描述

当我们期望智能体制定一份旅游计划时

  • 系统提示词中指明了可以利用DayWeather插件获取天气情况
  • 用户提示词中,指明了期望其查明天气情况

可以看到大模型输出到中途的时候停止了,因为其发现需要进行Function Call,并知道是要调用DayWeather插件,参数都填好了,但是因为我们的agent当前并未添加该插件,因此模型无法继续执行下去而停止了。

在这里插入图片描述

添加插件

在编排中,可以看到插件的作用,点击左上角 + 号后可以跳转到插件选择页面
在这里插入图片描述

现有插件选择

  • 联网问答:search_url
  • 高德地图:Search_around
  • 墨迹天气:DayWeather
  • 简易计算器:calculate
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    添加完四个Function Call插件后,我们可以继续提问原来的问题,发现agent调用了这四个插件
    在这里插入图片描述
    点击具体的Function Call调用信息,我们还可以看到调用时的函数名和参数以及一些额外信息
    在这里插入图片描述

三、自定义Function Call

什么时候会用到自定义的插件?

  • 官方插件没有你想要的功能
  • 付费插件费用太贵
  • 想连接特定的第三方API服务
  • 需要对接企业内部系统

自定义插件基本流程

在这里插入图片描述

我们使用一个简单的例子学习一下自定义插件的开发流程。

根据城市名字查询天气

填写插件基本信息
在这里插入图片描述

因为我们是想自己使用代码开发,所以选择在Coze IDE中创建,语言支持Node.js和Python,由于本人相对熟悉Python一点,所以选择了Python

在这里插入图片描述

我们知道插件就是工具列表,所以我们添加工具
在这里插入图片描述

点击确定后,我们可以看到样例,告诉了我们工具的相关要素

  • 工具名称:handler,是工具的入口
  • 参数
  • 需要在元数据tab中设置输入与输出,以便大模型能够识别和使用该工具
  • 响应

在这里插入图片描述

我们的Python代码如下

# 导入Coze运行时所需的Args类,用于获取输入参数和日志记录器
from runtime import Args
# 导入requests库,用于发送HTTP请求(调用天气API)
import requests #需要安装对应的库
# 定义插件的主入口函数handler;Coze平台会自动调用此函数
# 参数args是Coze传入的运行时上下文对象
# 返回值为dict类型,将作为插件的输出结果返回给Agent
def handler(args:Args):
    '''
    天气查询插件:
    根据城市地址查询天气信息,比如输入"北京",输出
    {
            high:"高温7°C"
            low:"低温-1°C",
            weather:"晴"
            week:"星期二"
    } 
    '''

    # ==== 1.解析输入===
    try:
        # 从args.input中获取location字段,并去除首尾空格(如用户输入"北京"
        # 注意:此处假设输入为对象属性访问(如args.input.location),适用于manifest中声明了 location字段的情况
        location = args.input.location.strip()
    except Exception:
        #若获取location失败(如字段不存在、输入非对象等),设为空字符串
        location = ""

    # ====2.城市编码映射(仅北京、天津,内置)===
    # 构建城市名称-天气API编码的映射字典(仅保留北京和天津两个城市,轻量且教学友好)
    city_code_map = {
        "北京":"101010100", # 北京市的天气API编码
        "天津":"101030100" # 天津市的天气API编码
    }


    # 根据用户输入的城市名,查找对应的编码;若找不到则返回 None
    city_code = city_code_map.get(location)
    # 不支持的城市(如输入"上海"或空字符串)→返回空值结构
    if not city_code:
        # 记录警告日志:提示该城市暂不支持(可在Coze后台查看)
        args.logger.warning(f"Unsupported location: '{location}'")
        # 返回标准化的空结果(所有字段为None),保证输出结构一致
        return {
            "high":None, #最高温度
            "low": None,#最低温度
            "weather":None, # 天气类型(如"晴")
            "week": None # 星期(如"星期二")
        } 

    # ==== 3.调用天气API==
    # 拼接完整API请求URL,替换{city_code}为实际城市编码
    url = f"http://t.weather.itboy.net/api/weather/city/{city_code}"
    try:
        # 发起GET请求,设置超时5秒(防止插件卡死)
        response = requests.get(url,timeout=5)
        # 若HTTP状态码非2xx,主动抛出异常(如404、500等)
        response.raise_for_status()
        # 将响应体解析为JSON字典(安全方式,避免使用危险的eval())
        data=response.json()
        # 检查 API业务层返回状态码(该API约定 status=200表示成功)
        if data.get("status")!= 200:
            # 若业务状态异常(如城市编码错误),抛出自定义异常
            raise ValueError("Weather API returned inon-200 status")
        # 从返回数据中提取「今日」天气预报(forecast列表第0项即为当天
        # 路径:data+forecast数组→第0个元素
        forecast=data["data"]["forecast"][0]
        # 构造并返回天气基本信息字典
        return {
            "high": forecast["high"],#字符串,如"高温7°C"
            "low": forecast["low"],#字符串,如"低温-1°C"
            "weather":forecast["type"],#字符串,如"晴"、"小雨"
            "week": forecast["week"]#字符串,如"星期二"
        }
    # 捕获所有可能的异常(网络错误、JSON解析失败、字段缺失等)
    except Exception as e:
        #记录错误日志,包含具体异常信息和请求城市,便于调试
        args.logger.error(f"Weather query failed for'{location}':{e}")
        #统一返回空值结构,确保插件健壮性(不会因异常导致Agent 崩溃
        return {
            "high":None,
            "low": None,
            "weather": None,
            "week": None
        }

在元数据中添加输入输出,以帮助用户/大模型更好地理解该工具

在这里插入图片描述

在测试前,需要将代码中用到的包提前安装好,然后就可以测试了

在这里插入图片描述

将工具发布

在这里插入图片描述

发布成功后,我们可以在资源库–>插件中找到工具列表,也可以点击具体的插件继续进行编辑

在这里插入图片描述

自定义插件使用

和使用已有插件一样,不过我们可以在个人资源库快速找到自己定义的插件

在这里插入图片描述

可以看到,agent调用了我们自定义的天气查询工具,当然,一般我们会在系统提示词中指明什么情况下应该调用某个工具,这样大模型便会更加清楚什么情况下应该调用工具啦。

在这里插入图片描述

四、补充:Function Call 与 MCP 的区别

Function Calling(函数调用) 更像是本地函数调用API直接调用

  • 开发者明确告诉AI:“你要调用这些特定的函数”

  • AI只能使用预定义的函数,不能自行发现新工具

  • 函数接口需要预先注册到系统中

  • 类似本地开发:你提前写好所有可用的功能接口

MCP(Model Context Protocol) 更像是动态服务发现和代理机制

  • AI可以动态发现可用的工具和资源

  • 通过标准协议连接到各种服务(数据库、文件系统、API等)

  • 服务器(MCP Server)提供工具目录,客户端(AI)可以按需使用

  • 类似代理:有一个中介系统帮AI找到并调用合适的工具

更准确的比喻

在这里插入图片描述

实际应用场景

  • Function Calling适合:固定功能集、简单集成、快速原型

  • MCP适合:复杂工具生态、多服务集成、动态环境

Function Calling更像“我知道要调用什么,直接调用”(比如在系统提示词中指明什么情况下调用具体的某个工具),而MCP更像“让系统帮我找到合适的工具并代理执行”。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐