从天气API调用到智能化服务:基于openJiuwen的智能天气助手智能体开发全流程
项目背景与价值
在数字化时代,天气信息已成为人们日常决策的重要依据。传统的天气应用多停留在数据展示层面,而智能天气助手则通过AI技术实现了从数据提供到智能服务的跃迁。本项目基于openJiuwen Agent Core框架,构建了一个能够理解自然语言、提供个性化建议、具备智能决策能力的天气助手。
项目地址:https://atomgit.com/openJiuwen?utm_source=csdn
项目环境搭建
环境要求
- Python 3.11+
- pip包管理器
安装依赖
# 克隆项目
git clone https://atomgit.com/openJiuwen/agent-core
cd agent-core
# 创建虚拟环境
python -m venv venv
source venv/bin/activate
# 安装依赖
pip install -e .
配置环境变量
在项目根目录创建.env文件:
API_BASE=xxx
API_KEY=xxxxx
MODEL_NAME=xxxx
MODEL_PROVIDER=openai
核心技术栈与架构
openJiuwen框架选择
我选择openJiuwen Agent Core作为开发框架,主要基于以下考虑:
- ReAct架构支持:支持推理与行动的智能体模式
- 工具集成能力:灵活的外部API集成机制
- 对话管理:强大的上下文理解与管理能力
- 可扩展性:模块化设计便于功能扩展
ReAct架构详解
ReAct(Reasoning and Acting)架构是本项目的核心,它允许智能体在推理(制定计划、进行逻辑思考)和行动(与外部工具交互)之间交替进行。这种架构特别适合需要外部知识和工具的复杂任务。
在智能天气助手中,ReAct架构的工作流程如下:
- 观察(Observation):接收用户输入,如"明天杭州天气如何?"
- 推理(Thought):分析用户意图,确定需要调用天气API
- 行动(Action):调用WeatherReporter工具查询天气
- 观察(Observation):获取天气API返回的结果
- 推理(Thought):分析天气数据,准备响应
- 最终响应(Final Response):向用户提供天气信息
# ReAct智能体的核心工作流程
class ReActAgent:
def invoke(self, input_data):
# 初始化对话历史
history = []
# 添加用户输入
history.append({"role": "user", "content": input_data["query"]})
# 循环直到任务完成
for iteration in range(MAX_ITERATIONS):
# 使用LLM生成下一步动作
response = self.model.generate(history)
# 解析LLM输出,判断是工具调用还是最终响应
if self._is_tool_call(response):
# 执行工具调用
tool_result = self._execute_tool(response)
# 将工具结果添加到历史
history.append({"role": "tool", "content": tool_result})
else:
# 返回最终结果
return {"result": response}
return {"result": "任务超时或无法完成"}
在实际的ReAct循环中,智能体能够:
- 分析用户查询的意图
- 决定是否需要调用外部工具
- 解析工具返回的结果
- 生成自然语言响应
- 处理错误和异常情况
系统架构设计
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ 用户输入 │───▶│ ReAct智能体 │───▶│ 响应生成 │
│ (自然语言) │ │ (决策引擎) │ │ (格式化) │
└─────────────────┘ └──────────────────┘ └─────────────────┘
│
▼
┌──────────────────┐
│ 天气API工具 │
│ (30日预报) │
└──────────────────┘
模块化实现详解
工具模块
工具模块负责与外部API交互,提供天气数据查询功能。
天气查询工具实现:
def build_weather_tool():
import requests
import json
def get_weather_info(location: str = "", date: str = ""):
"""通过一刻天气API获取30日天气信息"""
try:
# 如果date为空,使用当前日期
if not date or date.strip() == "":
from datetime import datetime
date = datetime.now().strftime("%Y-%m-%d")
# 如果location为空字符串或None,使用空值让API自动根据IP定位
city_param = location if location and location.strip() != "" else ""
url = f"https://v1.yiketianqi.com/free/month?appid=xxxx&appsecret=xxxx&unescape=1&city={city_param}"
response = requests.get(url, timeout=10)
if response.status_code == 200:
data = response.json()
if 'errcode' in data and data['errcode'] == 100:
# API返回错误,errcode为100表示错误
return {"error": f"无法获取天气信息: {data.get('errmsg', '未知错误')}"}
else:
# 成功获取天气数据,查找指定日期的天气
target_date_weather = None
for day_data in data.get('data', []):
if day_data.get('date') == date:
target_date_weather = day_data
break
if target_date_weather:
# 找到指定日期的天气数据
weather_info = {
"city": data.get("city", location or "当前定位"),
"date": date,
"weather": target_date_weather.get("wea", "未知"),
"temperature": f"最高{target_date_weather.get('tem_day', '?')}°C, 最低{target_date_weather.get('tem_night', '?')}°C",
"wind": f"{target_date_weather.get('win', '未知')} {target_date_weather.get('win_speed', '未知')}",
"all_data": data # 保留所有数据,以备需要
}
return weather_info
else:
# 如果没有找到指定日期,返回未来7天的天气预报,尽管API返回30天数据但实际代码中使用forecast_7days字段
forecast_list = []
for day_data in data.get('data', []):
forecast_list.append({
"date": day_data.get("date"),
"weather": day_data.get("wea", "未知"),
"temperature": f"最高{day_data.get('tem_day', '?')}°C, 最低{day_data.get('tem_night', '?')}°C",
"wind": f"{day_data.get('win', '未知')} {day_data.get('win_speed', '未知')}"
})
weather_info = {
"city": data.get("city", location or "当前定位"),
"date": date,
"weather": "未找到指定日期的天气数据",
"temperature": "N/A",
"wind": "N/A",
"forecast_7days": forecast_list, # 实际代码中是forecast_7days,尽管API返回30天数据
"all_data": data
}
return weather_info
else:
return {"error": f"API请求失败,状态码: {response.status_code}"}
except Exception as e:
return {"error": f"获取天气信息时发生错误: {str(e)}"}
from openJiuwen.core.utils.tool.function.function import LocalFunction
from openJiuwen.core.utils.tool.param import Param
return LocalFunction(
name="WeatherReporter",
description="天气查询插件,可以查询指定地点未来30天的天气信息,当城市为空时会根据IP自动定位",
params=[
Param(name="location", description="天气查询的地点,可为空(为空时将根据IP自动定位)", type="string", required=False),
Param(name="date", description="天气查询的时间,格式为YYYY-MM-DD", type="string", required=True),
],
func=get_weather_info
)
工具模块特点:
- 实现了完整的错误处理机制
- 支持自动IP定位功能,支持用户免说地点,交互更加自然。
- 提供了数据格式标准化
- 包含了超时处理机制
openJiuwen也支持使用@tool装饰器和封装Restful接口两种方式快速自定义工具,详见:agent-core开发指南->基础功能->自定义工具。
模型配置模块
模型配置模块负责设置LLM参数和API连接信息。
模型配置实现:
def build_model():
return ModelConfig(
model_provider=MODEL_PROVIDER,
model_info=BaseModelInfo(
model=MODEL_NAME,
api_base=API_BASE,
api_key=API_KEY,
temperature=0.7, # 控制生成的随机性,0.7提供平衡的创造性和一致性
top_p=0.9, # 控制输出的多样性,0.9保留最可能的90%词汇
timeout=30, # API调用超时时间
),
)
模型配置是智能体性能的关键因素。在智能天气助手中,我精心调整了以下参数:
- temperature (0.7): 这个值在创造性和一致性之间取得了良好平衡。对于天气助手,既需要一定的创造性来生成自然的响应,又需要保持信息的准确性。
- top_p (0.9): 核采样参数,确保输出在保持自然性的同时不会过于随机。
- timeout (30): 考虑到天气API响应和LLM推理的时间,设置30秒超时以确保用户体验。
模型,使用的是硅基流动提供的OpenAI兼容的API,这允许我利用成熟的LLM服务来实现复杂的推理和自然语言生成能力。模型需要理解自然语言查询、决定何时调用工具、处理工具返回的结果,并生成自然的响应。
提示词工程模块
提示词工程模块定义了智能体的行为规则和交互逻辑。
系统提示词设计:
def build_prompt():
template = (
"你是智能天气助手,主要负责回答用户的天气查询及相关生活建议。"
"1. 默认查今天({})的天气;"
"2. 调用工具时,直接使用中文城市名,例如:北京、上海、广州等;"
"3. 城市参数格式为中文城市名,如'北京'、'上海'、'广州'等;"
"4. 如果用户没有明确指定城市,可以将城市参数留空,API会根据IP自动定位;"
"5. 如果用户没有明确指定日期,使用今天;"
"6. 当用户询问穿衣建议、出行建议或类似问题时,如果涉及天气相关,应先查询天气,然后根据天气情况给出建议;"
"7. 如果用户的问题与天气关系不大,可以不使用天气工具,直接回答用户问题;"
"8. 对于穿衣建议类问题,如果用户没有指定城市,必须先自动定位查询本地天气,再给出穿衣建议。"
"9. 对于不依赖天气就可以作答的问题,视为超出能力范畴,不予回答,并为用户介绍你的能力。"
)
today = datetime.now().strftime("%Y-%m-%d")
return [{"role": "system", "content": template.format(today)}]
提示词工程的核心原则:
- 定义了明确的工具调用规则
- 规定了自动定位逻辑
- 设置了智能决策条件
- 确定了超出范围问题的处理方式
智能体核心模块
智能体核心模块整合了所有组件,创建完整的智能体实例。
智能体创建:
def create_weather_agent():
"""
创建天气查询智能体
"""
from openJiuwen.core.utils.tool.param import Param
from openJiuwen.core.utils.llm.base import BaseModelInfo
from openJiuwen.core.component.common.configs.model_config import ModelConfig
from openJiuwen.agent.react_agent import create_react_agent_config, ReActAgent
from openJiuwen.agent.common.schema import PluginSchema
from datetime import datetime
# 1. 创建模型配置
def build_model():
return ModelConfig(
model_provider=MODEL_PROVIDER,
model_info=BaseModelInfo(
model=MODEL_NAME,
api_base=API_BASE,
api_key=API_KEY,
temperature=0.7, # 控制生成的随机性,0.7提供平衡的创造性和一致性
top_p=0.9, # 控制输出的多样性,0.9保留最可能的90%词汇
timeout=30, # API调用超时时间
),
)
# 2. 创建提示词模板
def build_prompt():
template = (
"你是智能天气助手,主要负责回答用户的天气查询及相关生活建议。"
"1. 默认查今天({})的天气;"
"2. 调用工具时,直接使用中文城市名,例如:北京、上海、广州等;"
"3. 城市参数格式为中文城市名,如'北京'、'上海'、'广州'等;"
"4. 如果用户没有明确指定城市,可以将城市参数留空,API会根据IP自动定位;"
"5. 如果用户没有明确指定日期,使用今天;"
"6. 当用户询问穿衣建议、出行建议或类似问题时,如果涉及天气相关,应先查询天气,然后根据天气情况给出建议;"
"7. 如果用户的问题与天气关系不大,可以不使用天气工具,直接回答用户问题;"
"8. 对于穿衣建议类问题,如果用户没有指定城市,必须先自动定位查询本地天气,再给出穿衣建议。"
"9. 对于不依赖天气就可以作答的问题,视为超出能力范畴,不予回答,并为用户介绍你的能力。"
)
today = datetime.now().strftime("%Y-%m-%d")
return [{"role": "system", "content": template.format(today)}]
# 3. 创建Agent配置
agent_config = create_react_agent_config(
agent_id="weather_assistant",
agent_version="0.1.0",
description="Jiuwen 智能天气助手 - 不仅提供天气查询,还能根据天气情况提供穿衣建议、出行提示等智能服务",
model=build_model(),
prompt_template=build_prompt(),
)
# 4. 创建ReAct Agent实例
weather_agent = ReActAgent(agent_config)
# 5. 添加天气查询工具
weather_agent.add_tools([build_weather_tool()])
return weather_agent
效果展示
智能体运行起来,有一个提示信息展示和简单的交互界面,等待输入问题。

天气查询
直接问天气
如下图所示,问题是上海明天的天气。可以看到,能够正常调用天气查询工具,并且工具成功返回了了目标城市为上海的天气,最后智能体调用大模型,将api返回的天气进行整理润色,并给出了一些总结建议。


不带位置问天气
也支持不带地理位置直接问天气情况。如下图所示,问题是明天天气如何?可以看到,也是能够正常调用天气查询工具,并且自动识别出目标城市为杭州。


穿衣建议
针对问题:下周一上班,穿什么衣服合适,智能体的响应结果如下所示:

出行建议
针对问题:我下周要去深圳出差,给我一些出行建议,智能体的响应结果如下所示:

针对问题:周末适合户外活动吗?想带娃出去逛一逛。,智能体的响应结果如下所示:

项目总结
智能天气助手项目展示了AI技术在传统服务领域的应用价值。通过openJiuwen Agent Core框架,我成功构建了一个具备智能决策、自然语言理解、个性化服务等能力的智能助手。
项目的核心价值在于:
- 智能化升级:从数据查询到智能服务的跃迁
- 用户体验优化:自然语言交互,个性化服务
- 技术架构先进:ReAct架构,模块化设计
- 扩展性强:支持多种应用场景和功能扩展
通过本项目,我验证了ReAct架构在构建智能助手方面的有效性,展示了如何将简单的天气API数据转化为对用户有价值的智能服务。随着AI技术的不断发展,智能天气助手将为用户提供更加智能、便捷、个性化的服务体验。
关于openJiuwen的更多信息,可参考:
- openJiuwen项目地址:https://atomgit.com/openJiuwen?utm_source=csdn
- openJiuwen官网:https://www.openJiuwen.com?utm_source=csdn
更多推荐

所有评论(0)