Spaces:
Sleeping
Sleeping
Shageenderan Sapai commited on
Commit ·
a7684ad
1
Parent(s): 0426bd3
Align with Staging
Browse files- app/main.py +65 -12
- app/user.py +17 -1
- app/utils.py +143 -154
app/main.py
CHANGED
|
@@ -15,7 +15,7 @@ from openai import OpenAI
|
|
| 15 |
import psycopg2
|
| 16 |
from psycopg2 import sql
|
| 17 |
import os
|
| 18 |
-
from app.utils import add_to_cache, get_api_key, get_user_info, get_growth_guide_session, pop_cache, print_log, get_user, upload_mementos_to_db, get_user_summary, get_user_life_status, get_life_score
|
| 19 |
from dotenv import load_dotenv
|
| 20 |
import logging.config
|
| 21 |
import time
|
|
@@ -40,6 +40,20 @@ else:
|
|
| 40 |
for file in os.listdir(os.path.join('users', 'data')):
|
| 41 |
os.remove(os.path.join('users', 'data', file))
|
| 42 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 43 |
if not os.path.exists(os.path.join('users', 'to_upload')):
|
| 44 |
os.makedirs(os.path.join('users', 'to_upload'))
|
| 45 |
if not os.path.exists(os.path.join('mementos', 'to_upload')):
|
|
@@ -254,6 +268,10 @@ class ErrorResponse(BaseModel):
|
|
| 254 |
message: str
|
| 255 |
timestamp: datetime = datetime.now()
|
| 256 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 257 |
@app.get("/ok")
|
| 258 |
def ok_endpoint():
|
| 259 |
print_log("INFO", "health check endpoint")
|
|
@@ -382,6 +400,7 @@ def migrate_user(request: CreateUserItem, api_key: str = Security(get_api_key)):
|
|
| 382 |
api_response['challenges'] = user.challenges
|
| 383 |
api_response['other_focusses'] = user.other_focusses
|
| 384 |
api_response['scores'] = f"Personal Growth: {user.personal_growth_score} || Career: {user.career_growth_score} || Health/Wellness: {user.health_and_wellness_score} || Relationships: {user.relationship_score} || Mental Health: {user.mental_well_being_score}"
|
|
|
|
| 385 |
|
| 386 |
add_to_cache(user)
|
| 387 |
pop_cache(user.user_id)
|
|
@@ -424,7 +443,7 @@ def get_user_by_id(user_id: str, api_key: str = Security(get_api_key)):
|
|
| 424 |
api_response['other_focusses'] = user.other_focusses
|
| 425 |
api_response['reminders'] = user.reminders
|
| 426 |
api_response['scores'] = f"Personal Growth: {user.personal_growth_score} || Career: {user.career_growth_score} || Health/Wellness: {user.health_and_wellness_score} || Relationships: {user.relationship_score} || Mental Health: {user.mental_well_being_score}"
|
| 427 |
-
|
| 428 |
|
| 429 |
return api_response
|
| 430 |
except LookupError:
|
|
@@ -664,10 +683,12 @@ def chat(request: ChatItem, api_key: str = Security(get_api_key)):
|
|
| 664 |
if recent_run:
|
| 665 |
user.cancel_run(recent_run)
|
| 666 |
response = user.send_message(user.get_recent_message())
|
| 667 |
-
|
| 668 |
-
|
| 669 |
-
|
| 670 |
-
|
|
|
|
|
|
|
| 671 |
except LookupError:
|
| 672 |
print_log("ERROR",f"User not found for chat: {request.user_id}", extra={"user_id": request.user_id, "endpoint": "/chat"})
|
| 673 |
logger.error(f"User not found for chat: {request.user_id}", extra={"user_id": request.user_id, "endpoint": "/chat"})
|
|
@@ -929,12 +950,44 @@ def get_life_status_by_id(user_id: str, api_key: str = Security(get_api_key)):
|
|
| 929 |
|
| 930 |
@app.post("/add_booking_point")
|
| 931 |
def add_booking_point_by_user(user_id: str, api_key: str = Security(get_api_key)):
|
| 932 |
-
|
| 933 |
-
|
| 934 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 935 |
|
| 936 |
@app.post("/add_session_completion_point")
|
| 937 |
def add_session_completion_point_by_user(user_id: str, api_key: str = Security(get_api_key)):
|
| 938 |
-
|
| 939 |
-
|
| 940 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 15 |
import psycopg2
|
| 16 |
from psycopg2 import sql
|
| 17 |
import os
|
| 18 |
+
from app.utils import add_to_cache, get_api_key, get_user_info, get_growth_guide_session, pop_cache, print_log, get_user, upload_mementos_to_db, get_user_summary, get_user_life_status, create_pre_gg_report, get_life_score
|
| 19 |
from dotenv import load_dotenv
|
| 20 |
import logging.config
|
| 21 |
import time
|
|
|
|
| 40 |
for file in os.listdir(os.path.join('users', 'data')):
|
| 41 |
os.remove(os.path.join('users', 'data', file))
|
| 42 |
|
| 43 |
+
if not os.path.exists(os.path.join('bookings', 'data')):
|
| 44 |
+
os.makedirs(os.path.join('bookings', 'data'))
|
| 45 |
+
else:
|
| 46 |
+
# Folder exists, we want to clear all current booking data
|
| 47 |
+
for file in os.listdir(os.path.join('bookings', 'data')):
|
| 48 |
+
os.remove(os.path.join('bookings', 'data', file))
|
| 49 |
+
|
| 50 |
+
if not os.path.exists(os.path.join('bookings', 'to_upload')):
|
| 51 |
+
os.makedirs(os.path.join('bookings', 'to_upload'))
|
| 52 |
+
else:
|
| 53 |
+
# Folder exists, we want to clear all current booking data
|
| 54 |
+
for file in os.listdir(os.path.join('bookings', 'to_upload')):
|
| 55 |
+
os.remove(os.path.join('bookings', 'to_upload', file))
|
| 56 |
+
|
| 57 |
if not os.path.exists(os.path.join('users', 'to_upload')):
|
| 58 |
os.makedirs(os.path.join('users', 'to_upload'))
|
| 59 |
if not os.path.exists(os.path.join('mementos', 'to_upload')):
|
|
|
|
| 268 |
message: str
|
| 269 |
timestamp: datetime = datetime.now()
|
| 270 |
|
| 271 |
+
class BookingItem(BaseModel):
|
| 272 |
+
booking_id: str
|
| 273 |
+
|
| 274 |
+
|
| 275 |
@app.get("/ok")
|
| 276 |
def ok_endpoint():
|
| 277 |
print_log("INFO", "health check endpoint")
|
|
|
|
| 400 |
api_response['challenges'] = user.challenges
|
| 401 |
api_response['other_focusses'] = user.other_focusses
|
| 402 |
api_response['scores'] = f"Personal Growth: {user.personal_growth_score} || Career: {user.career_growth_score} || Health/Wellness: {user.health_and_wellness_score} || Relationships: {user.relationship_score} || Mental Health: {user.mental_well_being_score}"
|
| 403 |
+
api_response['recent_wins'] = user.recent_wins
|
| 404 |
|
| 405 |
add_to_cache(user)
|
| 406 |
pop_cache(user.user_id)
|
|
|
|
| 443 |
api_response['other_focusses'] = user.other_focusses
|
| 444 |
api_response['reminders'] = user.reminders
|
| 445 |
api_response['scores'] = f"Personal Growth: {user.personal_growth_score} || Career: {user.career_growth_score} || Health/Wellness: {user.health_and_wellness_score} || Relationships: {user.relationship_score} || Mental Health: {user.mental_well_being_score}"
|
| 446 |
+
api_response['recent_wins'] = user.recent_wins
|
| 447 |
|
| 448 |
return api_response
|
| 449 |
except LookupError:
|
|
|
|
| 683 |
if recent_run:
|
| 684 |
user.cancel_run(recent_run)
|
| 685 |
response = user.send_message(user.get_recent_message())
|
| 686 |
+
|
| 687 |
+
finally:
|
| 688 |
+
print_log("INFO",f"Assistant: {response['content']}", extra={"user_id": request.user_id, "endpoint": "/chat"})
|
| 689 |
+
logger.info(f"Assistant: {response['content']}", extra={"user_id": request.user_id, "endpoint": "/chat"})
|
| 690 |
+
|
| 691 |
+
return {"response": response}
|
| 692 |
except LookupError:
|
| 693 |
print_log("ERROR",f"User not found for chat: {request.user_id}", extra={"user_id": request.user_id, "endpoint": "/chat"})
|
| 694 |
logger.error(f"User not found for chat: {request.user_id}", extra={"user_id": request.user_id, "endpoint": "/chat"})
|
|
|
|
| 950 |
|
| 951 |
@app.post("/add_booking_point")
|
| 952 |
def add_booking_point_by_user(user_id: str, api_key: str = Security(get_api_key)):
|
| 953 |
+
try:
|
| 954 |
+
user = get_user(user_id)
|
| 955 |
+
user.add_point_for_booking()
|
| 956 |
+
return {"response": "ok"}
|
| 957 |
+
except Exception as e:
|
| 958 |
+
print_log("ERROR",f"Error: {str(e)}", extra={"user_id": user_id, "endpoint": "/add_booking_point"}, exc_info=True)
|
| 959 |
+
logger.error(f"Error: {str(e)}", extra={"user_id": user_id, "endpoint": "/add_booking_point"}, exc_info=True)
|
| 960 |
+
raise HTTPException(
|
| 961 |
+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
| 962 |
+
detail=str(e)
|
| 963 |
+
)
|
| 964 |
|
| 965 |
@app.post("/add_session_completion_point")
|
| 966 |
def add_session_completion_point_by_user(user_id: str, api_key: str = Security(get_api_key)):
|
| 967 |
+
try:
|
| 968 |
+
user = get_user(user_id)
|
| 969 |
+
user.add_point_for_completing_session()
|
| 970 |
+
return {"response": "ok"}
|
| 971 |
+
|
| 972 |
+
|
| 973 |
+
|
| 974 |
+
except Exception as e:
|
| 975 |
+
print_log("ERROR",f"Error: {str(e)}", extra={"user_id": user_id, "endpoint": "/add_session_completion_point"}, exc_info=True)
|
| 976 |
+
logger.error(f"Error: {str(e)}", extra={"user_id": user_id, "endpoint": "/add_session_completion_point"}, exc_info=True)
|
| 977 |
+
raise HTTPException(
|
| 978 |
+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
| 979 |
+
detail=str(e)
|
| 980 |
+
)
|
| 981 |
+
|
| 982 |
+
@app.post("/create_pre_gg_report")
|
| 983 |
+
def create_pre_gg_by_booking(request: BookingItem, api_key: str = Security(get_api_key)):
|
| 984 |
+
try:
|
| 985 |
+
create_pre_gg_report(request.booking_id)
|
| 986 |
+
return {"response": "ok"}
|
| 987 |
+
except Exception as e:
|
| 988 |
+
print_log("ERROR",f"Error: {str(e)}", extra={"booking_id": request.booking_id, "endpoint": "/create_pre_gg_report"}, exc_info=True)
|
| 989 |
+
logger.error(f"Error: {str(e)}", extra={"booking_id": request.booking_id, "endpoint": "/create_pre_gg_report"}, exc_info=True)
|
| 990 |
+
raise HTTPException(
|
| 991 |
+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
| 992 |
+
detail=str(e)
|
| 993 |
+
)
|
app/user.py
CHANGED
|
@@ -298,6 +298,7 @@ class User:
|
|
| 298 |
self.mental_well_being_score = 0
|
| 299 |
self.health_and_wellness_score = 0
|
| 300 |
self.reminders = None
|
|
|
|
| 301 |
|
| 302 |
# Read growth_plan.json and store it
|
| 303 |
# growth_plan = {"growthPlan": [
|
|
@@ -392,6 +393,13 @@ class User:
|
|
| 392 |
self.user_interaction_guidelines = self.generate_user_interaction_guidelines(user_info, client)
|
| 393 |
self.conversations = ConversationManager(client, self, asst_id)
|
| 394 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 395 |
def add_life_score_point(self, variable, points_added, notes):
|
| 396 |
if variable == 'Personal Growth':
|
| 397 |
self.personal_growth_score += points_added
|
|
@@ -439,6 +447,7 @@ class User:
|
|
| 439 |
if completed:
|
| 440 |
self.update_goal(current_goal, "COMPLETED")
|
| 441 |
self.add_life_score_point(variable = goal_area, points_added = 30, notes = "Completing a Goal")
|
|
|
|
| 442 |
|
| 443 |
if current_goal is None:
|
| 444 |
new_goal = UserDataItem(role="assistant", content=goal, area=goal_area, user_id=self.user_id, status="ONGOING", created_at=pd.Timestamp.now().strftime("%d-%m-%Y %a %H:%M:%S"), updated_at=pd.Timestamp.now().strftime("%d-%m-%Y %a %H:%M:%S"))
|
|
@@ -451,6 +460,7 @@ class User:
|
|
| 451 |
new_goal = UserDataItem(role="assistant", content=goal, area=goal_area, user_id=self.user_id, status="ONGOING", created_at=pd.Timestamp.now().strftime("%d-%m-%Y %a %H:%M:%S"), updated_at=pd.Timestamp.now().strftime("%d-%m-%Y %a %H:%M:%S"))
|
| 452 |
self.goal.append(new_goal)
|
| 453 |
self.add_life_score_point(variable = goal_area, points_added = 10, notes = "Setting a Goal")
|
|
|
|
| 454 |
else:
|
| 455 |
self.update_goal(current_goal, "ONGOING", content=goal)
|
| 456 |
|
|
@@ -832,8 +842,10 @@ class User:
|
|
| 832 |
## ADD POINT FOR CHANGE DATE
|
| 833 |
if self.growth_plan.current()['day'] == 7:
|
| 834 |
self.add_life_score_point(variable = self.get_current_goal(full=True).area, points_added = 5, notes = "Reaching Day 7")
|
|
|
|
| 835 |
elif self.growth_plan.current()['day'] == 14:
|
| 836 |
self.add_life_score_point(variable = self.get_current_goal(full=True).area, points_added = 10, notes = "Reaching Day 14")
|
|
|
|
| 837 |
|
| 838 |
logger.info(f"Today's action is {action}", extra={"user_id": self.user_id, "endpoint": "user_change_date"})
|
| 839 |
|
|
@@ -1073,17 +1085,21 @@ class User:
|
|
| 1073 |
|
| 1074 |
if (num_of_micro_actions_completed in (1,3,5)) or (num_of_micro_actions_completed % 10 == 0 and num_of_micro_actions_completed != 0):
|
| 1075 |
self.add_life_score_point(variable = self.get_current_goal(full=True).area, points_added = 10, notes = f"Completing the {num_of_micro_actions_completed}-th micro-action")
|
| 1076 |
-
|
|
|
|
| 1077 |
def trigger_deep_reflection_point(self, area_of_deep_reflection):
|
| 1078 |
if len(area_of_deep_reflection)>0:
|
| 1079 |
for area in area_of_deep_reflection:
|
| 1080 |
self.add_life_score_point(variable = area, points_added = 5, notes = f"Doing a deep reflection about {area}")
|
|
|
|
| 1081 |
|
| 1082 |
def add_point_for_booking(self):
|
| 1083 |
self.add_life_score_point(variable = self.get_current_goal(full=True).area, points_added = 5, notes = "Booking a GG session")
|
|
|
|
| 1084 |
|
| 1085 |
def add_point_for_completing_session(self):
|
| 1086 |
self.add_life_score_point(variable = self.get_current_goal(full=True).area, points_added = 20, notes = "Completing a GG session")
|
|
|
|
| 1087 |
|
| 1088 |
def build_ourcoach_report(self, overview, action_plan, gg_session_notes):
|
| 1089 |
logger.info(f"Building ourcoach report", extra={"user_id": self.user_id, "endpoint": "build_ourcoach_report"})
|
|
|
|
| 298 |
self.mental_well_being_score = 0
|
| 299 |
self.health_and_wellness_score = 0
|
| 300 |
self.reminders = None
|
| 301 |
+
self.recent_wins = []
|
| 302 |
|
| 303 |
# Read growth_plan.json and store it
|
| 304 |
# growth_plan = {"growthPlan": [
|
|
|
|
| 393 |
self.user_interaction_guidelines = self.generate_user_interaction_guidelines(user_info, client)
|
| 394 |
self.conversations = ConversationManager(client, self, asst_id)
|
| 395 |
|
| 396 |
+
def add_recent_wins(self, wins):
|
| 397 |
+
if len(self.recent_wins)<5:
|
| 398 |
+
self.recent_wins.insert(0,wins)
|
| 399 |
+
else:
|
| 400 |
+
self.recent_wins.pop()
|
| 401 |
+
self.recent_wins.insert(0,wins)
|
| 402 |
+
|
| 403 |
def add_life_score_point(self, variable, points_added, notes):
|
| 404 |
if variable == 'Personal Growth':
|
| 405 |
self.personal_growth_score += points_added
|
|
|
|
| 447 |
if completed:
|
| 448 |
self.update_goal(current_goal, "COMPLETED")
|
| 449 |
self.add_life_score_point(variable = goal_area, points_added = 30, notes = "Completing a Goal")
|
| 450 |
+
self.add_recent_wins(wins = "You have completed your goal!")
|
| 451 |
|
| 452 |
if current_goal is None:
|
| 453 |
new_goal = UserDataItem(role="assistant", content=goal, area=goal_area, user_id=self.user_id, status="ONGOING", created_at=pd.Timestamp.now().strftime("%d-%m-%Y %a %H:%M:%S"), updated_at=pd.Timestamp.now().strftime("%d-%m-%Y %a %H:%M:%S"))
|
|
|
|
| 460 |
new_goal = UserDataItem(role="assistant", content=goal, area=goal_area, user_id=self.user_id, status="ONGOING", created_at=pd.Timestamp.now().strftime("%d-%m-%Y %a %H:%M:%S"), updated_at=pd.Timestamp.now().strftime("%d-%m-%Y %a %H:%M:%S"))
|
| 461 |
self.goal.append(new_goal)
|
| 462 |
self.add_life_score_point(variable = goal_area, points_added = 10, notes = "Setting a Goal")
|
| 463 |
+
self.add_recent_wins(wins = "You have set your first goal!")
|
| 464 |
else:
|
| 465 |
self.update_goal(current_goal, "ONGOING", content=goal)
|
| 466 |
|
|
|
|
| 842 |
## ADD POINT FOR CHANGE DATE
|
| 843 |
if self.growth_plan.current()['day'] == 7:
|
| 844 |
self.add_life_score_point(variable = self.get_current_goal(full=True).area, points_added = 5, notes = "Reaching Day 7")
|
| 845 |
+
self.add_recent_wins(wins = "You have reached Day 7 of your growth journey!")
|
| 846 |
elif self.growth_plan.current()['day'] == 14:
|
| 847 |
self.add_life_score_point(variable = self.get_current_goal(full=True).area, points_added = 10, notes = "Reaching Day 14")
|
| 848 |
+
self.add_recent_wins(wins = "You have finished your growth journey!")
|
| 849 |
|
| 850 |
logger.info(f"Today's action is {action}", extra={"user_id": self.user_id, "endpoint": "user_change_date"})
|
| 851 |
|
|
|
|
| 1085 |
|
| 1086 |
if (num_of_micro_actions_completed in (1,3,5)) or (num_of_micro_actions_completed % 10 == 0 and num_of_micro_actions_completed != 0):
|
| 1087 |
self.add_life_score_point(variable = self.get_current_goal(full=True).area, points_added = 10, notes = f"Completing the {num_of_micro_actions_completed}-th micro-action")
|
| 1088 |
+
self.add_recent_wins(wins = "You have completed a micro action!")
|
| 1089 |
+
|
| 1090 |
def trigger_deep_reflection_point(self, area_of_deep_reflection):
|
| 1091 |
if len(area_of_deep_reflection)>0:
|
| 1092 |
for area in area_of_deep_reflection:
|
| 1093 |
self.add_life_score_point(variable = area, points_added = 5, notes = f"Doing a deep reflection about {area}")
|
| 1094 |
+
self.add_recent_wins(wins = f"You have done a deep reflection about your {area}!")
|
| 1095 |
|
| 1096 |
def add_point_for_booking(self):
|
| 1097 |
self.add_life_score_point(variable = self.get_current_goal(full=True).area, points_added = 5, notes = "Booking a GG session")
|
| 1098 |
+
self.add_recent_wins(wins = "You have booked a Growth Guide session!")
|
| 1099 |
|
| 1100 |
def add_point_for_completing_session(self):
|
| 1101 |
self.add_life_score_point(variable = self.get_current_goal(full=True).area, points_added = 20, notes = "Completing a GG session")
|
| 1102 |
+
self.add_recent_wins(wins = "You have completed a Growth Guide session!")
|
| 1103 |
|
| 1104 |
def build_ourcoach_report(self, overview, action_plan, gg_session_notes):
|
| 1105 |
logger.info(f"Building ourcoach report", extra={"user_id": self.user_id, "endpoint": "build_ourcoach_report"})
|
app/utils.py
CHANGED
|
@@ -22,8 +22,11 @@ from cachetools import TTLCache
|
|
| 22 |
import threading
|
| 23 |
import time
|
| 24 |
import uuid
|
| 25 |
-
|
| 26 |
from app.cache import CustomTTLCache, upload_file_to_s3
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
|
| 28 |
load_dotenv()
|
| 29 |
|
|
@@ -96,31 +99,8 @@ def get_user(user_id):
|
|
| 96 |
raise ReferenceError(f"User {user_id} pickle still being created")
|
| 97 |
raise LookupError(f"User [{user_id}] has not onboarded yet")
|
| 98 |
|
| 99 |
-
def
|
| 100 |
-
function_name =
|
| 101 |
-
logger.info(f"Generating user life score for user {user_id}", extra={'user_id': user_id, 'endpoint': function_name})
|
| 102 |
-
|
| 103 |
-
# Step 1: Call get_user to get user's info
|
| 104 |
-
try:
|
| 105 |
-
user = get_user(user_id)
|
| 106 |
-
# user_info = user.user_info
|
| 107 |
-
# user_messages = user.get_messages()
|
| 108 |
-
## all the life scores here
|
| 109 |
-
|
| 110 |
-
life_score = {
|
| 111 |
-
"personal_growth_score": user.personal_growth_score,
|
| 112 |
-
"career_growth_score": user.career_growth_score,
|
| 113 |
-
"relationship_score": user.relationship_score,
|
| 114 |
-
"mental_well_being_score": user.mental_well_being_score,
|
| 115 |
-
"health_and_wellness_score": user.health_and_wellness_score
|
| 116 |
-
}
|
| 117 |
-
except LookupError as e:
|
| 118 |
-
logger.error(f"Error fetching user data: {e}", extra={'user_id': user_id, 'endpoint': function_name})
|
| 119 |
-
raise e
|
| 120 |
-
|
| 121 |
-
return life_score
|
| 122 |
-
|
| 123 |
-
def generate_html(json_data, coach_name='Growth Guide'):
|
| 124 |
data = json_data["pre_growth_guide_session_report"]
|
| 125 |
user_overview = data["user_overview"]
|
| 126 |
personality_insights = data["personality_insights"]
|
|
@@ -290,7 +270,69 @@ def generate_html(json_data, coach_name='Growth Guide'):
|
|
| 290 |
</body>
|
| 291 |
</html>
|
| 292 |
'''
|
| 293 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 294 |
|
| 295 |
def get_user_summary(user_id):
|
| 296 |
function_name = get_user_summary.__name__
|
|
@@ -769,6 +811,53 @@ def get_user_summary(user_id):
|
|
| 769 |
logger.info(f"User summary generated successfully for user {user_id}", extra={'user_id': user_id, 'endpoint': function_name})
|
| 770 |
return reports
|
| 771 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 772 |
def get_user_life_status(user_id):
|
| 773 |
function_name = get_user_life_status.__name__
|
| 774 |
logger.info(f"Generating user life status for user {user_id}", extra={'user_id': user_id, 'endpoint': function_name})
|
|
@@ -787,72 +876,30 @@ def get_user_life_status(user_id):
|
|
| 787 |
[f"{message['role'].capitalize()}: {message['content']}" for message in user_messages]
|
| 788 |
)
|
| 789 |
|
|
|
|
| 790 |
# Build the system prompt according to the provided instructions
|
| 791 |
system_prompt = """
|
| 792 |
You are an AI assistant that generates a personalized life status report for users based on their profile and chat history. Your task is to analyze the provided user data and produce a JSON output following the specified schema.
|
| 793 |
|
| 794 |
**Instructions:**
|
| 795 |
|
| 796 |
-
1. **
|
| 797 |
-
- Calculate numerical scores for each of the following areas based on the user's profile and chat history, especially their responses to quantitative questions (e.g., "on a scale of 1 to 5, how do you feel about ..."):
|
| 798 |
-
- `personal_growth`
|
| 799 |
-
- `career_growth`
|
| 800 |
-
- `mental_well_being`
|
| 801 |
-
- `health_and_wellness`
|
| 802 |
-
- `relationship`
|
| 803 |
-
- Each score should be a float between 0 and 1. If an area hasn't been covered in the chat history, assign it a score of 0.
|
| 804 |
-
- Compute the `overall` score as the average of the non-zero area scores.
|
| 805 |
-
|
| 806 |
-
2. **Mantra of the Week:**
|
| 807 |
- Create a very short encouragement quote that encapsulates the user's journey toward achieving their goals.
|
| 808 |
- The mantra **MUST** be a single sentence with fewer than 5 words.
|
| 809 |
|
| 810 |
-
3. **This Week's Focus:**
|
| 811 |
-
- Identify the top three most important areas for the user from the five key areas:
|
| 812 |
-
- `personal_growth`
|
| 813 |
-
- `career_growth`
|
| 814 |
-
- `mental_well_being`
|
| 815 |
-
- `health_and_wellness`
|
| 816 |
-
- `relationship`
|
| 817 |
-
- For each selected area, provide a concise statement outlining the user's focus in that area.
|
| 818 |
-
|
| 819 |
-
4. **Suggested Action Items:**
|
| 820 |
-
- For the same three areas identified above, suggest concrete and actionable items that the user can undertake to make progress.
|
| 821 |
-
|
| 822 |
**Output Format:**
|
| 823 |
|
| 824 |
Produce your response in JSON format adhering to the following schema:
|
| 825 |
|
| 826 |
```json
|
| 827 |
{
|
| 828 |
-
"
|
| 829 |
-
"overall": float,
|
| 830 |
-
"personal_growth": float,
|
| 831 |
-
"health_and_wellness": float,
|
| 832 |
-
"mental_well_being": float,
|
| 833 |
-
"career_growth": float,
|
| 834 |
-
"relationship": float
|
| 835 |
-
},
|
| 836 |
-
"mantra_of_the_week": str,
|
| 837 |
-
"this_week_focus": [
|
| 838 |
-
{"area": str, "focus": str},
|
| 839 |
-
{"area": str, "focus": str},
|
| 840 |
-
{"area": str, "focus": str}
|
| 841 |
-
],
|
| 842 |
-
"action_items": [
|
| 843 |
-
{"area": str, "focus": str},
|
| 844 |
-
{"area": str, "focus": str},
|
| 845 |
-
{"area": str, "focus": str}
|
| 846 |
-
]
|
| 847 |
}
|
| 848 |
```
|
| 849 |
|
| 850 |
**Guidelines:**
|
| 851 |
|
| 852 |
-
- Ensure all numerical values are floats (e.g., 3.0 instead of 3).
|
| 853 |
- The `mantra_of_the_week` should be personalized, positive, and encouraging. It **MUST** be a single sentence with fewer than 5 words.
|
| 854 |
-
- Focus statements and action items should be clear, specific, and tailored to the user's context.
|
| 855 |
-
- Do not include any additional text or commentary outside of the JSON structure.
|
| 856 |
"""
|
| 857 |
|
| 858 |
# Combine user information and chat history for context
|
|
@@ -899,93 +946,13 @@ def get_user_life_status(user_id):
|
|
| 899 |
"schema": {
|
| 900 |
"type": "object",
|
| 901 |
"properties": {
|
| 902 |
-
"life_score": {
|
| 903 |
-
"type": "object",
|
| 904 |
-
"description": "Numerical life scores across different areas.",
|
| 905 |
-
"properties": {
|
| 906 |
-
"overall": {
|
| 907 |
-
"type": "number",
|
| 908 |
-
"description": "Overall life score, average of all area scores."
|
| 909 |
-
},
|
| 910 |
-
"personal_growth": {
|
| 911 |
-
"type": "number",
|
| 912 |
-
"description": "Life score for personal growth."
|
| 913 |
-
},
|
| 914 |
-
"health_and_wellness": {
|
| 915 |
-
"type": "number",
|
| 916 |
-
"description": "Life score for health and wellness."
|
| 917 |
-
},
|
| 918 |
-
"mental_well_being": {
|
| 919 |
-
"type": "number",
|
| 920 |
-
"description": "Life score for mental well-being."
|
| 921 |
-
},
|
| 922 |
-
"career_growth": {
|
| 923 |
-
"type": "number",
|
| 924 |
-
"description": "Life score for career growth."
|
| 925 |
-
},
|
| 926 |
-
"relationship": {
|
| 927 |
-
"type": "number",
|
| 928 |
-
"description": "Life score for relationships."
|
| 929 |
-
}
|
| 930 |
-
},
|
| 931 |
-
"required": [
|
| 932 |
-
"overall",
|
| 933 |
-
"personal_growth",
|
| 934 |
-
"health_and_wellness",
|
| 935 |
-
"mental_well_being",
|
| 936 |
-
"career_growth",
|
| 937 |
-
"relationship"
|
| 938 |
-
],
|
| 939 |
-
"additionalProperties": False
|
| 940 |
-
},
|
| 941 |
"mantra_of_the_week": {
|
| 942 |
"type": "string",
|
| 943 |
"description": "A very short encouragement quote that encapsulates the user's journey to achieve their goals."
|
| 944 |
-
},
|
| 945 |
-
"this_week_focus": {
|
| 946 |
-
"type": "array",
|
| 947 |
-
"description": "List of the user's top 3 most important areas with focus.",
|
| 948 |
-
"items": {
|
| 949 |
-
"type": "object",
|
| 950 |
-
"properties": {
|
| 951 |
-
"area": {
|
| 952 |
-
"type": "string",
|
| 953 |
-
"description": "The area of focus (e.g., 'personal_growth')."
|
| 954 |
-
},
|
| 955 |
-
"focus": {
|
| 956 |
-
"type": "string",
|
| 957 |
-
"description": "The focus within that area."
|
| 958 |
-
}
|
| 959 |
-
},
|
| 960 |
-
"required": ["area", "focus"],
|
| 961 |
-
"additionalProperties": False
|
| 962 |
-
}
|
| 963 |
-
},
|
| 964 |
-
"action_items": {
|
| 965 |
-
"type": "array",
|
| 966 |
-
"description": "List of suggested concrete action items for the user.",
|
| 967 |
-
"items": {
|
| 968 |
-
"type": "object",
|
| 969 |
-
"properties": {
|
| 970 |
-
"area": {
|
| 971 |
-
"type": "string",
|
| 972 |
-
"description": "The area of action (e.g., 'personal_growth')."
|
| 973 |
-
},
|
| 974 |
-
"focus": {
|
| 975 |
-
"type": "string",
|
| 976 |
-
"description": "Concrete action items in that area."
|
| 977 |
-
}
|
| 978 |
-
},
|
| 979 |
-
"required": ["area", "focus"],
|
| 980 |
-
"additionalProperties": False
|
| 981 |
-
}
|
| 982 |
}
|
| 983 |
},
|
| 984 |
"required": [
|
| 985 |
-
"
|
| 986 |
-
"mantra_of_the_week",
|
| 987 |
-
"this_week_focus",
|
| 988 |
-
"action_items"
|
| 989 |
],
|
| 990 |
"additionalProperties": False
|
| 991 |
}
|
|
@@ -1000,12 +967,34 @@ def get_user_life_status(user_id):
|
|
| 1000 |
)
|
| 1001 |
|
| 1002 |
# Get response and convert into dictionary
|
| 1003 |
-
|
| 1004 |
|
| 1005 |
except Exception as e:
|
| 1006 |
logger.error(f"OpenAI API call failed: {e}", extra={'user_id': user_id, 'endpoint': function_name})
|
| 1007 |
raise e
|
| 1008 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1009 |
# Step 4: Return the JSON reports
|
| 1010 |
logger.info(f"User life status generated successfully for user {user_id}", extra={'user_id': user_id, 'endpoint': function_name})
|
| 1011 |
return reports
|
|
|
|
| 22 |
import threading
|
| 23 |
import time
|
| 24 |
import uuid
|
|
|
|
| 25 |
from app.cache import CustomTTLCache, upload_file_to_s3
|
| 26 |
+
import pdfkit
|
| 27 |
+
import PyPDF2
|
| 28 |
+
import secrets
|
| 29 |
+
import string
|
| 30 |
|
| 31 |
load_dotenv()
|
| 32 |
|
|
|
|
| 99 |
raise ReferenceError(f"User {user_id} pickle still being created")
|
| 100 |
raise LookupError(f"User [{user_id}] has not onboarded yet")
|
| 101 |
|
| 102 |
+
def generate_html(json_data, coach_name='Growth Guide', booking_id = None):
|
| 103 |
+
function_name = generate_html.__name__
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 104 |
data = json_data["pre_growth_guide_session_report"]
|
| 105 |
user_overview = data["user_overview"]
|
| 106 |
personality_insights = data["personality_insights"]
|
|
|
|
| 270 |
</body>
|
| 271 |
</html>
|
| 272 |
'''
|
| 273 |
+
|
| 274 |
+
file_path = os.path.join("bookings", "data",f"{booking_id}.html")
|
| 275 |
+
path_to_upload = os.path.join("bookings", "to_upload",f"{booking_id}.pdf")
|
| 276 |
+
password = "Ourcoach2024!"
|
| 277 |
+
|
| 278 |
+
## SAVING HTML FILE
|
| 279 |
+
try:
|
| 280 |
+
# Open the file in write mode
|
| 281 |
+
with open(file_path, 'w', encoding='utf-8') as html_file:
|
| 282 |
+
html_file.write(html_content)
|
| 283 |
+
logger.info(f"File '{booking_id}.html' has been created successfully.", extra={'booking_id': booking_id, 'endpoint': function_name})
|
| 284 |
+
|
| 285 |
+
# Saving as PDF File
|
| 286 |
+
pdfkit.from_file(file_path, path_to_upload, options={'encoding': 'UTF-8'})
|
| 287 |
+
logger.info(f"File '{booking_id}.pdf' has been created successfully.", extra={'booking_id': booking_id, 'endpoint': function_name})
|
| 288 |
+
|
| 289 |
+
## ENCRYPTING PDF
|
| 290 |
+
logger.info(f"Encrypting '{booking_id}.pdf'...", extra={'booking_id': booking_id, 'endpoint': function_name})
|
| 291 |
+
with open(path_to_upload, 'rb') as file:
|
| 292 |
+
pdf_reader = PyPDF2.PdfReader(file)
|
| 293 |
+
pdf_writer = PyPDF2.PdfWriter()
|
| 294 |
+
|
| 295 |
+
# Add all pages to the writer
|
| 296 |
+
for page_num in range(len(pdf_reader.pages)):
|
| 297 |
+
pdf_writer.add_page(pdf_reader.pages[page_num])
|
| 298 |
+
|
| 299 |
+
# Encrypt the PDF with the given password
|
| 300 |
+
pdf_writer.encrypt(password)
|
| 301 |
+
|
| 302 |
+
with open(path_to_upload, 'wb') as encrypted_file:
|
| 303 |
+
pdf_writer.write(encrypted_file)
|
| 304 |
+
|
| 305 |
+
logger.info(f"Succesfully encrypted '{booking_id}.pdf'", extra={'booking_id': booking_id, 'endpoint': function_name})
|
| 306 |
+
|
| 307 |
+
except Exception as e:
|
| 308 |
+
logger.error(f"An error occurred: {e}", extra={'booking_id': booking_id, 'endpoint': function_name})
|
| 309 |
+
raise
|
| 310 |
+
|
| 311 |
+
filename = booking_id
|
| 312 |
+
|
| 313 |
+
logger.info(f"Uploading file {filename} to S3", extra={'booking_id': booking_id, 'endpoint': function_name})
|
| 314 |
+
bucket = 'core-ai-assets'
|
| 315 |
+
try:
|
| 316 |
+
if (AWS_ACCESS_KEY and AWS_SECRET_KEY):
|
| 317 |
+
session = boto3.session.Session(aws_access_key_id=AWS_ACCESS_KEY, aws_secret_access_key=AWS_SECRET_KEY, region_name=REGION)
|
| 318 |
+
else:
|
| 319 |
+
session = boto3.session.Session()
|
| 320 |
+
s3_client = session.client('s3')
|
| 321 |
+
with open(path_to_upload, "rb") as f:
|
| 322 |
+
## Upload to Production Folder
|
| 323 |
+
s3_client.upload_fileobj(f, bucket, f'staging/pre_gg_reports/{filename}.pdf')
|
| 324 |
+
logger.info(f"File {filename} uploaded successfully to S3", extra={'booking_id': booking_id, 'endpoint': function_name})
|
| 325 |
+
|
| 326 |
+
# Removing files
|
| 327 |
+
for file in os.listdir(os.path.join('bookings', 'data')):
|
| 328 |
+
os.remove(os.path.join('bookings', 'data', file))
|
| 329 |
+
for file in os.listdir(os.path.join('bookings', 'to_upload')):
|
| 330 |
+
os.remove(os.path.join('bookings', 'to_upload', file))
|
| 331 |
+
|
| 332 |
+
# force_file_move(os.path.join('users', 'to_upload', filename), os.path.join('users', 'data', filename))
|
| 333 |
+
except (FileNotFoundError, NoCredentialsError, PartialCredentialsError) as e:
|
| 334 |
+
logger.error(f"S3 upload failed for {filename}: {e}", extra={'booking_id': booking_id, 'endpoint': function_name})
|
| 335 |
+
raise
|
| 336 |
|
| 337 |
def get_user_summary(user_id):
|
| 338 |
function_name = get_user_summary.__name__
|
|
|
|
| 811 |
logger.info(f"User summary generated successfully for user {user_id}", extra={'user_id': user_id, 'endpoint': function_name})
|
| 812 |
return reports
|
| 813 |
|
| 814 |
+
def create_pre_gg_report(booking_id):
|
| 815 |
+
function_name = create_pre_gg_report.__name__
|
| 816 |
+
|
| 817 |
+
# Get user_id from booking_id
|
| 818 |
+
try:
|
| 819 |
+
logger.info(f"Retrieving booking details for {booking_id}", extra={'booking_id': booking_id, 'endpoint': function_name})
|
| 820 |
+
db_params = {
|
| 821 |
+
'dbname': 'ourcoach',
|
| 822 |
+
'user': 'ourcoach',
|
| 823 |
+
'password': 'hvcTL3kN3pOG5KteT17T',
|
| 824 |
+
'host': 'staging-ourcoach.cx8se8o0iaiy.ap-southeast-1.rds.amazonaws.com',
|
| 825 |
+
'port': '5432'
|
| 826 |
+
}
|
| 827 |
+
try:
|
| 828 |
+
with psycopg2.connect(**db_params) as conn:
|
| 829 |
+
with conn.cursor() as cursor:
|
| 830 |
+
query = sql.SQL("""
|
| 831 |
+
select user_id
|
| 832 |
+
from {table}
|
| 833 |
+
where id = %s
|
| 834 |
+
"""
|
| 835 |
+
).format(table=sql.Identifier('public', 'booking'))
|
| 836 |
+
cursor.execute(query, (booking_id,))
|
| 837 |
+
row = cursor.fetchone()
|
| 838 |
+
if (row):
|
| 839 |
+
colnames = [desc[0] for desc in cursor.description]
|
| 840 |
+
booking_data = dict(zip(colnames, row))
|
| 841 |
+
### MODIFY THE FORMAT OF USER DATA
|
| 842 |
+
user_id = booking_data['user_id']
|
| 843 |
+
logger.info(f"User info retrieved successfully for {user_id}", extra={'user_id': user_id, 'endpoint': function_name})
|
| 844 |
+
else:
|
| 845 |
+
logger.warning(f"No user info found for {user_id}", extra={'user_id': user_id, 'endpoint': function_name})
|
| 846 |
+
except psycopg2.Error as e:
|
| 847 |
+
logger.error(f"Database error while retrieving user info for {user_id}: {e}", extra={'user_id': user_id, 'endpoint': function_name})
|
| 848 |
+
raise
|
| 849 |
+
|
| 850 |
+
# Run get_user_summary
|
| 851 |
+
user_report = get_user_summary(user_id)
|
| 852 |
+
|
| 853 |
+
# Run generate_html
|
| 854 |
+
generate_html(user_report, booking_id=booking_id)
|
| 855 |
+
|
| 856 |
+
return True
|
| 857 |
+
except Exception as e:
|
| 858 |
+
logger.error(f"An error occured: {e}", extra={'booking_id': booking_id, 'endpoint': function_name})
|
| 859 |
+
raise
|
| 860 |
+
|
| 861 |
def get_user_life_status(user_id):
|
| 862 |
function_name = get_user_life_status.__name__
|
| 863 |
logger.info(f"Generating user life status for user {user_id}", extra={'user_id': user_id, 'endpoint': function_name})
|
|
|
|
| 876 |
[f"{message['role'].capitalize()}: {message['content']}" for message in user_messages]
|
| 877 |
)
|
| 878 |
|
| 879 |
+
logger.info(f"Fetched user data for: {user_id}", extra={'user_id': user_id, 'endpoint': function_name})
|
| 880 |
# Build the system prompt according to the provided instructions
|
| 881 |
system_prompt = """
|
| 882 |
You are an AI assistant that generates a personalized life status report for users based on their profile and chat history. Your task is to analyze the provided user data and produce a JSON output following the specified schema.
|
| 883 |
|
| 884 |
**Instructions:**
|
| 885 |
|
| 886 |
+
1. **Mantra of the Week:**
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 887 |
- Create a very short encouragement quote that encapsulates the user's journey toward achieving their goals.
|
| 888 |
- The mantra **MUST** be a single sentence with fewer than 5 words.
|
| 889 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 890 |
**Output Format:**
|
| 891 |
|
| 892 |
Produce your response in JSON format adhering to the following schema:
|
| 893 |
|
| 894 |
```json
|
| 895 |
{
|
| 896 |
+
"mantra_of_the_week": str
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 897 |
}
|
| 898 |
```
|
| 899 |
|
| 900 |
**Guidelines:**
|
| 901 |
|
|
|
|
| 902 |
- The `mantra_of_the_week` should be personalized, positive, and encouraging. It **MUST** be a single sentence with fewer than 5 words.
|
|
|
|
|
|
|
| 903 |
"""
|
| 904 |
|
| 905 |
# Combine user information and chat history for context
|
|
|
|
| 946 |
"schema": {
|
| 947 |
"type": "object",
|
| 948 |
"properties": {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 949 |
"mantra_of_the_week": {
|
| 950 |
"type": "string",
|
| 951 |
"description": "A very short encouragement quote that encapsulates the user's journey to achieve their goals."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 952 |
}
|
| 953 |
},
|
| 954 |
"required": [
|
| 955 |
+
"mantra_of_the_week"
|
|
|
|
|
|
|
|
|
|
| 956 |
],
|
| 957 |
"additionalProperties": False
|
| 958 |
}
|
|
|
|
| 967 |
)
|
| 968 |
|
| 969 |
# Get response and convert into dictionary
|
| 970 |
+
mantra = json.loads(response.choices[0].message.content)["mantra_of_the_week"]
|
| 971 |
|
| 972 |
except Exception as e:
|
| 973 |
logger.error(f"OpenAI API call failed: {e}", extra={'user_id': user_id, 'endpoint': function_name})
|
| 974 |
raise e
|
| 975 |
|
| 976 |
+
# Get current life score
|
| 977 |
+
life_score = {
|
| 978 |
+
"overall": user.personal_growth_score + user.career_growth_score + user.relationship_score + user.mental_well_being_score + user.health_and_wellness_score,
|
| 979 |
+
"personal_growth": user.personal_growth_score,
|
| 980 |
+
"health_and_wellness": user.health_and_wellness_score,
|
| 981 |
+
"mental_well_being": user.mental_well_being_score,
|
| 982 |
+
"career_growth": user.career_growth_score,
|
| 983 |
+
"relationship": user.relationship_score
|
| 984 |
+
}
|
| 985 |
+
# Get current goal
|
| 986 |
+
current_goal = user.goal if not user.goal else user.goal[-1].content
|
| 987 |
+
# Get life score achievements in list
|
| 988 |
+
recent_wins = user.recent_wins
|
| 989 |
+
# Combine everything
|
| 990 |
+
|
| 991 |
+
reports = {
|
| 992 |
+
"life_score": life_score,
|
| 993 |
+
"mantra_of_the_week": mantra,
|
| 994 |
+
"goal": current_goal,
|
| 995 |
+
"recent_wins": recent_wins
|
| 996 |
+
}
|
| 997 |
+
|
| 998 |
# Step 4: Return the JSON reports
|
| 999 |
logger.info(f"User life status generated successfully for user {user_id}", extra={'user_id': user_id, 'endpoint': function_name})
|
| 1000 |
return reports
|