当前位置: 首页 > news >正文

Function Call实战:用GPT-4调用天气API,实现实时信息查询

在过去,与AI模型交互时,我们只能从它已有的知识库中获取信息。但如果我们需要查询的是“此刻”的天气,“此刻”的股票价格,或者“此刻”的特定新闻,模型自身的知识储备就显得捉襟见肘了。
为了让AI能够触及真实世界、获取实时动态的信息,Function Calling (函数调用) 技术应运而生。作为GPT-4等先进模型的一大亮点,Function Calling允许AI模型“理解”外部可用的函数(或其他API),并在对话过程中,判断何时需要调用这些函数,以及如何准备调用所需的参数。
本文将带大家进入Function Calling的实战世界,以一个经典的案例——调用天气API查询实时天气——来展示如何利用GPT-4的这一强大功能,让AI真正“动起来”并获取最新信息。
一、 Function Calling:AI模型的新能力
核心思想:
Function Calling的核心在于,你向LLM提供一个可用函数的列表(描述其名称、功能、参数等),LLM在处理用户输入时,如果认为某个函数可以帮助它更好地回答问题,它就会输出一个结构化的JSON对象,其中包含要调用的函数名及其所需的参数。
工作流程:
定义可用函数 (You): 你向API描述你想让模型能够使用的函数(例如,get_weather(location, unit))。
用户提问 (User): 用户与模型对话,提出一个问题,例如“北京今天的天气怎么样?”
模型判断与输出 (GPT-4): GPT-4解析用户问题,识别出需要获取天气信息,并根据你提供的函数描述,生成一个JSON对象,指示调用get_weather函数,并填充参数location="北京"和unit="celsius"。
执行函数 (You): 你的应用程序接收到这个JSON对象,然后执行实际的Python函数(或调用外部API)。
模型接收结果 (GPT-4): 你将函数的执行结果(例如,一个JSON格式的天气数据),连同用户原始问题和模型先前的输出,再次发送给GPT-4。
模型生成最终回答 (GPT-4): GPT-4融合了函数结果和用户问题,生成一个最终的、易于理解的自然语言回答,例如“北京今天的天气是晴朗,气温 25 摄氏度。”
二、 实战场景:用GPT-4调用天气API
我们将使用以下组件来实现这个功能:
GPT-4 API: 作为智能的核心,负责理解用户意图和生成函数调用。
OpenWeatherMap API: 一个免费(有使用限制)的天气信息提供商,我们将通过它获取真实的天气数据。
Python: 作为主要的开发语言,用来处理API请求、执行函数调用以及与GPT-4 API交互。
LangChain: 为了简化API调用、Prompt管理和整体流程的构建,我们将利用LangChain框架。
1. 环境准备
安装必要的库:
<BASH>

pip install openai langchain-openai python-dotenv requests
获取OpenWeatherMap API Key:
访问 OpenWeatherMap官网 注册一个免费账户,获取API Key。
获取OpenAI API Key:
如果你还没有,访问 OpenAI官网 注册并获取API Key。
创建.env文件:
在项目根目录下创建 .env 文件,并填入你的API Keys:
<TEXT>

OPENAI_API_KEY=sk-your_openai_api_key
OPENWEATHER_API_KEY=your_openweathermap_api_key
2. 定义天气查询函数
我们的第一个步骤是定义一个Python函数,它能够接收城市名称和单位(摄氏度/华氏度)作为输入,并返回该城市的天气信息。我们将把这个函数暴露给GPT-4,以便它可以调用。
<PYTHON>

import os
import requests
from dotenv import load_dotenv
from typing import Optional
from langchain_core.tools import tool # LangChain's decorator for defining tools

# 加载API Keys
load_dotenv()

OPENWEATHER_API_KEY = os.getenv("OPENWEATHER_API_KEY")

# --- 定义一个核心的工具函数 ---
@tool("get_weather",
args_schema={
"location": {"type": "string", "description": "The city to get the weather for"},
"unit": {"type": "string", "description": "The unit of temperature: 'celsius' or 'fahrenheit'"},
},
return_direct=False # Set to False to indicate the result should be passed to the LLM
)
def get_weather(location: str, unit: str = "celsius") -> str:
"""
Fetches the current weather for a specified city and unit.
Valid units are 'celsius' and 'fahrenheit'.
"""
if not OPENWEATHER_API_KEY:
return "OpenWeatherMap API key not found. Please set OPENWEATHER_API_KEY in your .env file."

base_url = "http://api.openweathermap.org/data/2.5/weather?"

# Map units for the API call
if unit.lower() == "celsius":
api_unit = "metric"
elif unit.lower() == "fahrenheit":
api_unit = "imperial"
else:
return f"Invalid unit '{unit}'. Please use 'celsius' or 'fahrenheit'."

complete_url = base_url + "appid=" + OPENWEATHER_API_KEY + "&q=" + location + "&units=" + api_unit

response = requests.get(complete_url)
data = response.json()

if data["cod"] != "404":
main = data["main"]
weather_description = data["weather"][0]["description"]
temp = main["temp"]

return f"The weather in {location} is {weather_description} with a temperature of {temp:.1f} degrees {unit}."
else:
return f"City '{location}' not found. Please check the spelling."

# --- Example of using the function directly (for testing) ---
if __name__ == "__main__":
print(get_weather(location="London", unit="celsius"))
print(get_weather(location="New York", unit="fahrenheit"))
print(get_weather(location="InvalidCity", unit="celsius"))
print(get_weather(location="Paris", unit="kelvin")) # Test invalid unit
3. 构建 Agent 并集成 Function Calling
现在,我们将使用LangChain的ChatOpenAI的function_calling功能,并将其包装在一个Agent中。LangChain的Agent能够自动处理Tool的定义和LLM的函数调用。
<PYTHON>

import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langchain.agents import AgentExecutor, create_tool_calling_agent
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from typing import Any, Dict, List

# Load API Keys (ensure these are set in .env)
load_dotenv()

# Initialize the LLM with function calling enabled
# Use a powerful model like gpt-4 for best results with function calling
llm = ChatOpenAI(model="gpt-4", temperature=0, api_key=os.getenv("OPENAI_API_KEY"))

# --- Define the tools ---
# The `get_weather` function is already decorated with `@tool`.
# LangChain's `from_function` can also be used, but `@tool` is more concise here.
tools = [get_weather]

# --- Create the Agent Executor ---
# 1. Define the prompt for the agent
prompt = ChatPromptTemplate.from_messages([
("system", """You are a helpful assistant. You can answer questions about the weather by calling the appropriate tool.
If the user asks for information not related to weather, politely inform them that you can only provide weather information.
When you are done answering, say "TERMINATE".
"""),
MessagesPlaceholder(variable_name="chat_history", optional=True), # For conversation memory
("human", "{input}"),
MessagesPlaceholder(variable_name="agent_scratchpad"), # For tool calls and observations
])

# 2. Create an agent that uses the tools
# `create_tool_calling_agent` is designed for models that support tool calling.
agent = create_tool_calling_agent(llm, tools, prompt)

# 3. Create the Agent Executor
# This object will orchestrate the agent's interaction with the tools.
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True, handle_parsing_errors=True)

# --- Run the example ---
if __name__ == "__main__":
print("--- Starting Weather Query Agent ---")

# Example 1: Ask about a city and specific unit
user_query_1 = "What is the weather like in Tokyo, in Fahrenheit?"
print(f"\nUser Query: {user_query_1}")
response_1 = agent_executor.invoke({"input": user_query_1, "chat_history": []})
print(f"Agent Response: {response_1['output']}")

# Example 2: Ask about another city, default unit (celsius)
user_query_2 = "How is the weather in Berlin?"
print(f"\nUser Query: {user_query_2}")
response_2 = agent_executor.invoke({"input": user_query_2, "chat_history": []})
print(f"Agent Response: {response_2['output']}")

# Example 3: Ask a question that does not involve weather
user_query_3 = "Tell me a joke."
print(f"\nUser Query: {user_query_3}")
response_3 = agent_executor.invoke({"input": user_query_3, "chat_history": []})
print(f"Agent Response: {response_3['output']}")

# Example 4: Ask about a non-existent city
user_query_4 = "What's the weather in the moon?"
print(f"\nUser Query: {user_query_4}")
response_4 = agent_executor.invoke({"input": user_query_4, "chat_history": []})
print(f"Agent Response: {response_4['output']}")
4. 运行与解释
当你运行上面的Python脚本时,你会看到如下的交互过程(verbose=True会显示Agent的内部思考和工具调用):
Query 1: "What is the weather like in Tokyo, in Fahrenheit?"
Agent 接收到你的问题。
Agent 识别出需要获取天气信息,并且需要使用 "Tokyo" 作为城市,"Fahrenheit" 作为单位。
Agent 调用 get_weather 工具,参数为 location="Tokyo" 和 unit="fahrenheit"。
Python 端的 get_weather 函数被执行,它调用 OpenWeatherMap API,获取东京的天气数据。
get_weather 函数返回一个包含天气描述的字符串。
Agent 接收到这个结果,并将其作为最终答案返回给你。
输出可能如下(具体天气数据会变化):
<TEXT>

User Query: What is the weather like in Tokyo, in Fahrenheit?
> Entering new AgentExecutor chain...
Tool Call:
```json
{
"action": "get_weather",
"action_input": {
"location": "Tokyo",
"unit": "fahrenheit"
}
}
get_weather: The weather in Tokyo is clear sky with a temperature of 75.2 degrees fahrenheit.
Observation: The weather in Tokyo is clear sky with a temperature of 75.2 degrees fahrenheit.
Thought:I have successfully retrieved the weather information for Tokyo in Fahrenheit. I can now provide this to the user.
Final Answer: The weather in Tokyo is clear sky with a temperature of 75.2 degrees fahrenheit.
Agent Response: The weather in Tokyo is clear sky with a temperature of 75.2 degrees fahrenheit.

Query 2: "How is the weather in Berlin?"
Agent 识别出需要天气信息。
用户没有指定单位,Agent会使用默认单位(我们已经在 @tool 装饰器中设定为 "celsius")。
Agent 调用 get_weather 工具,参数为 location="Berlin" 和 unit="celsius"。
Python 函数执行,返回柏林的天气信息。
Query 3: "Tell me a joke."
Agent 接收到这个问题,发现它与天气无关。
根据系统Prompt中的指示(“If the user asks for information not related to weather, politely inform them that you can only provide weather information.”),Agent不会调用任何工具,而是直接生成一个包含此信息的回答。
输出可能如下:
<TEXT>

User Query: Tell me a joke.
> Entering new AgentExecutor chain...
Thought:I cannot tell jokes as my functionality is limited to providing weather information. I need to inform the user about this limitation.
Final Answer: I apologize, but I can only provide weather information.

Agent Response: I apologize, but I can only provide weather information.
Query 4: "What's the weather in the moon?"
Agent 识别需要天气信息,“the moon”作为位置。
get_weather 函数会被调用,但 OpenWeatherMap API 可能无法识别“the moon”作为一个有效地点。
get_weather 函数会返回“City 'the moon' not found.”。
Agent 接收到这个错误信息,并将其作为最终答案呈现。
三、 总结与进阶
通过这个实战案例,我们掌握了如何利用GPT-4的Function Calling能力:
定义工具: 使用@tool装饰器,为Python函数提供清晰的描述、参数和返回值说明。
集成到LangChain Agent: 使用create_tool_calling_agent 和 AgentExecutor 将工具与LLM连接起来。
处理函数调用: Agent会自动识别何时调用哪个函数,并传递正确的参数。
接收函数结果: Agent能接收函数返回的结果,并用它来生成最终的用户回答。
场景限定: 通过Prompt设计,可以约束Agent的行为,使其专注于特定任务(如天气查询)。
进阶方向:
多工具集成: 集成更多类型的工具,如股票行情API、计算器、搜索引擎等,构建更全面的Agent。
复杂逻辑与决策: 让Agent能够根据检索结果,决定下一步是再调用一个工具,还是进行组合,或是直接回答。
错误处理与鲁棒性: 增强get_weather等函数内或Agent层面的错误处理,例如API调用失败、数据格式错误等,并设计相应的重试或回退机制。
对话记忆: 集成chat_history,让Agent能够理解多轮对话中的上下文,例如用户在一个问题中提到“它”指代的是上一次提到的城市。
多Agent协作: 将Function Calling Agent与其他类型的Agent(如专门负责生成文档的Agent、专门负责测试代码的Agent)结合,实现更复杂的自动化流程。
Function Calling技术极大地扩展了AI的能力边界,使其能够与我们的数字世界更紧密地结合。通过实践,您将更能体会到这种“让AI调用工具”的力量。

文章转载自:

http://Ah8wViuE.Lffrh.cn
http://f8BGMCu6.Lffrh.cn
http://RLf7a73f.Lffrh.cn
http://kutMeRD2.Lffrh.cn
http://uATDDK7w.Lffrh.cn
http://un3bwLV6.Lffrh.cn
http://kAMqvZZj.Lffrh.cn
http://5qnWI9u6.Lffrh.cn
http://AaeZFTWX.Lffrh.cn
http://a0fUBSfs.Lffrh.cn
http://nWsVnky3.Lffrh.cn
http://hYuv5csm.Lffrh.cn
http://5DitmHdo.Lffrh.cn
http://LcncsLpn.Lffrh.cn
http://cSnoes6X.Lffrh.cn
http://QRpYmuSK.Lffrh.cn
http://C5AxuEtC.Lffrh.cn
http://wL8MUfru.Lffrh.cn
http://RhDRAjB8.Lffrh.cn
http://8reWVFbg.Lffrh.cn
http://go4PP1RW.Lffrh.cn
http://lAJlD93M.Lffrh.cn
http://RCCsJIIl.Lffrh.cn
http://kT0fUt7e.Lffrh.cn
http://T5cqdguD.Lffrh.cn
http://FvIrP11d.Lffrh.cn
http://tXN3BtFu.Lffrh.cn
http://ubOB7r2w.Lffrh.cn
http://4ksB0O5S.Lffrh.cn
http://dNJ21PCp.Lffrh.cn
http://www.dtcms.com/a/367562.html

相关文章:

  • 2025年热门视频转文字工具测评,助你快速把视频转成文字稿!
  • 基于SpringBoot的家政保洁预约系统【2026最新】
  • C语言中calloc函数
  • flowable基础入门
  • PDF24 Creator:免费的多功能PDF工具
  • 数据可视化大屏精选开源项目
  • rh134第二章复习总结
  • 搭建机器学习模型的数据管道架构方案
  • 富士施乐DocuCentre S2110故障代码01
  • 机器学习 - 使用 ID3 算法从原理到实际举例理解决策树
  • 智能家居芯片:技术核心与创新突破
  • (D题|矿井突水水流漫延模型与逃生方案)2025年高教杯全国大学生数学建模国赛解题思路|完整代码论文集合
  • C#之LINQ
  • [bat-cli] docs | 控制器
  • 你读过哪些深入浅出的(技术)书籍?
  • C++程序员必懂:std::bad_function_call异常的真相与预防秘诀
  • 一篇文章带你彻底搞懂 JVM 垃圾收集器
  • 深度学习之第七课卷积神经网络 (CNN)调整学习率
  • 为什么研发文档总是缺少关键信息
  • Redissson分布式锁
  • C++字符串字符替换程序
  • 2025数学建模国赛A题思路首发!
  • 力扣-二分法想法
  • simple-check-100
  • 自学嵌入式第三十五天:网络编程-网站
  • 分词器详解(二)
  • Webug3.0通关笔记18 中级进阶第06关 实战练习:DisCuz论坛SQL注入漏洞
  • Docker学习记录
  • springboot配置多数据源(mysql、hive)
  • 机器学习如何精准预测高值