OpenAI开发系列(十三):利用Function calling功能开发基于大模型的实时天气查询助手

授权声明: 本文基于九天Hector的原创课程资料创作,已获得其正式授权。
原课程出处:九天Hector的B站主页,感谢九天Hector为学习者带来的宝贵知识。
请尊重原创,转载或引用时,请标明来源。

全文共4000余字,预计阅读时间约15~25分钟 | 满满干货(附代码),建议收藏!

本文目标:完整构建一个借助Function calling功能调用外部工具API的开发流程,实现天气信息的实时查询

1

代码下载点这里

一、介绍

函数调用(Function Calling)在程序设计中起着基础性的角色,它允许在代码中激活特定函数以执行特定任务。这一概念不仅在一般编程环境中非常重要,而且在高度复杂的大模型应用中也具有关键价值。通用大模型本身就拥有跨领域的知识基础,这无疑是一种显著优势。然而,通过引入Function Calling,可以进一步扩充这些模型的专业领域知识和能力。例如:

  1. 数据库交互:通过封装外部数据库API,模型不仅可以作为SQL代码解释器,还可以一键查询数据库,从而显著提高其实用性。
  2. 天气信息查询:通过与外部实时天气查询工具的API集成,模型可以轻松地成为一个智能的天气查询机器人。

这些只是冰山一角。Function Calling的真正实用价值在于它能够显著提升大型语言模型的敏捷性和实用性。虽然“Function Calling”这个名词可能让人联想到对外部函数的基础调用,但其实际应用远不止于此。除了进行基础的数值运算,更常见的是通过在函数内嵌入API来赋予模型额外的能力。

本文以实时查询天气的API工具为例,介绍让Chat Completion 模型接入天气查询API的方法。

二、OpenWeather注册及API key获取方法

2.1 什么是API

API(应用程序编程接口,Application Programming Interface)是一组预定义的规则和协议,用于构建和集成不同的软件应用。简而言之,API 是一种让不同软件之间进行交流的手段。在API的帮助下,开发者可以调用某个服务或库提供的特定功能,而不需要了解其内部的实现细节。这样不仅可以加速开发进程,还可以促进软件组件之间的可复用性和互操作性。比如:当你在手机应用中查看天气预报时,应用可能就是通过某个天气服务的Web API来获取数据的。

2.2 OpenWeatherAPI介绍

为了实现天气信息的实时查询功能,首先需要找到一个可靠且提供详细气象数据的优秀API。这一步是整个开发流程中的关键环节。

OpenWeather是一家提供全球气象数据服务的公司,该服务主要通过API(应用程序编程接口)来实现。开发者可以使用这些API来获取一系列的气象信息,从基础的当前天气和预报,到更高级的气候模型和卫星图像。

它提供的主要服务:

  1. 实时天气数据:包括温度、湿度、风速、风向、大气压等。
  2. 天气预报:短期(几小时)和长期(多天或多周)的天气预测。
  3. 历史天气数据:过去的天气情况和气象统计信息。
  4. 高级气象数据:雷达图、卫星图像、大气成分分析等。
  5. 灾害预警:极端天气情况(如台风、洪水等)的预警服务。

基于这样一个开放的天气查询API,如果将其封装为一个本地的函数,那么利用Function calling的能力,即可以赋予大模型查询实时天气信息的能力。

2.3 OpenWeather注册并获取API key

如果需要调用OpenWeather服务,和OpenAI的API使用过程类似,首先需要先注册OpenWeather账号,并获取OpenWeather API Key。

OpenWeather API key获取流程如下:(官网地址:https://openweathermap.org/,无需魔法上网)。

  • Step 1:注册

登录OpenWeather官网并点击Sign—>create an Account,按照提示完成账户注册。

image-20230725144332355

image-20230725144425459

  • Step 2:获取API-key

登陆完成后,可在API keys页面查看当前账户的API key

image-20230725144832990

image-20230725144906692

  • Step 3:设置为环境变量

和OpenAI API key类似,为方便后续调用,也可以直接将OpenWeather API key设置为环境变量,变量名为OPENWEATHER_API_KEY。

image-20230725145231822

如果不清楚如何配置本地环境变量的,参考这篇:OpenAI开发系列(五):实现Jupyter本地环境下的OpenAI API调用

三、OpenWeather API使用方法

3.1 API功能说明及计费规则

关于OpenWeather API的功能、调用方法和免费额度,可以在OpenWeather API介绍页面进行查看:https://openweathermap.org/api

image-20230726083515355

如果使用One Call 3.0 API,每个用户每天有1000次免费查询的额度,超过1000次则按照0.0015美元/次进行计费。

3.2 实时天气查询API调用方法

在官网先查看实时天气信息的API Doc,该页面包含了借助API进行实时天气信息查询方法:https://openweathermap.org/current

image-20230726084136085

不同于OpenAI提供了Python库作为API接入方式,OpenWeather API是通过https协议进行通信,所以使用Python调用OpenWeather API的基本步骤为:

  • Step 1:构建请求URL

HTTPs请求是通过URL(统一资源定位符)来标识网络上的一个资源的,所以对于OpenWeather实时查询天气的API来说,这个URL就是:https://api.openweathermap.org/data/2.5/weather

  • Step 2:设置查询参数

HTTPs请求通常包括查询参数,这些参数用于定制或过滤应返回的信息,对于OpenWeather API来说,官网提供了参数如下:

image-20230726084811916

这个API要求输入纬度(latitude)、经度(longitude)和一个唯一的API密钥(appid)以获取特定地区的天气信息。此外,它还提供了多种可选参数(optional parameters),包括数据类型过滤(exclude,可选如:current, minutely, hourly, etc.)、测量单位设置(units,可选如:standard, metric, imperial)以及语言选择(lang),从而增加了API在使用时的灵活性和个性化选项。

  • Step 3:发送GET请求

使用Python的requests库,通过其.get()函数传递构建好的URL和查询参数,向OpenWeather API发送GET请求。

  • Step 4:解析响应

等待API服务返回结果之后,即可围绕该结果进行解析,默认情况下是JOSN格式。根据上述的第一步至第四步的流程,将这些操作封装成一个单独的函数,用以测试与OpenWeather API的连通性。以下是完整的代码实现:

import os
import requests

def query_weather(api_key, city="Beijing", units="metric", language="zh_cn"):
    # 构建请求URL
    url = "https://api.openweathermap.org/data/2.5/weather"

    # 设置查询参数
    params = {
        "q": city,                 # 查询的城市,默认为北京
        "appid": api_key,          # API密钥
        "units": units,            # 测量单位,默认为摄氏度
        "lang": language           # 输出语言,默认为简体中文
    }

    # 发送GET请求
    response = requests.get(url, params=params)

    # 检查响应状态
    if response.status_code == 200:
        # 解析响应数据
        data = response.json()

        # 打印获取到的数据
        print(f"查询城市: {city}")
        print(f"温度: {data['main']['temp']}°{units[0].upper()}")
        print(f"天气描述: {data['weather'][0]['description']}")
        print(f"湿度: {data['main']['humidity']}%")
        print(f"风速: {data['wind']['speed']} m/s")
        
        return data
    
    else:
        print(f"查询失败,状态码:{response.status_code}")
        print("响应数据:", response.text)

调用看下输出结果:

if __name__ == "__main__":
    open_weather_key = os.getenv("OPENWEATHER_API_KEY")  # 从环境变量获取API密钥
    if open_weather_key:
        query_weather(open_weather_key)  # 调用函数,查询北京的天气
    else:
        print("请确保环境变量中有OpenWeather的API密钥。")

image-20230828095558048

测试成功!

四、如何用OpenWeather API赋能给大模型气象的实时数据

在成功本地调用OpenWeather API并获取实时气象数据之后,如果要赋能大语言模型这种能力,就需要利用Function Calling机制进行整合,在OpenAI开发系列(十一):Function calling功能的实际应用流程与案例解析中,详细描述了Function Calling的全流程。用在此场景下的话,就可以将这个API视为一个“外部函数”,通过Function Calling的方法,将其集成到大语言模型中,从而拓展其实用性和功能。

5

  • Step 1:测试Chat Completion模型有OpenWeather的相关知识

这一步往往是最初就需要验证的,要基于某一个场景做开发,必须先确定大模型是否具备相关的辅助知识。

response = openai.ChatCompletion.create(
  model="gpt-3.5-turbo-16k-0613",
  messages=[
    {"role": "user", "content": "你知道Open Weather吗?"}
  ]
)

看下大模型的回复结果:

response.choices[0].message['content']

image-20230828104136033

  • Step 2:确认Chat Completion模型对Open Weather API返回数据的解析能力

这一步是关键环节,它不仅有助于确定功能函数应采取的输入输出格式,而且也确保大模型能准确解读并回应Open Weather API返回的数据。测试代码如下:

先获取到某个城市的天气信息,此处举例为”北京市“,其输出如下:

open_weather_key = os.getenv("OPENWEATHER_API_KEY")  # 从环境变量获取API密钥
    
city_weather = query_weather(open_weather_key, city="beijing")  # 调用函数,查询北京的天气

city_weather

看下返回的数据情况:

image-20230828105222211

然后将其格式化的数据传入大模型,看大模型是否能够正确的解读:

response = openai.ChatCompletion.create(
  model="gpt-3.5-turbo-16k-0613",
  messages=[
    {"role": "system", "content": "这是当前北京市的实时天气数据:%s, 来源于OpenWeather API:https://api.openweathermap.org/data/2.5/weather" % city_weather},
    {"role": "user", "content": "请问:当前北京市的天气如何?"}
  ]
)
response.choices[0].message['content']

看下结果:

image-20230828105654060

  • Step 3:根据实际需求编写功能函数

当确定了大模型的基础能力后,就需要据此开发功能函数,目标就是要:调用OpenWeather API实时获取到天气信息,函数代码如下:

import os
import requests
import json

def query_openweather_function(city="Beijing", units="metric", language="zh_cn", api_key=os.getenv("OPENWEATHER_API_KEY"), ):
    """
    使用OpenWeather API查询指定城市的实时天气信息,并将结果以JSON格式的字符串返回。
    
    参数:
    city (str): 必填参数。需要查询天气的城市,默认为北京,如果输入的地区是中国的中文字符,就换成对应的英文名称,如北京市,正确的输入应该为"beijing"
    units (str): 计量单位,默认为摄氏度(metric)。
    language (str): 输出信息的语言,默认为简体中文(zh_cn)。
    api_key (str): 用于访问OpenWeather的API密钥。
    
    返回:
    str: 查询到的天气信息,以JSON格式的字符串返回。如果查询失败,返回包含错误信息的JSON格式字符串。
    """
    # 构建请求的URL
    url = "https://api.openweathermap.org/data/2.5/weather"

    # 设置查询参数
    params = {
        "q": city,
        "appid": api_key,
        "units": units,
        "lang": language
    }

    # 发送GET请求
    response = requests.get(url, params=params)

    # 检查响应状态
    if response.status_code == 200:
        # 解析响应数据
        data = response.json()


        # 将结果转换为JSON格式的字符串
        return json.dumps(data)
    else:
        # 创建一个错误消息
        error_message = {
            "错误": f"查询失败,状态码:{response.status_code}",
            "响应数据": response.text
        }

        # 将错误消息转换为JSON格式的字符串
        return json.dumps(error_message)
  • Step 4:测试实时天气信息获取函数是否能正常运行
if __name__ == "__main__":
    # open_weather_key = os.getenv("OPENWEATHER_API_KEY")  # 从环境变量中获取API密钥
    if open_weather_key:
        # 调用函数并打印返回的JSON格式字符串
        print(query_openweather_function())
    else:
        print("请确保环境变量中有OpenWeather的API密钥。")

输出如下,运行正常。
image-20230828103705249

这里面有一个关键点:就是输出城市的中英文对应关系,经测试Open Weather API是无法识别中文城市名的,所以需要自动识别中文城市名对转化成对应的英文名。

response = openai.ChatCompletion.create(
  model="gpt-4-0613",
  messages=[
    {"role": "user", "content": "请问,杭州市的英文名称是?"}
  ]
)
response.choices[0].message['content']

看下结果:

image-20230726092347583

  • Step 5:创建功能函数的JSON Schema描述

OpenAI开发系列(十二):Function calling功能的流程优化与多轮对话实现中:已经优化了功能函数对应的JSON Schema对象描述的自动生成流程,因此,在这里可以直接使用封装好的AutoFunctionGenerator类来为query_openweather_function生成相应的JSON Schema对象。

导入后调用这个类,得到其JSON Schema格式,代码如下:

if __name__ == '__main__':
    functions_list = [query_openweather_function]
    generator = AutoFunctionGenerator(functions_list)
    function_descriptions = generator.auto_generate()

看下大模型的生成结果:

image-20230828111938869

能发现,模型提取的函数关键信息非常到位。

  • Step 6:激活Function calling对话流程

同样使用在OpenAI开发系列(十二):Function calling功能的流程优化与多轮对话实现中已经优化好的messages自动拼接流程ChatConversation封装类和和多轮对话函数chat_with_assistant,调用测试如下:

测试在不带入外部功能函数时,Chat模型能否准确回答当前天气情况;

大模型会出现”幻觉“,随便回答,看下回复结果:

image-20230828123137642

在原始状态下,大模型并不具备实时查询天气信息的能力。

在对话中允许模型挂载外部功能函数库时,再次询问当前天气情况,得到结果如下:

image-20230828123349938

对比一下:

image-20230828123443747

这也就意味着:Chat Completion模型具备了实时查询天气的能力,能够对天气问题做出准确回答。

以上成功的构建了一个完整的开发流程,该流程利用Function calling功能调用外部API(OpenWeather API)。通过这种方式,大语言模型可以迅速地与各种外部工具集成,从而显著扩展其应用范围和功能。这不仅开放了广阔的技术应用可能性,还大大加速了AI应用的开发进程。以OpenWeather API为例,不仅可以实现实时天气信息的获取,还可以进一步开发未来天气预测或历史天气统计等高级功能,以适应各种不同的应用场景。每一个新增功能都可以看作是一个独立的AI应用开发项目,这也正是Function calling功能能大幅缩短AI应用开发周期的关键所在。

五、总结

本篇文章讲述了如何在OpenWeather注册并获取API key,同时解释了什么是外部工具API以及OpenWeatherAPI的基本介绍。之后,详解了OpenWeather API的使用方法,包括API功能说明、计费规则以及实时天气查询API的调用方法。在此基础上,展示了如何使用Function calling来实现Chat模型的实时天气查询,最后介绍了如何使用Few-shot提示来优化函数。此内容为实现Function calling调用外部工具API,具有参考和启发价值。

最后,感谢您阅读这篇文章!如果您觉得有所收获,别忘了点赞、收藏并关注我,这是我持续创作的动力。您有任何问题或建议,都可以在评论区留言,我会尽力回答并接受您的反馈。如果您希望了解某个特定主题,也欢迎告诉我,我会乐于创作与之相关的文章。谢谢您的支持,期待与您共同成长!

  • 5
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
这个错误通常出现在 UG NX 二次开发中使用“回调函数”进行异步操作时。具体原因可能是在回调函数中调用了“KI”(Kernel Interface)函数,而前一个 KI 函数尚未完成,导致了这个错误。 解决方案是在回调函数中不要直接调用 KI 函数,而是将需要调用的 KI 函数加入到队列中,等待前一个 KI 函数完成后再执行下一个 KI 函数。以下是一个示例代码: ```c++ // 定义队列 std::queue<std::function<void()>> g_kiQueue; // 定义互斥锁 std::mutex g_kiMutex; // 将需要执行的 KI 函数加入队列 void AddToKIQueue(std::function<void()> func) { std::lock_guard<std::mutex> lock(g_kiMutex); g_kiQueue.push(func); } // 在主循环中调用,执行队列中的 KI 函数 void ProcessKIQueue() { std::lock_guard<std::mutex> lock(g_kiMutex); while (!g_kiQueue.empty()) { auto func = g_kiQueue.front(); g_kiQueue.pop(); func(); } } // 回调函数示例 void MyCallback(void* userData) { // 将需要执行的 KI 函数加入队列 AddToKIQueue([](){ // 调用 KI 函数 UF_CAM_ask_machine_tool_definition(...); }); } ``` 在上面的示例中,我们使用了一个队列和一个互斥锁来实现异步执行 KI 函数。在回调函数中,我们将需要执行的 KI 函数加入到队列中。在主循环中,我们调用 `ProcessKIQueue` 函数来执行队列中的 KI 函数。这样就可以避免在回调函数中直接调用 KI 函数而导致的“KI before the previous call completes”错误。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

算法小陈

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值