Skip to content

函数调用(Function Calling)

介绍

文心一言提供函数调用功能,模型根据用户需求以及对函数的描述确定何时以及如何调用函数。函数调用功能的典型使用流程如下:

  1. 用户提供对一组函数的名称、功能、请求参数(输入参数)和响应参数(返回值)的描述;
  2. 模型根据用户需求以及函数描述信息,智能确定是否应该调用函数、调用哪一个函数、以及在调用该函数时需要如何设置输入参数;
  3. 用户根据模型的提示调用函数,并将函数的响应传递给模型;
  4. 模型综合对话上下文信息,以自然语言形式给出满足用户需求的回答。

借由函数调用,用户可以从大模型获取结构化数据,进而利用编程手段将大模型与已有的内外部API结合以构建应用。

在ERNIE Bot中,erniebot.ChatCompletion.create接口提供函数调用功能。关于该接口的更多详情请参考ChatCompletion API文档

使用示例

假设我们有如下的函数实现:

def get_current_temperature(location: str, unit: str) -> dict:
    return {"temperature": 25, "unit": "摄氏度"}

在接下来的例子中,我们将尝试让大模型“指导”我们调用这个函数以完成指定的任务。需要说明的是,get_current_temperature是出于演示目的定义的一个硬编码的dummy函数,在实际生产中可将其替换为真正具备相应功能的API。

  1. 首先,对函数的基本信息进行描述,使用JSON Schema格式描述函数的请求参数与响应参数。

    functions = [
        {
            "name": "get_current_temperature",
            "description": "获取指定城市的气温",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {
                        "type": "string",
                        "description": "城市名称",
                    },
                    "unit": {
                        "type": "string",
                        "enum": [
                            "摄氏度",
                            "华氏度",
                        ],
                    },
                },
                "required": [
                    "location",
                    "unit",
                ],
            },
            "responses": {
                "type": "object",
                "properties": {
                    "temperature": {
                        "type": "integer",
                        "description": "城市气温",
                    },
                    "unit": {
                        "type": "string",
                        "enum": [
                            "摄氏度",
                            "华氏度",
                        ],
                    },
                },
            },
        },
    ]
    

    代码中定义了一个列表functions,作为示例,其中仅包含对一个函数get_current_temperature的名称、请求参数等信息的描述。

  2. 接着,将以上信息与对需要完成的任务的自然语言描述一同传给erniebot.ChatCompletion API。

    import erniebot
    
    erniebot.api_type = "aistudio"
    erniebot.access_token = "<eb-access-token>"
    
    messages = [
        {
            "role": "user",
            "content": "深圳市今天气温如何?",
        }
    ]
    
    response = erniebot.ChatCompletion.create(
        model="ernie-3.5",
        messages=messages,
        functions=functions,
    )
    assert hasattr(response, "function_call")
    function_call = response.function_call
    print(function_call)
    

    以上代码中的断言语句用于确保response中包含function_call字段。在实际生产中通常还需要考虑response中不包含function_call的情况,这意味着模型选择不调用任何函数。以上代码的输出结果可能如下(由于大模型生成结果具有不确定性,执行上述代码的结果与本示例不一定一致):

    {"name": "get_current_temperature", "thoughts": "我需要获取指定城市的气温", "arguments": "{"unit":"摄氏度","location":"深圳市"}"}
    

    function_call是一个字典,其中包含的键namethoughts分别对应大模型选择调用的函数名称以及模型的思考过程。function_call["arguments"]是一个JSON格式的字符串,其中包含了调用函数时需要用到的参数。

  3. 然后,根据模型的提示调用相应函数得到结果。

    import json
    
    name2function = {"get_current_temperature": get_current_temperature}
    func = name2function[function_call["name"]]
    args = json.loads(function_call["arguments"])
    res = func(location=args["location"], unit=args["unit"])
    

    以上代码从function_call中获取模型选择调用的函数名称(function_call["name"]),通过该名称找到对应的函数,并从function_call["arguments"]中解析需要传入函数的参数,最终完成对函数的调用。

  4. 最后,将模型上一轮的响应以及函数的响应加入到对话上下文信息中,再次传递给模型。回传给模型的函数响应内容应当是JSON格式的字符串(如"{"temperature":25,"unit":"摄氏度"}"),在本示例中,函数的响应是一个字典,因此需要先调用json.dumps函数对其进行编码。

    messages.append(
        {
            "role": "assistant",
            "content": None,
            "function_call": function_call,
        }
    )
    messages.append(
        {
            "role": "function",
            "name": function_call["name"],
            "content": json.dumps(res, ensure_ascii=False),
        }
    )
    response = erniebot.ChatCompletion.create(
        model="ernie-3.5",
        messages=messages,
        functions=functions,
    )
    print(response.result)
    

    输出结果可能如下:

    深圳市今天的温度是25摄氏度,天气还算舒适,建议穿轻薄的衣服出门。
    

    可以看出,模型根据函数的响应对我们的问题“深圳市今天气温如何?”作出了解答。