Python + LangChain Agent 实战:从单城市查询到多城市天气智能对比
LangChain系列文章超链接:
《Python+LangChain+大模型实战:使用通用配置加载器的Few‑Shot小样本提示词教程》
《使用Python版LangChain调用外部函数实战:实现智能天气查询》
《Python + LangChain Agent 实战:从单城市查询到多城市天气智能对比》
一、前言
在LangChain框架的实际应用中,Chain(链式)架构凭借其简洁高效的特性,成为处理简单工具调用场景的常用选择,尤其在天气查询这类具有明确流程的任务中,能够快速实现“调用天气函数—获取数据—返回结果”的固定链路。我们可以轻松通过Chain方式直接调用天气函数,按照预设的参数和流程,精准获取单个城市的气温、降水、风力等基础气象信息,满足“查询扬州今日天气”这类简单且明确的需求,如《使用Python版LangChain调用外部函数实战:实现智能天气查询》这边文章中所实现的功能。
但Chain架构的核心局限的在于其固定化的执行逻辑——它如同一条预设好轨道的列车,只能按照既定路线推进,无法根据实际需求的变化灵活调整方向。这种局限性在面对复杂的自然语言提问时,会变得尤为突出,比如当用户提出“比较一下南京和扬州哪个城市的天气更适合出去踏青”这样的需求时,Chain方式便会陷入无能为力的困境。踏青的适宜度不仅需要对比两地的基础气象数据,还需结合气温舒适度、降水概率、风力大小等多重因素综合判断,而固定模式的Chain只能机械调用天气函数获取单一数据,无法自主规划“查询两地天气—提取关键指标—对比分析—得出结论”的完整流程,更无法应对这种需要多步骤推理和动态决策的复杂场景。
正是这种Chain架构在复杂任务中的适配短板,推动了LangChain Agent(智能体)模式的引入与应用,成为破解复杂天气查询及各类多步骤任务的核心解决方案。与Chain“固定流程、被动执行”的逻辑不同,Agent搭载了具备自主思考能力的决策模块,相当于为工具调用赋予了“大脑”,其核心优势在于动态规划与灵活适配的能力。面对“比较南京和扬州哪个更适合踏青”这类复杂需求时,Agent无需预设固定流程,而是先自主拆解需求:明确踏青所需的核心气象指标(如气温在15-25℃、无降水、风力≤3级等),再规划执行步骤——先调用天气函数分别获取两地的实时及未来1-2天的气象数据,接着提取关键指标进行对比分析,若遇到数据不完整的情况,还能自主二次调用工具补充查询,最终整合所有信息得出“哪座城市更适合踏青”的明确结论。这种“理解需求—规划步骤—调用工具—分析结果—优化调整”的闭环能力,不仅完美破解了Chain模式无法应对的复杂天气查询难题,更让AI工具跳出了“机械执行”的局限,真正实现了从“被动响应”到“主动决策”的升级,让LangChain框架在实际应用中更具灵活性、智能化和实用性。
二、Chain架构的问题
《使用Python版LangChain调用外部函数实战:实现智能天气查询》这篇文章中,使用LangChain包中的chain链调用挑起查询的外部函数实现了大模型的天气查询功能,如告知大模型“帮我查询一下扬州的天气”,大模型能实时查询出当前的天气,具体代码可参考前文。但是如果告知大模型“对比一下南京和扬州的天气,哪个城市更适合出去踏青”,大模型则无能为力。具体输出如下:
E:\pycharm_code\.venv\Scripts\python.exe E:\pycharm_code\langchain_test\langchain_chain.py
{'app_id': 'ab203b794f7b27b777bb48f4eb30838c'}
ab203b794f7b27b777bb48f4eb30838c
定位成功:Nanjing City, CN
{'coord': {'lon': 118.7915, 'lat': 32.0616}, 'weather': [{'id': 800, 'main': 'Clear', 'description': '晴', 'icon': '01n'}], 'base': 'stations', 'main': {'temp': 19.26, 'feels_like': 18.49, 'temp_min': 19.26, 'temp_max': 19.26, 'pressure': 1012, 'humidity': 48, 'sea_level': 1012, 'grnd_level': 1010}, 'visibility': 10000, 'wind': {'speed': 2.44, 'deg': 110, 'gust': 3.64}, 'clouds': {'all': 0}, 'dt': 1776601919, 'sys': {'country': 'CN', 'sunrise': 1776547906, 'sunset': 1776594956}, 'timezone': 28800, 'id': 1799962, 'name': 'Nanjing', 'cod': 200}
使用天气查询返回的结果:
根据您提供的实时数据,以下是南京当前的天气情况解析:
**总体概况:**
目前南京天气晴朗,气温舒适,体感较为凉爽。
**详细数据:**
* **天气状况:** 晴(Clear),天空无云(云量为 0%)。
* **气温:** 当前温度为 **19.26°C**,体感温度约为 18.49°C。今日最低温和最高温均为 19.26°C(数据更新于当前时刻,未显示全天范围)。
* **湿度与气压:** 空气湿度为 **48%**,较为干爽;气压为 **1012 hPa**,处于标准水平。
* **风况:** 风向为东南偏东(110度),风速 **2.44 米/秒**(约 8.8 公里/小时),阵风风速可达 3.64 米/秒。
* **能见度:** 10 公里,视野清晰。
* **日出日落:** 今日日出时间为 05:31(UTC+8),日落时间为 18:35(UTC+8)。
**总结:**
这是一个适合户外活动的夜晚,气温适宜,微风轻拂,且无降水风险。
进程已结束,退出代码为 0
从代码输出可以看出,大模型只查询了南京的实时天气,并非调用天气函数分别查询南京和扬州的天气,然后根据两次查询的天气结果,分析得出哪个城市更适合出去踏青。我们来看一下Chain的整个流程图:

这张流程图展示了一个基于固定 Chain 的天气查询处理流程,其核心缺点在于 Chain 的工作模式是预先定义好的线性流程,只能按固定的 “用户输入→提取信息→调用天气工具→分析数据→输出结果” 路径执行,无法自主判断用户意图、灵活选择工具或调整流程,而引入 Agent 的核心价值就是让流程从 “固定执行” 升级为 “智能决策”,由 Agent 根据用户问题自主判断是否需要调用工具、调用哪个工具、以及如何组合工具完成任务,从而解决 Chain 模式无法应对复杂多变场景的根本问题。
三、Agent 核心介绍
LangChain Agent(智能体)是LangChain框架中具备自主决策、动态规划和工具调用能力的核心模块,本质是“决策大脑+工具集合”的组合体,核心目标是解决Chain架构无法应对的多步骤、复杂逻辑、需要动态调整的任务。与Chain的“固定流程执行”不同,Agent拥有自主思考和推理能力,能够根据用户输入的自然语言需求,自主判断任务目标、拆解执行步骤、选择合适的工具(如天气查询函数、数据处理工具等),并根据工具返回的中间结果,灵活调整执行策略,直至完成任务、输出最终答案。
LangChain Agent的核心价值的在于“智能化适配复杂场景”,尤其适用于需求模糊、步骤不固定、需要多工具协作的任务——除了前文提到的多城市天气对比踏青适宜度,还可应用于多数据源整合、复杂问题拆解、多工具联动等场景。其核心特点可概括为三点:一是自主决策,无需预设固定流程,能根据需求动态规划步骤;二是工具联动,可灵活调用各类预设工具(函数、API、数据库等),弥补自身能力局限;三是闭环迭代,能根据中间结果校验执行效果,及时调整策略,避免无效执行。
执行流程
LangChain Agent的执行流程核心是“决策-执行-反馈”的标准闭环逻辑,具体的执行流程如下图所示:

核心决策模块全程主导,根据用户需求拆解步骤、调度工具,结合反馈结果动态调整执行策略——若数据不完整则补充调用工具,若结论不明确则进一步获取信息,直至输出清晰、准确的最终答案,下面逐个解释一下每个模块的工作:
-
用户需求输入:接收用户自然语言需求(如“比较南京和扬州哪个更适合踏青”),传递至核心决策模块。
-
Agent核心决策模块:架构核心,负责解析用户需求、拆解任务步骤、判断下一步行动(如“需要调用天气函数获取两地数据”“需要对比气象指标”),同时接收反馈模块的结果,调整执行策略。
-
工具选择与调度模块:根据核心决策模块的指令,选择适配的工具(如天气查询函数),并调度工具执行,传递相关参数(如城市名称、查询时间)。
-
工具集合:Agent可调用的各类外部工具,包括函数、API、数据库等,本文场景中主要为天气查询函数,用于获取城市气象数据。
-
结果反馈与校验模块:接收工具执行的中间结果(如两地气象数据),校验数据完整性和有效性,反馈给核心决策模块,供其判断是否需要继续调用工具或进入下一步分析。
-
最终结果输出模块:将核心决策模块整合分析后的最终结论,以自然语言形式反馈给用户。
四、项目结构
langchain_test/
├── utils/
│ └── weather_util.py
├── config_loader.py
├── init_llm.py
└── langchain_agent.py
五、完整分文件源代码
1. config_loader.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
@Project :pythonProject
@File :config_loader.py
@Author :BillFang
@Date :2026/4/11 14:39
@Description :
"""
import configparser
import os
from typing import Dict, Any
class ConfigLoader:
# 单例模式:整个程序只加载一次配置,避免重复读文件
_instance = None
_config = None
def __new__(cls, config_path: str = r"D:/pythonCode/pythonProject/resources/config.properties"):
if cls._instance is None:
cls._instance = super().__new__(cls)
cls._instance._load_config(config_path)
return cls._instance
def _load_config(self, config_path: str):
"""内部方法:加载配置文件,做基础校验"""
if not os.path.exists(config_path):
raise FileNotFoundError(
f"配置文件不存在: {os.path.abspath(config_path)}\n"
"请在项目根目录创建 config.properties 文件,参考模板格式。"
)
# 用utf-8编码读取,避免中文乱码
self._config = configparser.ConfigParser()
self._config.read(config_path, encoding="utf-8")
def get(self, section: str, key: str) -> str:
"""
通用获取配置的方法
:param section: 配置的分组(比如[xiaomi]就是"xiaomi")
:param key: 配置的键名(比如api_key)
"""
try:
return self._config[section][key].strip()
except KeyError as e:
raise ValueError(
f"配置缺失: 找不到 [{section}] 下的 {key} 配置,请检查 config.ini"
) from e
def get_xiaomi_config(self) -> Dict[str, Any]:
"""专门获取小米MiMo模型的完整配置,自动转换类型"""
section = "xiaomi"
# 必填配置
config = {
"api_key": self.get(section, "api_key"),
"api_base_url": self.get(section, "api_base_url"),
"model": self.get(section, "model"),
}
# 可选配置,带默认值,用户不写也不会报错
try:
config["temperature"] = float(self.get(section, "temperature"))
except:
config["temperature"] = 0.7
try:
config["max_tokens"] = int(self.get(section, "max_tokens"))
except:
config["max_tokens"] = 1024
return config
def get_openweather_config(self) -> Dict[str, Any]:
section = "openweather"
# 必填配置
config = {
"app_id": self.get(section, "app_id"),
}
return config
这是一个配置加载工具类,采用单例模式确保只加载一次配置,负责读取指定路径下的 config.properties 配置文件,提供通用配置获取方法,并专门封装了获取小米大模型和天气接口配置的函数,为程序提供稳定的配置服务。
2. weather_util.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
@Project :pythonProject
@File :weather_util.py
@Author :BillFang
@Date :2026/4/15 09:19
@Description :
"""
import requests
from langchain_core.tools import tool
from config_loader import ConfigLoader
class OpenWeather():
def __init__(self, APPID):
self.app_id = APPID
def get_lat_lon(self, city_name):
geo_url = "http://api.openweathermap.org/geo/1.0/direct"
params = {
"q": city_name,
"limit": 1,
"appid": self.app_id,
}
try:
res = requests.get(geo_url, params=params)
res.raise_for_status()
data = res.json()
if not data:
print("未找到该城市")
return None, None
lat = data[0]["lat"]
lon = data[0]["lon"]
name = data[0]["name"]
country = data[0]["country"]
print(f"定位成功:{name}, {country}")
return lat, lon
except Exception as e:
print("获取经纬度失败:", e)
return None, None
@tool
def get_city_weather_data(city_name) -> dict:
"""
调用 OpenWeatherMap API 获取指定经纬度的天气信息
:param lat: 纬度
:param lon: 经度
:param appid: OpenWeatherMap 申请的 API Key
:return: 天气数据字典 / None
"""
config_loader = ConfigLoader()
openweather_config = config_loader.get_openweather_config()
print(openweather_config)
print(openweather_config["app_id"])
weather_client = OpenWeather(APPID=openweather_config["app_id"])
base_url = "https://api.openweathermap.org/data/2.5/weather"
lat, lon = weather_client.get_lat_lon(city_name)
# 请求参数
params = {
"lat": lat,
"lon": lon,
"appid": weather_client.app_id,
"units": "metric", # 单位:metric=摄氏度,imperial=华氏度,默认开尔文
"lang": "zh_cn" # 返回中文描述
}
try:
# 发送 GET 请求
response = requests.get(base_url, params=params)
# 检查请求是否成功
response.raise_for_status()
# 解析 JSON 数据
weather_data = response.json()
return weather_data
except requests.exceptions.RequestException as e:
print(f"请求出错:{e}")
return None
if __name__ == '__main__':
# 方法加上@tool时必须使用.invoke方法调用
print(get_city_weather_data.invoke('扬州'))
这段代码是天气查询工具模块,通过 OpenWeather API 获取城市天气,先根据城市名获取经纬度,再查询实时天气,封装成 LangChain 可调用的工具函数,供 Agent 自动调用使用。
3. init_llm.py
# !/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
@Project :pythonProject
@File :init_llm.py
@Author :BillFang
@Date :2026/4/17 15:38
@Description :
"""
from typing import Any, Sequence
from langchain_core.messages import AIMessage
from langchain_core.prompt_values import PromptValue
from langchain_core.runnables import Runnable
from langchain_openai import ChatOpenAI
from config_loader import ConfigLoader
from weather_util import get_city_weather_data
def load_llm_config() -> dict:
"""
加载LLM配置信息
Returns:
dict: 包含api_key、base_url、model的配置字典
"""
try:
config_loader = ConfigLoader()
xiaomi_config = config_loader.get_xiaomi_config()
return {
"api_key": xiaomi_config["api_key"],
"base_url": xiaomi_config["api_base_url"],
"model": xiaomi_config["model"]
}
except KeyError as e:
raise ValueError(f"配置文件缺少必要的键: {e}")
except Exception as e:
raise RuntimeError(f"加载配置失败: {e}")
def init_llm() -> ChatOpenAI:
"""
初始化LLM实例并绑定工具
Returns:
ChatOpenAI: 绑定了天气查询工具的LLM实例
"""
llm_config = load_llm_config()
llm = ChatOpenAI(
api_key=llm_config["api_key"],
base_url=llm_config["base_url"],
model=llm_config["model"]
)
return llm
def init_llm_with_tools() -> Runnable[PromptValue | str | Sequence[Any], AIMessage]:
# 绑定工具
llm = init_llm()
tools = [get_city_weather_data]
return llm.bind_tools(tools)
这段代码是LLM 模型初始化工具模块,负责从配置文件加载大模型参数、创建模型实例,并给模型绑定天气查询工具,供上层 Agent 调用,整体功能简洁且专一。
4. langchain_agent.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
@Project :pythonProject
@File :langchain_agent.py
@Author :BillFang
@Date :2026/4/17 13:58
@Description : LangGraph Agent 实现天气查询功能
"""
# 标准库导入
from typing import Annotated, Literal
# 第三方库导入
from langchain_core.messages import SystemMessage, HumanMessage
from langgraph.graph import MessagesState, StateGraph
from langgraph.prebuilt import ToolNode
# 本地模块导入
from init_llm import init_llm_with_tools
from weather_util import get_city_weather_data
# 初始化LLM实例
llm = init_llm()
def main():
"""主函数:执行天气查询示例"""
try:
# 构建工作流
agent = create_agent(
llm,
tools=[get_city_weather_data],
system_prompt="你是一个非常厉害的AI助手,但不了解实时的一些知识"
)
# 执行查询
query = "今天北京和扬州的天气比较,哪个城市的天气更适合出去踏青?"
result = agent.invoke(
{"messages": [HumanMessage("今天北京和扬州的天气比较,哪个城市的天气更适合出去踏青?")]}
, debug=True)
print(result["messages"][-1].content)
except Exception as e:
print(f"程序执行失败: {e}")
if __name__ == '__main__':
main()
该代码通过create_agent构建具备工具调用能力的 AI Agent,先从外部模块加载大模型和天气查询工具函数,定义主函数构建工作流,将天气工具绑定到 Agent 并设置系统提示词,然后传入包含多城市天气对比的复杂用户查询,Agent 会自主判断是否需要调用工具、自动执行天气查询工具获取数据,最终整理结果输出,整体实现了不依赖固定流程、可自主决策完成复杂天气任务的智能交互。
六、运行结果
查询结果:
根据查询到的天气数据,我来为您分析一下北京和扬州的天气情况:
**北京天气:**
- 天气状况:晴天
- 温度:20.94°C
- 湿度:32%
- 风速:3.27 m/s
- 能见度:10公里
**扬州天气:**
- 天气状况:阴天,多云
- 温度:21.75°C
- 湿度:64%
- 风速:3.29 m/s
- 能见度:10公里
**综合比较:**
从踏青的角度来看,**北京的天气更适合出去踏青**,原因如下:
1. **天气状况**:北京是晴天,阳光充足,视野开阔,非常适合户外活动;而扬州是阴天多云,光线相对较暗。
2. **湿度条件**:北京湿度较低(32%),体感舒适;扬州湿度较高(64%),可能会感觉有些闷热潮湿。
3. **温度适宜**:两个城市的温度都很舒适(20-22°C左右),但北京的干燥天气更适合长时间户外活动。
4. **能见度**:两地能见度都很好(10公里),但晴天的北京视野会更加开阔。
**建议**:如果您今天计划踏青,北京是更好的选择。不过扬州的温度稍高一点,如果您更喜欢温和的天气,也可以考虑扬州,只是需要做好防云遮阳的准备。
进程已结束,退出代码为 0
七、运行结果分析
本次运行结果完美验证了LangChain Agent在复杂天气查询场景中的核心优势,结合输出内容与程序逻辑,可从4个核心维度展开分析,清晰体现Agent与传统Chain架构的本质区别:
第一,自主理解复杂需求,无需人工拆解。用户需求为“比较北京和扬州哪个城市的天气更适合出去踏青”,属于典型的多步骤复杂需求,需经历“获取两地数据—提取核心指标—对比分析—给出结论”四个环节。Agent无需预设固定流程,通过核心决策模块自动解析需求核心(踏青适宜度的关键气象指标),无需人工干预即可启动完整执行链路,这是传统Chain架构无法实现的——Chain仅能执行“单一城市天气查询”的固定流程,无法应对多城市对比、综合分析类需求。
第二,自主多轮调用工具,保障数据完整性。运行过程中,Agent根据需求自主判断需要调用2次天气查询工具(分别获取北京、扬州的实时气象数据),无需人工编写多轮调用逻辑。工具调用后,自动接收返回的JSON数据(包含气温、湿度、风速、能见度等核心信息),并校验数据完整性,确保后续分析有足够的数据支撑,避免了传统代码中“手动调用工具、手动校验数据”的繁琐操作。
第三,智能分析数据,输出人性化结论。Agent不仅能获取实时气象数据,还能结合“踏青”场景的需求,自动提取关键对比指标(天气状况、湿度、温度、能见度),并进行结构化分析——明确指出北京晴天、低湿度的优势,同时客观说明扬州的特点及适配人群,最终给出可落地的踏青建议。这种“数据获取—分析解读—建议输出”的一体化能力,让结果更具实用性,面向最终用户可直接开箱即用,而传统工具调用仅能返回原始JSON数据,需额外编写分析逻辑。
第四,闭环执行,容错性强。程序运行过程中,agent自动判断是否需要继续调用工具:若工具返回数据完整,则进入分析环节;若数据缺失(如某城市经纬度获取失败、气象数据为空),则会自动重新调用工具补充查询,直至获取有效数据。本次运行中,两地气象数据均完整返回,Agent顺利完成分析并输出结论,进程正常结束,充分体现了其闭环迭代的执行特性。
此外,运行结果还直观对比了“Agent智能查询”与“传统大模型直接查询”的差异——若直接询问大模型天气,会因无法访问实时数据而无法给出有效答案(参考参考文档中“直接询问大模型”的输出结果),而Agent通过调用OpenWeatherMap API获取实时数据,完美解决了大模型“知识库过期、无实时访问能力”的痛点,让查询结果更精准、更具时效性。
八、总结
本文以“多城市天气对比踏青适宜度”为实战场景,完整实现了LangChain Agent的天气查询功能,从项目架构设计、代码实现到运行验证,清晰展现了Agent如何破解传统Chain架构的局限,核心总结如下:
从核心逻辑来看,传统单城市天气查询的核心痛点的是“固定流程+单次调用+无记忆+无分析”,仅能满足简单的查询需求,无法应对多步骤、复杂逻辑的场景;而LangChain Agent则实现了“自主决策+多轮调用+上下文记忆+智能分析”的升级,其核心价值在于为大模型赋予了“主动思考”的能力——无需人工预设执行步骤,无需手动处理工具调用与数据校验,即可自主拆解复杂需求、调度工具、分析数据、输出结论,真正实现了从“机械执行”到“智能决策”的跨越。
从实战价值来看,本文采用标准工程化项目结构(分模块封装配置、工具、LLM初始化、主程序),代码可直接复用、可扩展:config_loader.py实现配置统一管理,避免硬编码带来的维护难题;weather_util.py封装天气查询工具,通过@tool装饰器快速集成到LangChain生态;init_llm.py统一初始化LLM并绑定工具,降低代码冗余;langchain_agent.py通过create_agent函数构建agent,实现Agent的闭环执行。这种结构设计不仅提升了代码的可读性和可维护性,也为后续拓展多工具(如快递查询、股票查询)提供了便捷——只需新增工具函数,无需重构核心流程。
从技术意义来看,本次实战清晰验证了LangChain工具调用能力的核心价值:LangChain Agent是连接大模型与外部世界的“桥梁”,通过将外部API(如OpenWeatherMap)封装为Tool,让大模型突破了“知识库过期”“无实时访问能力”的局限,拓展了大模型的应用边界。无论是多城市天气对比、多数据源整合,还是复杂问题拆解,Agent都能凭借其自主决策和闭环迭代能力,高效完成任务,相比传统代码更具智能化、灵活性和扩展性。
综上,LangChain Agent并非对Chain架构的替代,而是对复杂场景的补充与升级——简单、固定流程的任务可采用Chain实现高效执行,而多步骤、复杂逻辑、需要动态调整的任务,Agent则是更优选择。本文的实战案例不仅为LangChain Agent的学习提供了可落地的参考,也为大模型应用开发(尤其是实时数据查询类场景)提供了思路,后续可通过新增错误重试、参数校验、多轮对话记忆等功能,进一步提升程序的健壮性和用户体验。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)