Skip to content

JustForFunnnn/WeatherAgent

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

17 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

天气预报 Agent

一个命令行天气助手:用自然语言询问某个城市的天气,Agent 通过 Azure OpenAI 的 function calling 调用 Open-Meteo(免密钥)查询并返回该城市的当前实时天气

你> 北京今天天气怎么样?
助手> 北京当前晴,气温 28.3°C(体感 30.1°C),湿度 45%,风速 12.5 km/h。

特性

  • 🗣️ 自然语言交互:终端 REPL 对话,直接问"上海天气怎么样"。
  • 🔧 Function Calling:天气查询作为一个工具(get_weather)暴露给 LLM,由模型自己决定何时调用。
  • 🌤️ 免密钥天气源:Open-Meteo,自带 geocoding(城市名 → 经纬度),无需注册。
  • 🪝 Hook 机制:在 Agent 生命周期点(调用 LLM、函数调用、出错)触发回调,内置日志/观测 hook,可扩展监控、权限等。
  • 🛡️ 健壮:城市查不到、网络/服务出错都会优雅提示,REPL 不崩。
  • 全程可测:41 个单元测试,外部依赖全部 mock,离线即可运行。

架构

手写的简短 tool-calling 循环串起若干个职责单一的模块:

模块 职责
config.py 从环境变量(含 .env)加载并校验 Azure 配置
weather.py 对接 Open-Meteo:geocode + 当前天气 + WMO 天气码映射 + 错误处理
tools.py function-calling 层:工具 JSON schema + 把 tool_call 分发到具体实现
agent.py 编排器:持有 AzureOpenAI client,跑 tool-calling 循环,在生命周期点触发 hook
hooks.py Hook 机制:HookManager(注册/触发)+ 内置 logging_hook
colors.py 终端 ANSI 上色工具(仅在真实终端上色,管道/文件保持纯文本)
cli.py 交互式 REPL 入口

数据流

用户输入 ─► agent.handle(user_msg)
   ├─ 追加 user message,emit before_llm_call
   ├─ 调用 Azure OpenAI(messages + tools schema),emit after_llm_call
   ├─ 模型返回 tool_calls?
   │    ├─ 是 ─► emit before_tool_call → tools.dispatch → Open-Meteo
   │    │        → emit after_tool_call → 工具结果回填历史 ►► 再问一轮
   │    └─ 否 ─► 最终回答 ─► 返回给 CLI 打印
   └─ 出错 ─► emit on_error → 友好提示,REPL 不崩
   (max_tool_iterations = 5,防止工具反复触发导致死循环)

技术栈

Python · openaiAzureOpenAI client)· requests(Open-Meteo)· python-dotenv · pytest

配置

复制 .env.example.env,填入你的 Azure OpenAI API key:

AZURE_OPENAI_API_KEY=<你的-key>
AZURE_OPENAI_ENDPOINT=https://hgzch-mfb0pfgz-eastus2.cognitiveservices.azure.com/
AZURE_OPENAI_API_VERSION=2024-12-01-preview
AZURE_OPENAI_DEPLOYMENT=gpt-5-mini

.env 已被 .gitignore 排除,不会进 git。API key 只通过环境变量读取,绝不硬编码。 AZURE_OPENAI_DEPLOYMENT 填的是你在 Azure 上的部署名(不是模型名),且需要支持 function calling。

安装

python -m venv .venv
.venv\Scripts\Activate.ps1
pip install -r requirements.txt

运行

python -m weather_agent.cli

本项目采用 src/ 布局且未做 pip 安装,运行模块需要把 src 加入导入路径。 若直接运行报找不到模块,设置 PYTHONPATH=src 即可:

$env:PYTHONUTF8="1"; $env:PYTHONPATH="src"
python -m weather_agent.cli

输入 exit / quit / 退出 结束对话。

Hook 机制

Agent 在以下生命周期事件触发 hook,回调签名为 callback(event: str, data: dict)

事件 触发时机 data
before_llm_call 每次调用 LLM 前 iteration, message_count
after_llm_call LLM 返回后 tool_calls, content
before_tool_call 执行工具前 name, arguments
after_tool_call 执行工具后 name, arguments, result
on_error 调用出错时 error

CLI 默认开启内置的 logging_hook,把这些事件打印成日志。Hook 失败会被捕获并记录,绝不影响主流程。自定义 hook 示例:

from weather_agent.hooks import HookManager
from weather_agent.agent import WeatherAgent
from weather_agent.config import load_config

hooks = HookManager()
hooks.register("before_tool_call",
               lambda event, data: print(f"即将调用 {data['name']}"))

agent = WeatherAgent.from_config(load_config(), hooks=hooks)
print(agent.handle("深圳天气"))

Hook 目前为"观测型"(不改变控制流)。如需权限校验等"拦截型"能力,before_tool_call 是天然的扩展点。

日志输出

日志写到 stderr、对话写到 stdout,按角色分色(仅在真实终端上色,管道/重定向时自动关闭):

输出 颜色
系统提示 / 助手回复 🟢 绿色
用户输入(你> 🟡 黄色
函数调用相关日志 🔵 蓝色
错误 🔴 红色
其他日志(调用 LLM、返回最终回答等) 无色

运行时的典型日志:

→ 调用 LLM(第 1 轮,2 条消息)
← LLM 请求函数调用: get_weather          (蓝色)
  ⚙ 执行函数 get_weather({'city': '上海'})  (蓝色)
  ✓ 函数 get_weather 返回 {...}            (蓝色)
→ 调用 LLM(第 2 轮,4 条消息)
← LLM 返回最终回答

测试

所有外部依赖(Azure OpenAI、Open-Meteo)均 mock,离线运行:

$env:PYTHONPATH="src"; python -m pytest -v

项目结构

weather/
├── .env.example          # 环境变量模板(key 留空)
├── requirements.txt
├── pyproject.toml        # pytest 配置(pythonpath=src)
├── README.md
├── src/weather_agent/
│   ├── config.py
│   ├── weather.py
│   ├── tools.py
│   ├── agent.py
│   ├── hooks.py
│   ├── colors.py
│   └── cli.py
└── tests/                # config / weather / tools / agent / hooks / colors / cli

错误处理

情况 处理
城市查不到 工具返回 {"error": "city_not_found"},模型用自然语言告知用户
Open-Meteo 网络/服务错误 工具返回 {"error": "weather_service_unavailable"}
Azure OpenAI 出错 CLI 捕获并提示"AI 服务暂时不可用",REPL 不退出
工具参数非法 JSON 退化为空参数,交给模型自纠(不崩整轮)
工具调用次数过多 max_tool_iterations(5)兜底

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages