SateeshAmbesange commited on
Commit
a5b50c3
·
verified ·
1 Parent(s): 36282b5

Update backend/app.py

Browse files
Files changed (1) hide show
  1. backend/app.py +33 -20
backend/app.py CHANGED
@@ -1,3 +1,4 @@
 
1
  from fastapi import FastAPI, HTTPException
2
  from fastapi.staticfiles import StaticFiles
3
  from fastapi.middleware.cors import CORSMiddleware
@@ -8,16 +9,26 @@ import numpy as np
8
  import os
9
  from huggingface_hub import hf_hub_download
10
 
11
- # Global dictionary to hold loaded model assets
 
 
 
 
 
 
 
 
 
 
12
  model_assets = {}
13
 
14
  @asynccontextmanager
15
  async def lifespan(app: FastAPI):
16
- print("STARTUP: Beginning model assets download and load.")
17
  try:
18
  REPO_ID = "SateeshAmbesange/PragyanAI-Super30_ReactJS_RecommendationSystem"
19
  use_auth_token = os.environ.get("HUGGING_FACE_HUB_TOKEN") is not None
20
- print(f"STARTUP: Downloading model files from repo '{REPO_ID}' with auth token: {use_auth_token}")
21
 
22
  movies_file = hf_hub_download(repo_id=REPO_ID, filename="movies_df.joblib", use_auth_token=use_auth_token)
23
  cosine_file = hf_hub_download(repo_id=REPO_ID, filename="cosine_sim_matrix.joblib", use_auth_token=use_auth_token)
@@ -26,22 +37,24 @@ async def lifespan(app: FastAPI):
26
  model_assets['cosine_sim'] = joblib.load(cosine_file)
27
  model_assets['indices'] = pd.Series(model_assets['movies_df'].index, index=model_assets['movies_df']['title'])
28
 
29
- print(f"STARTUP: Model assets loaded successfully with {len(model_assets['movies_df'])} movies.")
30
  except Exception as e:
31
- print(f"FATAL: Failed to download or load model assets: {e}")
32
  model_assets['movies_df'] = None
33
  model_assets['cosine_sim'] = None
34
  model_assets['indices'] = None
35
- raise e # Raise exception to prevent app startup on failure
 
36
  yield
37
- print("SHUTDOWN: Clearing model assets.")
 
38
  model_assets.clear()
39
 
40
  app = FastAPI(lifespan=lifespan)
41
 
42
  app.add_middleware(
43
  CORSMiddleware,
44
- allow_origins=["*"], # For production, restrict origins for security
45
  allow_credentials=True,
46
  allow_methods=["*"],
47
  allow_headers=["*"],
@@ -49,28 +62,29 @@ app.add_middleware(
49
 
50
  @app.get("/api/movies")
51
  async def get_movie_list():
52
- print("API CALL: /api/movies")
53
  movies_df = model_assets.get('movies_df')
54
  if movies_df is None:
55
- print("ERROR: model_assets['movies_df'] is None in /api/movies")
56
  raise HTTPException(status_code=503, detail="Model assets not available.")
 
57
  titles = movies_df['title'].sort_values().unique().tolist()
58
- print(f"API RESPONSE: Serving {len(titles)} movie titles.")
59
  return {"movies": titles}
60
 
61
  @app.get("/api/recommend")
62
  async def get_recommendations_api(title: str):
63
- print(f"API CALL: /api/recommend for title '{title}'")
64
  movies_df = model_assets.get('movies_df')
65
  cosine_sim = model_assets.get('cosine_sim')
66
  indices = model_assets.get('indices')
67
 
68
  if not movies_df or not cosine_sim or not indices:
69
- print("ERROR: Model assets missing in /api/recommend")
70
- raise HTTPException(status_code=503, detail="Model assets not available.")
71
 
72
  if title not in indices:
73
- print(f"ERROR: Movie title '{title}' not found in indices")
74
  raise HTTPException(status_code=404, detail="Movie not found")
75
 
76
  try:
@@ -82,17 +96,16 @@ async def get_recommendations_api(title: str):
82
  return score if isinstance(score, (int, float, np.number)) and np.isfinite(score) else -1
83
 
84
  sim_scores = sorted(sim_scores, key=sort_key, reverse=True)
85
- sim_scores = sim_scores[1:11] # exclude the queried movie itself
86
 
87
  movie_indices = [i[0] for i in sim_scores]
88
  recommendations = movies_df.iloc[movie_indices][['title', 'id']].to_dict(orient='records')
89
 
90
- print(f"API RESPONSE: Returning {len(recommendations)} recommendations for '{title}'")
91
  return {"recommendations": recommendations}
92
  except Exception as e:
93
- print(f"ERROR: Exception in /api/recommend: {e}")
94
  raise HTTPException(status_code=500, detail=f"Internal server error: {e}")
95
 
96
- # Serve React static files from 'static' directory
97
  app.mount("/", StaticFiles(directory="static", html=True), name="static")
98
-
 
1
+ import logging
2
  from fastapi import FastAPI, HTTPException
3
  from fastapi.staticfiles import StaticFiles
4
  from fastapi.middleware.cors import CORSMiddleware
 
9
  import os
10
  from huggingface_hub import hf_hub_download
11
 
12
+ # Configure logging to file and stdout
13
+ logging.basicConfig(
14
+ level=logging.DEBUG,
15
+ format='%(asctime)s [%(levelname)s] %(message)s',
16
+ handlers=[
17
+ logging.FileHandler("space_runtime.log"),
18
+ logging.StreamHandler()
19
+ ]
20
+ )
21
+
22
+ # Global variable to hold model assets
23
  model_assets = {}
24
 
25
  @asynccontextmanager
26
  async def lifespan(app: FastAPI):
27
+ logging.info("STARTUP: Loading model assets...")
28
  try:
29
  REPO_ID = "SateeshAmbesange/PragyanAI-Super30_ReactJS_RecommendationSystem"
30
  use_auth_token = os.environ.get("HUGGING_FACE_HUB_TOKEN") is not None
31
+ logging.info(f"Downloading model files from {REPO_ID} with auth token: {use_auth_token}")
32
 
33
  movies_file = hf_hub_download(repo_id=REPO_ID, filename="movies_df.joblib", use_auth_token=use_auth_token)
34
  cosine_file = hf_hub_download(repo_id=REPO_ID, filename="cosine_sim_matrix.joblib", use_auth_token=use_auth_token)
 
37
  model_assets['cosine_sim'] = joblib.load(cosine_file)
38
  model_assets['indices'] = pd.Series(model_assets['movies_df'].index, index=model_assets['movies_df']['title'])
39
 
40
+ logging.info(f"Model assets loaded successfully: {len(model_assets['movies_df'])} movies")
41
  except Exception as e:
42
+ logging.error(f"FATAL ERROR: Could not load model assets: {e}", exc_info=True)
43
  model_assets['movies_df'] = None
44
  model_assets['cosine_sim'] = None
45
  model_assets['indices'] = None
46
+ raise e
47
+
48
  yield
49
+
50
+ logging.info("SHUTDOWN: Clearing model assets.")
51
  model_assets.clear()
52
 
53
  app = FastAPI(lifespan=lifespan)
54
 
55
  app.add_middleware(
56
  CORSMiddleware,
57
+ allow_origins=["*"], # For production, restrict this to your frontend domain
58
  allow_credentials=True,
59
  allow_methods=["*"],
60
  allow_headers=["*"],
 
62
 
63
  @app.get("/api/movies")
64
  async def get_movie_list():
65
+ logging.debug("API CALL: /api/movies")
66
  movies_df = model_assets.get('movies_df')
67
  if movies_df is None:
68
+ logging.error("Model assets unavailable in /api/movies")
69
  raise HTTPException(status_code=503, detail="Model assets not available.")
70
+
71
  titles = movies_df['title'].sort_values().unique().tolist()
72
+ logging.debug(f"API RESPONSE: Serving {len(titles)} movie titles")
73
  return {"movies": titles}
74
 
75
  @app.get("/api/recommend")
76
  async def get_recommendations_api(title: str):
77
+ logging.debug(f"API CALL: /api/recommend for title '{title}'")
78
  movies_df = model_assets.get('movies_df')
79
  cosine_sim = model_assets.get('cosine_sim')
80
  indices = model_assets.get('indices')
81
 
82
  if not movies_df or not cosine_sim or not indices:
83
+ logging.error("Model assets missing in /api/recommend")
84
+ raise HTTPException(status_code=503, detail="Model assets are not available.")
85
 
86
  if title not in indices:
87
+ logging.error(f"Movie title '{title}' not found in indices")
88
  raise HTTPException(status_code=404, detail="Movie not found")
89
 
90
  try:
 
96
  return score if isinstance(score, (int, float, np.number)) and np.isfinite(score) else -1
97
 
98
  sim_scores = sorted(sim_scores, key=sort_key, reverse=True)
99
+ sim_scores = sim_scores[1:11] # Exclude the queried movie itself
100
 
101
  movie_indices = [i[0] for i in sim_scores]
102
  recommendations = movies_df.iloc[movie_indices][['title', 'id']].to_dict(orient='records')
103
 
104
+ logging.debug(f"API RESPONSE: Returning {len(recommendations)} recommendations for '{title}'")
105
  return {"recommendations": recommendations}
106
  except Exception as e:
107
+ logging.error(f"Exception in /api/recommend: {e}", exc_info=True)
108
  raise HTTPException(status_code=500, detail=f"Internal server error: {e}")
109
 
110
+ # Serve React frontend static files from 'static' folder
111
  app.mount("/", StaticFiles(directory="static", html=True), name="static")