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> getIncidentsStream() // active incidents only Stream> getIncidentHistoryStream() // last 20, any status Stream getIncidentStream(String id) // single incident // Other collections 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 location; // {name, lat, lng} final List signalSources; final String? mediaUrl; final DateTime? timestamp; } ``` ### Resource(`mobile/lib/models/resource.dart`) ### AgentTrace(`mobile/lib/models/agent_log.dart`) ``` class AgentTrace { final String id; final String agentName; final String action; final double confidence; final DateTime timestamp; } ``` ### ActionSimulation(`mobile/lib/models/simulation.dart`) ``` class ActionSimulation { final String id; final String incidentId; final String actionType; final String description; final Map impactPrediction; // before_state, after_state, improvement_metrics final Map stakeholderNotifications; // public, hospitals, utility_providers, law_enforcement final DateTime timestamp; } ``` ## 13. 演示场景 ### 场景 1:城市洪水 —— 伊斯兰堡 G-10 **触发**:带有默认 payload 的 `POST /api/run-scenario` **注入**:在 `33.6938, 73.0213` (G-10) 发生 HIGH 严重程度的洪水 **Pipeline 流程**: 1. 信号融合跳过(除非预先注入,否则没有待处理的社交信号) 2. 检测器分类:`flood` → 人口 5,000 → 持续 8 小时 3. 规划器分配 3 个资源(HIGH 优先级) 4. 模拟器生成洪水响应模板 + 乌尔都语公众警报 5. 记录器输出摘要日志 **预期 UI**:地图上的 G-10 出现红色标记;事件卡片显示 HIGH 徽章;模拟显示救援船调度和疏散通道。 ### 场景 2:多危机 —— G-10 洪水 + I-8 热浪 **触发**:`POST /api/run-scenario` **注入**:HIGH 洪水 (G-10) + MEDIUM 热浪 (I-8) **Pipeline 流程**: - 规划器必须从共享资源池中进行分配 - HIGH 洪水首先获得分配的 3 个资源 - MEDIUM 热浪从剩余池中获得 2 个 - 权衡日志解释了优先级推理 **预期 UI**:地图上出现两个标记(红色 + 琥珀色);资源分配页面显示带有权衡说明的分配情况;模拟页面显示两个独立的前/后面板。 ### 场景 3:误报 —— F-11 **设计**:通过 `/api/report` 为 F-11 提交了一份洪水信号。一份高可信度的相互冲突的实地报告反驳了它。系统的信号可信度比较逻辑识别出冲突,将原始信号标记为 `noise`,事件置信度随之下降。模拟程序生成实用程序检查通知,而不是完整的紧急警报。 **预期 UI**:事件短暂出现在仪表板上并带有 LOW 置信度徽章,然后转换为 `false_alarm` 状态,并在模拟页面中可见撤回通知。 ## 14. 配置与环境 ### `.env` 文件(根目录 —— 永不提交) ``` # Google APIs GOOGLE_MAPS_API_KEY=your_google_cloud_api_key GEMINI_API_KEY=your_gemini_api_key # Groq(可选 — 用于池的多个密钥) GROQ_API_KEY=gsk_... GROQ_API_KEYS=gsk_key1,gsk_key2,gsk_key3 # comma-separated pool # 行为标志 PREFER_GROQ=True # True = use Groq first, False = use Gemini only DEBUG=True # Flutter BACKEND_URL=http://192.168.x.x:8000 FLUTTER_MAPS_KEY=your_google_android_maps_key ``` ### Firebase 配置 - **`backend/firebase_config.py`**:从环境变量或文件加载 Firebase Admin SDK 服务账号 JSON。初始化 `firebase_admin` 并返回 `db = firestore.client()`。 - **`backend/.firebaserc`**:Firebase 项目引用。 - **`mobile/`**:包含用于初始化 Flutter Firebase SDK 的 `google-services.json` (Android)。 - **自定义 Firestore 数据库**:该应用使用命名数据库(`bakhabarai-db`)而不是默认数据库 —— 在 `ApiService._firestore` 中配置。 ### Flutter Android Manifest Google Maps Android SDK API 密钥通过 `AndroidManifest.xml` 注入: ``` ``` ## 15. 运行项目 ### 前置条件 - Python 3.11+ - Flutter SDK 3.x + Android Studio + Android SDK(API 级别 21+) - 启用了以下 API 的 Google Cloud 项目: - Maps SDK for Android - Geocoding API - Distance Matrix API - Directions API - Places API (New) - Google Weather API(如果您的区域可用) - 启用了 Firestore 的 Firebase 项目(命名数据库:`bakhabarai-db`) - 带有 Google Play 服务的物理 Android 设备或模拟器 ### 后端设置 ``` cd backend # 创建并激活虚拟环境 python -m venv .venv .venv\Scripts\activate # Windows # 或者:source .venv/bin/activate # macOS/Linux # 安装依赖项 pip install -r requirements.txt # 配置环境 cp ../.env.example ../.env # 使用您的 API 密钥编辑 .env # 启动服务器 uvicorn main:app --reload --host 0.0.0.0 --port 8000 ``` 服务器将打印一个包含所有活跃端点的横幅。`--host 0.0.0.0` 标志允许同一网络下的物理 Android 设备进行连接。 ### Flutter 设置 ``` cd mobile # 获取依赖项 flutter pub get # 连接 Android 设备或启动模拟器 # 将 api_service.dart 的 baseUrl 更新为您机器的本地 IP: # static const String baseUrl = 'http://YOUR_MACHINE_IP:8000/api'; # 在 debug 模式下运行 flutter run # 构建 release APK flutter build apk --release # 输出:build/app/outputs/flutter-apk/app-release.apk ``` ### 查看 Agent 追踪(ADK Web UI) ``` cd backend adk web # 在 http://localhost:8000/adk 打开 — 显示结构化 trace viewer ``` ## 16. 目录结构 ``` bakhabarai/ ├── mobile/ # Flutter Android app │ ├── lib/ │ │ ├── main.dart # App entry + Firebase init + theme setup │ │ ├── core/ │ │ │ ├── theme.dart # AppColors, AppTextStyles, AppTheme │ │ │ ├── router.dart # Named routes + GoRouter │ │ │ ├── auth_provider.dart # Firebase Auth state │ │ │ └── utils.dart # Shared utility functions │ │ ├── screens/ │ │ │ ├── splash_screen.dart │ │ │ ├── auth/ │ │ │ │ ├── signup_screen.dart │ │ │ │ └── otp_screen.dart │ │ │ ├── home_screen.dart │ │ │ ├── map_screen.dart │ │ │ ├── incidents_screen.dart │ │ │ ├── incident_detail_screen.dart │ │ │ ├── resource_allocation_screen.dart │ │ │ ├── simulation_screen.dart │ │ │ ├── agent_logs_screen.dart │ │ │ ├── ai_assistant_chat_screen.dart │ │ │ └── report_screen.dart │ │ ├── widgets/ │ │ │ ├── bottom_nav_bar.dart │ │ │ ├── skeleton_loader.dart │ │ │ └── top_app_bar.dart │ │ ├── models/ │ │ │ ├── incident.dart │ │ │ ├── resource.dart │ │ │ ├── agent_log.dart │ │ │ └── simulation.dart │ │ └── services/ │ │ ├── api_service.dart # Dio REST + Firestore real-time streams │ │ ├── location_service.dart │ │ └── notification_service.dart │ ├── android/ │ │ └── app/src/main/ │ │ └── AndroidManifest.xml │ └── pubspec.yaml │ ├── backend/ # FastAPI + Google ADK │ ├── main.py # FastAPI app, CORS, startup banner │ ├── config.py # .env loading, API key parsing │ ├── tracer.py # AgentTracer — in-memory + Firestore logging │ ├── firebase_config.py # Firebase Admin SDK initialization │ ├── data_model.py # Shared Pydantic models │ ├── agents/ │ │ ├── __init__.py │ │ ├── pipeline.py # Main 5-stage async orchestrator │ │ ├── signal_collector.py # Stage 1: SignalFusionAgent │ │ ├── detector.py # Stage 2: DetectorAgent │ │ ├── planner.py # Stage 3: ResourcePlannerAgent │ │ ├── executor.py # Stage 4: SimulationStakeholderAgent │ │ ├── reporter.py # Stage 5: ReporterAgent │ │ ├── model_config.py # Gemini + Groq pool initialization │ │ └── adk_runtime.py # ADK agent runner utilities │ ├── routers/ │ │ └── mock_data_router.py # All /api/* endpoints │ ├── tools/ │ │ ├── maps_tool.py # Geocoding, Directions, Distance Matrix, Places │ │ ├── weather_tool.py # Google Weather API wrapper │ │ ├── firebase_tools.py # Firestore CRUD helpers │ │ └── mock_tools.py # Mock data loader utilities │ ├── services/ │ │ └── firebase_service.py # High-level Firebase service layer │ ├── data/ │ │ ├── mock_social_posts.json │ │ ├── mock_emergency_calls.json │ │ ├── mock_field_reports.json │ │ ├── mock_sensors.json │ │ └── scenarios/ │ │ ├── scenario_1_flood.json │ │ ├── scenario_2_multi_crisis.json │ │ └── scenario_3_false_alarm.json │ └── requirements.txt │ ├── traces/ # Auto-exported agent trace JSONs ├── specs/ # Feature specifications ├── .env # API keys — never commit ├── .env.example # Safe template ├── .gitignore ├── AGENTS.md # Project constitution ├── README.md # Quick start └── DOCUMENTATION.md # This file ``` ## 团队 **Team Solvit** — Google AI Seekho Antigravity Hackathon 2026 | 姓名 | GitHub | |---|---| | Nauman Arif | [@naumanaarif](https://github.com/naumanaarif) | | Hamza Ali | [@Hamza-asm](https://github.com/Hamza-asm) | | Ismail Dad Khan | [@IsmailDadKhan](https://github.com/IsmailDadKhan) |
标签:AI智能体, AV绕过, FastAPI, Flutter, 危机响应, 城市应急管理, 多智能体协同, 逆向工具