LogicGoInfotechSpaces commited on
Commit
c248b26
·
1 Parent(s): dccf408

Add test.py and enhanced debug logging for recommendation generation

Browse files
Files changed (2) hide show
  1. app/smart_recommendation.py +10 -2
  2. test.py +266 -0
app/smart_recommendation.py CHANGED
@@ -260,14 +260,20 @@ class SmartBudgetRecommender:
260
  return filtered_recommendations
261
 
262
  # If no recommendations found, try to generate one
263
- # First, get category name
264
- category_name = self._get_category_name(category_id)
265
 
266
  # If budget_amount is provided, use it
267
  if budget_amount and budget_amount > 0:
 
 
 
268
  avg_expense = budget_amount
269
  else:
270
  # Try to get budget data for this category
 
 
 
271
  try:
272
  # Try to find budgets with this category_id
273
  try:
@@ -332,6 +338,7 @@ class SmartBudgetRecommender:
332
  return []
333
 
334
  # Generate recommendation
 
335
  data = {
336
  "average_monthly": avg_expense,
337
  "total": avg_expense,
@@ -342,6 +349,7 @@ class SmartBudgetRecommender:
342
  }
343
 
344
  confidence = self._calculate_confidence(data)
 
345
 
346
  # Always try OpenAI first
347
  ai_result = self._get_ai_recommendation(category_name, data, avg_expense)
 
260
  return filtered_recommendations
261
 
262
  # If no recommendations found, try to generate one
263
+ print(f"🔍 get_recommendation_for_category: No recommendations found, trying to generate one")
264
+ print(f"🔍 get_recommendation_for_category: budget_amount = {budget_amount}")
265
 
266
  # If budget_amount is provided, use it
267
  if budget_amount and budget_amount > 0:
268
+ print(f"🔍 get_recommendation_for_category: Using provided budget_amount: {budget_amount}")
269
+ # First, get category name
270
+ category_name = self._get_category_name(category_id)
271
  avg_expense = budget_amount
272
  else:
273
  # Try to get budget data for this category
274
+ print(f"🔍 get_recommendation_for_category: No budget_amount provided, trying to get budget data")
275
+ # First, get category name
276
+ category_name = self._get_category_name(category_id)
277
  try:
278
  # Try to find budgets with this category_id
279
  try:
 
338
  return []
339
 
340
  # Generate recommendation
341
+ print(f"🔍 get_recommendation_for_category: Generating recommendation for category_name={category_name}, avg_expense={avg_expense}")
342
  data = {
343
  "average_monthly": avg_expense,
344
  "total": avg_expense,
 
349
  }
350
 
351
  confidence = self._calculate_confidence(data)
352
+ print(f"🔍 get_recommendation_for_category: Confidence calculated: {confidence}")
353
 
354
  # Always try OpenAI first
355
  ai_result = self._get_ai_recommendation(category_name, data, avg_expense)
test.py ADDED
@@ -0,0 +1,266 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Test script for POST /recommendations/check endpoint
3
+ Tests the new endpoint that checks user data and provides category-specific recommendations
4
+ """
5
+
6
+ import requests
7
+ import json
8
+ from datetime import datetime
9
+
10
+ # Update this to your API URL
11
+ # For local: http://localhost:8000 (requires server running)
12
+ # For Hugging Face: https://logicgoinfotechspaces-smart-budget-recommendation.hf.space
13
+ BASE_URL = "https://logicgoinfotechspaces-smart-budget-recommendation.hf.space"
14
+
15
+ # Test data from find_user_with_data.py
16
+ TEST_USER_ID = "6741abd38d30ab5b7176397f"
17
+ TEST_CATEGORY_ID = "6741abd38d30ab5b71763984"
18
+
19
+ def test_recommendations_check_with_data():
20
+ """Test POST /recommendations/check with user that has previous data"""
21
+ print("=" * 60)
22
+ print("Test 1: POST /recommendations/check (User with Previous Data)")
23
+ print("=" * 60)
24
+
25
+ try:
26
+ request_body = {
27
+ "user_id": TEST_USER_ID,
28
+ "category_id": TEST_CATEGORY_ID
29
+ }
30
+
31
+ print(f"\nRequest Body:")
32
+ print(json.dumps(request_body, indent=2))
33
+
34
+ response = requests.post(
35
+ f"{BASE_URL}/recommendations/check",
36
+ json=request_body,
37
+ headers={"Content-Type": "application/json"}
38
+ )
39
+
40
+ print(f"\nStatus Code: {response.status_code}")
41
+
42
+ if response.status_code == 200:
43
+ result = response.json()
44
+ print(f"\nResponse:")
45
+ print(json.dumps(result, indent=2))
46
+
47
+ if result.get("has_previous_data"):
48
+ print("\n[OK] User has previous data")
49
+ if result.get("recommendations"):
50
+ print(f"[OK] Found {len(result['recommendations'])} recommendation(s)")
51
+ for rec in result["recommendations"]:
52
+ print(f"\n Category: {rec.get('category')}")
53
+ print(f" Category ID: {rec.get('category_id')}")
54
+ print(f" Average Expense: Rs.{rec.get('average_expense', 0):,.2f}")
55
+ print(f" Recommended Budget: Rs.{rec.get('recommended_budget', 0):,.2f}")
56
+ print(f" Confidence: {rec.get('confidence', 0)*100:.1f}%")
57
+ print(f" Action: {rec.get('action', 'N/A')}")
58
+ print(f" Reason: {rec.get('reason', 'N/A')}")
59
+ else:
60
+ print("[WARNING] No recommendations returned")
61
+ else:
62
+ print("\n[INFO] User does not have previous data")
63
+ print(f"Message: {result.get('message', 'N/A')}")
64
+
65
+ return response.status_code == 200
66
+ else:
67
+ print(f"\n[ERROR] Request failed")
68
+ print(f"Response: {response.text}")
69
+ return False
70
+
71
+ except Exception as e:
72
+ print(f"\n[ERROR] Exception: {e}")
73
+ import traceback
74
+ traceback.print_exc()
75
+ return False
76
+
77
+ def test_recommendations_check_with_budget_amount():
78
+ """Test POST /recommendations/check with budget_amount provided"""
79
+ print("\n" + "=" * 60)
80
+ print("Test 2: POST /recommendations/check (With Budget Amount)")
81
+ print("=" * 60)
82
+
83
+ try:
84
+ request_body = {
85
+ "user_id": TEST_USER_ID,
86
+ "category_id": TEST_CATEGORY_ID,
87
+ "budget_amount": 10000.0
88
+ }
89
+
90
+ print(f"\nRequest Body:")
91
+ print(json.dumps(request_body, indent=2))
92
+
93
+ response = requests.post(
94
+ f"{BASE_URL}/recommendations/check",
95
+ json=request_body,
96
+ headers={"Content-Type": "application/json"}
97
+ )
98
+
99
+ print(f"\nStatus Code: {response.status_code}")
100
+
101
+ if response.status_code == 200:
102
+ result = response.json()
103
+ print(f"\nResponse:")
104
+ print(json.dumps(result, indent=2))
105
+
106
+ if result.get("recommendations"):
107
+ print(f"\n[OK] Generated {len(result['recommendations'])} recommendation(s) based on budget_amount")
108
+ for rec in result["recommendations"]:
109
+ print(f"\n Category: {rec.get('category')}")
110
+ print(f" Category ID: {rec.get('category_id')}")
111
+ print(f" Average Expense: Rs.{rec.get('average_expense', 0):,.2f}")
112
+ print(f" Recommended Budget: Rs.{rec.get('recommended_budget', 0):,.2f}")
113
+ print(f" Confidence: {rec.get('confidence', 0)*100:.1f}%")
114
+ print(f" Action: {rec.get('action', 'N/A')}")
115
+ print(f" Reason: {rec.get('reason', 'N/A')}")
116
+ else:
117
+ print("\n[WARNING] No recommendations returned even with budget_amount")
118
+
119
+ return response.status_code == 200
120
+ else:
121
+ print(f"\n[ERROR] Request failed")
122
+ print(f"Response: {response.text}")
123
+ return False
124
+
125
+ except Exception as e:
126
+ print(f"\n[ERROR] Exception: {e}")
127
+ import traceback
128
+ traceback.print_exc()
129
+ return False
130
+
131
+ def test_recommendations_check_new_user():
132
+ """Test POST /recommendations/check with a new user (no previous data)"""
133
+ print("\n" + "=" * 60)
134
+ print("Test 3: POST /recommendations/check (New User - No Previous Data)")
135
+ print("=" * 60)
136
+
137
+ try:
138
+ request_body = {
139
+ "user_id": "000000000000000000000000", # Non-existent user
140
+ "category_id": TEST_CATEGORY_ID
141
+ }
142
+
143
+ print(f"\nRequest Body:")
144
+ print(json.dumps(request_body, indent=2))
145
+
146
+ response = requests.post(
147
+ f"{BASE_URL}/recommendations/check",
148
+ json=request_body,
149
+ headers={"Content-Type": "application/json"}
150
+ )
151
+
152
+ print(f"\nStatus Code: {response.status_code}")
153
+
154
+ if response.status_code == 200:
155
+ result = response.json()
156
+ print(f"\nResponse:")
157
+ print(json.dumps(result, indent=2))
158
+
159
+ if not result.get("has_previous_data"):
160
+ print("\n[OK] Correctly identified user has no previous data")
161
+ print(f"Message: {result.get('message', 'N/A')}")
162
+ else:
163
+ print("\n[WARNING] User was identified as having data (unexpected)")
164
+
165
+ return response.status_code == 200
166
+ else:
167
+ print(f"\n[ERROR] Request failed")
168
+ print(f"Response: {response.text}")
169
+ return False
170
+
171
+ except Exception as e:
172
+ print(f"\n[ERROR] Exception: {e}")
173
+ import traceback
174
+ traceback.print_exc()
175
+ return False
176
+
177
+ def test_recommendations_check_new_user_with_budget():
178
+ """Test POST /recommendations/check with new user but with budget_amount"""
179
+ print("\n" + "=" * 60)
180
+ print("Test 4: POST /recommendations/check (New User with Budget Amount)")
181
+ print("=" * 60)
182
+
183
+ try:
184
+ request_body = {
185
+ "user_id": "000000000000000000000000", # Non-existent user
186
+ "category_id": TEST_CATEGORY_ID,
187
+ "budget_amount": 5000.0
188
+ }
189
+
190
+ print(f"\nRequest Body:")
191
+ print(json.dumps(request_body, indent=2))
192
+
193
+ response = requests.post(
194
+ f"{BASE_URL}/recommendations/check",
195
+ json=request_body,
196
+ headers={"Content-Type": "application/json"}
197
+ )
198
+
199
+ print(f"\nStatus Code: {response.status_code}")
200
+
201
+ if response.status_code == 200:
202
+ result = response.json()
203
+ print(f"\nResponse:")
204
+ print(json.dumps(result, indent=2))
205
+
206
+ if result.get("recommendations"):
207
+ print(f"\n[OK] Generated recommendation for new user based on budget_amount")
208
+ for rec in result["recommendations"]:
209
+ print(f"\n Category: {rec.get('category')}")
210
+ print(f" Category ID: {rec.get('category_id')}")
211
+ print(f" Average Expense: Rs.{rec.get('average_expense', 0):,.2f}")
212
+ print(f" Recommended Budget: Rs.{rec.get('recommended_budget', 0):,.2f}")
213
+ print(f" Confidence: {rec.get('confidence', 0)*100:.1f}%")
214
+ print(f" Action: {rec.get('action', 'N/A')}")
215
+ print(f" Reason: {rec.get('reason', 'N/A')}")
216
+ else:
217
+ print("\n[WARNING] No recommendations returned even with budget_amount")
218
+
219
+ return response.status_code == 200
220
+ else:
221
+ print(f"\n[ERROR] Request failed")
222
+ print(f"Response: {response.text}")
223
+ return False
224
+
225
+ except Exception as e:
226
+ print(f"\n[ERROR] Exception: {e}")
227
+ import traceback
228
+ traceback.print_exc()
229
+ return False
230
+
231
+ if __name__ == "__main__":
232
+ print("\n" + "=" * 60)
233
+ print("Smart Budget Recommendation API - Test Suite")
234
+ print("POST /recommendations/check Endpoint Tests")
235
+ print("=" * 60)
236
+ print(f"\nBase URL: {BASE_URL}")
237
+ print(f"Test User ID: {TEST_USER_ID}")
238
+ print(f"Test Category ID: {TEST_CATEGORY_ID}")
239
+ print("\nTesting against Hugging Face deployment")
240
+ print("(For local testing, change BASE_URL to http://localhost:8000 and start server with: uvicorn app.main:app --reload)\n")
241
+
242
+ results = []
243
+
244
+ # Run all tests
245
+ results.append(("User with Previous Data", test_recommendations_check_with_data()))
246
+ results.append(("With Budget Amount", test_recommendations_check_with_budget_amount()))
247
+ results.append(("New User (No Data)", test_recommendations_check_new_user()))
248
+ results.append(("New User with Budget Amount", test_recommendations_check_new_user_with_budget()))
249
+
250
+ # Summary
251
+ print("\n" + "=" * 60)
252
+ print("Test Summary")
253
+ print("=" * 60)
254
+ for test_name, passed in results:
255
+ status = "[PASS]" if passed else "[FAIL]"
256
+ print(f"{status} - {test_name}")
257
+
258
+ passed_count = sum(1 for _, passed in results if passed)
259
+ print(f"\nTotal: {passed_count}/{len(results)} tests passed")
260
+
261
+ print("\n" + "=" * 60)
262
+ print("API Documentation available at:")
263
+ print(f" - Swagger UI: {BASE_URL}/docs")
264
+ print(f" - ReDoc: {BASE_URL}/redoc")
265
+ print("=" * 60)
266
+