Spaces:
Running
Running
Upload 2 files
Browse files- README_NEW.md +449 -0
- ethics_and_safety_report.txt +287 -0
README_NEW.md
ADDED
|
@@ -0,0 +1,449 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# HaramGuard — Agentic AI Safety System for Hajj Crowd Management
|
| 2 |
+
|
| 3 |
+
HaramGuard is a real-time, multi-agent decision-support system that integrates computer vision, risk modeling, reflective bias correction, and LLM-based coordination to assist human operators in preventing crowd crush during Hajj and Umrah.
|
| 4 |
+
|
| 5 |
+
Designed for deployment at the Grand Mosque (Masjid al-Haram), the system analyzes video feeds, estimates crowd risk levels, and generates structured operational recommendations — while maintaining strict human-in-the-loop governance, safety guardrails, and full auditability.
|
| 6 |
+
|
| 7 |
+
**Capstone Project · Tuwaiq Academy**
|
| 8 |
+
**Developed by: Adeem Alotaibi, Reem Alamoudi, Munirah Alsubaie, Nourah Alhumaid
|
| 9 |
+
Supervised by: Eng. Omer Nacar**
|
| 10 |
+
|
| 11 |
+
---
|
| 12 |
+
|
| 13 |
+
## Table of Contents
|
| 14 |
+
|
| 15 |
+
1. [Overview](#1-overview)
|
| 16 |
+
2. [Problem Definition](#2-problem-definition)
|
| 17 |
+
3. [Solution / System Architecture](#3-solution--system-architecture)
|
| 18 |
+
4. [Agentic System Design (Agents Description)](#4-agentic-system-design-agents-description)
|
| 19 |
+
5. [Human-in-the-Loop Design](#5-human-in-the-loop-design)
|
| 20 |
+
6. [Guardrails](#6-guardrails)
|
| 21 |
+
7. [System Architecture Diagram](#7-system-architecture-diagram)
|
| 22 |
+
8. [Installation & Running](#8-installation--running)
|
| 23 |
+
9. [Repository Structure](#9-repository-structure)
|
| 24 |
+
10. [Iterative Improvements](#10-iterative-improvements)
|
| 25 |
+
11. [Ethics & Safety](#11-ethics--safety)
|
| 26 |
+
12. [Limitations & Future Work](#12-limitations--future-work)
|
| 27 |
+
|
| 28 |
+
---
|
| 29 |
+
|
| 30 |
+
## 1. Overview
|
| 31 |
+
|
| 32 |
+
HaramGuard is implemented as a **single-pipeline, multi-agent** system. One orchestration layer (`RealTimePipeline` in `backend/pipeline.py`) runs a fixed sequence of five agents per video frame and maintains a single shared state. The pipeline does not replace the operator; it produces a stream of recommendations and alerts that the operator may approve, reject, or ignore via a React dashboard.
|
| 33 |
+
|
| 34 |
+
- **Backend:** Python (FastAPI), Ultralytics YOLO, OpenCV, NumPy, SciPy; SQLite persistence via `HajjFlowDB` (`backend/core/database.py`). Optional Streamlit dashboard entry point in `dashboard.py`.
|
| 35 |
+
- **Frontend:** React 18, Vite, Tailwind CSS, Lucide icons; polls the backend REST API for real-time state and displays KPIs, risk gauge, proposed actions, and decisions log with approve/reject/delete controls.
|
| 36 |
+
- **Data flow:** Video frames → PerceptionAgent → RiskAgent → ReflectionAgent → OperationsAgent → CoordinatorAgent (when a decision exists). State is updated each frame and persisted (risk events every 30 frames; reflection every frame; decisions and coordinator plans when emitted). The FastAPI server exposes `/api/realtime/state`, `/api/frames/buffer`, `/api/actions/{id}/approve`, `/api/actions/{id}/reject`, `/api/reset`, and `/health`.
|
| 37 |
+
|
| 38 |
+
---
|
| 39 |
+
|
| 40 |
+
## 2. Problem Definition
|
| 41 |
+
|
| 42 |
+
### 2.1 Real-World Problem
|
| 43 |
+
|
| 44 |
+
Mass gatherings during Hajj and Umrah create extreme crowd densities in and around the Grand Mosque. Crowd crush and stampede events have occurred in the past, with serious consequences. Effective crowd management depends on timely detection of rising density and flow bottlenecks, and on recommending proportionate interventions (e.g. opening gates, directing flow, broadcasting guidance) before conditions become critical.
|
| 45 |
+
|
| 46 |
+
Manual monitoring of many camera feeds is error-prone and does not scale. Operators need a system that (1) continuously estimates crowd density and risk from video, (2) explains why a risk level was assigned, and (3) suggests concrete actions while leaving all execution decisions to humans.
|
| 47 |
+
|
| 48 |
+
### 2.2 Significance
|
| 49 |
+
|
| 50 |
+
- **Safety:** Reducing the likelihood of crowd crush by earlier, evidence-based recommendations.
|
| 51 |
+
- **Scale:** Supporting operators who cannot watch every feed; the system aggregates perception and risk into a single, interpretable state.
|
| 52 |
+
- **Accountability:** Every recommendation is logged with reasoning (risk events, reflection log, decisions, coordinator plans), supporting post-incident review and governance.
|
| 53 |
+
- **Context:** The system is designed to respect the religious and social context of Hajj (no individual identification, human authority over actions, alignment with consultation-based decision-making).
|
| 54 |
+
|
| 55 |
+
---
|
| 56 |
+
|
| 57 |
+
## 3. Solution / System Architecture
|
| 58 |
+
|
| 59 |
+
### 3.1 High-Level Design
|
| 60 |
+
|
| 61 |
+
HaramGuard uses a **deterministic, unidirectional pipeline**:
|
| 62 |
+
|
| 63 |
+
1. **PerceptionAgent** turns each video frame into a structured `FrameResult` (person count, density, spacing, 3×3 spatial grid for hotspots, annotated frame). It uses a YOLO model (path and size in `backend/config.py`); an optional VisionCountAgent (Claude Vision) is available in code but disabled in the default pipeline.
|
| 64 |
+
2. **RiskAgent** maintains a sliding window of `FrameResult`s and computes a risk score and level (LOW/MEDIUM/HIGH) using four paths: Fruin-style EMA of count, instant high-count floor, pre-emptive rate-of-change, and spatial clustering from the 3×3 grid. Output is `RiskResult`.
|
| 65 |
+
3. **ReflectionAgent** observes `RiskResult` and `FrameResult`, detects four bias patterns (chronic LOW, rising trend ignored, count–risk mismatch, over-estimation), and corrects risk level/score when needed. All reflections are logged to the database.
|
| 66 |
+
4. **OperationsAgent** emits a `Decision` only when the risk level *changes* (event-driven). Priority (P0/P1/P2) is derived from config thresholds aligned with RiskAgent. P0 decisions are rate-limited per zone. Decisions are stored in the database; actions and selected gates are left empty until the Coordinator fills them.
|
| 67 |
+
5. **CoordinatorAgent** is invoked by the pipeline for **every** decision (P0, P1, P2). It calls an LLM (Groq API) to generate a structured plan (threat level, executive summary, selected gates, immediate actions, Arabic alert, confidence). A ReAct loop (reason → act → observe, max 3 iterations) validates output with six guardrails (GR-C1–C6); the pipeline then fills the decision's actions, justification, and selected_gates from the plan and stores the plan in the database.
|
| 68 |
+
|
| 69 |
+
**Single state:** One `state` dictionary is updated each frame and exposed to the FastAPI server; the React dashboard polls it. All numeric thresholds and caps live in `backend/config.py`.
|
| 70 |
+
|
| 71 |
+
### 3.2 Data Flow
|
| 72 |
+
|
| 73 |
+
- **Input:** Video frames from a file or camera (path set by `VIDEO_PATH` in config).
|
| 74 |
+
- **Output:** Per-frame state (frame_id, person_count, density_score, risk_score, risk_level, trend, latest_decision, coordinator_plan, arabic_alert, reflection_summary, risk_history, decisions_log, etc.) plus persisted records in SQLite: `risk_events`, `op_decisions`, `coordinator_plans`, `reflection_log`.
|
| 75 |
+
- **Interfaces:** Backend: FastAPI on port 8000 (configurable via `API_PORT`). Frontend: Vite dev server (e.g. port 5173), configurable via `VITE_API_BASE_URL` for the API base URL.
|
| 76 |
+
|
| 77 |
+
---
|
| 78 |
+
|
| 79 |
+
## 4. Agentic System Design (Agents Description)
|
| 80 |
+
|
| 81 |
+
The pipeline runs five agents in order each frame. Each agent is implemented in a single module under `backend/agents/`. Data flows unidirectionally; agents do not call each other directly.
|
| 82 |
+
|
| 83 |
+
### 4.1 PerceptionAgent (`perception_agent.py`)
|
| 84 |
+
|
| 85 |
+
- **Role:** Convert a raw video frame into a `FrameResult`: person count, density score, average spacing, bounding boxes, annotated frame, track IDs, occupation percentage, and a 3×3 spatial grid (grid_counts, grid_max, hotspot_zone) for downstream hotspot detection. Based on Umm Al-Qura University (UQU) Haram crowd research: local clustering in one cell can indicate risk even when global count is moderate.
|
| 86 |
+
- **Design pattern:** Tool use — YOLO for detection and tracking; optional VisionCountAgent (Claude Vision) for an alternative count when an Anthropic key is provided. In the current default pipeline, PerceptionAgent is instantiated without an Anthropic key (YOLO-only).
|
| 87 |
+
- **Guardrails:** GR1 — person count capped at `MAX_PERSONS` (1000 in agent class). GR2 — density score capped at `MAX_DENSITY` (50.0).
|
| 88 |
+
- **Input:** Raw frame (numpy array). **Output:** `FrameResult` (see `backend/core/models.py`).
|
| 89 |
+
|
| 90 |
+
### 4.2 RiskAgent (`risk_agent.py`)
|
| 91 |
+
|
| 92 |
+
- **Role:** Maintain a sliding window (30 frames) of recent `FrameResult`s and compute a scalar risk score in [0, 1] and a discrete risk level (LOW / MEDIUM / HIGH), plus trend (rising / stable / falling). Final score is the maximum of four paths: (1) Fruin smooth — EMA of current person count normalized to `RISK_HIGH_COUNT` (50), with spacing and trend weights; (2) instant floor — if current count ≥ HIGH_COUNT, score floor 0.70; (3) pre-emptive ROC — 5-frame growth and EMA thresholds; (4) spatial clustering — if any 3×3 grid cell has ≥ `GRID_CELL_HIGH` persons (from FrameResult), floor 0.70. Score is clamped to [0, 1] (GR3).
|
| 93 |
+
- **Design pattern:** Sliding window + multi-path weighted scoring. Window size, thresholds, and weights are in `config.py`.
|
| 94 |
+
- **Input:** `FrameResult`. **Output:** `RiskResult` (frame_id, risk_score, risk_level, trend, level_changed, window_avg, window_max, density_ema, density_pct).
|
| 95 |
+
|
| 96 |
+
### 4.3 ReflectionAgent (`reflection_agent.py`)
|
| 97 |
+
|
| 98 |
+
- **Role:** Critique the current risk assessment and correct it when one of four bias patterns is detected: (1) chronic LOW — N consecutive LOW frames with average person count above threshold → upgrade to MEDIUM; (2) rising trend ignored — trend=rising, risk=LOW, count above threshold → upgrade to MEDIUM; (3) count–risk mismatch — high person count but LOW risk → upgrade to MEDIUM or HIGH; (4) over-estimation — HIGH risk but person count below threshold (e.g. < 15) → downgrade to MEDIUM. All reflections are persisted to `reflection_log` by the pipeline.
|
| 99 |
+
- **Design pattern:** Reflection (observe → critique → correct → log). History window and thresholds in config (`REFLECTION_BIAS_WINDOW`, `REFLECTION_CROWD_LOW_THRESH`, `REFLECTION_HIGH_CROWD_THRESH`, `REFLECTION_OVER_EST_THRESH`).
|
| 100 |
+
- **Input:** `RiskResult`, `FrameResult`. **Output:** Reflection dict; pipeline applies corrections to `RiskResult` before passing to OperationsAgent.
|
| 101 |
+
|
| 102 |
+
### 4.4 OperationsAgent (`operations_agent.py`)
|
| 103 |
+
|
| 104 |
+
- **Role:** Map the (possibly reflection-corrected) risk level to an operational priority (P0 / P1 / P2) and emit a `Decision` only when the risk level *changes*. Priority is derived from config (`OPS_P0_SCORE`, `OPS_P1_SCORE`) aligned with RiskAgent thresholds. P0 emission is rate-limited per zone (cooldown 300 s in agent class). The decision's actions and selected_gates are left empty; the pipeline fills them via CoordinatorAgent and then stores the decision in `op_decisions`.
|
| 105 |
+
- **Design pattern:** Event-driven; no decision when level unchanged.
|
| 106 |
+
- **Input:** `RiskResult`, context string (e.g. `Mecca_Main_Area`). **Output:** `Decision` or None.
|
| 107 |
+
|
| 108 |
+
### 4.5 CoordinatorAgent (`coordinator_agent.py`)
|
| 109 |
+
|
| 110 |
+
- **Role:** For every decision (P0, P1, or P2), produce a structured action plan using the Groq LLM (model in agent, e.g. `openai/gpt-oss-120b`). Plan includes threat_level, executive_summary, selected_gates, immediate_actions, actions_justification, arabic_alert, confidence_score. Implements a ReAct loop (max 3 iterations): reason (build prompt from RiskResult, Decision, frame buffer; optional feedback from failed validation) → act (LLM call, parse JSON) → observe (run guardrails GR-C1–C6); repeat until valid or max iterations. Pipeline fills the decision's actions, justification, and selected_gates from the plan and stores the plan in `coordinator_plans`.
|
| 111 |
+
- **Design pattern:** ReAct (reason → act → observe) + output guardrails.
|
| 112 |
+
- **Input:** `RiskResult`, `Decision`, list of recent `FrameResult`s. **Output:** Plan dict.
|
| 113 |
+
|
| 114 |
+
### 4.6 VisionCountAgent (`vision_count_agent.py`) — Optional
|
| 115 |
+
|
| 116 |
+
- **Role:** Provide an alternative person count by sending a subset of frames to a vision API (e.g. Claude Vision). Designed to be called from PerceptionAgent in hybrid mode to improve count in dense or occluded scenes. Not used in the default pipeline (PerceptionAgent is instantiated with `anthropic_key=None`).
|
| 117 |
+
- **Design pattern:** Tool use; sampling and rate limiting internal to avoid API overload.
|
| 118 |
+
|
| 119 |
+
---
|
| 120 |
+
|
| 121 |
+
## 5. Human-in-the-Loop Design
|
| 122 |
+
|
| 123 |
+
HaramGuard is a **decision-support** system, not an autonomous enforcement system. Every action that affects the physical world (opening gates, dispatching security, broadcasting alerts) is a **recommendation** to a human operator. No such action is executed by the system alone.
|
| 124 |
+
|
| 125 |
+
- **OperationsAgent** emits prioritized decisions (P0/P1/P2) and stores them; **CoordinatorAgent** produces Arabic alert text and action plans (gates, immediate actions) for each decision. These are shown on the React dashboard as "proposed actions."
|
| 126 |
+
- **Human operator** approves or rejects each proposed action via the dashboard. The API records approve/reject via `/api/actions/{id}/approve` and `/api/actions/{id}/reject`; the system does not execute any action itself.
|
| 127 |
+
- **Operator responsibilities:** Treat system silence (e.g. API down or pipeline stopped) as a trigger to switch to manual monitoring; review P0 recommendations and Arabic alerts before any broadcast or deployment; use the dashboard as one input among others (e.g. direct camera views, on-ground reports).
|
| 128 |
+
|
| 129 |
+
This design aligns with the principle of consultation (Shura) and with due diligence in decisions that affect lives: the machine informs, the human decides.
|
| 130 |
+
|
| 131 |
+
---
|
| 132 |
+
|
| 133 |
+
## 6. Guardrails
|
| 134 |
+
|
| 135 |
+
Guardrails are hard constraints and validations applied in code to keep outputs within safe and interpretable bounds. The following are implemented in the current repository.
|
| 136 |
+
|
| 137 |
+
| ID | Agent | Guardrail | Justification |
|
| 138 |
+
| --- | --- | --- | --- |
|
| 139 |
+
| **GR1** | PerceptionAgent | Person count capped at MAX_PERSONS (1000 in agent) | Prevents implausibly high counts from YOLO artifacts from propagating to risk and alerts. |
|
| 140 |
+
| **GR2** | PerceptionAgent | Density score capped at MAX_DENSITY (50.0) | Keeps density in a bounded range for downstream risk formulas. |
|
| 141 |
+
| **GR3** | RiskAgent | Risk score clamped to [0.0, 1.0] | Ensures threshold comparisons (e.g. 0.35, 0.65) remain valid. |
|
| 142 |
+
| **GR4** | OperationsAgent | P0 rate-limited per zone (cooldown 300 s in agent) | Reduces alert fatigue; risk is still logged; only decision emission is rate-limited. |
|
| 143 |
+
| **GR-C1** | CoordinatorAgent | Required JSON fields enforced; missing set to safe defaults | Prevents dashboard or downstream logic from breaking when the LLM omits fields. |
|
| 144 |
+
| **GR-C2** | CoordinatorAgent | threat_level whitelist (CRITICAL, HIGH, MEDIUM, LOW) | Avoids invalid or adversarial values that would break UI or logic. |
|
| 145 |
+
| **GR-C3** | CoordinatorAgent | confidence_score in [0, 1]; otherwise 0.5 | Normalizes LLM output so confidence is comparable. |
|
| 146 |
+
| **GR-C4** | CoordinatorAgent | Full range enforcement: threat_level overridden to match actual risk_score thresholds (LOW/MEDIUM/HIGH) | Prevents LLM from returning HIGH threat during MEDIUM risk or CRITICAL during LOW risk. |
|
| 147 |
+
| **GR-C5** | CoordinatorAgent | Arabic alert fallback if empty | Ensures safety-critical Arabic alert is never empty on the dashboard. |
|
| 148 |
+
| **GR-C6** | CoordinatorAgent | selected_gates must be non-empty list; otherwise fallback | Ensures operators receive concrete gate recommendations. |
|
| 149 |
+
| **RF1** | ReflectionAgent | Chronic LOW bias: N consecutive LOW with avg count above threshold → MEDIUM | Addresses sliding-window lag during rapid escalation. |
|
| 150 |
+
| **RF2** | ReflectionAgent | Rising trend ignored: trend=rising, LOW, count above threshold → MEDIUM | Corrects inconsistent state (rising crowd with LOW risk). |
|
| 151 |
+
| **RF3** | ReflectionAgent | Count–risk mismatch: high count but LOW risk → upgrade to MEDIUM/HIGH | Corrects mathematically inconsistent states. |
|
| 152 |
+
| **RF4** | ReflectionAgent | Over-estimation: HIGH risk but count < threshold (e.g. 15) → MEDIUM | Reduces false HIGH from empty or near-empty frames. |
|
| 153 |
+
|
| 154 |
+
Each guardrail is implemented in the corresponding agent file; further justification is documented in `ethics_and_safety_report.txt`.
|
| 155 |
+
|
| 156 |
+
---
|
| 157 |
+
|
| 158 |
+
## 7. System Architecture Diagram
|
| 159 |
+
|
| 160 |
+
```text
|
| 161 |
+
┌───────────────┐
|
| 162 |
+
│ Video Frame │
|
| 163 |
+
└───────┬───────┘
|
| 164 |
+
│
|
| 165 |
+
▼
|
| 166 |
+
┌───────────────┐
|
| 167 |
+
│PerceptionAgent│
|
| 168 |
+
└───────┬───────┘
|
| 169 |
+
│
|
| 170 |
+
▼
|
| 171 |
+
┌───────────────┐
|
| 172 |
+
│ RiskAgent │
|
| 173 |
+
└───────┬───────┘
|
| 174 |
+
│
|
| 175 |
+
▼
|
| 176 |
+
┌───────────────┐
|
| 177 |
+
│ReflectionAgent│
|
| 178 |
+
└───────┬───────┘
|
| 179 |
+
│
|
| 180 |
+
▼
|
| 181 |
+
┌───────────────┐
|
| 182 |
+
│OperationsAgent│
|
| 183 |
+
└───────┬───────┘
|
| 184 |
+
│
|
| 185 |
+
▼
|
| 186 |
+
┌───────────────┐
|
| 187 |
+
│CoordinatorAgent│
|
| 188 |
+
└───────┬───────┘
|
| 189 |
+
│
|
| 190 |
+
▼
|
| 191 |
+
┌───────────────┐
|
| 192 |
+
│ HajjFlowDB │
|
| 193 |
+
│ (SQLite) │
|
| 194 |
+
└───────┬───────┘
|
| 195 |
+
│
|
| 196 |
+
▼
|
| 197 |
+
┌───────────────┐
|
| 198 |
+
│ FastAPI │
|
| 199 |
+
│ REST API │
|
| 200 |
+
└───────┬───────┘
|
| 201 |
+
│
|
| 202 |
+
▼
|
| 203 |
+
┌───────────────┐
|
| 204 |
+
│ React │
|
| 205 |
+
│ Dashboard │
|
| 206 |
+
│(Human-in-the- │
|
| 207 |
+
│ Loop) │
|
| 208 |
+
└───────────────┘
|
| 209 |
+
```
|
| 210 |
+
|
| 211 |
+
---
|
| 212 |
+
|
| 213 |
+
## 8. Installation & Running
|
| 214 |
+
|
| 215 |
+
### 8.1 Prerequisites
|
| 216 |
+
|
| 217 |
+
- Python 3.9+ (backend)
|
| 218 |
+
- Node.js 18+ (frontend)
|
| 219 |
+
- Groq API key (required for CoordinatorAgent). Anthropic API key optional (only if enabling VisionCountAgent in the pipeline).
|
| 220 |
+
|
| 221 |
+
### 8.2 Backend
|
| 222 |
+
|
| 223 |
+
```bash
|
| 224 |
+
cd backend
|
| 225 |
+
python -m venv venv
|
| 226 |
+
source venv/bin/activate # Windows: venv\Scripts\activate
|
| 227 |
+
pip install -r requirements.txt
|
| 228 |
+
```
|
| 229 |
+
|
| 230 |
+
Set `GROQ_API_KEY` in the environment or in `backend/config.py`. Set `VIDEO_PATH` to a valid video file path (default: `hajj_real_video.mp4` in the backend directory). Set `MODEL_PATH` if using a different YOLO weight file (default: `yolo11l.pt`).
|
| 231 |
+
|
| 232 |
+
```bash
|
| 233 |
+
python api.py
|
| 234 |
+
```
|
| 235 |
+
|
| 236 |
+
API listens on `http://0.0.0.0:8000` by default (port configurable via `API_PORT` in config).
|
| 237 |
+
|
| 238 |
+
### 8.3 Frontend
|
| 239 |
+
|
| 240 |
+
```bash
|
| 241 |
+
cd frontend
|
| 242 |
+
npm install
|
| 243 |
+
npm run dev
|
| 244 |
+
```
|
| 245 |
+
|
| 246 |
+
Dashboard at `http://localhost:5173` (or the port Vite reports). If the API is not at `http://localhost:8000`, set `VITE_API_BASE_URL` in `frontend/.env` or the environment.
|
| 247 |
+
|
| 248 |
+
### 8.4 Evaluation
|
| 249 |
+
|
| 250 |
+
From the backend directory:
|
| 251 |
+
|
| 252 |
+
```bash
|
| 253 |
+
python evaluation.py
|
| 254 |
+
```
|
| 255 |
+
|
| 256 |
+
Outputs are written to `backend/outputs/eval/` (and optionally `backend/outputs/plots/`). See `RUN.md` for more detail and troubleshooting.
|
| 257 |
+
|
| 258 |
+
---
|
| 259 |
+
|
| 260 |
+
## 9. Repository Structure
|
| 261 |
+
|
| 262 |
+
```text
|
| 263 |
+
Haramguard 2/
|
| 264 |
+
├── README.md
|
| 265 |
+
├── README_OLD.md
|
| 266 |
+
├── README_NEW.md
|
| 267 |
+
├── RUN.md
|
| 268 |
+
├── ITERATIVE_IMPROVEMENT2.md
|
| 269 |
+
├── changes.md
|
| 270 |
+
├── ethics_and_safety_report.txt
|
| 271 |
+
├── backend/
|
| 272 |
+
│ ├── README.md
|
| 273 |
+
│ ├── config.py
|
| 274 |
+
│ ├── requirements.txt
|
| 275 |
+
│ ├── api.py
|
| 276 |
+
│ ├── pipeline.py
|
| 277 |
+
│ ├── evaluation.py
|
| 278 |
+
│ ├── dashboard.py
|
| 279 |
+
│ ├── core/
|
| 280 |
+
│ │ ├── __init__.py
|
| 281 |
+
│ │ ├── models.py
|
| 282 |
+
│ │ └── database.py
|
| 283 |
+
│ ├── agents/
|
| 284 |
+
│ │ ├── __init__.py
|
| 285 |
+
│ │ ├── perception_agent.py
|
| 286 |
+
│ │ ├── risk_agent.py
|
| 287 |
+
│ │ ├── reflection_agent.py
|
| 288 |
+
│ │ ├── operations_agent.py
|
| 289 |
+
│ │ ├── coordinator_agent.py
|
| 290 |
+
│ │ └── vision_count_agent.py
|
| 291 |
+
│ └── outputs/
|
| 292 |
+
│ └── eval/
|
| 293 |
+
│ ├── summary.json
|
| 294 |
+
│ ├── full_results.json
|
| 295 |
+
│ └── evalResults.md
|
| 296 |
+
└── frontend/
|
| 297 |
+
├── package.json
|
| 298 |
+
├── package-lock.json
|
| 299 |
+
├── index.html
|
| 300 |
+
├── vite.config.js
|
| 301 |
+
├── tailwind.config.js
|
| 302 |
+
├── postcss.config.js
|
| 303 |
+
├── .env
|
| 304 |
+
├── STATE_REFERENCE.md
|
| 305 |
+
├── src/
|
| 306 |
+
│ ├── main.jsx
|
| 307 |
+
│ ├── App.jsx
|
| 308 |
+
│ ├── index.css
|
| 309 |
+
│ ├── pages/
|
| 310 |
+
│ │ └── Dashboard.jsx
|
| 311 |
+
│ ├── Fin.svg
|
| 312 |
+
│ └── kaaba.svg
|
| 313 |
+
└── dist/
|
| 314 |
+
├── index.html
|
| 315 |
+
└── assets/
|
| 316 |
+
```
|
| 317 |
+
|
| 318 |
+
---
|
| 319 |
+
|
| 320 |
+
## 10. Iterative Improvements
|
| 321 |
+
|
| 322 |
+
HaramGuard was developed through **14 documented iterations**, each addressing a measured problem with a verifiable before/after result. The first 10 iterations are documented in `ITERATIVE_IMPROVEMENT2.md`; the following 4 are documented in `changes.md`.
|
| 323 |
+
|
| 324 |
+
### Summary Table
|
| 325 |
+
|
| 326 |
+
| # | Title | Problem | Before | After |
|
| 327 |
+
|---|-------|---------|--------|-------|
|
| 328 |
+
| 1 | YOLO Model Upgrade | nano model detected 3–4 persons on 30+ person frames | ~10% recall | ~85% recall (~8× improvement) |
|
| 329 |
+
| 2 | Count-Based Risk Scoring | Density-based formula: HIGH risk mathematically unreachable on aerial cameras | Scene C accuracy: 0% | Scene C accuracy: 100% |
|
| 330 |
+
| 3 | ReflectionAgent Added | 30-frame sliding window caused 20+ frame blind spot during rapid escalation | Uncorrected bias | 5/5 bias detectors passing |
|
| 331 |
+
| 4 | Risk–Priority Threshold Alignment | HIGH risk (score 0.66) incorrectly received P1 instead of P0 | Risk→Priority alignment: ~75% | 100% alignment |
|
| 332 |
+
| 5 | Hybrid PerceptionAgent (YOLO + Claude Vision) | Dense crowd under-count due to white ihram occlusion | 3–4 persons detected | Matches ground truth |
|
| 333 |
+
| 6 | Modular Architecture | Entire system in one notebook — untestable, unconfigurable | 0 isolated tests | 6 independent agent modules |
|
| 334 |
+
| 7 | SQLite Audit Trail | Reflection corrections lost after session — no auditability | Console logs only | Full SQLite history |
|
| 335 |
+
| 8 | Evaluation Framework | No systematic metrics — manual testing only | Manual testing | 8 quantified metrics, 4 scenarios |
|
| 336 |
+
| 9 | Condition-Based Risk Factors | High compression + clustering still reported LOW risk | Compression undetected | Compression/clustering detected |
|
| 337 |
+
| 10 | Weight Recalibration | Condition factors weakened the primary count signal | System accuracy: 50% (2/4) | System accuracy: 75% (3/4) |
|
| 338 |
+
| 11 | Risk Index Direction Fix | 17 persons + shrinking crowd → 82% risk (peak window bug) | window_peak = max(counts) | current_count EMA — risk falls with crowd |
|
| 339 |
+
| 12 | Trend Score Bidirectionality | t_score always ≥ 0.4 even during rapid crowd decrease | Decreasing crowd added constant risk | t_score = 0.0 when crowd shrinking fast |
|
| 340 |
+
| 13 | Arabic UI & Decision Log | English-only labels; decisions replaced on each poll | English labels, lost history | Arabic labels (منخفض/متوسط/عالي), cumulative log |
|
| 341 |
+
| 14 | Clean Dashboard State | FALLBACK_STATE showed fake HIGH emergency on load | Fake P0 alert on startup | ZERO_STATE — clean until real data arrives |
|
| 342 |
+
|
| 343 |
+
### Key Iterations in Detail
|
| 344 |
+
|
| 345 |
+
**Iteration 2 — Count-Based Scoring (most critical architectural fix)**
|
| 346 |
+
|
| 347 |
+
The original formula computed pixel density: `persons / (frame_pixels / 10,000)`. For a 1920×1080 aerial frame (~2M pixels), even 100 persons yields density = 0.5, far below the HIGH threshold of 20. The system was architecturally incapable of ever reporting HIGH risk. Replacing the primary signal with absolute person count normalized to a Hajj-calibrated threshold of 50 persons brought Scene C accuracy from 0% to 100%.
|
| 348 |
+
|
| 349 |
+
**Iteration 4 — Threshold Alignment (critical safety fix)**
|
| 350 |
+
|
| 351 |
+
RiskAgent labeled scores ≥ 0.65 as HIGH, but OperationsAgent only issued P0 for scores ≥ 0.70. A score of 0.66 — a genuine HIGH emergency — would receive P1 (routine monitoring) instead of P0 (immediate response). Aligning both thresholds to 0.65/0.35 in `config.py` fixed this safety gap and brought Risk→Priority alignment to 100%.
|
| 352 |
+
|
| 353 |
+
**Iteration 11 — Risk Index Direction Fix**
|
| 354 |
+
|
| 355 |
+
The EMA was computed using `max(counts)` over the last window, causing the risk to remain inflated long after the crowd had dispersed. Example: 70 persons 15 frames ago but only 17 now → 82% risk. Switching to `current_count` as the EMA input allows risk to decrease in proportion to the actual crowd, while the EMA still smooths out frame-to-frame noise.
|
| 356 |
+
|
| 357 |
+
**Iteration 14 — Clean Dashboard State**
|
| 358 |
+
|
| 359 |
+
`FALLBACK_STATE` was a hardcoded demo object showing a fake P0 HIGH emergency, designed for UI screenshots. It was left in production code and flashed on screen before the backend connected — showing operators a false emergency every time the dashboard loaded. Replacing it with `ZERO_STATE` (all zeros, LOW level, empty arrays) ensures the dashboard starts clean.
|
| 360 |
+
|
| 361 |
+
---
|
| 362 |
+
|
| 363 |
+
## 11. Ethics & Safety
|
| 364 |
+
|
| 365 |
+
### 11.1 Human-in-the-Loop Design
|
| 366 |
+
|
| 367 |
+
HaramGuard is a decision-support system, not an autonomous enforcement system. Every output is a recommendation to a human operator — no gate opens, no security is dispatched, no PA broadcast is made without a human approving the action. This design aligns with the Islamic principle of consultation (Shura) and with due diligence in decisions that affect the lives of millions of pilgrims.
|
| 368 |
+
|
| 369 |
+
### 11.2 Privacy & Surveillance
|
| 370 |
+
|
| 371 |
+
HaramGuard processes crowd count data only — not individual identities.
|
| 372 |
+
|
| 373 |
+
- No facial recognition is performed
|
| 374 |
+
- No biometric data is stored
|
| 375 |
+
- YOLO detects person bounding boxes (anonymous blobs only)
|
| 376 |
+
- Claude Vision counts persons without identification
|
| 377 |
+
- SQLite stores: risk scores, counts, timestamps — **no personal data**
|
| 378 |
+
|
| 379 |
+
None of the database tables (`risk_events`, `op_decisions`, `coordinator_plans`, `reflection_log`) contain personally identifiable information (PII). Bounding box data is discarded after spacing calculation and tracking IDs are not persisted.
|
| 380 |
+
|
| 381 |
+
### 11.3 Fairness & Bias
|
| 382 |
+
|
| 383 |
+
YOLO models trained on general datasets may under-detect pilgrims in white ihram clothing (domain shift). Two mitigations are implemented:
|
| 384 |
+
|
| 385 |
+
- **VisionCountAgent** (Claude Vision) provides a context-aware second counting layer that understands "pilgrims in white garments"
|
| 386 |
+
- **ReflectionAgent** detects chronic under-counting (CHRONIC_LOW_BIAS) and corrects upward, preventing model bias from causing under-response
|
| 387 |
+
|
| 388 |
+
Residual risk: under-count in extreme occlusion remains possible and is documented in `evaluation.py` Section 6 as a known limitation.
|
| 389 |
+
|
| 390 |
+
### 11.4 Transparency & Explainability
|
| 391 |
+
|
| 392 |
+
Every decision in HaramGuard is logged with human-readable reasoning:
|
| 393 |
+
|
| 394 |
+
- **RiskAgent:** logs risk_score, trend, window_avg
|
| 395 |
+
- **ReflectionAgent:** logs critique text explaining why bias was detected (e.g. `"RISING_TREND_IGNORED: trend=rising, persons=25, but risk=LOW. Upgraded to MEDIUM."`)
|
| 396 |
+
- **OperationsAgent:** logs which playbook actions were triggered and why
|
| 397 |
+
- **CoordinatorAgent:** logs GPT confidence score and any guardrail corrections applied
|
| 398 |
+
|
| 399 |
+
Operators can audit every decision post-incident by querying the SQLite database.
|
| 400 |
+
|
| 401 |
+
### 11.5 Conservative Bias by Design
|
| 402 |
+
|
| 403 |
+
The system is deliberately tuned to err toward higher risk:
|
| 404 |
+
|
| 405 |
+
- `HIGH_COUNT = 50` (not 100) — triggers HIGH alert at moderate crowd sizes
|
| 406 |
+
- ReflectionAgent corrections always go **upward** — never downgrade an assessment
|
| 407 |
+
- Missing confidence score defaults to 0.5 (not 0)
|
| 408 |
+
|
| 409 |
+
Rationale: in crowd safety, a false alarm is far less costly than a missed stampede.
|
| 410 |
+
|
| 411 |
+
### 11.6 Potential Misuse Scenarios
|
| 412 |
+
|
| 413 |
+
| Scenario | Risk | Mitigation |
|
| 414 |
+
|----------|------|------------|
|
| 415 |
+
| Surveillance creep | System extended to track individuals | Bounding boxes discarded after use; no tracking IDs in DB; Vision prompt states "count only — do not identify" |
|
| 416 |
+
| False positive causing panic | Incorrect HIGH alert triggers overreaction | HITL design; ReflectionAgent monitors for oscillation; 30-frame window smooths spikes; P0 rate limiting |
|
| 417 |
+
| System failure during peak crowd | Pipeline crash → operators lose visibility | Fail-safe per-agent isolation; operators trained to treat silence as trigger for manual monitoring |
|
| 418 |
+
| Adversarial prompt injection | Malicious input manipulates LLM output | Structured JSON-only output; GR-C1–C5 guardrails validate every field; threat_level constrained to whitelist |
|
| 419 |
+
| Disproportionate security response | P0 triggers aggressive enforcement harming pilgrims | Playbook actions are crowd-management only (open gates, PA broadcast, crowd guides) — not enforcement; human operator has final authority |
|
| 420 |
+
|
| 421 |
+
### 11.7 Fail-Safe Behavior
|
| 422 |
+
|
| 423 |
+
If any agent fails, the pipeline continues with safe defaults:
|
| 424 |
+
|
| 425 |
+
- **PerceptionAgent fails** → returns empty FrameResult (count=0)
|
| 426 |
+
- **RiskAgent fails** → previous risk level is retained
|
| 427 |
+
- **VisionCountAgent fails** → falls back to YOLO count (logged in flags)
|
| 428 |
+
- **CoordinatorAgent fails** → P0 decision still issued without GPT plan
|
| 429 |
+
- **DB write fails** → logged to console, pipeline continues
|
| 430 |
+
|
| 431 |
+
No single point of failure can silence an alert.
|
| 432 |
+
|
| 433 |
+
---
|
| 434 |
+
|
| 435 |
+
## 12. Limitations & Future Work
|
| 436 |
+
|
| 437 |
+
- **Single-camera, single-zone:** The pipeline processes one video stream per instance. Real deployment at the Grand Mosque would require multiple cameras and zones. Future work: multi-zone state and one pipeline per camera with aggregation at the API or dashboard layer.
|
| 438 |
+
|
| 439 |
+
- **Synthetic-only evaluation:** Quantitative metrics in `evaluation.py` are computed on synthetically generated scenarios with known ground-truth counts. Real aerial footage has occlusion, blur, and lighting conditions not fully captured. Future work: annotate real frames and measure real-world accuracy and recall.
|
| 440 |
+
|
| 441 |
+
- **No Hajj-specific fine-tuning:** The YOLO model is pre-trained on general datasets. Pilgrims in white ihram can be under-detected (domain shift). VisionCountAgent and ReflectionAgent mitigate this in part when enabled. Future work: fine-tune a detector on Hajj-annotated data to improve recall (estimated +15%).
|
| 442 |
+
|
| 443 |
+
- **Coordinator output quality not automatically measured:** Evaluation covers risk levels, priorities, and guardrail compliance — not the appropriateness or clarity of generated Arabic plans and alerts. Future work: human-expert rubric and sample-based evaluation of plan quality.
|
| 444 |
+
|
| 445 |
+
- **Production scaling:** The architecture supports running multiple pipeline instances; the dashboard and API would need to be extended for per-zone or per-camera state and approve/reject controls per zone.
|
| 446 |
+
|
| 447 |
+
---
|
| 448 |
+
|
| 449 |
+
**HaramGuard — Capstone Project · Tuwaiq Academy**
|
ethics_and_safety_report.txt
ADDED
|
@@ -0,0 +1,287 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
╔══════════════════════════════════════════════════════════════════╗
|
| 3 |
+
║ HaramGuard — Ethics, Safety & Guardrails Report ║
|
| 4 |
+
╚══════════════════════════════════════════════════════════════════╝
|
| 5 |
+
|
| 6 |
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
| 7 |
+
SECTION 1 — ETHICAL CONSIDERATIONS
|
| 8 |
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
| 9 |
+
|
| 10 |
+
1.1 Human-in-the-Loop (HITL) Design
|
| 11 |
+
─────────────────────────────────────
|
| 12 |
+
HaramGuard is a DECISION-SUPPORT system, not an autonomous enforcement
|
| 13 |
+
system. Every output is a recommendation to human operators.
|
| 14 |
+
|
| 15 |
+
OperationsAgent → emits action list (P0/P1/P2)
|
| 16 |
+
CoordinatorAgent → produces Arabic alert text
|
| 17 |
+
Human operator → decides whether to execute
|
| 18 |
+
|
| 19 |
+
No gate opens, no security is dispatched, no PA broadcasts without
|
| 20 |
+
a human approving the action. The system informs — humans decide.
|
| 21 |
+
|
| 22 |
+
Justification: Crowd management decisions affect thousands of pilgrims.
|
| 23 |
+
Automated enforcement without human review violates Islamic ethics of
|
| 24 |
+
consultation (Shura) and due diligence in decisions affecting lives.
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
1.2 Privacy & Surveillance
|
| 28 |
+
────────────────────────────
|
| 29 |
+
HaramGuard processes crowd COUNT data only — not individual identities.
|
| 30 |
+
|
| 31 |
+
- No facial recognition is performed
|
| 32 |
+
- No biometric data is stored
|
| 33 |
+
- YOLO detects person bounding boxes (anonymous blobs)
|
| 34 |
+
- Claude Vision counts persons (no identification)
|
| 35 |
+
- SQLite stores: risk scores, counts, timestamps — NO personal data
|
| 36 |
+
|
| 37 |
+
Stored data schema:
|
| 38 |
+
risk_events → frame_id, risk_score, risk_level, trend
|
| 39 |
+
op_decisions → priority, actions, risk_score
|
| 40 |
+
coordinator_plans → threat_level, arabic_alert, confidence
|
| 41 |
+
reflection_log → bias corrections, scores
|
| 42 |
+
|
| 43 |
+
None of these tables contain personally identifiable information (PII).
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
1.3 Fairness & Bias
|
| 47 |
+
─────────────────────
|
| 48 |
+
Potential bias: YOLO models trained on general datasets may under-detect
|
| 49 |
+
pilgrims in white ihram clothing (domain shift).
|
| 50 |
+
|
| 51 |
+
Mitigation implemented:
|
| 52 |
+
- VisionCountAgent (Claude Vision) provides a second counting layer
|
| 53 |
+
that is context-aware and understands "pilgrims in white garments"
|
| 54 |
+
- ReflectionAgent detects chronic under-counting (CHRONIC_LOW_BIAS)
|
| 55 |
+
and corrects upward — preventing bias from causing under-response
|
| 56 |
+
|
| 57 |
+
Residual risk: Model may still under-count in extreme occlusion.
|
| 58 |
+
Documented in evaluation.py Section 6 (Known Limitations).
|
| 59 |
+
|
| 60 |
+
|
| 61 |
+
1.4 Transparency & Explainability
|
| 62 |
+
────────────────────────────────────
|
| 63 |
+
Every decision in HaramGuard is logged with reasoning:
|
| 64 |
+
|
| 65 |
+
RiskAgent: logs risk_score, trend, window_avg — human-readable
|
| 66 |
+
ReflectionAgent: logs critique text explaining why bias was detected
|
| 67 |
+
OperationsAgent: logs which playbook actions were triggered and why
|
| 68 |
+
CoordinatorAgent: logs GPT-4o confidence score + guardrail issues
|
| 69 |
+
|
| 70 |
+
Example reflection log entry:
|
| 71 |
+
"RISING_TREND_IGNORED: trend=rising, persons=25, but risk=LOW.
|
| 72 |
+
Upgraded to MEDIUM."
|
| 73 |
+
|
| 74 |
+
Operators can audit every decision post-incident.
|
| 75 |
+
|
| 76 |
+
|
| 77 |
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
| 78 |
+
SECTION 2 — SYSTEM SAFETY
|
| 79 |
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
| 80 |
+
|
| 81 |
+
2.1 Fail-Safe Behavior
|
| 82 |
+
────────────────────────
|
| 83 |
+
If any agent fails, the pipeline continues with safe defaults:
|
| 84 |
+
|
| 85 |
+
PerceptionAgent fails → returns empty FrameResult (count=0)
|
| 86 |
+
RiskAgent fails → previous risk level is retained
|
| 87 |
+
VisionCountAgent fails → falls back to YOLO count (logged in flags)
|
| 88 |
+
CoordinatorAgent fails → P0 decision still issued without GPT plan
|
| 89 |
+
DB write fails → logged to console, pipeline continues
|
| 90 |
+
|
| 91 |
+
No single point of failure can silence an alert.
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
2.2 Conservative Bias by Design
|
| 95 |
+
──────────────────────────────────
|
| 96 |
+
The system is deliberately tuned to err toward HIGHER risk:
|
| 97 |
+
|
| 98 |
+
HIGH_COUNT = 50 (not 100) — triggers HIGH alert at moderate crowds
|
| 99 |
+
ReflectionAgent corrections always go UPWARD (never downgrade)
|
| 100 |
+
Missing confidence → defaults to 0.5 (not 0)
|
| 101 |
+
|
| 102 |
+
Rationale: In crowd safety, a false alarm is far less costly than a
|
| 103 |
+
missed stampede. The system is asymmetrically cautious.
|
| 104 |
+
|
| 105 |
+
|
| 106 |
+
2.3 Rate Limiting as Safety Mechanism
|
| 107 |
+
────────────────────────────────────────
|
| 108 |
+
P0 alerts are rate-limited to 1 per 5 minutes per zone (OPS_RATE_LIMIT_SEC=300).
|
| 109 |
+
|
| 110 |
+
Purpose: Prevents alert fatigue. If operators receive P0 every 10 seconds,
|
| 111 |
+
they stop responding. Rate limiting ensures each P0 is taken seriously.
|
| 112 |
+
|
| 113 |
+
This is a safety feature, not a suppression feature — the underlying
|
| 114 |
+
risk is still tracked and logged even when alerts are suppressed.
|
| 115 |
+
|
| 116 |
+
|
| 117 |
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
| 118 |
+
SECTION 3 — POTENTIAL MISUSE SCENARIOS
|
| 119 |
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
| 120 |
+
|
| 121 |
+
Scenario 1: Surveillance Creep
|
| 122 |
+
────────────────────────────────
|
| 123 |
+
Risk: System extended to track individuals, not just crowds.
|
| 124 |
+
Impact: Privacy violation, chilling effect on religious practice.
|
| 125 |
+
Mitigation:
|
| 126 |
+
- Code explicitly discards bounding box data after spacing calculation
|
| 127 |
+
- No tracking IDs are persisted to DB
|
| 128 |
+
- Vision prompt explicitly states "count only — do not identify"
|
| 129 |
+
- Data retention policy: DB rows contain no PII by design
|
| 130 |
+
|
| 131 |
+
|
| 132 |
+
Scenario 2: False Positive Causing Panic
|
| 133 |
+
──────────────────────────────────────────
|
| 134 |
+
Risk: System triggers HIGH alert incorrectly, security overreacts,
|
| 135 |
+
causing the very stampede it was meant to prevent.
|
| 136 |
+
Impact: Physical harm to pilgrims.
|
| 137 |
+
Mitigation:
|
| 138 |
+
- HITL design: human operator approves all P0 actions
|
| 139 |
+
- ReflectionAgent monitors for oscillation and bias
|
| 140 |
+
- 30-frame sliding window smooths single-frame spikes
|
| 141 |
+
- P0 rate limiting prevents cascading false alarms
|
| 142 |
+
|
| 143 |
+
|
| 144 |
+
Scenario 3: System Failure During Peak Crowd
|
| 145 |
+
──────────────────────────────────────────────
|
| 146 |
+
Risk: Pipeline crashes during Tawaf peak hours, operators lose
|
| 147 |
+
visibility entirely.
|
| 148 |
+
Impact: No alerts, potential missed stampede event.
|
| 149 |
+
Mitigation:
|
| 150 |
+
- Fail-safe design: each agent failure is isolated
|
| 151 |
+
- DB is written every 30 frames — worst case 1 second of lost data
|
| 152 |
+
- Operators are trained to treat system silence as a trigger to
|
| 153 |
+
switch to manual monitoring protocols
|
| 154 |
+
|
| 155 |
+
|
| 156 |
+
Scenario 4: Adversarial Prompt Injection (CoordinatorAgent)
|
| 157 |
+
─────────────────────────────────────────────────────────────
|
| 158 |
+
Risk: Attacker manipulates input data to inject malicious instructions
|
| 159 |
+
into the GPT-4o prompt.
|
| 160 |
+
Impact: Fabricated alerts, incorrect actions.
|
| 161 |
+
Mitigation:
|
| 162 |
+
- CoordinatorAgent prompt uses structured JSON-only output
|
| 163 |
+
- GR-C1..5 guardrails validate every field of the response
|
| 164 |
+
- threat_level constrained to whitelist: {CRITICAL, HIGH, MEDIUM, LOW}
|
| 165 |
+
- Consistency check: low risk_score cannot produce CRITICAL threat
|
| 166 |
+
- _guardrail_issues logged for every correction
|
| 167 |
+
|
| 168 |
+
|
| 169 |
+
Scenario 5: Disproportionate Security Response
|
| 170 |
+
────────────────────────────────────────────────
|
| 171 |
+
Risk: P0 alert triggers aggressive security deployment that harms
|
| 172 |
+
pilgrims rather than protecting them.
|
| 173 |
+
Impact: Physical harm, violation of dignity of worshippers.
|
| 174 |
+
Mitigation:
|
| 175 |
+
- Playbook actions are crowd management actions, not enforcement:
|
| 176 |
+
P0: open gates, PA broadcast, dispatch crowd guides
|
| 177 |
+
(NOT: lockdown, force dispersal, barriers that trap people)
|
| 178 |
+
- Human operator has final authority on response type
|
| 179 |
+
- System recommends — operators decide magnitude of response
|
| 180 |
+
|
| 181 |
+
|
| 182 |
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
| 183 |
+
SECTION 4 — GUARDRAILS: IMPLEMENTATION & JUSTIFICATION
|
| 184 |
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
| 185 |
+
|
| 186 |
+
┌─────┬──────────────────────┬────────────────────────────────────────┐
|
| 187 |
+
│ ID │ Agent │ Guardrail │
|
| 188 |
+
├─────┼──────────────────────┼────────────────────────────────────────┤
|
| 189 |
+
│ GR1 │ PerceptionAgent │ Person count capped at MAX_PERSONS=1000│
|
| 190 |
+
│ │ │ Justification: YOLO occasionally hallu-│
|
| 191 |
+
│ │ │ cinates thousands of detections on busy │
|
| 192 |
+
│ │ │ textures. Cap prevents impossible counts│
|
| 193 |
+
│ │ │ from propagating to risk score. │
|
| 194 |
+
├─────┼──────────────────────┼────────────────────────────────────────┤
|
| 195 |
+
│ GR2 │ PerceptionAgent │ Density score capped at MAX_DENSITY=50 │
|
| 196 |
+
│ │ │ Justification: Density formula can │
|
| 197 |
+
│ │ │ overflow on small frames. Cap ensures │
|
| 198 |
+
│ │ │ score stays in interpretable range. │
|
| 199 |
+
├─────┼──────────────────────┼────────────────────────────────────────┤
|
| 200 |
+
│ GR3 │ RiskAgent │ Risk score clamped to [0.0, 1.0] │
|
| 201 |
+
│ │ │ Justification: Weighted sum of 3 scores│
|
| 202 |
+
│ │ │ could theoretically exceed 1.0 due to │
|
| 203 |
+
│ │ │ floating point. Clamp ensures all │
|
| 204 |
+
│ │ │ downstream thresholds remain valid. │
|
| 205 |
+
├─────┼──────────────────────┼────────────────────────────────────────┤
|
| 206 |
+
│ GR4 │ OperationsAgent │ P0 rate-limited: 1 per 5 min per zone │
|
| 207 |
+
│ │ │ Justification: Alert fatigue is a real │
|
| 208 |
+
│ │ │ safety hazard. Operators who see 20 P0 │
|
| 209 |
+
│ │ │ alerts/hour begin ignoring them. │
|
| 210 |
+
├─────┼──────────────────────┼────────────────────────────────────────┤
|
| 211 |
+
│GR-C1│ CoordinatorAgent │ Required JSON fields enforced │
|
| 212 |
+
│ │ │ Justification: LLMs occasionally omit │
|
| 213 |
+
│ │ │ fields. Missing arabic_alert or │
|
| 214 |
+
│ │ │ threat_level would break the dashboard.│
|
| 215 |
+
├─────┼──────────────────────┼────────────────────────────────────────┤
|
| 216 |
+
│GR-C2│ CoordinatorAgent │ threat_level whitelist enforced │
|
| 217 |
+
│ │ │ Justification: Prevents GPT-4o from │
|
| 218 |
+
│ │ │ returning values like "EXTREME" or │
|
| 219 |
+
│ │ │ "UNKNOWN" that break downstream logic. │
|
| 220 |
+
├─────┼──────────────────────┼────────────────────────────────────────┤
|
| 221 |
+
│GR-C3│ CoordinatorAgent │ confidence_score validated in [0,1] │
|
| 222 |
+
│ │ │ Justification: LLMs sometimes return │
|
| 223 |
+
│ │ │ confidence as percentage (85 vs 0.85). │
|
| 224 |
+
├─────┼──────────────────────┼────────────────────────────────────────┤
|
| 225 |
+
│GR-C4│ CoordinatorAgent │ Consistency: low risk ≠ CRITICAL threat│
|
| 226 |
+
│ │ │ Justification: Prevents hallucinated │
|
| 227 |
+
│ │ │ CRITICAL alerts when risk_score < 0.4. │
|
| 228 |
+
│ │ │ Cross-validates LLM output with agent │
|
| 229 |
+
│ │ │ computed score. │
|
| 230 |
+
├─────┼──────────────────────┼────────────────────────────────────────┤
|
| 231 |
+
│GR-C5│ CoordinatorAgent │ Arabic alert fallback if empty │
|
| 232 |
+
│ │ │ Justification: Arabic alert is │
|
| 233 |
+
│ │ │ safety-critical. Empty string on │
|
| 234 |
+
│ │ │ dashboard during P0 is unacceptable. │
|
| 235 |
+
├─────┼──────────────────────┼────────────────────────────────────────┤
|
| 236 |
+
│ RF1 │ ReflectionAgent │ Chronic LOW bias detection │
|
| 237 |
+
│ │ │ Justification: Sliding window lag can │
|
| 238 |
+
│ │ │ cause 20+ frames of LOW during rapid │
|
| 239 |
+
│ │ │ escalation. This guardrail prevents │
|
| 240 |
+
│ │ │ the system from missing an emergency. │
|
| 241 |
+
├─────┼──────────────────────┼────────────────────────────────────────┤
|
| 242 |
+
│ RF2 │ ReflectionAgent │ Rising trend + LOW = upgrade to MEDIUM │
|
| 243 |
+
│ │ │ Justification: A rising crowd with LOW │
|
| 244 |
+
│ │ │ risk is a contradictory state that │
|
| 245 |
+
│ │ │ indicates calibration failure. │
|
| 246 |
+
├─────┼──────────────────────┼────────────────────────────────────────┤
|
| 247 |
+
│ RF3 │ ReflectionAgent │ Count-risk mismatch: 80+ persons + LOW │
|
| 248 |
+
│ │ │ Justification: Absolute count override │
|
| 249 |
+
│ │ │ ensures mathematical impossibilities │
|
| 250 |
+
│ │ │ (80 people = LOW risk) are corrected. │
|
| 251 |
+
└─────┴──────────────────────┴────────────────────────────────────────┘
|
| 252 |
+
|
| 253 |
+
Total: 12 guardrails across 4 agents
|
| 254 |
+
Each guardrail: implemented in code + justified architecturally
|
| 255 |
+
|
| 256 |
+
|
| 257 |
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
| 258 |
+
SECTION 5 — EVALUATION SUMMARY (Rubric Checklist)
|
| 259 |
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
| 260 |
+
|
| 261 |
+
✅ End-to-end performance metrics → evaluation.py Section 5
|
| 262 |
+
75-100% system accuracy across 4 synthetic scenarios
|
| 263 |
+
139 fps average throughput
|
| 264 |
+
|
| 265 |
+
✅ Component-level evaluation → evaluation.py Sections 1-4
|
| 266 |
+
PerceptionAgent, RiskAgent, ReflectionAgent, OperationsAgent
|
| 267 |
+
each evaluated independently with unit tests
|
| 268 |
+
|
| 269 |
+
✅ Error analysis methodology → evaluation.py Section 6
|
| 270 |
+
Convergence speed, oscillation rate, FP rate, 5 known limitations
|
| 271 |
+
each with documented mitigation
|
| 272 |
+
|
| 273 |
+
✅ Evidence of iterative improvement → evaluation.py Section 7
|
| 274 |
+
4 documented iterations (v1→v2→v3→v4→v5)
|
| 275 |
+
each with before/after measurable metric
|
| 276 |
+
|
| 277 |
+
✅ Ethical considerations → this file Section 1
|
| 278 |
+
HITL design, privacy-by-design, fairness, transparency
|
| 279 |
+
|
| 280 |
+
✅ System safety → this file Section 2
|
| 281 |
+
Fail-safe behavior, conservative bias, rate limiting
|
| 282 |
+
|
| 283 |
+
✅ Potential misuse scenarios → this file Section 3
|
| 284 |
+
5 scenarios with impact assessment and mitigation
|
| 285 |
+
|
| 286 |
+
✅ Guardrails implemented & justified → this file Section 4
|
| 287 |
+
12 guardrails, each with implementation + architectural justification
|