Futuresony commited on
Commit
528eda9
·
verified ·
1 Parent(s): afd0ce1

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +78 -20
app.py CHANGED
@@ -1,40 +1,98 @@
1
  import os
2
- from fastapi import FastAPI, Request, HTTPException
3
- import uvicorn
 
 
 
4
  from gradio_client import Client
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
- # Keys
7
- VALID_API_KEY = os.getenv("APP_API_KEY") # for your FastAPI security
8
- SPACE_API_KEY = os.getenv("SPACE_API_KEY") # for your hosted HF Space
 
 
 
9
 
10
- # Connect to hosted space
11
- client = Client("Futuresony/Mr.Events")
12
- #Futuresony/Mr.Events
13
- #Futuresony/ABSA_Test_Space
14
 
15
- app = FastAPI()
 
 
16
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  @app.post("/chat")
18
- async def chat(request: Request):
19
  data = await request.json()
20
 
21
- # API key check from headers or JSON
22
  api_key = request.headers.get("X-API-Key") or data.get("api_key")
23
  if api_key != VALID_API_KEY:
 
24
  raise HTTPException(status_code=403, detail="Invalid API Key")
25
 
26
  user_message = data.get("message")
27
  if not user_message:
28
  raise HTTPException(status_code=400, detail="Message is required")
29
 
30
- # Call your hosted Space
31
- result = client.predict(
32
- query=user_message,
33
- api_key=SPACE_API_KEY,
34
- api_name="/chat"
35
- )
 
 
 
 
 
 
 
36
 
37
- return {"response": result}
 
 
 
 
 
38
 
 
39
  if __name__ == "__main__":
40
- uvicorn.run(app, host="0.0.0.0", port=7860)
 
 
1
  import os
2
+ import time
3
+ import logging
4
+ from fastapi import FastAPI, Request, HTTPException, Depends
5
+ from fastapi.responses import JSONResponse
6
+ from fastapi.concurrency import run_in_threadpool
7
  from gradio_client import Client
8
+ import uvicorn
9
+ from typing import Dict
10
+
11
+ # ---------------- CONFIG ----------------
12
+ VALID_API_KEY = os.getenv("APP_API_KEY") # Your FastAPI security key
13
+ SPACE_API_KEY = os.getenv("SPACE_API_KEY") # Hugging Face Space key
14
+ SPACE_NAME = os.getenv("SPACE_NAME", "Futuresony/Mr.Events") # default space
15
+
16
+ if not VALID_API_KEY or not SPACE_API_KEY:
17
+ raise RuntimeError("❌ APP_API_KEY and SPACE_API_KEY must be set as environment variables.")
18
+
19
+ # ---------------- LOGGER ----------------
20
+ logging.basicConfig(
21
+ level=logging.INFO,
22
+ format="%(asctime)s [%(levelname)s] %(message)s",
23
+ )
24
+ logger = logging.getLogger("prod-api")
25
+
26
+ # ---------------- CLIENT ----------------
27
+ client = Client(SPACE_NAME)
28
 
29
+ # ---------------- FASTAPI APP ----------------
30
+ app = FastAPI(
31
+ title="Production Chat API",
32
+ description="Secure API that connects to Hugging Face Space",
33
+ version="1.0.0"
34
+ )
35
 
36
+ # ---------------- RATE LIMITER ----------------
37
+ RATE_LIMIT = 5 # max requests
38
+ WINDOW = 60 # per 60 seconds
39
+ client_requests: Dict[str, list] = {} # tracks requests per IP
40
 
41
+ def rate_limiter(request: Request):
42
+ client_ip = request.client.host
43
+ now = time.time()
44
 
45
+ if client_ip not in client_requests:
46
+ client_requests[client_ip] = []
47
+
48
+ # remove old requests outside time window
49
+ client_requests[client_ip] = [
50
+ t for t in client_requests[client_ip] if now - t < WINDOW
51
+ ]
52
+
53
+ if len(client_requests[client_ip]) >= RATE_LIMIT:
54
+ logger.warning(f"Rate limit exceeded for {client_ip}")
55
+ raise HTTPException(status_code=429, detail="Too many requests. Try again later.")
56
+
57
+ client_requests[client_ip].append(now)
58
+
59
+ # ---------------- ROUTES ----------------
60
  @app.post("/chat")
61
+ async def chat(request: Request, _: None = Depends(rate_limiter)):
62
  data = await request.json()
63
 
64
+ # API key check
65
  api_key = request.headers.get("X-API-Key") or data.get("api_key")
66
  if api_key != VALID_API_KEY:
67
+ logger.warning("Unauthorized access attempt.")
68
  raise HTTPException(status_code=403, detail="Invalid API Key")
69
 
70
  user_message = data.get("message")
71
  if not user_message:
72
  raise HTTPException(status_code=400, detail="Message is required")
73
 
74
+ try:
75
+ logger.info(f"Processing request from {request.client.host}: {user_message}")
76
+
77
+ # Call Hugging Face Space
78
+ result = await run_in_threadpool(
79
+ client.predict,
80
+ query=user_message,
81
+ api_key=SPACE_API_KEY,
82
+ api_name="/chat"
83
+ )
84
+
85
+ logger.info(f"Response delivered to {request.client.host}")
86
+ return {"response": result}
87
 
88
+ except Exception as e:
89
+ logger.error(f"Space call failed: {str(e)}")
90
+ return JSONResponse(
91
+ status_code=500,
92
+ content={"error": "Internal Server Error", "details": str(e)},
93
+ )
94
 
95
+ # ---------------- ENTRY ----------------
96
  if __name__ == "__main__":
97
+ logger.info("🚀 Starting Production Chat API...")
98
+ uvicorn.run("main:app", host="0.0.0.0", port=7860, reload=False, workers=2)