ai-weather-assistant

May 27, 2026 · View on GitHub

基于 Next.js 15 + DeepSeek V4 + AG-UI/A2UI Protocol 的智能天气预报助手。支持自然语言查询天气、自动定位用户城市、流式实时回复,并以可视化卡片展示天气数据和出行建议。

功能特性

  • 自然语言交互 — 输入「今天天气怎么样?」即可查询,无需指定城市时自动获取定位
  • 流式实时回复 — 基于 AG-UI Protocol + SSE,逐字流式输出,体验流畅
  • A2UI 声明式 UI — 通过 A2UI v0.9 协议动态创建 Surface/Component,实现灵活的卡片渲染
  • 可视化天气卡片 — 温度、湿度、风速、天气状况以渐变卡片呈现,配色随天气变化
  • 出行建议卡片 — AI 生成的穿衣/带伞/防晒等建议以独立卡片展示
  • 智能城市纠错 — 输入无效城市时,通过 AG-UI 中断协议显示城市输入卡片,等待用户输入正确城市后继续查询
  • 双 API 容灾 — Open-Meteo 不可用时自动切换 wttr.in 备用 API

技术栈

层级技术
框架Next.js 15 (App Router) + React 19
LLMDeepSeek V4 API(OpenAI 兼容)
流式协议AG-UI Protocol + A2UI v0.9 over SSE
天气数据Open-Meteo(主)+ wttr.in(备)
定位Browser Geolocation + Nominatim 逆地理编码
样式Tailwind CSS v4
语言TypeScript

快速开始

# 1. 安装依赖
npm install

# 2. 配置环境变量
echo 'DEEPSEEK_API_KEY=sk-your-key' > .env.local
# API Key 获取:https://platform.deepseek.com

# 3. 启动开发服务器
npm run dev
# 打开 http://localhost:3000

项目结构

app/
  api/agent/route.ts    # AG-UI HTTP Endpoint — 接收消息,流式返回 AG-UI/A2UI 事件
  page.tsx              # 主页
  layout.tsx            # 根布局
components/
  chat.tsx              # 聊天 UI — AG-UI 事件订阅、A2UI 集成、中断处理、流式渲染
  weather-card.tsx      # 天气数据卡片(渐变背景,配色随天气变化)
  tips-card.tsx         # 出行建议卡片(琥珀色主题)
  city-input-card.tsx   # 城市输入卡片(AG-UI 中断时显示,输入框+确认按钮)
  a2ui-components.tsx   # A2UI 组件实现(A2UIWeatherCard、A2UITipsCard、A2UICityInputCard)
lib/
  agent.ts              # Agent 核心逻辑 — DeepSeek 流式调用 + 工具循环 + AG-UI 中断/恢复
  deepseek.ts           # DeepSeek API 客户端(基于 OpenAI SDK)
  tools.ts              # 天气工具定义 + 双 API 执行(Open-Meteo → wttr.in fallback)
  a2ui-types.ts         # A2UI v0.9 协议类型定义
  a2ui-catalog.ts       # A2UI Catalog 注册(WeatherCard/TipsCard/CityInputCard 渲染器)
  a2ui-renderer.tsx     # A2UI Surface 渲染器(管理组件树和 DataModel)

架构概览

用户浏览器                                Next.js Server
┌──────────────────────────┐              ┌──────────────────┐
│  Chat UI                 │  SSE 请求    │  Agent (AsyncGen) │
│  ├─ HttpAgent            │ ──────────►  │  DeepSeek V4 API  │
│  ├─ A2UIRenderer         │ ◄─────────── │  Weather Tool     │
│  ├─ WeatherCard          │  AG-UI/A2UI  │  A2UI Events      │
│  └─ TipsCard             │  事件流      └──────────────────┘
│                          │                      │
│  客户端工具执行:          │                      ▼
│  get_user_location       │            Open-Meteo / wttr.in
│  ├─ Browser Geolocation  │
│  └─ Nominatim 逆地理编码  │
└──────────────────────────┘

请求流程(未指定城市时):用户输入 → HttpAgent POST 到 /api/agent → LLM 调用 get_user_location(客户端工具)→ 服务端中断流,前端执行浏览器定位 + Nominatim 逆地理编码获取城市名 → 前端携带定位结果再次请求 /api/agent → LLM 调用 get_weather → 服务端查询天气 API → 创建 A2UI Surface (WeatherCard + TipsCard) → 结果回传 LLM → 生成自然语言回复 → 提取 <tips> 更新 A2UI DataModel → AG-UI/A2UI 事件流式返回前端 → 按事件流顺序渲染。

请求流程(已指定城市时):跳过定位环节,LLM 直接调用 get_weather 查询天气。

请求流程(城市无效时 — AG-UI 中断):用户输入无效城市 → LLM 调用 get_weather → 工具返回错误 → Agent 发出 AG-UI 中断(RUN_FINISHED { outcome: { type: "interrupt" } })→ 前端渲染 CityInputCard → 用户输入正确城市并确认 → 前端发送 resume 请求 → Agent 用修正后的城市重新查询 → 返回天气结果。

A2UI 事件流顺序

  1. a2ui_create_surface — 创建 Surface
  2. a2ui_update_components — 定义组件树(Column → [WeatherCard, TipsCard])
  3. a2ui_update_data_model — 更新天气数据到 /weather
  4. TEXT_MESSAGE_* — LLM 流式回复
  5. a2ui_update_data_model — 更新出行建议到 /tips(如有)

详细设计文档见 REQUIREMENTS.md

需求设计

REQUIREMENTS