MohdUmar0223 commited on
Commit
fee5ee3
·
verified ·
1 Parent(s): e96feea

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +42 -52
app.py CHANGED
@@ -34,16 +34,24 @@ from datetime import datetime, timezone
34
  try:
35
  import spaces
36
  except ImportError:
37
- class spaces:
38
- _is_mock = True
39
- @staticmethod
40
- def GPU(func_or_duration=None, **kwargs):
41
- if callable(func_or_duration):
42
- return func_or_duration
43
- def decorator(func):
44
- return func
45
- return decorator
46
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
 
48
  from config import get_device, HAS_SPACES
49
  from services.forecast.service import forecast_aqi
@@ -98,9 +106,9 @@ async def _async_handle_forecast_ui(aqi_text_input: str, lat_val: str, lon_val:
98
  return f"❌ Execution Failed: {str(e)}", None, ""
99
 
100
 
101
- @spaces.GPU
102
  def handle_forecast_ui(aqi_text_input: str, lat_val: str, lon_val: str):
103
- """Gradio handler for AQI Forecasting."""
104
  return asyncio.run(_async_handle_forecast_ui(aqi_text_input, lat_val, lon_val))
105
 
106
 
@@ -140,9 +148,9 @@ async def _async_handle_vision_ui(input_image):
140
  return f"❌ Analysis Failed: {str(e)}", ""
141
 
142
 
143
- @spaces.GPU
144
  def handle_vision_ui(input_image):
145
- """Gradio handler for Satellite Vision."""
146
  return asyncio.run(_async_handle_vision_ui(input_image))
147
 
148
 
@@ -211,8 +219,8 @@ with gr.Blocks(title="AQI Intelligence Engine — HF ZeroGPU Edition", theme=gr.
211
  f"""
212
  ### 🖥️ Active Deployment Info
213
  - **Primary Compute Hardware**: `{device_active}`
214
- - **HuggingFace `spaces` SDK Available**: `{not getattr(spaces, "_is_mock", False)}`
215
- - **ZeroGPU Status**: `{"Active & Ready for dynamic GPU acceleration" if not getattr(spaces, "_is_mock", False) else "Running on standard CPU mode (Universal Compatibility)"}`
216
 
217
  ### 🔌 REST API Endpoints
218
  When deployed on Hugging Face Spaces, you can query REST endpoints directly:
@@ -222,16 +230,18 @@ with gr.Blocks(title="AQI Intelligence Engine — HF ZeroGPU Edition", theme=gr.
222
  """
223
  )
224
 
225
- from fastapi.middleware.cors import CORSMiddleware
226
  from starlette.responses import JSONResponse
227
  from starlette.requests import Request
228
 
229
- def register_api_routes(fastapi_app):
230
- """Register custom REST API endpoints on the parent FastAPI app."""
 
 
 
 
 
231
 
232
- @fastapi_app.post("/api/v1/forecast")
233
- @fastapi_app.post("/api/forecast")
234
- @fastapi_app.post("/forecast")
235
  async def api_forecast(request: Request):
236
  """REST API endpoint for historical AQI prediction."""
237
  try:
@@ -246,9 +256,7 @@ def register_api_routes(fastapi_app):
246
  logger.error(f"API Forecast error: {e}")
247
  return JSONResponse({"error": str(e)}, status_code=400)
248
 
249
- @fastapi_app.post("/api/v1/analyze-image")
250
- @fastapi_app.post("/api/analyze-image")
251
- @fastapi_app.post("/analyze-image")
252
  async def api_analyze_image(request: Request):
253
  """REST API endpoint for satellite image pollution breakdown."""
254
  try:
@@ -268,9 +276,7 @@ def register_api_routes(fastapi_app):
268
  logger.error(f"API Vision error: {e}")
269
  return JSONResponse({"error": str(e)}, status_code=400)
270
 
271
- @fastapi_app.get("/api/v1/health")
272
- @fastapi_app.get("/api/health")
273
- @fastapi_app.get("/health")
274
  async def api_health(request: Request):
275
  """Health check endpoint."""
276
  return JSONResponse({
@@ -280,36 +286,22 @@ def register_api_routes(fastapi_app):
280
  "version": "2.0.0",
281
  })
282
 
283
- # Save the original create_app method from Gradio
284
- _orig_create_app = demo.create_app
285
 
286
- def custom_create_app(*args, **kwargs):
287
- """Intercept Gradio's app creation to inject custom middleware and REST routes."""
288
- fastapi_app = _orig_create_app(*args, **kwargs)
289
-
290
- # Configure CORS on the FastAPI app
291
- fastapi_app.add_middleware(
292
  CORSMiddleware,
293
  allow_origins=["*"],
294
  allow_credentials=True,
295
  allow_methods=["*"],
296
  allow_headers=["*"],
297
  )
298
-
299
- # Register our custom REST API routes
300
- register_api_routes(fastapi_app)
301
-
302
- # Log the registered routes for debugging
303
- routes = [route.path for route in fastapi_app.routes]
304
- logger.info(f"Custom REST API routes successfully injected on Gradio FastAPI app: {routes}")
305
-
306
- return fastapi_app
307
-
308
- # Monkey-patch demo's create_app method
309
- demo.create_app = custom_create_app
310
-
311
- # Initialize the Gradio queue
312
- demo.queue()
313
 
314
  # Export Gradio demo as root app object for Hugging Face ZeroGPU SDK
315
  app = demo
@@ -317,5 +309,3 @@ app = demo
317
  if __name__ == "__main__":
318
  # Local development only — on HF Spaces, uvicorn runs the app directly
319
  demo.launch(server_name="0.0.0.0", server_port=7860, share=False)
320
-
321
-
 
34
  try:
35
  import spaces
36
  except ImportError:
37
+ spaces = None
 
 
 
 
 
 
 
 
38
 
39
+ def gpu_decorator(func=None, duration=None):
40
+ """ZeroGPU decorator wrapper that applies spaces.GPU on HF or identity on CPU."""
41
+ if spaces is not None:
42
+ try:
43
+ if func is None:
44
+ return spaces.GPU(duration=duration) if duration else spaces.GPU
45
+ if callable(func):
46
+ return spaces.GPU(func)
47
+ return spaces.GPU
48
+ except Exception:
49
+ pass
50
+ if func is None:
51
+ return lambda f: f
52
+ if callable(func):
53
+ return func
54
+ return lambda f: f
55
 
56
  from config import get_device, HAS_SPACES
57
  from services.forecast.service import forecast_aqi
 
106
  return f"❌ Execution Failed: {str(e)}", None, ""
107
 
108
 
109
+ @gpu_decorator
110
  def handle_forecast_ui(aqi_text_input: str, lat_val: str, lon_val: str):
111
+ """Gradio handler for AQI Forecasting wrapped with @gpu_decorator."""
112
  return asyncio.run(_async_handle_forecast_ui(aqi_text_input, lat_val, lon_val))
113
 
114
 
 
148
  return f"❌ Analysis Failed: {str(e)}", ""
149
 
150
 
151
+ @gpu_decorator
152
  def handle_vision_ui(input_image):
153
+ """Gradio handler for Satellite Vision wrapped with @gpu_decorator."""
154
  return asyncio.run(_async_handle_vision_ui(input_image))
155
 
156
 
 
219
  f"""
220
  ### 🖥️ Active Deployment Info
221
  - **Primary Compute Hardware**: `{device_active}`
222
+ - **HuggingFace `spaces` SDK Available**: `{spaces is not None}`
223
+ - **ZeroGPU Status**: `{"Active & Ready for dynamic GPU acceleration" if spaces is not None else "Running on standard CPU mode (Universal Compatibility)"}`
224
 
225
  ### 🔌 REST API Endpoints
226
  When deployed on Hugging Face Spaces, you can query REST endpoints directly:
 
230
  """
231
  )
232
 
 
233
  from starlette.responses import JSONResponse
234
  from starlette.requests import Request
235
 
236
+ # Initialize the Gradio queue — this creates the underlying FastAPI app object
237
+ # MUST be called before registering REST routes on demo.app
238
+ demo.queue()
239
+
240
+
241
+ def register_api_routes(gradio_app):
242
+ """Register custom REST API endpoints on the Gradio FastAPI app."""
243
 
244
+ @gradio_app.post("/api/v1/forecast")
 
 
245
  async def api_forecast(request: Request):
246
  """REST API endpoint for historical AQI prediction."""
247
  try:
 
256
  logger.error(f"API Forecast error: {e}")
257
  return JSONResponse({"error": str(e)}, status_code=400)
258
 
259
+ @gradio_app.post("/api/v1/analyze-image")
 
 
260
  async def api_analyze_image(request: Request):
261
  """REST API endpoint for satellite image pollution breakdown."""
262
  try:
 
276
  logger.error(f"API Vision error: {e}")
277
  return JSONResponse({"error": str(e)}, status_code=400)
278
 
279
+ @gradio_app.get("/api/v1/health")
 
 
280
  async def api_health(request: Request):
281
  """Health check endpoint."""
282
  return JSONResponse({
 
286
  "version": "2.0.0",
287
  })
288
 
 
 
289
 
290
+ # Register REST API routes on the Gradio underlying FastAPI app
291
+ try:
292
+ from fastapi.middleware.cors import CORSMiddleware
293
+ # Explicitly configure CORS on the underlying FastAPI app to allow direct requests from the browser
294
+ demo.app.add_middleware(
 
295
  CORSMiddleware,
296
  allow_origins=["*"],
297
  allow_credentials=True,
298
  allow_methods=["*"],
299
  allow_headers=["*"],
300
  )
301
+ register_api_routes(demo.app)
302
+ logger.info("CORS middleware and REST API routes registered successfully on Gradio FastAPI app.")
303
+ except Exception as e:
304
+ logger.warning(f"Could not register REST API routes or CORS (will be available via Gradio only): {e}")
 
 
 
 
 
 
 
 
 
 
 
305
 
306
  # Export Gradio demo as root app object for Hugging Face ZeroGPU SDK
307
  app = demo
 
309
  if __name__ == "__main__":
310
  # Local development only — on HF Spaces, uvicorn runs the app directly
311
  demo.launch(server_name="0.0.0.0", server_port=7860, share=False)