Commit
·
4040861
1
Parent(s):
c248b26
Improve OpenAI prompt to provide varied recommendations (increase/decrease/keep) based on spending trends and patterns
Browse files- app/smart_recommendation.py +77 -11
app/smart_recommendation.py
CHANGED
|
@@ -264,11 +264,14 @@ class SmartBudgetRecommender:
|
|
| 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")
|
|
@@ -339,13 +342,57 @@ class SmartBudgetRecommender:
|
|
| 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":
|
| 345 |
-
"count":
|
| 346 |
-
"months_analyzed":
|
| 347 |
-
"std_dev":
|
| 348 |
-
"monthly_values":
|
| 349 |
}
|
| 350 |
|
| 351 |
confidence = self._calculate_confidence(data)
|
|
@@ -898,13 +945,32 @@ class SmartBudgetRecommender:
|
|
| 898 |
)
|
| 899 |
|
| 900 |
prompt = (
|
| 901 |
-
"You are an Indian personal finance coach. "
|
| 902 |
-
"
|
| 903 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 904 |
"Respond strictly as JSON with the following keys:\n"
|
| 905 |
'{ "recommended_budget": number, "action": "increase|decrease|keep", "reason": "string" }.\n'
|
| 906 |
-
"
|
| 907 |
-
|
| 908 |
)
|
| 909 |
|
| 910 |
try:
|
|
@@ -919,7 +985,7 @@ class SmartBudgetRecommender:
|
|
| 919 |
"messages": [
|
| 920 |
{"role": "user", "content": prompt}
|
| 921 |
],
|
| 922 |
-
"temperature": 0.
|
| 923 |
"response_format": {"type": "json_object"},
|
| 924 |
},
|
| 925 |
timeout=30,
|
|
|
|
| 264 |
print(f"🔍 get_recommendation_for_category: budget_amount = {budget_amount}")
|
| 265 |
|
| 266 |
# If budget_amount is provided, use it
|
| 267 |
+
using_budget_amount_only = False
|
| 268 |
if budget_amount and budget_amount > 0:
|
| 269 |
print(f"🔍 get_recommendation_for_category: Using provided budget_amount: {budget_amount}")
|
| 270 |
# First, get category name
|
| 271 |
category_name = self._get_category_name(category_id)
|
| 272 |
avg_expense = budget_amount
|
| 273 |
+
# Mark that we're using budget_amount only (no historical data)
|
| 274 |
+
using_budget_amount_only = True
|
| 275 |
else:
|
| 276 |
# Try to get budget data for this category
|
| 277 |
print(f"🔍 get_recommendation_for_category: No budget_amount provided, trying to get budget data")
|
|
|
|
| 342 |
|
| 343 |
# Generate recommendation
|
| 344 |
print(f"🔍 get_recommendation_for_category: Generating recommendation for category_name={category_name}, avg_expense={avg_expense}")
|
| 345 |
+
|
| 346 |
+
# If we only have budget_amount (no historical data), create simulated variation
|
| 347 |
+
# to help OpenAI make better recommendations based on category type
|
| 348 |
+
if using_budget_amount_only:
|
| 349 |
+
# Create simulated monthly values with realistic variation based on category
|
| 350 |
+
# This helps OpenAI understand spending patterns and make smarter recommendations
|
| 351 |
+
if "food" in category_name.lower() or "groceries" in category_name.lower() or "drinks" in category_name.lower():
|
| 352 |
+
# Food categories tend to have moderate variation
|
| 353 |
+
monthly_values = [
|
| 354 |
+
avg_expense * 0.92,
|
| 355 |
+
avg_expense * 0.96,
|
| 356 |
+
avg_expense,
|
| 357 |
+
avg_expense * 1.04,
|
| 358 |
+
avg_expense * 1.08,
|
| 359 |
+
]
|
| 360 |
+
elif "transport" in category_name.lower() or "travel" in category_name.lower():
|
| 361 |
+
# Transport can vary more
|
| 362 |
+
monthly_values = [
|
| 363 |
+
avg_expense * 0.85,
|
| 364 |
+
avg_expense * 0.95,
|
| 365 |
+
avg_expense,
|
| 366 |
+
avg_expense * 1.10,
|
| 367 |
+
avg_expense * 1.15,
|
| 368 |
+
]
|
| 369 |
+
else:
|
| 370 |
+
# Default: moderate variation
|
| 371 |
+
monthly_values = [
|
| 372 |
+
avg_expense * 0.90,
|
| 373 |
+
avg_expense * 0.95,
|
| 374 |
+
avg_expense,
|
| 375 |
+
avg_expense * 1.05,
|
| 376 |
+
avg_expense * 1.10,
|
| 377 |
+
]
|
| 378 |
+
|
| 379 |
+
# Calculate std_dev from simulated values
|
| 380 |
+
mean = sum(monthly_values) / len(monthly_values)
|
| 381 |
+
variance = sum((x - mean) ** 2 for x in monthly_values) / len(monthly_values)
|
| 382 |
+
std_dev = variance ** 0.5
|
| 383 |
+
months_analyzed = len(monthly_values)
|
| 384 |
+
else:
|
| 385 |
+
monthly_values = data.get("monthly_values", [avg_expense])
|
| 386 |
+
std_dev = data.get("std_dev", 0.0)
|
| 387 |
+
months_analyzed = data.get("months_analyzed", 1)
|
| 388 |
+
|
| 389 |
data = {
|
| 390 |
"average_monthly": avg_expense,
|
| 391 |
+
"total": sum(monthly_values),
|
| 392 |
+
"count": months_analyzed,
|
| 393 |
+
"months_analyzed": months_analyzed,
|
| 394 |
+
"std_dev": std_dev,
|
| 395 |
+
"monthly_values": monthly_values,
|
| 396 |
}
|
| 397 |
|
| 398 |
confidence = self._calculate_confidence(data)
|
|
|
|
| 945 |
)
|
| 946 |
|
| 947 |
prompt = (
|
| 948 |
+
"You are an expert Indian personal finance coach. "
|
| 949 |
+
"Analyze the user's spending history and provide a smart, personalized budget recommendation.\n\n"
|
| 950 |
+
"IMPORTANT: You MUST analyze the spending pattern and provide a recommendation that is DIFFERENT from just keeping the same amount.\n\n"
|
| 951 |
+
"Analysis Guidelines:\n"
|
| 952 |
+
"1. TRENDING UPWARD: If monthly values show an increasing trend (later months > earlier months), "
|
| 953 |
+
" recommend INCREASE by 10-25% to accommodate the growth trend.\n"
|
| 954 |
+
" Example: [180000, 190000, 200000] → Recommend ~220000-250000 (increase)\n\n"
|
| 955 |
+
"2. TRENDING DOWNWARD: If monthly values show a decreasing trend (later months < earlier months), "
|
| 956 |
+
" recommend DECREASE by 5-15% to reflect the reduction.\n"
|
| 957 |
+
" Example: [220000, 210000, 200000] → Recommend ~180000-190000 (decrease)\n\n"
|
| 958 |
+
"3. HIGH VARIATION: If std_dev is high (>15% of average), recommend INCREASE by 15-25% "
|
| 959 |
+
" to create a safety buffer for unpredictable spending.\n"
|
| 960 |
+
" Example: std_dev = 30000, avg = 200000 → Recommend ~230000-250000 (increase)\n\n"
|
| 961 |
+
"4. STABLE & LOW VARIATION: Only if spending is very stable (std_dev < 5% of average) "
|
| 962 |
+
" AND no clear trend, then KEEP with a small 5% buffer.\n"
|
| 963 |
+
" Example: [200000, 200000, 200000] with std_dev < 10000 → Recommend ~210000 (keep with buffer)\n\n"
|
| 964 |
+
"5. SINGLE DATA POINT: If only one month of data, recommend INCREASE by 10-15% "
|
| 965 |
+
" to account for potential variability.\n\n"
|
| 966 |
+
"Given the user's spending history:\n"
|
| 967 |
+
f"{summary}\n\n"
|
| 968 |
+
"CRITICAL: Do NOT always recommend 'keep'. Analyze the pattern and provide increase/decrease/keep based on the actual data trends.\n"
|
| 969 |
+
"The recommended_budget MUST reflect your analysis - if there's a trend, the budget should reflect it.\n\n"
|
| 970 |
"Respond strictly as JSON with the following keys:\n"
|
| 971 |
'{ "recommended_budget": number, "action": "increase|decrease|keep", "reason": "string" }.\n'
|
| 972 |
+
"The reason must be specific, explain the trend you observed, and justify why you chose increase/decrease/keep.\n"
|
| 973 |
+
"Use rupees for all amounts. Round recommended_budget to nearest 100.\n"
|
| 974 |
)
|
| 975 |
|
| 976 |
try:
|
|
|
|
| 985 |
"messages": [
|
| 986 |
{"role": "user", "content": prompt}
|
| 987 |
],
|
| 988 |
+
"temperature": 0.7, # Increased for more varied and creative recommendations
|
| 989 |
"response_format": {"type": "json_object"},
|
| 990 |
},
|
| 991 |
timeout=30,
|