利用ChatGPT的函数调用功能实现:实时查询天气

By 刘志军 , 2023-06-15, 分类: 思考

chatgpt

image-20230614223818614

OpenAI 今天发布几个重磅更新

1、 开放 16k 上下文的 GPT-3.5-Turbo 模型(gpt-3.5-turbo-16k),是目前的4倍 2、 新的 GPT-4 和 3.5 Turbo 模型 3、Chat Completions API 中的新增加函数调用功能 (实时获取网络数据成为可能) 4、embeddings模型的成本降低75% 5、gpt-3.5-turbo的输入token成本降低了25% (开发者的福音)

其中最令人兴奋的功能应该当属函数调用功能,我们都知道ChatGPT训练的数据是基于2021年之前的,你要问一些实时性相关的问题就没法回答你了,而函数调用让实时获取网络数据成为可能,比如查询天气预报、查股票、推荐个近期的电影之类的。

哪些模型支持函数调用?

gpt-3.5-turbo-0613gpt-4-0613 这两个模型都支持函数调用。

函数调用的流程是什么?

1、用户发起提问时,调用一次带有函数描述的completions接口,gpt会判断是否支持调用函数,如果可以就从用户的提问信息中提取出函数所需要的参数。 2、开发者拿到gpt提取出来的参数后自行调用函数并返回结果 3、将函数的返回结果再次发给GPT做总结归纳为自然语言

image-20230614235909239

需要注意的地方:

  1. 整个过程gpt会执行两次,第一次调用从问题中提取函数参数,第二次对函数返回结果做归纳总结
  2. 函数调用并不是由gpt调用,而是开发者来调用

举个真实例子

这里我以实时获取天气预报为例子演示函数调用的流程,天气预报接口我用的第三方高德API,免费,每天几千次的调用额度。申请注册流程这里省略,自行研究。

# 获取天气函数
def get_weather(city_name: str):
    url = "https://restapi.amap.com/v3/weather/weatherInfo?"

    params = {"key": "替换成你自己的key",
              "city": "110000"}
    city_code = "110000"

    for city in CITIES:
        if city_name in city.get("city"):
            city_code = city.get("adcode")
            break
    params['city'] = city_code

    response = requests.get(url=url, params=params)
    # 返回结果:
    # {'count': '1',
    #  'info': 'OK',
    #  'infocode': '10000',
    #  'lives': [{'adcode': '440300',
    #             'city': '深圳市',
    #             'humidity': '81',
    #             'humidity_float': '81.0',
    #             'province': '广东',
    #             'reporttime': '2023-06-14 15:00:43',
    #             'temperature': '29',
    #             'temperature_float': '29.0',
    #             'weather': '大雨',
    #             'winddirection': '西南',
    #             'windpower': '≤3'}],
    #  'status': '1'}
    return response.json().get("lives")[0]

这个函数就是用来查询天气情况的,参数 city_name 是城市的名字,因为高德API只支持通过城市代码查天气,所以我这里做了一次根据城市名找到对应编码的查询

接口返回的结果中包含有温度(temperature)、风度(windpower)、风向(winddirection)、湿度(humidity)、天气(weather)等字段信息。

天气函数准备好后,用户开始提问:“深圳天气如何?“, 第一次调用`ChatCompletion`接口。

response = openai.ChatCompletion.create(
            model="gpt-3.5-turbo-0613",
            messages=[{"role": "user", "content": "深圳天气如何?"}],
            functions=[
                {
                    "name": "get_weather",
                    "description": "获取指定地区的当前天气情况",
                    "parameters": {
                        "type": "object",
                        "properties": {
                            "city_name": {
                                "type": "string",
                                "description": "城市,例如:深圳",
                            },
                        },
                        "required": ["city_name"],
                    },
                }
            ],
            function_call="auto",
        )

这里我们指定了一个functions 参数,该参数描述了函数的名字以及参数类型,比如我们这里定义了city_name的参数,gpt 就会从用户问题中提取出city_name。

response的返回结果是:

  "choices": [
    {
      "finish_reason": "function_call",
      "index": 0,
      "message": {
        "content": null,
        "function_call": {
          "arguments": "{\n  \"city_name\": \"\u6df1\u5733\"\n}",
          "name": "get_weather"
        },
        "role": "assistant"
      }
    }
  ],

gpt 给我们返回的message中有function_call 字段,而且 arguments 里面提取了city_name这个字段的值。

第二步:从返回结果中提取参数后调用函数, 这个过程不是交给gpt处理,而是由开发者自己调用该函数,gpt做的事情是把函数需要的参数提取出来。

message = response["choices"][0]["message"]
function_call = message.get("function_call")
if function_call:
    arguments = function_call.get("arguments")
    arguments = json.loads(arguments)
    function_response = get_weather(
        city_name=arguments.get("city_name"),
    )
    function_response = json.dumps(function_response)

注意,这里要将函数调用返回的结果做一些json转换

第三交步:把返回结果给gpt做总结归纳

second_response = openai.ChatCompletion.create(
        model="gpt-3.5-turbo-0613",
        messages=[
            {"role": "user", "content": "深圳今天的天气?"},
            message,
            {
                "role": "function",
                "name": "get_weather",
                "content": function_response,
            },
        ],
    )
    return second_response

注意messages列表中最后一条消息中role角色是 function, 最后得到的结果second_response中的content内容为:

content: 深圳今天的天气是大雨,气温为25℃,风向是西北风,风力为3级,湿度为95%。

最后,我们把逻辑集成到我们微信中得到的效果是这样的:

image-20230615094319668

完整源代码:https://gist.github.com/lzjun567/04310ae22dc80005997179c1e591b397


关注公众号「Python之禅」,回复「1024」免费获取Python资源

python之禅

猜你喜欢

2023-03-17
伪装成小白,让ChatGPT教我写代码
2023-04-19
开发者关心的ChatGPT API额度、Token、价格
2023-04-27
如何解决ChatGPT 的 Something went wrong 错误
2023-04-29
如何不提供账号密码找人代充ChatGPT Plus
2023-06-29
官方gpt3.5, gpt4.0、github copilot chat、gpt3.5 api、gpt4 api 对比,谁更牛?
2023-05-10
用 ChatGPT 搭建一个 Telegram 机器人
2023-10-18
ChatGPT Plus GPT4 功能汇总
2023-03-19
一个集成了GPT-4的免费编辑器 Cursor
2023-11-14
我的第一个GPTs
2023-05-26
如何注册一个美国苹果账号 Apple ID