IngSeb0 commited on
Commit
1fabaeb
·
1 Parent(s): 5029af1

Add Hugging Face Space Docker metadata

Browse files
Files changed (2) hide show
  1. .gitignore +2 -0
  2. README.md +417 -1
.gitignore ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+
2
+ doctl-1.158.0-windows-amd64/
README.md CHANGED
@@ -1 +1,417 @@
1
- # ReliefLensAI
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: ReliefLens AI
3
+ emoji: 🚨
4
+ colorFrom: red
5
+ colorTo: blue
6
+ sdk: docker
7
+ app_port: 7860
8
+ pinned: false
9
+ ---
10
+ # ReliefLens AI
11
+
12
+ ReliefLens AI is a multimodal, human-in-the-loop emergency triage demo built for the AMD Developer Hackathon. It accepts public field evidence such as text, image uploads, optional audio, browser location, map-selected location, and textual place references, then produces prioritized incidents with recommended resources, location confidence, and operational explanations.
13
+
14
+ ## Public demo
15
+
16
+ - Hugging Face Space frontend: `https://lablab-ai-amd-developer-hackathon-relieflens-frontend.hf.space`
17
+ - AMD FastAPI backend: `http://129.212.185.232:8080`
18
+
19
+ ## Application routes
20
+
21
+ - Public portal: `/emergencies`
22
+ - Private admin: `/admin`
23
+ - Admin login: `/admin/login`
24
+ - Admin incident queue: `/admin/incidents`
25
+ - Admin incident detail: `/admin/incidents/[id]`
26
+ - Admin telemetry: `/admin/telemetry`
27
+
28
+ The public portal is limited to evidence submission and public-safe confirmation details. Sensitive incident management stays behind authenticated admin routes.
29
+
30
+ ## What the system does
31
+
32
+ - Ingests image, text, optional audio, and location hints
33
+ - Resolves location from the best available source without inventing exact coordinates
34
+ - Produces prioritized incidents with severity, findings, and recommended resources
35
+ - Separates public intake from private incident management
36
+ - Shows admin telemetry for backend health and AMD demo metrics
37
+
38
+ ## Location resolution
39
+
40
+ ReliefLens does not pretend that a photo alone can reveal exact location. Location is resolved in this order:
41
+
42
+ 1. Browser geolocation, if the user shares it
43
+ 2. Manual map click, if the user selects or corrects a point
44
+ 3. Image GPS EXIF, if present
45
+ 4. Textual location hints such as `Santa Ana`
46
+ 5. `Location requires human review` when evidence is insufficient
47
+
48
+ If there is no browser location, no map point, no EXIF GPS, and no usable text location, the incident stays unresolved and requires human review.
49
+
50
+ ## Evidence intake behavior
51
+
52
+ The public `/emergencies` portal supports:
53
+
54
+ - image upload
55
+ - optional audio recording or upload
56
+ - `What is happening?`
57
+ - `Where is this happening?`
58
+ - `Use my current location`
59
+ - map click to adjust or set location
60
+ - `Analyze Evidence`
61
+
62
+ Current behavior uses deterministic, rule-based fallback analysis:
63
+
64
+ - text, filenames, and location hints drive incident classification
65
+ - audio files are accepted but returned as `received_not_transcribed` when no ASR model is connected
66
+ - images are inspected only for metadata and optional EXIF GPS
67
+ - the system does not claim real vision inference unless a model is explicitly connected later
68
+
69
+ ## Qwen-powered incident analysis
70
+
71
+ Rescue Evidence Intelligence can analyze submitted evidence with a Qwen model through an OpenAI-compatible API.
72
+
73
+ Required backend variables:
74
+
75
+ - `QWEN_BASE_URL`
76
+ - `QWEN_API_KEY`
77
+ - `QWEN_MODEL`
78
+ - `QWEN_ENABLED`
79
+
80
+ Behavior:
81
+
82
+ - if `QWEN_ENABLED=false`, the backend uses the existing rule-based fallback classifier
83
+ - if `QWEN_ENABLED=true`, the backend attempts Qwen analysis first
84
+ - if the model server times out, returns malformed JSON, or is unavailable, the backend falls back to `rule_based_fallback`
85
+ - the frontend never receives the API key
86
+
87
+ The admin dashboard shows:
88
+
89
+ - incident type
90
+ - severity
91
+ - confidence
92
+ - detected risks
93
+ - evidence summary
94
+ - recommended resources
95
+ - requires human review
96
+ - analysis provider: `qwen` or `rule_based_fallback`
97
+
98
+ ## Admin incident management
99
+
100
+ Authenticated admins can:
101
+
102
+ - sign in through `/admin/login`
103
+ - review the full incident queue
104
+ - inspect detailed evidence metadata
105
+ - update incident status, review state, notes, and assigned team
106
+ - inspect backend and AMD telemetry
107
+
108
+ Required backend environment variables:
109
+
110
+ - `ADMIN_USERNAME`
111
+ - `ADMIN_PASSWORD`
112
+ - `ADMIN_TOKEN_SECRET`
113
+ - `ADMIN_TOKEN_EXPIRE_MINUTES`
114
+
115
+ These values must stay on the backend. Do not expose them through `NEXT_PUBLIC_*` variables or commit secrets to git.
116
+
117
+ ## Safety
118
+
119
+ - Synthetic demo data only
120
+ - Human-in-the-loop required
121
+ - Not connected to emergency services
122
+ - Not for real-world dispatch
123
+ - AI suggestions are advisory only
124
+
125
+ ## Security limitations
126
+
127
+ - The hackathon MVP uses bearer token authentication for `/api/admin/*`
128
+ - The frontend stores the admin access token in `sessionStorage`
129
+ - This is acceptable for the demo, but production should use HTTPS end-to-end and secure HttpOnly cookies
130
+ - Admin credentials must be configured from backend environment variables, not frontend code
131
+
132
+ ## Architecture
133
+
134
+ Local development:
135
+
136
+ `Next.js frontend -> /backend rewrite proxy -> FastAPI backend`
137
+
138
+ Hugging Face Space deployment:
139
+
140
+ `Hugging Face Docker Space -> nginx on :7860 -> Next.js frontend -> AMD FastAPI backend -> AMD Qwen OpenAI-compatible endpoint`
141
+
142
+ The browser does not call `localhost:8080`, `127.0.0.1:8080`, the AMD FastAPI public IP, or the AMD Qwen endpoint directly from client-side code. Local frontend requests use `/backend`. The Hugging Face Space build uses same-origin `/api`, which nginx proxies to the AMD FastAPI backend at runtime.
143
+
144
+ ## Backend endpoints
145
+
146
+ - `GET /health`
147
+ - `GET /api/demo/incidents`
148
+ - `GET /api/demo/scenario`
149
+ - `POST /api/demo/run`
150
+ - `POST /api/evidence/intake`
151
+ - `GET /api/evidence/status/{tracking_code}`
152
+ - `POST /api/demo/analyze-image`
153
+ - `POST /api/admin/login`
154
+ - `GET /api/admin/me`
155
+ - `GET /api/admin/incidents`
156
+ - `GET /api/admin/incidents/{incident_id}`
157
+ - `PATCH /api/admin/incidents/{incident_id}`
158
+ - `GET /api/admin/telemetry`
159
+ - `GET /api/amd/performance`
160
+
161
+ ## Local development
162
+
163
+ ### Backend
164
+
165
+ ```bash
166
+ cd backend
167
+ set ADMIN_USERNAME=admin
168
+ set ADMIN_PASSWORD=admin123
169
+ set ADMIN_TOKEN_SECRET=local-dev-secret-change-me
170
+ set ADMIN_TOKEN_EXPIRE_MINUTES=720
171
+ set QWEN_ENABLED=false
172
+ python -m pytest tests -v
173
+ python -m uvicorn main:app --host 0.0.0.0 --port 8080 --reload
174
+ ```
175
+
176
+ Run locally with Qwen disabled:
177
+
178
+ - keep `QWEN_ENABLED=false`
179
+ - the backend will use the rule-based fallback pipeline
180
+
181
+ Run locally with Qwen through vLLM or another OpenAI-compatible server:
182
+
183
+ ```bash
184
+ cd backend
185
+ set QWEN_BASE_URL=http://127.0.0.1:8000/v1
186
+ set QWEN_API_KEY=token-abc123
187
+ set QWEN_MODEL=Qwen/Qwen2.5-7B-Instruct
188
+ set QWEN_ENABLED=true
189
+ python -m uvicorn main:app --host 0.0.0.0 --port 8080 --reload
190
+ ```
191
+
192
+ ### Frontend
193
+
194
+ ```bash
195
+ cd frontend
196
+ npm install
197
+ npm run build
198
+ npm run dev
199
+ ```
200
+
201
+ Local frontend environment file:
202
+
203
+ ```env
204
+ NEXT_PUBLIC_API_URL=/backend
205
+ NEXT_PUBLIC_API_BASE_URL=/backend
206
+ NEXT_PUBLIC_BACKEND_URL=/backend
207
+ BACKEND_ORIGIN=http://localhost:8080
208
+ ```
209
+
210
+ Local proxy checks:
211
+
212
+ - `http://localhost:3000/backend/health`
213
+ - `http://localhost:3000/admin/login`
214
+
215
+ Local admin login test credentials:
216
+
217
+ - username: `admin`
218
+ - password: `admin123`
219
+
220
+ ## Deployment to AMD Cloud
221
+
222
+ Recommended topology:
223
+
224
+ - AMD VM: FastAPI backend on `:8080`
225
+ - AMD VM: external Qwen OpenAI-compatible endpoint on `:8000`
226
+ - Hugging Face Space: public container on `:7860`
227
+
228
+ On the AMD VM:
229
+
230
+ ```bash
231
+ git clone https://github.com/<your-org-or-user>/ReliefLensAI.git
232
+ cd ReliefLensAI
233
+ bash scripts/deploy_backend_amd.sh
234
+ cp backend/.env.example backend/.env
235
+ ```
236
+
237
+ Edit `backend/.env` for your VM. Minimum values:
238
+
239
+ ```env
240
+ APP_ENV=production
241
+ DEBUG=false
242
+ DEMO_MODE=false
243
+ STORAGE_PATH=./data
244
+ CORS_ORIGINS=https://YOUR_SPACE.hf.space
245
+
246
+ QWEN_ENABLED=true
247
+ QWEN_BASE_URL=http://127.0.0.1:8000/v1
248
+ QWEN_API_KEY=amd-qwen-demo-key
249
+ QWEN_MODEL=Qwen/Qwen2-7B-Instruct
250
+
251
+ ADMIN_USERNAME=admin
252
+ ADMIN_PASSWORD=admin123
253
+ ADMIN_TOKEN_SECRET=relieflens-demo-secret-change-this
254
+ ADMIN_TOKEN_EXPIRE_MINUTES=720
255
+ ```
256
+
257
+ Then start the backend:
258
+
259
+ ```bash
260
+ bash scripts/start_backend_amd.sh
261
+ curl http://127.0.0.1:8080/health
262
+ curl http://129.212.185.232:8080/health
263
+ ```
264
+
265
+ If Qwen is running separately on the same VM, verify it first:
266
+
267
+ ```bash
268
+ curl http://127.0.0.1:8000/v1/models -H "Authorization: Bearer amd-qwen-demo-key"
269
+ ```
270
+
271
+ ## Deployment to Hugging Face Docker Space
272
+
273
+ The repository now includes a root `Dockerfile` for a single Hugging Face Docker Space container.
274
+
275
+ Container behavior:
276
+
277
+ - Next.js frontend runs internally on `127.0.0.1:3000`
278
+ - `nginx` exposes only port `7860`
279
+ - `/` routes to the Next.js frontend
280
+ - `/api/*` routes to the AMD FastAPI backend via `BACKEND_ORIGIN`
281
+ - `/health` routes to `${BACKEND_ORIGIN}/health`
282
+
283
+ Public browser behavior:
284
+
285
+ - the browser calls same-origin `/api` in the Hugging Face Space build
286
+ - no Qwen secret is exposed to the frontend bundle
287
+ - the Space does not call Qwen directly
288
+ - Qwen credentials stay only on the AMD backend environment
289
+
290
+ Space variables:
291
+
292
+ - `NEXT_PUBLIC_API_URL=/api`
293
+ - `NEXT_PUBLIC_API_BASE_URL=/api`
294
+ - `NEXT_PUBLIC_BACKEND_URL=/api`
295
+ - `BACKEND_ORIGIN=http://129.212.185.232:8080`
296
+
297
+ Do not put `QWEN_API_KEY`, admin credentials, or token secrets in any `NEXT_PUBLIC_*` variable or Hugging Face frontend variable.
298
+
299
+ Build and push flow:
300
+
301
+ 1. Push this repository to the Hugging Face Space repo.
302
+ 2. Configure the Space variables above.
303
+ 3. Wait for the Docker build to finish.
304
+ 4. Test:
305
+ - `https://YOUR_SPACE.hf.space/health`
306
+ - `https://YOUR_SPACE.hf.space/api/demo/incidents`
307
+ - `https://YOUR_SPACE.hf.space/emergencies`
308
+
309
+ The Space container uses the root `Dockerfile` and serves the full app on port `7860`.
310
+
311
+ Deployment flow:
312
+
313
+ 1. Create a Docker Space on Hugging Face.
314
+ 2. Push this repository root to the Space repository.
315
+ 3. Configure these Variables:
316
+ - `NEXT_PUBLIC_API_URL=/api`
317
+ - `NEXT_PUBLIC_API_BASE_URL=/api`
318
+ - `NEXT_PUBLIC_BACKEND_URL=/api`
319
+ - `BACKEND_ORIGIN=http://129.212.185.232:8080`
320
+ 4. Wait for the Docker build.
321
+ 5. Validate:
322
+ - `https://YOUR_SPACE.hf.space/health`
323
+ - `https://YOUR_SPACE.hf.space/api/demo/incidents`
324
+ - `https://YOUR_SPACE.hf.space/admin/login`
325
+
326
+ ## Hugging Face Space + AMD Qwen Deployment
327
+
328
+ This deployment mode keeps both Qwen and FastAPI on AMD infrastructure while Hugging Face hosts only the public UI and reverse proxy.
329
+
330
+ Architecture:
331
+
332
+ `Hugging Face Docker Space -> nginx on :7860 -> Next.js on :3000 -> AMD FastAPI on :8080 -> AMD Qwen OpenAI-compatible endpoint`
333
+
334
+ Required AMD backend runtime variables:
335
+
336
+ - `QWEN_ENABLED=true`
337
+ - `QWEN_BASE_URL=http://127.0.0.1:8000/v1`
338
+ - `QWEN_MODEL=Qwen/Qwen2-7B-Instruct`
339
+ - `QWEN_API_KEY=amd-qwen-demo-key`
340
+
341
+ Required Hugging Face Space variables:
342
+
343
+ - `NEXT_PUBLIC_API_URL=/api`
344
+ - `NEXT_PUBLIC_API_BASE_URL=/api`
345
+ - `NEXT_PUBLIC_BACKEND_URL=/api`
346
+ - `BACKEND_ORIGIN=http://129.212.185.232:8080`
347
+
348
+ Optional local Docker smoke test before pushing to Hugging Face:
349
+
350
+ ```bash
351
+ docker build -t relieflens-space .
352
+ docker run --rm -p 7860:7860 \
353
+ -e NEXT_PUBLIC_API_URL=/api \
354
+ -e NEXT_PUBLIC_API_BASE_URL=/api \
355
+ -e NEXT_PUBLIC_BACKEND_URL=/api \
356
+ -e BACKEND_ORIGIN=http://129.212.185.232:8080 \
357
+ relieflens-space
358
+ ```
359
+
360
+ Then test:
361
+
362
+ - `http://localhost:7860/health`
363
+ - `http://localhost:7860/api/demo/incidents`
364
+ - `http://localhost:7860/admin/login`
365
+
366
+ ## Final deployment checklist
367
+
368
+ 1. Verify Qwen on AMD:
369
+ - `curl http://127.0.0.1:8000/v1/models -H "Authorization: Bearer amd-qwen-demo-key"`
370
+ 2. Start AMD backend:
371
+ - `bash scripts/start_backend_amd.sh`
372
+ 3. Verify AMD backend locally:
373
+ - `curl http://127.0.0.1:8080/health`
374
+ 4. Verify AMD backend publicly:
375
+ - `curl http://129.212.185.232:8080/health`
376
+ 5. Configure Hugging Face Space variables:
377
+ - `NEXT_PUBLIC_API_URL=/api`
378
+ - `NEXT_PUBLIC_API_BASE_URL=/api`
379
+ - `NEXT_PUBLIC_BACKEND_URL=/api`
380
+ - `BACKEND_ORIGIN=http://129.212.185.232:8080`
381
+ 6. Push to a new Docker Space.
382
+ 7. Test:
383
+ - `https://SPACE.hf.space/health`
384
+ - `https://SPACE.hf.space/api/demo/incidents`
385
+ - `https://SPACE.hf.space/emergencies`
386
+ 8. Submit the seeded flood report and verify the admin dashboard shows `analysis_provider=qwen`.
387
+
388
+ ## Known limitations
389
+
390
+ - Qwen analysis depends on a reachable OpenAI-compatible model server returning valid JSON
391
+ - If Qwen is disabled or fails, the system falls back to rule-based analysis
392
+ - Audio is accepted but not transcribed unless an ASR model is connected later
393
+ - EXIF GPS is only available for images that actually contain GPS metadata
394
+ - Text-location resolution is intentionally conservative and does not invent precise coordinates
395
+ - Map clicks are user-provided hints, not verified GPS
396
+ - Human review remains mandatory for operational use
397
+
398
+ ## Flood demo case
399
+
400
+ To test the seeded flood case in the admin dashboard or API, use evidence like:
401
+
402
+ - Evidence text:
403
+ `A severe flash flood is affecting a residential area. Streets are partially flooded, several vehicles are stuck, and people may be trapped inside nearby buildings. Water level appears to be rising quickly after heavy rainfall.`
404
+ - Image findings:
405
+ `Flooded urban street, muddy water reaching residential entrances, stuck cars, people moving to higher ground.`
406
+ - Audio transcript:
407
+ `No audio uploaded.`
408
+ - Location:
409
+ browser geolocation with `confidence=0.90`
410
+
411
+ Expected result:
412
+
413
+ - `incident_type=flood`
414
+ - `severity=critical`
415
+ - `priority=P0`
416
+ - `requires_human_review=true`
417
+ - provider `qwen` when available, otherwise `rule_based_fallback`