已复制
全屏展示
复制代码

到底什么是ChatGPT的函数调用function calling

· 3 min read

function calling 这个词一听还以为是 GPT 帮我去调用函数,实际上并不是这样。

使用场景

我们在和 GPT 聊天的过程中,可能会涉及一些特定的问题,比如在聊天时,我突然问 GPT :北京今天天气怎么样?

很显然 GPT 是不知道实时的天气的,那怎么办呢,用 function calling 可以实现,我们可以提前定义好一个函数,这个函数有一个城市参数,函数内部会去调用 API 查询这个城市当前的天气情况。

请注意:这个调用天气的接口是我们自己提前写好的,当用户问天气相关问题时才会触发调用,并不是 GPT 帮我调用。

实际示例

请看下面示例:

  • 我定义了 2 个函数tools,一个是查询指定城市的天气,一个是查询指定用户的地址。
  • 函数调用分两步:1、GPT 帮我提取出问题中的参数,比如城市。2、把提取出的参数传递个 GPT,生成最终的回答。
  • 如果没有触发定义的tools ,则正常回答问题即可。
from openai import OpenAI
import json

gpt_model = "gpt-3.5-turbo"
client = OpenAI(api_key='sk-xxx')


def get_current_weather(city):
    # 实际上需要调用 API 接口 查询 city 的天气,然后再返回查到的温度。
    return "25"


def get_user_address(username):
    # 实际上需要调用 API 接口 查询 username 的地址,然后再返回查到的地址。
    return "北京"


tools = [
    {
        "type": "function",
        "function": {
            "name": "get_current_weather",
            "description": "Get the current weather",
            "parameters": {
                "type": "object",
                "properties": {
                    "city": {
                        "type": "string",
                        "description": "The city name",
                    }
                },
                "required": ["city"],
            },
        }
    },
    {
        "type": "function",
        "function": {
            "name": "get_user_address",
            "description": "Get the user address",
            "parameters": {
                "type": "object",
                "properties": {
                    "username": {
                        "type": "string",
                        "description": "The username",
                    }
                },
                "required": ["username"],
            },
        }
    }
]

messages = [
    {
        "role": "system",
        "content": "Don't make assumptions about what values to plug into functions. Ask for clarification if a user request is ambiguous."
    },
    {
        "role": "user",
        "content": "北京天气怎么样,张阳的住址在哪儿呢?",
    }
]

gpt_response = client.chat.completions.create(
    model=gpt_model,
    messages=messages,
    tools=tools,
    tool_choice="auto",
)
first_message = gpt_response.choices[0].message

# 检查是否提取到了参数,如果提取到了,直接执行
tool_calls = first_message.tool_calls
if tool_calls:
    messages.append(first_message)
    for tool_call in tool_calls:
        function_name = tool_call.function.name
        
        # 这里需要捕获错误,json.loads有可能会报错
        function_args = json.loads(tool_call.function.arguments)
        
        function_response = ""
        if function_name == "get_current_weather":
            function_response = get_current_weather(city=function_args.get("city"))
        elif function_name == "get_user_address":
            function_response = get_user_address(username=function_args.get("username"))
        if function_response is not None:
            messages.append({
                "tool_call_id": tool_call.id,
                "role": "tool",
                "name": function_name,
                "content": function_response,
            })
    gpt_response = client.chat.completions.create(
        model=gpt_model,
        messages=messages,
    )
print(gpt_response.choices[0].message.content)

返回结果:

$ python x.py 
北京的天气是晴天。张阳的住址是北京。

如果换成下面的问题,则不会触发 tools 的调用:

messages = [
    {
        "role": "system",
        "content": "Don't make assumptions about what values to plug into functions. Ask for clarification if a user request is ambiguous."
    },
    {
        "role": "user",
        "content": "Python是什么?",
    }
]

返回结果:

$ python x.py 
请问您想了解Python的什么信息? 是一种编程语言还是其他方面的信息? 请提供更多细节,以便我可以为您提供准确的答案。

总结

实际上可以把 函数调用立即成一些列的触发器,我们提前定义好这些触发器 tools,一旦用户问的问题触发了这些问题,并且 GPT 帮我们提取出了指定的参数,就一个自动调用函数。让人感觉 GPT 帮你调用了函数以后。

🔗

文章推荐