mgbam commited on
Commit
eaf2b94
Β·
verified Β·
1 Parent(s): ea97c29

Update app/main.py

Browse files
Files changed (1) hide show
  1. app/main.py +42 -24
app/main.py CHANGED
@@ -1,57 +1,74 @@
1
  """
2
- CryptoSentinelΒ AI – FastAPI entry‑point
 
 
 
3
  """
 
4
  import os
 
 
5
  from fastapi import FastAPI, Request, BackgroundTasks
6
- from fastapi.responses import HTMLResponse, StreamingResponse, JSONResponse
7
  from fastapi.staticfiles import StaticFiles
 
8
  from apscheduler.schedulers.background import BackgroundScheduler
9
- from dotenv import load_dotenv
10
  from price_fetcher import fetch_prices, CURRENT_PRICES
11
- from sentiment import analyze_sentiment, SentimentCache
12
- from pathlib import Path
13
  import json
14
  import asyncio
15
 
16
- load_dotenv()
17
 
18
- app = FastAPI(title="CryptoSentinelΒ AI")
19
- templ_dir = Path(__file__).parent / "templates"
20
- app.mount("/static", StaticFiles(directory=Path(__file__).parent / "static"), name="static")
 
21
 
 
 
 
 
 
 
 
 
22
  scheduler = BackgroundScheduler(daemon=True)
23
- scheduler.add_job(fetch_prices, "interval", seconds=10) # refresh price cache
24
  scheduler.start()
25
 
26
  @app.on_event("shutdown")
27
- def shutdown_event():
28
  scheduler.shutdown(wait=False)
29
 
30
- # ---------- ROUTES -----------------------------------------------------------
 
 
 
 
 
 
31
 
32
  @app.get("/", response_class=HTMLResponse)
33
  async def index(request: Request):
34
- from fastapi.templating import Jinja2Templates
35
- templates = Jinja2Templates(directory=str(templ_dir))
36
  return templates.TemplateResponse("index.html", {"request": request})
37
 
38
- @app.get("/prices")
39
- async def prices():
40
- """JSON endpoint for latest cached prices."""
41
- return JSONResponse(CURRENT_PRICES)
42
 
43
  @app.post("/sentiment")
44
- async def sentiment(request: Request, background_tasks: BackgroundTasks):
45
  body = await request.json()
46
  text = body.get("text", "")
47
- # Run expensive inference in background to keep latency low
48
  background_tasks.add_task(SentimentCache.compute, text)
49
  return {"status": "processing"}
50
 
51
  @app.get("/sentiment/stream")
52
- async def sentiment_stream():
53
- """Server‑sent events stream – pushes sentiment results."""
54
- async def event_generator():
55
  last_id = 0
56
  while True:
57
  if SentimentCache.latest_id != last_id:
@@ -59,4 +76,5 @@ async def sentiment_stream():
59
  data = json.dumps(SentimentCache.latest_result)
60
  yield f"id:{last_id}\ndata:{data}\n\n"
61
  await asyncio.sleep(1)
62
- return StreamingResponse(event_generator(), media_type="text/event-stream")
 
 
1
  """
2
+ CryptoSentinel AI β€” FastAPI app entry point
3
+ - Fetches live prices from CoinGecko
4
+ - Provides real-time sentiment analysis using Hugging Face Transformers
5
+ - Compatible with Hugging Face Spaces (safe caching)
6
  """
7
+
8
  import os
9
+ from pathlib import Path
10
+
11
  from fastapi import FastAPI, Request, BackgroundTasks
12
+ from fastapi.responses import HTMLResponse, JSONResponse, StreamingResponse
13
  from fastapi.staticfiles import StaticFiles
14
+ from fastapi.templating import Jinja2Templates
15
  from apscheduler.schedulers.background import BackgroundScheduler
16
+
17
  from price_fetcher import fetch_prices, CURRENT_PRICES
18
+ from sentiment import SentimentCache
 
19
  import json
20
  import asyncio
21
 
22
+ # ──────────────────────────────────────────────────────────────────────────────
23
 
24
+ # Define paths
25
+ BASE_DIR = Path(__file__).parent
26
+ TEMPLATES_DIR = BASE_DIR / "templates"
27
+ STATIC_DIR = BASE_DIR / "static"
28
 
29
+ # Create FastAPI app
30
+ app = FastAPI(title="CryptoSentinel AI")
31
+ templates = Jinja2Templates(directory=str(TEMPLATES_DIR))
32
+ app.mount("/static", StaticFiles(directory=STATIC_DIR), name="static")
33
+
34
+ # ──────────────────────────────────────────────────────────────────────────────
35
+
36
+ # Start background job to update prices
37
  scheduler = BackgroundScheduler(daemon=True)
38
+ scheduler.add_job(fetch_prices, trigger="interval", seconds=10)
39
  scheduler.start()
40
 
41
  @app.on_event("shutdown")
42
+ def stop_scheduler():
43
  scheduler.shutdown(wait=False)
44
 
45
+ @app.on_event("startup")
46
+ def warm_up_model():
47
+ # Pre-warm Hugging Face model on startup to avoid first-request latency
48
+ SentimentCache.compute("The market is bullish today!")
49
+
50
+ # ──────────────────────────────────────────────────────────────────────────────
51
+ # ROUTES
52
 
53
  @app.get("/", response_class=HTMLResponse)
54
  async def index(request: Request):
 
 
55
  return templates.TemplateResponse("index.html", {"request": request})
56
 
57
+ @app.get("/prices", response_class=JSONResponse)
58
+ async def get_prices():
59
+ return CURRENT_PRICES
 
60
 
61
  @app.post("/sentiment")
62
+ async def analyze_sentiment(request: Request, background_tasks: BackgroundTasks):
63
  body = await request.json()
64
  text = body.get("text", "")
 
65
  background_tasks.add_task(SentimentCache.compute, text)
66
  return {"status": "processing"}
67
 
68
  @app.get("/sentiment/stream")
69
+ async def stream_sentiment():
70
+ """Server-Sent Events stream for pushing sentiment updates."""
71
+ async def event_stream():
72
  last_id = 0
73
  while True:
74
  if SentimentCache.latest_id != last_id:
 
76
  data = json.dumps(SentimentCache.latest_result)
77
  yield f"id:{last_id}\ndata:{data}\n\n"
78
  await asyncio.sleep(1)
79
+
80
+ return StreamingResponse(event_stream(), media_type="text/event-stream")