garvitcpp commited on
Commit
29884c5
·
verified ·
1 Parent(s): c8713c8

Update app/api/routes.py

Browse files
Files changed (1) hide show
  1. app/api/routes.py +85 -65
app/api/routes.py CHANGED
@@ -3,86 +3,110 @@ from app.models.recipe import Recipe
3
  import json
4
  import asyncio
5
  import os
 
 
 
6
  from app.services import extraction
7
  from app.services import image_query
8
 
9
  api_bp = Blueprint('api', __name__, url_prefix='/api')
10
 
 
 
 
 
 
 
 
 
 
 
11
  @api_bp.route('/form-data', methods=['GET'])
12
  def get_form_data():
13
- # Use os.path.join to create a platform-independent path
14
  file_path = os.path.join(os.getcwd(), 'form_data.json')
15
  try:
16
  with open(file_path, 'r') as file:
17
  data = file.read()
18
  return data
19
  except FileNotFoundError:
 
20
  return jsonify({"error": f"File not found at {file_path}"}), 404
21
  except Exception as e:
 
22
  return jsonify({"error": str(e)}), 500
23
 
24
  @api_bp.route('/recommend', methods=['POST'])
25
- async def recommend_recipes(): # Make this function async
26
- data = request.json
27
- category = data.get('category')
28
- dietary_preference = data.get('dietary_preference')
29
- ingredients = data.get('ingredients', [])
30
- calories = data.get('calories')
31
- time = data.get('time')
32
- keywords = data.get('keywords', [])
33
- keywords_name = data.get('keywords_name', [])
34
-
35
  try:
 
 
 
 
 
 
 
 
 
36
  if calories is not None:
37
  calories = int(calories)
38
  if time is not None:
39
  time = int(time)
40
- except ValueError:
41
- return jsonify({"error": "Calories and time must be integers if provided"}), 400
42
-
43
- feature_weights_recommend = {
44
- 'ingredients': 0.15, 'category': 0.25, 'dietary': 0.20,
45
- 'calories': 0.10, 'time': 0.10, 'keywords': 0.10, 'keywords_name': 0.10
46
- }
47
-
48
- # Use await to call the async function
49
- recommendations = await current_app.recommendation_system.get_recommendations(
50
- category=category,
51
- dietary_preference=dietary_preference,
52
- ingredients=ingredients,
53
- calories=calories,
54
- time=time,
55
- keywords=keywords,
56
- keywords_name=keywords_name,
57
- feature_weights=feature_weights_recommend
58
- )
59
-
60
- return jsonify([vars(recipe) for recipe in recommendations])
 
 
 
 
61
 
62
  @api_bp.route('/extract-recipe-attributes', methods=['POST'])
63
  async def recommend_recipes2():
 
 
 
64
  try:
65
  data = request.get_json()
66
  if not data:
67
  return jsonify({"error": "No data provided"}), 400
68
-
69
  raw_text = data.get('text')
70
  if not raw_text:
71
  return jsonify({"error": "No search text provided"}), 400
72
 
73
- # Extract recipe attributes
74
- extracted_info = extraction.extract_recipe_attributes(raw_text) # Call the extraction function
 
75
 
76
- # Check if extraction was successful
77
  if 'error' in extracted_info:
 
78
  return jsonify(extracted_info), 500
79
-
80
  feature_weights_extract = {
81
  'ingredients': 0.50, 'category': 0.0, 'dietary': 0.0,
82
  'calories': 0.0, 'time': 0.0, 'keywords': 0.40, 'keywords_name': 0.10
83
  }
84
 
85
- # Access the extracted attributes
86
  category = extracted_info.get('category', '')
87
  calories = extracted_info.get('calories', None)
88
  time = extracted_info.get('time', None)
@@ -90,17 +114,17 @@ async def recommend_recipes2():
90
  keywords_name = extracted_info.get('keywords_name', [])
91
  ingredients = extracted_info.get('ingredients', [])
92
 
93
- # Convert calories and time to integers if they exist
94
  try:
95
  calories = int(calories) if calories else None
96
  time = int(time) if time else None
97
  except (ValueError, TypeError):
98
  return jsonify({"error": "Invalid calories or time value"}), 400
99
 
100
- # Get recommendations using the recommendation system
 
101
  recommendations = await current_app.recommendation_system.get_recommendations(
102
  category=category,
103
- ingredients=ingredients, # Adjust if you plan to add ingredients in the extraction function
104
  calories=calories,
105
  time=time,
106
  keywords=keywords,
@@ -108,42 +132,44 @@ async def recommend_recipes2():
108
  feature_weights=feature_weights_extract
109
  )
110
 
111
- # Convert recommendations to JSON-serializable format
112
  recipe_list = [vars(recipe) for recipe in recommendations]
113
-
114
  return jsonify(recipe_list)
115
-
116
  except Exception as e:
 
 
 
117
  return jsonify({"error": str(e)}), 500
118
-
119
- # searchImage
120
  @api_bp.route('/analyze-food-image', methods=['POST'])
121
  async def handle_analyze_food_image():
 
 
 
122
  try:
123
  if 'image' not in request.files:
124
  return jsonify({"error": "No image file provided"}), 400
125
 
126
  file = request.files['image']
127
-
128
  if file.filename == '':
129
  return jsonify({"error": "No selected file"}), 400
130
 
131
- # Call the analyze function with the file
132
  description = image_query.analyze_food_image(file)
133
 
134
- # Extract recipe attributes
135
- extracted_info = extraction.extract_recipe_attributes(description) # Call the extraction function
136
 
137
- # Check if extraction was successful
138
  if 'error' in extracted_info:
139
  return jsonify(extracted_info), 500
140
-
141
  feature_weights_extract = {
142
  'ingredients': 0.50, 'category': 0.0, 'dietary': 0.0,
143
  'calories': 0.0, 'time': 0.0, 'keywords': 0.40, 'keywords_name': 0.10
144
  }
145
 
146
- # Access the extracted attributes
147
  category = extracted_info.get('category', '')
148
  calories = extracted_info.get('calories', None)
149
  time = extracted_info.get('time', None)
@@ -151,17 +177,15 @@ async def handle_analyze_food_image():
151
  keywords_name = extracted_info.get('keywords_name', [])
152
  ingredients = extracted_info.get('ingredients', [])
153
 
154
- # Convert calories and time to integers if they exist
155
  try:
156
  calories = int(calories) if calories else None
157
  time = int(time) if time else None
158
  except (ValueError, TypeError):
159
  return jsonify({"error": "Invalid calories or time value"}), 400
160
 
161
- # Get recommendations using the recommendation system
162
  recommendations = await current_app.recommendation_system.get_recommendations(
163
  category=category,
164
- ingredients=ingredients, # Adjust if you plan to add ingredients in the extraction function
165
  calories=calories,
166
  time=time,
167
  keywords=keywords,
@@ -169,20 +193,17 @@ async def handle_analyze_food_image():
169
  feature_weights=feature_weights_extract
170
  )
171
 
172
- # Convert recommendations to JSON-serializable format
173
  recipe_list = [vars(recipe) for recipe in recommendations]
174
-
175
  return jsonify(recipe_list)
176
-
177
  except Exception as e:
 
 
178
  return jsonify({"error": str(e)}), 500
179
 
180
  @api_bp.route('/health', methods=['GET'])
181
  def health_check():
182
- """
183
- Simple health check endpoint to keep the space awake.
184
- Returns a 200 OK status with a basic message.
185
- """
186
  return jsonify({
187
  "status": "alive",
188
  "message": "Recipe Recommendation Service is Running",
@@ -192,5 +213,4 @@ def health_check():
192
  "/api/extract-recipe-attributes",
193
  "/api/analyze-food-image"
194
  ]
195
- }), 200
196
-
 
3
  import json
4
  import asyncio
5
  import os
6
+ import sys
7
+ import traceback
8
+ import resource
9
  from app.services import extraction
10
  from app.services import image_query
11
 
12
  api_bp = Blueprint('api', __name__, url_prefix='/api')
13
 
14
+ def log_memory(tag=""):
15
+ """Helper to print current RAM usage to logs"""
16
+ try:
17
+ usage = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
18
+ # Linux returns KB, convert to MB
19
+ usage_mb = usage / 1024
20
+ print(f"[{tag}] MEMORY USAGE: {usage_mb:.2f} MB", file=sys.stderr)
21
+ except Exception:
22
+ pass
23
+
24
  @api_bp.route('/form-data', methods=['GET'])
25
  def get_form_data():
 
26
  file_path = os.path.join(os.getcwd(), 'form_data.json')
27
  try:
28
  with open(file_path, 'r') as file:
29
  data = file.read()
30
  return data
31
  except FileNotFoundError:
32
+ print(f"Error: File not found at {file_path}", file=sys.stderr)
33
  return jsonify({"error": f"File not found at {file_path}"}), 404
34
  except Exception as e:
35
+ traceback.print_exc(file=sys.stderr)
36
  return jsonify({"error": str(e)}), 500
37
 
38
  @api_bp.route('/recommend', methods=['POST'])
39
+ async def recommend_recipes():
40
+ print(">>> RECOMMEND ENDPOINT HIT", file=sys.stderr)
41
+ log_memory("Start Recommend")
42
+
 
 
 
 
 
 
43
  try:
44
+ data = request.json
45
+ category = data.get('category')
46
+ dietary_preference = data.get('dietary_preference')
47
+ ingredients = data.get('ingredients', [])
48
+ calories = data.get('calories')
49
+ time = data.get('time')
50
+ keywords = data.get('keywords', [])
51
+ keywords_name = data.get('keywords_name', [])
52
+
53
  if calories is not None:
54
  calories = int(calories)
55
  if time is not None:
56
  time = int(time)
57
+
58
+ feature_weights_recommend = {
59
+ 'ingredients': 0.15, 'category': 0.25, 'dietary': 0.20,
60
+ 'calories': 0.10, 'time': 0.10, 'keywords': 0.10, 'keywords_name': 0.10
61
+ }
62
+
63
+ recommendations = await current_app.recommendation_system.get_recommendations(
64
+ category=category,
65
+ dietary_preference=dietary_preference,
66
+ ingredients=ingredients,
67
+ calories=calories,
68
+ time=time,
69
+ keywords=keywords,
70
+ keywords_name=keywords_name,
71
+ feature_weights=feature_weights_recommend
72
+ )
73
+
74
+ log_memory("End Recommend")
75
+ return jsonify([vars(recipe) for recipe in recommendations])
76
+
77
+ except Exception as e:
78
+ print("!!! CRITICAL ERROR IN RECOMMEND !!!", file=sys.stderr)
79
+ traceback.print_exc(file=sys.stderr)
80
+ return jsonify({"error": str(e)}), 500
81
+
82
 
83
  @api_bp.route('/extract-recipe-attributes', methods=['POST'])
84
  async def recommend_recipes2():
85
+ print(">>> SEARCH (EXTRACT) ENDPOINT HIT", file=sys.stderr)
86
+ log_memory("Start Search")
87
+
88
  try:
89
  data = request.get_json()
90
  if not data:
91
  return jsonify({"error": "No data provided"}), 400
92
+
93
  raw_text = data.get('text')
94
  if not raw_text:
95
  return jsonify({"error": "No search text provided"}), 400
96
 
97
+ # 1. Extract Attributes (Using Gemini/AI)
98
+ print(f"Extracting attributes for: {raw_text[:50]}...", file=sys.stderr)
99
+ extracted_info = extraction.extract_recipe_attributes(raw_text)
100
 
 
101
  if 'error' in extracted_info:
102
+ print(f"Extraction Error: {extracted_info}", file=sys.stderr)
103
  return jsonify(extracted_info), 500
104
+
105
  feature_weights_extract = {
106
  'ingredients': 0.50, 'category': 0.0, 'dietary': 0.0,
107
  'calories': 0.0, 'time': 0.0, 'keywords': 0.40, 'keywords_name': 0.10
108
  }
109
 
 
110
  category = extracted_info.get('category', '')
111
  calories = extracted_info.get('calories', None)
112
  time = extracted_info.get('time', None)
 
114
  keywords_name = extracted_info.get('keywords_name', [])
115
  ingredients = extracted_info.get('ingredients', [])
116
 
 
117
  try:
118
  calories = int(calories) if calories else None
119
  time = int(time) if time else None
120
  except (ValueError, TypeError):
121
  return jsonify({"error": "Invalid calories or time value"}), 400
122
 
123
+ # 2. Get Recommendations (Using Huge DataFrame)
124
+ print("Calling Recommendation System...", file=sys.stderr)
125
  recommendations = await current_app.recommendation_system.get_recommendations(
126
  category=category,
127
+ ingredients=ingredients,
128
  calories=calories,
129
  time=time,
130
  keywords=keywords,
 
132
  feature_weights=feature_weights_extract
133
  )
134
 
135
+ log_memory("End Search")
136
  recipe_list = [vars(recipe) for recipe in recommendations]
 
137
  return jsonify(recipe_list)
138
+
139
  except Exception as e:
140
+ print("!!! CRITICAL ERROR IN SEARCH !!!", file=sys.stderr)
141
+ # This is the line that will finally show you WHY it crashes
142
+ traceback.print_exc(file=sys.stderr)
143
  return jsonify({"error": str(e)}), 500
144
+
145
+
146
  @api_bp.route('/analyze-food-image', methods=['POST'])
147
  async def handle_analyze_food_image():
148
+ print(">>> IMAGE ANALYSIS ENDPOINT HIT", file=sys.stderr)
149
+ log_memory("Start Image")
150
+
151
  try:
152
  if 'image' not in request.files:
153
  return jsonify({"error": "No image file provided"}), 400
154
 
155
  file = request.files['image']
 
156
  if file.filename == '':
157
  return jsonify({"error": "No selected file"}), 400
158
 
159
+ print("Analyzing Food Image...", file=sys.stderr)
160
  description = image_query.analyze_food_image(file)
161
 
162
+ print(f"Image Description: {description[:50]}...", file=sys.stderr)
163
+ extracted_info = extraction.extract_recipe_attributes(description)
164
 
 
165
  if 'error' in extracted_info:
166
  return jsonify(extracted_info), 500
167
+
168
  feature_weights_extract = {
169
  'ingredients': 0.50, 'category': 0.0, 'dietary': 0.0,
170
  'calories': 0.0, 'time': 0.0, 'keywords': 0.40, 'keywords_name': 0.10
171
  }
172
 
 
173
  category = extracted_info.get('category', '')
174
  calories = extracted_info.get('calories', None)
175
  time = extracted_info.get('time', None)
 
177
  keywords_name = extracted_info.get('keywords_name', [])
178
  ingredients = extracted_info.get('ingredients', [])
179
 
 
180
  try:
181
  calories = int(calories) if calories else None
182
  time = int(time) if time else None
183
  except (ValueError, TypeError):
184
  return jsonify({"error": "Invalid calories or time value"}), 400
185
 
 
186
  recommendations = await current_app.recommendation_system.get_recommendations(
187
  category=category,
188
+ ingredients=ingredients,
189
  calories=calories,
190
  time=time,
191
  keywords=keywords,
 
193
  feature_weights=feature_weights_extract
194
  )
195
 
196
+ log_memory("End Image")
197
  recipe_list = [vars(recipe) for recipe in recommendations]
 
198
  return jsonify(recipe_list)
199
+
200
  except Exception as e:
201
+ print("!!! CRITICAL ERROR IN IMAGE ANALYSIS !!!", file=sys.stderr)
202
+ traceback.print_exc(file=sys.stderr)
203
  return jsonify({"error": str(e)}), 500
204
 
205
  @api_bp.route('/health', methods=['GET'])
206
  def health_check():
 
 
 
 
207
  return jsonify({
208
  "status": "alive",
209
  "message": "Recipe Recommendation Service is Running",
 
213
  "/api/extract-recipe-attributes",
214
  "/api/analyze-food-image"
215
  ]
216
+ }), 200