naumanaarif/BakhabarAI
GitHub: naumanaarif/BakhabarAI
该系统是一个基于多 Agent 架构的城市危机情报与应急响应平台,旨在通过融合异构实时数据并借助 AI pipeline,解决城市灾害管理中信息碎片化与决策迟缓的问题。
Stars: 1 | Forks: 0
# BakhabarAI
## 目录
1. [项目概述](#1-project-overview)
2. [解决方案设计理念](#2-solution-design-philosophy)
3. [系统架构](#3-system-architecture)
4. [后端:FastAPI](#4-backend-fastapi)
5. [Agent 编排:Google ADK](#5-agent-orchestration-google-adk)
6. [API 集成](#6-api-integrations)
7. [数据策略:真实与模拟](#7-data-strategy-real-vs-mock)
8. [Firebase 集成](#8-firebase-integration)
9. [Flutter 移动应用](#9-flutter-mobile-application)
10. [设计系统](#10-design-system)
11. [页面与导航](#11-screens--navigation)
12. [数据模型](#12-data-models)
13. [演示场景](#13-demo-scenarios)
14. [配置与环境](#14-configuration--environment)
15. [运行项目](#15-running-the-project)
16. [目录结构](#16-folder-structure)
## 1. 项目概述
**BakhabarAI** 是一个专为巴基斯坦城市环境构建的全栈、多 Agent 危机情报系统。其目的是解决市政应急管理面临的核心挑战:信息碎片化、充满噪音且传递缓慢,从而阻碍了及时、协调的灾难响应。
该系统接收异构信号(实时天气数据、市民报告、传感器遥测数据、紧急呼叫),将它们送入由 **Google Antigravity (ADK)** 编排的 5 阶段 AI Agent pipeline,并直接通过 **Firebase Firestore** 实时将结构化的危机情报——严重程度分类、资源分配计划、影响模拟和利益相关者通知——推送到高级的 Flutter 移动仪表板中。
**核心能力:**
- 带有置信度评分的实时城市危机检测
- 具备权衡推理的多危机资源分配
- 针对每个事件的影响前后模拟
- AI 生成的双语利益相关者通知(英语 + 罗马乌尔都语)
- 终端用户可见的实时 Agent 追踪日志
- 带有即时地图可见性的市民事件报告
- 通过信号冲突解决进行误报检测
## 2. 解决方案设计理念
### 为什么选择 Agentic AI?
传统的基于规则的应急系统无法处理真实世界危机数据的模糊性、规模和噪音。BakhabarAI 采用代理方法,每个专门的 AI Agent 负责一项职责,并将结构化的、丰富的上下文传递给下一个环节。这反映了真实应急运营中心的工作方式——在信号接收、分析、计划、执行和报告方面具有不同的角色。
### 混合智能模型
该系统有意结合了:
- **确定性逻辑**,用于时间紧迫的结构化操作(资源贪婪分配、信号可信度评分、数据库写入)
- **LLM 推理**,用于模糊的判断任务(危机类型分类、影响叙述生成、乌尔都语警报起草)
- 从 Firestore 到 Flutter 客户端的**实时流**,因此无需轮询
### 优雅降级
每个依赖 LLM 的阶段都有硬编码的确定性回退方案。如果 Groq 或 Gemini API 不可用,pipeline 将继续输出基于模板的结果。这确保了系统在现场演示或生产事件期间绝不会发生静默失败。
## 3. 系统架构
```
graph TD
%% Style Definitions
classDef default fill:#ffffff,stroke:#6b6b6b,stroke-width:1px,color:#1a1a1a;
classDef highlight fill:#ff6036,stroke:#ff6036,stroke-width:2px,color:#ffffff;
classDef softBg fill:#f4f1e9,stroke:#6b6b6b,stroke-width:1px,color:#1a1a1a;
classDef dbStyle fill:#ffffff,stroke:#ef4444,stroke-width:1.5px,color:#1a1a1a;
classDef apiStyle fill:#ffffff,stroke:#f59e0b,stroke-width:1.5px,color:#1a1a1a;
subgraph Mobile["📱 Flutter Mobile App (Android APK)"]
direction TB
Nav["4-Tab Navigation & Map UI
(Glassmorphic Overlays)"] DioClient["Dio HTTP Client"] FS_SDK["Firebase Firestore SDK"] end subgraph Backend["⚙️ FastAPI Backend (Python 3.11+)"] direction TB APIServer["FastAPI Server
(Uvicorn)"] Tracer["AgentTracer Log Collector"] subgraph Routes["REST Endpoints"] API_Incidents["/api/incidents"] API_Scenario["/api/run-scenario"] API_Report["/api/report"] API_Logs["/api/logs"] API_Places["/api/places/autocomplete"] end end subgraph ADK["🤖 Google ADK Agent Pipeline"] direction TB ADK_Orch["Google ADK Orchestration
(SequentialAgent)"] S1["Stage 1: SignalFusionAgent
(Normalizes Signal Feed)"] S2["Stage 2: DetectorAgent
(Classifies Severity & Type)"] S3["Stage 3: ResourcePlannerAgent
(Resource Trade-off & Rules)"] S4["Stage 4: SimulationAgent
(Simulates Actions & Routes)"] S5["Stage 5: ReporterAgent
(Generates Outcomes & Stakeholder Alerts)"] ADK_Orch --> S1 S1 --> S2 S2 --> S3 S3 --> S4 S4 --> S5 end subgraph DB["🔥 Firebase Firestore"] direction TB C_Signals[("signals")] C_Incidents[("incidents")] C_Resources[("resources")] C_Simulations[("action_simulations")] C_Logs[("agent_logs")] end subgraph Ext["🗺️ Google Maps Platform APIs"] direction TB API_Geo["Geocoding API"] API_Dist["Distance Matrix API"] API_Dir["Directions API"] API_PlNew["Places API (New)"] API_Weather["Weather API"] end subgraph LLM["🧠 Large Language Models"] direction TB Gemini["Gemini 2.0 Flash (Primary via ADK)"] Groq["Groq Llama-3.1-8b (Secondary Fallback)"] end %% Flow and Connections DioClient <-->|HTTP / REST| APIServer FS_SDK <.->|Real-time Streams| DB APIServer -->|Triggers Pipeline Async| ADK_Orch APIServer <-->|CRUD Operations| DB ADK -->|Writes Outcomes / Logs| DB ADK -->|Tool Calls| Ext ADK <-->|Reasoning & Alert Drafts| LLM Tracer -->|Persists Agent Steps| DB %% Apply Classes class Mobile softBg; class ADK softBg; class APIServer highlight; class ADK_Orch highlight; class Nav highlight; class C_Signals,C_Incidents,C_Resources,C_Simulations,C_Logs dbStyle; class API_Geo,API_Dist,API_Dir,API_PlNew,API_Weather apiStyle; ``` ### 组件职责 | 组件 | 技术 | 职责 | |:---|:---|:---| | 移动客户端 | Flutter (Dart) | 仪表板、地图、报告、实时流 | | HTTP 层 | Dio | 向 FastAPI 发起 REST 调用以执行操作 | | 实时层 | Firebase Firestore SDK | 实时事件、日志、资源、模拟流 | | API 服务器 | FastAPI (uvicorn) | 路由处理、pipeline 触发、CORS | | Agent Pipeline | Google ADK | 编排 5 阶段危机处理 | | 主 LLM | 通过 ADK 调用 Gemini 2.0 Flash | 分类、模拟生成 | | 辅助 LLM | Groq llama-3.1-8b-instant (通过 litellm) | 文本补全、速率限制回退池 | | 数据持久化 | Firebase Firestore | 所有结构化数据 | | 追踪记录器 | 自定义 `AgentTracer` | Agent 日志的内存 + Firestore 持久化 | | 地图 | Google Maps Platform | 地理编码、路线规划、地点自动补全 | ## 4. 后端:FastAPI ### 入口点:`backend/main.py` FastAPI 应用启动时采用了开放 CORS 的配置(允许来自任何源的移动应用请求),包含了主路由器,并打印了一个列出所有活跃端点的启动横幅。 ``` app = FastAPI(title="BakhabarAI Backend", version="1.0.0") app.add_middleware(CORSMiddleware, allow_origins=["*"], ...) app.include_router(mock_data_router.router) ``` ### API 端点:`backend/routers/mock_data_router.py` 所有路由均带有 `/api` 前缀。 | 方法 | 端点 | 描述 | |:---|:---|:---| | `GET` | `/api/incidents` | 从 Firestore 获取所有**活跃**事件。将 Firestore `GeoPoint` 标准化为 `{lat, lng}` JSON。 | | `GET` | `/api/incidents/{id}` | 根据文档 ID 获取单个事件。 | | `POST` | `/api/report` | 接收市民报告。对位置进行地理编码,立即在 Firestore 中创建初步事件,保存信号,然后异步触发 pipeline。 | | `POST` | `/api/run-scenario` | 将两个硬编码的伊斯兰堡演示事件(G-10 洪水,I-8 热浪)注入 Firestore,然后在后台启动完整的 pipeline。立即返回 `202 Accepted`。 | | `GET` | `/api/logs` | 从内存中的 `AgentTracer` 返回所有 Agent 追踪条目。 | | `GET` | `/api/places/autocomplete` | 代理 Google Places Autocomplete(优先使用新 API,经典 API 作为回退)。 | | `GET` | `/api/debug/ping` | 健康检查。返回服务器状态和追踪计数。 | | `DELETE` | `/api/debug/logs` | 在全新运行场景之前清除内存中的追踪缓冲区。 | | `GET` | `/api/debug/incidents` | 返回所有 Firestore 事件,不论状态如何(用于调试)。 | ### 市民报告流程(`POST /api/report`) 1. 从消息文本中提取位置名称(寻找 `"in"`、`"at"` 或 `:` 模式) 2. 通过 Google Geocoding API 对提取的位置进行地理编码 3. **立即在 Firestore 中创建一个 `MEDIUM`(中等)置信度的初步事件**(以便它能无延迟地显示在地图上) 4. 如果提交了 `media_url`,请将其直接附加到事件文档中 5. 将原始信号保存到 Firestore 中,并标记 `trigger_type: "manual"` 6. 作为异步后台任务启动危机 pipeline 以细化该事件 7. 立即返回 `{"status": "success"}`(非阻塞) ### Agent 追踪记录器:`backend/tracer.py` `AgentTracer` 是一个单例,在所有 pipeline 阶段中共享使用。每次调用 `tracer.log(...)` 都会做两件事: 1. **内存追加**:将追踪条目添加到 `self.traces[]` 中(由 `/api/logs` 提供) 2. **后台 Firestore 写入**:使用守护线程将日志持久化到 `agent_logs` Firestore 集合中(供 Flutter 应用的实时流使用) ``` class AgentTracer: def log(self, agent_name, action, input_data, output_data, confidence): # 1. Append to in-memory list self.traces.append({...}) # 2. Write to Firestore in background thread (non-blocking) threading.Thread(target=FirebaseService.add_agent_log, ...).start() ``` ## 5. Agent 编排:Google ADK ### 框架 BakhabarAI 使用 **Google Antigravity Agent Development Kit (ADK)**,包含 `google.adk.agents.Agent` 和 `google.adk.tools.FunctionTool`。该 pipeline 在 `backend/agents/pipeline.py` 中实现,为一个异步编排函数 `run_crisis_simulation()`。 ### 模型策略:`backend/agents/model_config.py` 该系统采用**双 LLM 池策略**,以最大化吞吐量并处理速率限制: - **Gemini 2.0 Flash**(通过 `google.adk.models.google_llm.Gemini`)—— 原生支持 ADK 的主要模型。在 Groq 不可用时使用。 - **Groq llama-3.1-8b-instant**(通过 `google.adk.models.lite_llm.LiteLlm`)—— 速度更快、吞吐量更高的模型。来自不同账户的多个 Groq API 密钥构成了一个资源池,每个 pipeline 阶段都分配有自己专用的密钥,以避免 TPM 冲突。 每个 Agent 都被分配了一个固定的池槽。在遇到 429 速率限制错误时,该 Agent 会轮询所有池槽,然后再回退到 Gemini。 ``` _AGENT_SLOT = { "SignalFusionAgent": 0, # Groq key 1 "DetectorAgent": 1, # Groq key 2 "ResourcePlannerAgent": 2, # Groq key 3 "SimulationStakeholderAgent": 3, # Groq key 4 "ReporterAgent": 4, # Groq key 5 } ``` ### 阶段 1 —— 信号融合(`SignalFusionAgent`) **文件**:`backend/agents/signal_collector.py` **触发者**:所有非手动 pipeline 运行(场景触发、天气信号) **功能:** - 从 `signals` Firestore 集合中获取所有 `pending`(待处理)信号 - 增加在场景 payload 中传入的任何 `mock_signals` - 分批次(每批 4 个)处理信号 - 根据信号内容关键字**确定性地**推断危机类型(无需 LLM): - `"pani"`、`"flood"`、`"baarish"` → `flood` - `"garmi"`、`"heat"`、`"temperature"` → `heatwave` - `"aag"`、`"fire"`、`"pm2.5"`、`"smog"` → `fire` - `"bijli"`、`"blackout"`、`"outage"` → `power_outage` - 分配基于可信度的严重程度:≥0.8 → HIGH,≥0.5 → MEDIUM,其余为 LOW - 调用 `process_signal_evaluations()` 将结果提交给 Firestore - 标记已处理的信号以防止重复处理(会话缓存 + 数据库状态检查) **去重逻辑:** 双层保护 —— 会话级 `set()` 和 Firestore 文档状态检查(`"verified"` / `"processed"` / `"noise"`)。 ### 阶段 2 —— 危机检测(`DetectorAgent`) **文件**:`backend/agents/detector.py` **触发者**:所有非手动 pipeline 运行 **功能:** - 查询没有 `affected_population`(即未分类)的活跃事件 - 为每个事件构建确定性的回退分类(人口估算、持续时间、按危机类型划分的蔓延风险) - 尝试使用 **Groq 文本补全**(JSON 模式,约 200 token)来分类严重程度、受影响人口、预期持续时间和演变预测 - 如果 Groq 失败,则使用确定性回退 - 调用 `process_incident_classifications()` 将丰富后的数据写回 Firestore **回退 类型→人口 映射:** ``` flood → 5,000 people | heatwave → 10,000 | fire → 2,500 accident → 400 | power_outage → 15,000 | protest → 3,000 ``` **手动报告会跳过阶段 2** —— 因为事件类型已经从市民的消息中得知。 ### 阶段 3 —— 资源规划(`ResourcePlannerAgent`) **文件**:`backend/agents/planner.py` **始终运行**(包括手动报告) **功能:** - 获取所有没有 `assigned_resources` 的活跃事件 - 从 Firestore 获取所有 `status: "available"` 的资源 - 应用**贪婪优先级算法** —— 无需 LLM,完全确定: - 按严重程度对事件进行排序(HIGH → MEDIUM → LOW) - 分配资源:HIGH 获得 3 个,MEDIUM 获得 2 个,LOW 获得 1 个 - 调用 `process_resource_allocations()` 将分配结果写入 Firestore - 记录权衡解释字符串,以便在仪表板上显示 ### 阶段 4 —— 影响模拟(`SimulationStakeholderAgent`) **文件**:`backend/agents/executor.py` **始终运行** **功能:** - 检查每个活跃事件是否有最近的模拟记录(小于 1 小时),以避免重复生成 - 根据危机类型构建**基于模板的回退模拟**: - `before_state`:响应前情况的英文描述 - `after_state`:协调响应结果的英文描述 - `improvement_metrics`:`response_time_reduction`、`safety_boost` - `notifications`:四个利益相关者消息 —— `public`(罗马乌尔都语)、`hospitals`、`utility_providers`、`law_enforcement` - 尝试使用 **Groq 文本补全**来生成更丰富、由 LLM 撰写的模拟以及正确的乌尔都语警报 - 通过 `process_simulations_and_messages()` 将结果提交到 `action_simulations` Firestore 集合 **公开通知示例(乌尔都语):** ``` ⚠️ FLOOD ALERT: Paani bhar gaya. Buland jagah par jayen foran. ``` ### 阶段 5 —— 最终报告(`ReporterAgent`) **文件**:`backend/agents/reporter.py` **始终作为最终阶段运行** **功能:** 统计按严重程度分组的所有活跃事件 - 生成摘要字符串:`"Pipeline complete ✅ — 3 active incident(s) (HIGH=1, MEDIUM=2, LOW=0). Trigger: mock."` - 通过 `tracer.log()` 记录摘要,同时用于内存 API 和 Firestore 持久化 - 无 Firestore 写入 —— 纯粹是一个用于记录和可观测性的阶段 ### Pipeline 触发模式 | 触发类型 | 阶段 1 | 阶段 2 | 阶段 3 | 阶段 4 | 阶段 5 | |:---|:---:|:---:|:---:|:---:|:---:| | `mock`(运行场景) | ✅ | ✅ | ✅ | ✅ | ✅ | | `manual`(市民报告) | ⏭ 跳过 | ⏭ 跳过 | ✅ | ✅ | ✅ | ## 6. API 集成 ### Google Maps Platform 所有 Google Maps 集成都封装在 `backend/tools/maps_tool.py` 中,使用 `httpx` 异步 HTTP 调用。 #### Geocoding API 将文本地址转换为 `{lat, lng}` 坐标。在提交市民报告时使用,将位置名称(例如 `"G-10, Islamabad"`)解析为 Firestore `GeoPoint` 所需的精确坐标。 ``` GET https://maps.googleapis.com/maps/api/geocode/json ?address=G-10, Islamabad &key={GOOGLE_MAPS_API_KEY} ``` **回退机制**:如果缺少 API 密钥或调用失败,则使用针对伊斯兰堡常见区域的硬编码坐标映射(G-10 → `33.6844, 73.0479`;I-8 → `33.6811, 73.0805`)。 #### Distance Matrix API 计算起点/终点对之间的旅行时间和距离。Planner Agent 使用它来确定哪些资源距离每个事件最近。 ``` GET https://maps.googleapis.com/maps/api/distancematrix/json ?origins=G-10, Islamabad &destinations=I-8, Islamabad &key={GOOGLE_MAPS_API_KEY} ``` #### Directions API 返回路线几何图形(折线、步骤)以用于调度模拟。Executor Agent 使用它来生成逼真的路线数据。 ``` GET https://maps.googleapis.com/maps/api/directions/json ?origin=Rescue HQ, Islamabad &destination=G-10, Islamabad &key={GOOGLE_MAPS_API_KEY} ``` #### Places API (New) + 经典回退 支持报告事件页面中的实时位置自动补全。后端代理此请求以在服务器端保护 API 密钥。 ``` # 新版 Places API(首先尝试) POST https://places.googleapis.com/v1/places:autocomplete Headers: X-Goog-Api-Key: {key} Body: {"input": "G-10", "includedRegionCodes": ["pk"]} # 传统备用方案 GET https://maps.googleapis.com/maps/api/place/autocomplete/json ?input=G-10&components=country:pk&key={key} ``` #### Reverse Geocode 将 `{lat, lng}` 转换回人类可读的地址。用于从原始 GPS 坐标显示位置名称。 #### Google Maps Flutter SDK(移动端) Flutter 应用使用 `google_maps_flutter` 来渲染交互式危机地图。自定义的 `Marker` 组件被放置在每个事件的坐标处,并按严重程度进行颜色编码。地图类型为 `normal`,带有自定义内边距以考虑到底部导航栏。 ### Google Weather API 通过 Google Maps Platform Weather 端点(`backend/tools/weather_tool.py`)使用,以获取特定位置当前的温度、降水量、风速和风暴风险。天气数据作为真实世界的信号源送入阶段 1,以验证或反驳社会/传感器信号。 **Base URL**: `https://weather.googleapis.com/v1` ## 7. 数据策略:真实与模拟 一个核心的设计决策是在真实 API 数据和模拟信号数据之间进行严格的分离。**Flutter UI 绝对没有硬编码数据** —— 它从 Firestore 流或 FastAPI 端点获取所有内容。 ### 真实数据(实时 API) | 数据类型 | 来源 | 用途 | |:---|:---|:---| | 地图切片与渲染 | Google Maps Flutter SDK | 交互式危机地图 | | 事件坐标 | Google Geocoding API | 解析市民报告位置 | | 旅行时间与距离 | Google Distance Matrix API | 阶段 3 中的资源邻近度 | | 路线折线 | Google Directions API | 阶段 4 中的调度路线 | | 地点建议 | Google Places API (New) | 报告页面自动补全 | | 天气状况 | Google Weather API | 阶段 1 中的信号验证 | ### 模拟数据(模拟信号) 所有模拟数据都位于 `backend/data/` 中,代表在黑客松环境下无法由真实 API 提供的信号类型。 #### `mock_social_posts.json` 复制市民 WhatsApp/Twitter 报告的罗马乌尔都语和英语帖子: ``` { "source_type": "social", "content": "G-10 mein pani bhar gaya hai, gaariyan phans gayi hain", "credibility_score": 0.7, "is_mock": true } ``` #### `mock_emergency_calls.json` 15(救援)服务呼叫的文字记录,包含位置和严重程度指标。 #### `mock_field_reports.json` 来自交通警察或急救人员的结构化输入 —— 高可信度(`0.85-0.95`)。 #### `mock_sensors.json` 来自雨水传感器、热量监控器和电网电力传感器的带有数值读数的遥测数据。 #### `backend/data/scenarios/` 三个预配置的场景 JSON 文件定义了每次演示的信号组合: | 场景 | 文件 | 危机 | 关键特性 | |:---|:---|:---|:---| | 1 | `scenario_1_flood.json` | G-10 城市洪水 | 单一危机检测 | | 2 | `scenario_2_multi_crisis.json` | G-10 洪水 + I-8 热浪 | 资源权衡分配 | | 3 | `scenario_3_false_alarm.json` | F-11 洪水(误报) | 冲突检测与撤回 | ## 8. Firebase 集成 Firebase Firestore 充当 FastAPI 后端和 Flutter 移动应用之间的实时数据层。 ### 集合 | 集合 | 文档 | 目的 | |:---|:---|:---| | `incidents` | 每个活跃危机一个 | 核心事件数据,包含类型、严重程度、位置(GeoPoint)、置信度、人口、资源 | | `signals` | 每个接收的信号一个 | 带有状态生命周期的原始信号数据:`pending` → `verified`/`noise` → `processed` | | `resources` | 每个应急单位一个 | 资源池,包含类型、状态(`available`/`deployed`)、分配的事件 | | `action_simulations` | 每个事件模拟一个 | 前/后状态、改进指标、利益相关者通知 | | `agent_logs` | 每个追踪条目一个 | Agent 名称、操作描述、置信度、时间戳 | ### 事件生命周期 ``` Citizen submits report (POST /api/report) ↓ Preliminary incident created immediately → status: "active", confidence: 0.3 ↓ Pipeline runs in background ↓ Stage 1: Signal verified → confidence boosted to ~0.58 Stage 2: Classification → affected_population, expected_duration_hours added Stage 3: Resources assigned → assigned_resources[] populated Stage 4: Simulation created → action_simulations document created Stage 5: Summary logged → agent_logs entry ↓ Flutter Firestore stream fires → incident appears on map & dashboard instantly ``` ### Flutter ↔ Firestore 实时流(`api_service.dart`) Flutter 中的 `ApiService` 类维护着活跃的 Firestore 监听器: ``` // Incidents stream — filtered to active only Stream
(Glassmorphic Overlays)"] DioClient["Dio HTTP Client"] FS_SDK["Firebase Firestore SDK"] end subgraph Backend["⚙️ FastAPI Backend (Python 3.11+)"] direction TB APIServer["FastAPI Server
(Uvicorn)"] Tracer["AgentTracer Log Collector"] subgraph Routes["REST Endpoints"] API_Incidents["/api/incidents"] API_Scenario["/api/run-scenario"] API_Report["/api/report"] API_Logs["/api/logs"] API_Places["/api/places/autocomplete"] end end subgraph ADK["🤖 Google ADK Agent Pipeline"] direction TB ADK_Orch["Google ADK Orchestration
(SequentialAgent)"] S1["Stage 1: SignalFusionAgent
(Normalizes Signal Feed)"] S2["Stage 2: DetectorAgent
(Classifies Severity & Type)"] S3["Stage 3: ResourcePlannerAgent
(Resource Trade-off & Rules)"] S4["Stage 4: SimulationAgent
(Simulates Actions & Routes)"] S5["Stage 5: ReporterAgent
(Generates Outcomes & Stakeholder Alerts)"] ADK_Orch --> S1 S1 --> S2 S2 --> S3 S3 --> S4 S4 --> S5 end subgraph DB["🔥 Firebase Firestore"] direction TB C_Signals[("signals")] C_Incidents[("incidents")] C_Resources[("resources")] C_Simulations[("action_simulations")] C_Logs[("agent_logs")] end subgraph Ext["🗺️ Google Maps Platform APIs"] direction TB API_Geo["Geocoding API"] API_Dist["Distance Matrix API"] API_Dir["Directions API"] API_PlNew["Places API (New)"] API_Weather["Weather API"] end subgraph LLM["🧠 Large Language Models"] direction TB Gemini["Gemini 2.0 Flash (Primary via ADK)"] Groq["Groq Llama-3.1-8b (Secondary Fallback)"] end %% Flow and Connections DioClient <-->|HTTP / REST| APIServer FS_SDK <.->|Real-time Streams| DB APIServer -->|Triggers Pipeline Async| ADK_Orch APIServer <-->|CRUD Operations| DB ADK -->|Writes Outcomes / Logs| DB ADK -->|Tool Calls| Ext ADK <-->|Reasoning & Alert Drafts| LLM Tracer -->|Persists Agent Steps| DB %% Apply Classes class Mobile softBg; class ADK softBg; class APIServer highlight; class ADK_Orch highlight; class Nav highlight; class C_Signals,C_Incidents,C_Resources,C_Simulations,C_Logs dbStyle; class API_Geo,API_Dist,API_Dir,API_PlNew,API_Weather apiStyle; ``` ### 组件职责 | 组件 | 技术 | 职责 | |:---|:---|:---| | 移动客户端 | Flutter (Dart) | 仪表板、地图、报告、实时流 | | HTTP 层 | Dio | 向 FastAPI 发起 REST 调用以执行操作 | | 实时层 | Firebase Firestore SDK | 实时事件、日志、资源、模拟流 | | API 服务器 | FastAPI (uvicorn) | 路由处理、pipeline 触发、CORS | | Agent Pipeline | Google ADK | 编排 5 阶段危机处理 | | 主 LLM | 通过 ADK 调用 Gemini 2.0 Flash | 分类、模拟生成 | | 辅助 LLM | Groq llama-3.1-8b-instant (通过 litellm) | 文本补全、速率限制回退池 | | 数据持久化 | Firebase Firestore | 所有结构化数据 | | 追踪记录器 | 自定义 `AgentTracer` | Agent 日志的内存 + Firestore 持久化 | | 地图 | Google Maps Platform | 地理编码、路线规划、地点自动补全 | ## 4. 后端:FastAPI ### 入口点:`backend/main.py` FastAPI 应用启动时采用了开放 CORS 的配置(允许来自任何源的移动应用请求),包含了主路由器,并打印了一个列出所有活跃端点的启动横幅。 ``` app = FastAPI(title="BakhabarAI Backend", version="1.0.0") app.add_middleware(CORSMiddleware, allow_origins=["*"], ...) app.include_router(mock_data_router.router) ``` ### API 端点:`backend/routers/mock_data_router.py` 所有路由均带有 `/api` 前缀。 | 方法 | 端点 | 描述 | |:---|:---|:---| | `GET` | `/api/incidents` | 从 Firestore 获取所有**活跃**事件。将 Firestore `GeoPoint` 标准化为 `{lat, lng}` JSON。 | | `GET` | `/api/incidents/{id}` | 根据文档 ID 获取单个事件。 | | `POST` | `/api/report` | 接收市民报告。对位置进行地理编码,立即在 Firestore 中创建初步事件,保存信号,然后异步触发 pipeline。 | | `POST` | `/api/run-scenario` | 将两个硬编码的伊斯兰堡演示事件(G-10 洪水,I-8 热浪)注入 Firestore,然后在后台启动完整的 pipeline。立即返回 `202 Accepted`。 | | `GET` | `/api/logs` | 从内存中的 `AgentTracer` 返回所有 Agent 追踪条目。 | | `GET` | `/api/places/autocomplete` | 代理 Google Places Autocomplete(优先使用新 API,经典 API 作为回退)。 | | `GET` | `/api/debug/ping` | 健康检查。返回服务器状态和追踪计数。 | | `DELETE` | `/api/debug/logs` | 在全新运行场景之前清除内存中的追踪缓冲区。 | | `GET` | `/api/debug/incidents` | 返回所有 Firestore 事件,不论状态如何(用于调试)。 | ### 市民报告流程(`POST /api/report`) 1. 从消息文本中提取位置名称(寻找 `"in"`、`"at"` 或 `:` 模式) 2. 通过 Google Geocoding API 对提取的位置进行地理编码 3. **立即在 Firestore 中创建一个 `MEDIUM`(中等)置信度的初步事件**(以便它能无延迟地显示在地图上) 4. 如果提交了 `media_url`,请将其直接附加到事件文档中 5. 将原始信号保存到 Firestore 中,并标记 `trigger_type: "manual"` 6. 作为异步后台任务启动危机 pipeline 以细化该事件 7. 立即返回 `{"status": "success"}`(非阻塞) ### Agent 追踪记录器:`backend/tracer.py` `AgentTracer` 是一个单例,在所有 pipeline 阶段中共享使用。每次调用 `tracer.log(...)` 都会做两件事: 1. **内存追加**:将追踪条目添加到 `self.traces[]` 中(由 `/api/logs` 提供) 2. **后台 Firestore 写入**:使用守护线程将日志持久化到 `agent_logs` Firestore 集合中(供 Flutter 应用的实时流使用) ``` class AgentTracer: def log(self, agent_name, action, input_data, output_data, confidence): # 1. Append to in-memory list self.traces.append({...}) # 2. Write to Firestore in background thread (non-blocking) threading.Thread(target=FirebaseService.add_agent_log, ...).start() ``` ## 5. Agent 编排:Google ADK ### 框架 BakhabarAI 使用 **Google Antigravity Agent Development Kit (ADK)**,包含 `google.adk.agents.Agent` 和 `google.adk.tools.FunctionTool`。该 pipeline 在 `backend/agents/pipeline.py` 中实现,为一个异步编排函数 `run_crisis_simulation()`。 ### 模型策略:`backend/agents/model_config.py` 该系统采用**双 LLM 池策略**,以最大化吞吐量并处理速率限制: - **Gemini 2.0 Flash**(通过 `google.adk.models.google_llm.Gemini`)—— 原生支持 ADK 的主要模型。在 Groq 不可用时使用。 - **Groq llama-3.1-8b-instant**(通过 `google.adk.models.lite_llm.LiteLlm`)—— 速度更快、吞吐量更高的模型。来自不同账户的多个 Groq API 密钥构成了一个资源池,每个 pipeline 阶段都分配有自己专用的密钥,以避免 TPM 冲突。 每个 Agent 都被分配了一个固定的池槽。在遇到 429 速率限制错误时,该 Agent 会轮询所有池槽,然后再回退到 Gemini。 ``` _AGENT_SLOT = { "SignalFusionAgent": 0, # Groq key 1 "DetectorAgent": 1, # Groq key 2 "ResourcePlannerAgent": 2, # Groq key 3 "SimulationStakeholderAgent": 3, # Groq key 4 "ReporterAgent": 4, # Groq key 5 } ``` ### 阶段 1 —— 信号融合(`SignalFusionAgent`) **文件**:`backend/agents/signal_collector.py` **触发者**:所有非手动 pipeline 运行(场景触发、天气信号) **功能:** - 从 `signals` Firestore 集合中获取所有 `pending`(待处理)信号 - 增加在场景 payload 中传入的任何 `mock_signals` - 分批次(每批 4 个)处理信号 - 根据信号内容关键字**确定性地**推断危机类型(无需 LLM): - `"pani"`、`"flood"`、`"baarish"` → `flood` - `"garmi"`、`"heat"`、`"temperature"` → `heatwave` - `"aag"`、`"fire"`、`"pm2.5"`、`"smog"` → `fire` - `"bijli"`、`"blackout"`、`"outage"` → `power_outage` - 分配基于可信度的严重程度:≥0.8 → HIGH,≥0.5 → MEDIUM,其余为 LOW - 调用 `process_signal_evaluations()` 将结果提交给 Firestore - 标记已处理的信号以防止重复处理(会话缓存 + 数据库状态检查) **去重逻辑:** 双层保护 —— 会话级 `set()` 和 Firestore 文档状态检查(`"verified"` / `"processed"` / `"noise"`)。 ### 阶段 2 —— 危机检测(`DetectorAgent`) **文件**:`backend/agents/detector.py` **触发者**:所有非手动 pipeline 运行 **功能:** - 查询没有 `affected_population`(即未分类)的活跃事件 - 为每个事件构建确定性的回退分类(人口估算、持续时间、按危机类型划分的蔓延风险) - 尝试使用 **Groq 文本补全**(JSON 模式,约 200 token)来分类严重程度、受影响人口、预期持续时间和演变预测 - 如果 Groq 失败,则使用确定性回退 - 调用 `process_incident_classifications()` 将丰富后的数据写回 Firestore **回退 类型→人口 映射:** ``` flood → 5,000 people | heatwave → 10,000 | fire → 2,500 accident → 400 | power_outage → 15,000 | protest → 3,000 ``` **手动报告会跳过阶段 2** —— 因为事件类型已经从市民的消息中得知。 ### 阶段 3 —— 资源规划(`ResourcePlannerAgent`) **文件**:`backend/agents/planner.py` **始终运行**(包括手动报告) **功能:** - 获取所有没有 `assigned_resources` 的活跃事件 - 从 Firestore 获取所有 `status: "available"` 的资源 - 应用**贪婪优先级算法** —— 无需 LLM,完全确定: - 按严重程度对事件进行排序(HIGH → MEDIUM → LOW) - 分配资源:HIGH 获得 3 个,MEDIUM 获得 2 个,LOW 获得 1 个 - 调用 `process_resource_allocations()` 将分配结果写入 Firestore - 记录权衡解释字符串,以便在仪表板上显示 ### 阶段 4 —— 影响模拟(`SimulationStakeholderAgent`) **文件**:`backend/agents/executor.py` **始终运行** **功能:** - 检查每个活跃事件是否有最近的模拟记录(小于 1 小时),以避免重复生成 - 根据危机类型构建**基于模板的回退模拟**: - `before_state`:响应前情况的英文描述 - `after_state`:协调响应结果的英文描述 - `improvement_metrics`:`response_time_reduction`、`safety_boost` - `notifications`:四个利益相关者消息 —— `public`(罗马乌尔都语)、`hospitals`、`utility_providers`、`law_enforcement` - 尝试使用 **Groq 文本补全**来生成更丰富、由 LLM 撰写的模拟以及正确的乌尔都语警报 - 通过 `process_simulations_and_messages()` 将结果提交到 `action_simulations` Firestore 集合 **公开通知示例(乌尔都语):** ``` ⚠️ FLOOD ALERT: Paani bhar gaya. Buland jagah par jayen foran. ``` ### 阶段 5 —— 最终报告(`ReporterAgent`) **文件**:`backend/agents/reporter.py` **始终作为最终阶段运行** **功能:** 统计按严重程度分组的所有活跃事件 - 生成摘要字符串:`"Pipeline complete ✅ — 3 active incident(s) (HIGH=1, MEDIUM=2, LOW=0). Trigger: mock."` - 通过 `tracer.log()` 记录摘要,同时用于内存 API 和 Firestore 持久化 - 无 Firestore 写入 —— 纯粹是一个用于记录和可观测性的阶段 ### Pipeline 触发模式 | 触发类型 | 阶段 1 | 阶段 2 | 阶段 3 | 阶段 4 | 阶段 5 | |:---|:---:|:---:|:---:|:---:|:---:| | `mock`(运行场景) | ✅ | ✅ | ✅ | ✅ | ✅ | | `manual`(市民报告) | ⏭ 跳过 | ⏭ 跳过 | ✅ | ✅ | ✅ | ## 6. API 集成 ### Google Maps Platform 所有 Google Maps 集成都封装在 `backend/tools/maps_tool.py` 中,使用 `httpx` 异步 HTTP 调用。 #### Geocoding API 将文本地址转换为 `{lat, lng}` 坐标。在提交市民报告时使用,将位置名称(例如 `"G-10, Islamabad"`)解析为 Firestore `GeoPoint` 所需的精确坐标。 ``` GET https://maps.googleapis.com/maps/api/geocode/json ?address=G-10, Islamabad &key={GOOGLE_MAPS_API_KEY} ``` **回退机制**:如果缺少 API 密钥或调用失败,则使用针对伊斯兰堡常见区域的硬编码坐标映射(G-10 → `33.6844, 73.0479`;I-8 → `33.6811, 73.0805`)。 #### Distance Matrix API 计算起点/终点对之间的旅行时间和距离。Planner Agent 使用它来确定哪些资源距离每个事件最近。 ``` GET https://maps.googleapis.com/maps/api/distancematrix/json ?origins=G-10, Islamabad &destinations=I-8, Islamabad &key={GOOGLE_MAPS_API_KEY} ``` #### Directions API 返回路线几何图形(折线、步骤)以用于调度模拟。Executor Agent 使用它来生成逼真的路线数据。 ``` GET https://maps.googleapis.com/maps/api/directions/json ?origin=Rescue HQ, Islamabad &destination=G-10, Islamabad &key={GOOGLE_MAPS_API_KEY} ``` #### Places API (New) + 经典回退 支持报告事件页面中的实时位置自动补全。后端代理此请求以在服务器端保护 API 密钥。 ``` # 新版 Places API(首先尝试) POST https://places.googleapis.com/v1/places:autocomplete Headers: X-Goog-Api-Key: {key} Body: {"input": "G-10", "includedRegionCodes": ["pk"]} # 传统备用方案 GET https://maps.googleapis.com/maps/api/place/autocomplete/json ?input=G-10&components=country:pk&key={key} ``` #### Reverse Geocode 将 `{lat, lng}` 转换回人类可读的地址。用于从原始 GPS 坐标显示位置名称。 #### Google Maps Flutter SDK(移动端) Flutter 应用使用 `google_maps_flutter` 来渲染交互式危机地图。自定义的 `Marker` 组件被放置在每个事件的坐标处,并按严重程度进行颜色编码。地图类型为 `normal`,带有自定义内边距以考虑到底部导航栏。 ### Google Weather API 通过 Google Maps Platform Weather 端点(`backend/tools/weather_tool.py`)使用,以获取特定位置当前的温度、降水量、风速和风暴风险。天气数据作为真实世界的信号源送入阶段 1,以验证或反驳社会/传感器信号。 **Base URL**: `https://weather.googleapis.com/v1` ## 7. 数据策略:真实与模拟 一个核心的设计决策是在真实 API 数据和模拟信号数据之间进行严格的分离。**Flutter UI 绝对没有硬编码数据** —— 它从 Firestore 流或 FastAPI 端点获取所有内容。 ### 真实数据(实时 API) | 数据类型 | 来源 | 用途 | |:---|:---|:---| | 地图切片与渲染 | Google Maps Flutter SDK | 交互式危机地图 | | 事件坐标 | Google Geocoding API | 解析市民报告位置 | | 旅行时间与距离 | Google Distance Matrix API | 阶段 3 中的资源邻近度 | | 路线折线 | Google Directions API | 阶段 4 中的调度路线 | | 地点建议 | Google Places API (New) | 报告页面自动补全 | | 天气状况 | Google Weather API | 阶段 1 中的信号验证 | ### 模拟数据(模拟信号) 所有模拟数据都位于 `backend/data/` 中,代表在黑客松环境下无法由真实 API 提供的信号类型。 #### `mock_social_posts.json` 复制市民 WhatsApp/Twitter 报告的罗马乌尔都语和英语帖子: ``` { "source_type": "social", "content": "G-10 mein pani bhar gaya hai, gaariyan phans gayi hain", "credibility_score": 0.7, "is_mock": true } ``` #### `mock_emergency_calls.json` 15(救援)服务呼叫的文字记录,包含位置和严重程度指标。 #### `mock_field_reports.json` 来自交通警察或急救人员的结构化输入 —— 高可信度(`0.85-0.95`)。 #### `mock_sensors.json` 来自雨水传感器、热量监控器和电网电力传感器的带有数值读数的遥测数据。 #### `backend/data/scenarios/` 三个预配置的场景 JSON 文件定义了每次演示的信号组合: | 场景 | 文件 | 危机 | 关键特性 | |:---|:---|:---|:---| | 1 | `scenario_1_flood.json` | G-10 城市洪水 | 单一危机检测 | | 2 | `scenario_2_multi_crisis.json` | G-10 洪水 + I-8 热浪 | 资源权衡分配 | | 3 | `scenario_3_false_alarm.json` | F-11 洪水(误报) | 冲突检测与撤回 | ## 8. Firebase 集成 Firebase Firestore 充当 FastAPI 后端和 Flutter 移动应用之间的实时数据层。 ### 集合 | 集合 | 文档 | 目的 | |:---|:---|:---| | `incidents` | 每个活跃危机一个 | 核心事件数据,包含类型、严重程度、位置(GeoPoint)、置信度、人口、资源 | | `signals` | 每个接收的信号一个 | 带有状态生命周期的原始信号数据:`pending` → `verified`/`noise` → `processed` | | `resources` | 每个应急单位一个 | 资源池,包含类型、状态(`available`/`deployed`)、分配的事件 | | `action_simulations` | 每个事件模拟一个 | 前/后状态、改进指标、利益相关者通知 | | `agent_logs` | 每个追踪条目一个 | Agent 名称、操作描述、置信度、时间戳 | ### 事件生命周期 ``` Citizen submits report (POST /api/report) ↓ Preliminary incident created immediately → status: "active", confidence: 0.3 ↓ Pipeline runs in background ↓ Stage 1: Signal verified → confidence boosted to ~0.58 Stage 2: Classification → affected_population, expected_duration_hours added Stage 3: Resources assigned → assigned_resources[] populated Stage 4: Simulation created → action_simulations document created Stage 5: Summary logged → agent_logs entry ↓ Flutter Firestore stream fires → incident appears on map & dashboard instantly ``` ### Flutter ↔ Firestore 实时流(`api_service.dart`) Flutter 中的 `ApiService` 类维护着活跃的 Firestore 监听器: ``` // Incidents stream — filtered to active only Stream
- > getIncidentsStream() // active incidents only
Stream
- > getIncidentHistoryStream() // last 20, any status
Stream
- > getAgentLogsStream() // sorted latest-first
Stream
- > getResourcesStream() // full pool
Stream
- > getSimulationsStream() // sorted latest-first
```
所有流都以防御性方式处理 Firestore 的 `GeoPoint`、`Timestamp` 和嵌套 map 的反序列化,并在解析错误时输出 `debugPrint`。
### Firebase Authentication
用户身份验证使用 Firebase Auth 以及模拟的手机号 + OTP 流程。身份验证**仅用于提交报告** —— 所有事件查看都是公开的。`mobile/lib/core/auth_provider.dart` 中的 `AuthProvider` 管理着身份验证状态,并通过 Flutter 的 `Provider` 将其暴露出来。
## 9. Flutter 移动应用
### 技术
- **框架**:Flutter (Dart),目标平台为 Android APK
- **状态管理**:`Provider` + `StatefulWidget`(按屏幕划分)
- **HTTP 客户端**:在调试模式下使用带 `LogInterceptor` 的 `Dio`
- **实时数据**:Firebase Firestore SDK (`cloud_firestore`)
- **地图**:`google_maps_flutter`
- **图标**:仅使用 `lucide_icons` —— 不使用 Material 或 Cupertino 图标
- **字体**:`google_fonts`(Poppins、Inter、JetBrains Mono)
### `ApiService`(`mobile/lib/services/api_service.dart`)
包含两种数据访问方式的核心服务类:
1. **Firestore 流** —— 用于实时数据(事件、日志、资源、模拟)。无需轮询。
2. **Dio REST 调用** —— 用于执行操作(提交报告、运行场景、地点自动补全)。
`baseUrl` 被配置为运行 FastAPI 的机器的本地网络 IP(`http://192.168.x.x:8000/api`),使得同一 Wi-Fi 下的物理 Android 设备能够进行连接。
### `LocationService`(`mobile/lib/services/location_service.dart`)
请求设备位置权限并获取当前的 GPS 坐标。在 `HomeScreen` 上用于在地图上显示用户位置,并在报告表单中预填坐标。
### `NotificationService`(`mobile/lib/services/notification_service.dart`)
处理后端 pipeline 分发的事件警报的本地推送通知设置。
## 10. 设计系统
设计系统通过 `mobile/lib/core/theme.dart` 严格执行。没有任何屏幕或组件直接使用硬编码的颜色或字体声明。
### 调色板(`AppColors`)
| Token | Hex | 用法 |
|:---|:---|:---|
| `primary` | `#f4f1e9` | 温暖的灰白色脚手架背景 |
| `accent` | `#ff6036` | 珊瑚橙 —— CTA、激活状态、边框 |
| `textPrimary` | `#1a1a1a` | 接近黑色的正文和标题文本 |
| `textMuted` | `#6b6b6b` | 次要标签、时间戳 |
| `cardBg` | `#ffffff` | 卡片和输入框背景 |
| `severityHigh` | `#ef4444` | 红色 —— HIGH 严重程度指示器 |
| `severityMedium` | `#f59e0b` | 琥珀色 —— MEDIUM 严重程度指示器 |
| `severityLow` | `#22c55e` | 绿色 —— LOW 严重程度 + 成功状态 |
### 排版(`AppTextStyles`)
| 样式 | 字体 | 粗细 | 大小 |
|:---|:---|:---|:---|
| `h1` | Poppins | Bold (700) | 24px |
| `h2` | Poppins | SemiBold (600) | 18px |
| `body` | Inter | Regular (400) | 14px |
| `bodyMuted` | Inter | Regular (400) | 14px + 静音色 |
| `label` | Inter | Medium (500) | 12px |
| `mono` | JetBrains Mono | Regular | 12px —— 仅用于 Agent 日志 |
### 组件规则
- **按钮**:52px 高度,16px 边框半径,珊瑚色填充 + 白色文本
- **卡片**:白色背景,16px 半径,`0 4px 12px rgba(0,0,0,0.08)` 阴影
- **严重程度卡片边框**:4px 左侧边框(HIGH 为红色,MEDIUM 为琥珀色)
- **输入框**:52px 高度,12px 半径,2px 珊瑚色聚焦边框
- **严重程度徽章**:6px 半径的药丸形状,彩色背景,白色文本
- **毛玻璃效果**:`rgba(255,255,255,0.85)` + `12px` 背景模糊 —— **仅**用于地图弹窗卡片
### 加载状态
每个获取数据的屏幕在 Firestore 流或 API 调用处于待定状态时,都会显示一个 `SkeletonLoader` 组件(`mobile/lib/widgets/skeleton_loader.dart`),并带有微光动画。在加载过程中,任何屏幕都不会显示空白内容。
## 11. 页面与导航
### 导航结构
```
Stack Navigator:
└── SplashScreen → AuthWrapper
├── SignupScreen → OtpScreen → MainShell
└── (if logged in) → MainShell
Bottom Tab Navigator (MainShell) — 4 tabs:
├── Tab 0: HomeScreen (overview + mini map + incident previews)
├── Tab 1: MapScreen (full map + crisis markers)
├── Tab 2: AIAssistantChatScreen (AI chat for incident queries)
└── Tab 3: AgentLogsScreen (real-time agent trace timeline)
Push Navigation:
HomeScreen → IncidentsScreen
IncidentsScreen → IncidentDetailScreen
IncidentDetailScreen → ResourceAllocationScreen
IncidentDetailScreen → SimulationScreen
IncidentsScreen → ResourceAllocationScreen (all crises)
IncidentsScreen → SimulationScreen (all crises)
SimulationScreen → AgentLogsScreen
HomeScreen → ReportScreen (auth required)
```
### 页面描述
| 页面 | 文件 | 关键特性 |
|:---|:---|:---|
| `SplashScreen` | `splash_screen.dart` | 应用 Logo + 加载动画 |
| `HomeScreen` | `home_screen.dart` | 迷你地图、事件摘要卡片、位置权限弹窗、“运行场景”按钮 |
| `MapScreen` | `map_screen.dart` | 完整的 Google Maps,带有严重程度颜色的标记、危机弹窗卡片(毛玻璃效果) |
| `AIAssistantChatScreen` | `ai_assistant_chat_screen.dart` | 用于查询事件并获取 AI 响应的聊天界面 |
| `AgentLogsScreen` | `agent_logs_screen.dart` | 在 JetBrains Mono 中可滚动的按时间排序的 Agent 追踪日志 |
| `IncidentsScreen` | `incidents_screen.dart` | 带有严重程度徽章的所有活跃事件的可筛选列表 |
| `IncidentDetailScreen` | `incident_detail_screen.dart` | 完整的事件档案 —— 地图、信号、媒体、人口、持续时间、置信度条 |
| `ResourceAllocationScreen` | `resource_allocation_screen.dart` | 资源池可视化、分配列表、权衡说明 |
| `SimulationScreen` | `simulation_screen.dart` | 前/后选项卡,针对不同受众的利益相关者通知 |
| `ReportScreen` | `report_screen.dart` | 带有位置自动补全、事件类型、照片上传、文本描述的表单 |
## 12. 数据模型
### Incident(`mobile/lib/models/incident.dart`)
```
class Incident {
final String crisisId;
final String type; // flood | heatwave | accident | fire | power_outage | protest
final String severity; // HIGH | MEDIUM | LOW
final double confidence; // 0.0 – 1.0
final String status; // active | resolved | false_alarm
final int? affectedPopulation;
final int? expectedDurationHours;
final String? peakImpactTime;
final Map
标签:AI智能体, AV绕过, FastAPI, Flutter, 危机响应, 城市应急管理, 多智能体协同, 逆向工具