Persona Integration & Modified User Context

#12
by BMCVRN - opened
app/__pycache__/assistants.cpython-312.pyc CHANGED
Binary files a/app/__pycache__/assistants.cpython-312.pyc and b/app/__pycache__/assistants.cpython-312.pyc differ
 
app/__pycache__/flows.cpython-312.pyc CHANGED
Binary files a/app/__pycache__/flows.cpython-312.pyc and b/app/__pycache__/flows.cpython-312.pyc differ
 
app/__pycache__/main.cpython-312.pyc CHANGED
Binary files a/app/__pycache__/main.cpython-312.pyc and b/app/__pycache__/main.cpython-312.pyc differ
 
app/__pycache__/user.cpython-312.pyc CHANGED
Binary files a/app/__pycache__/user.cpython-312.pyc and b/app/__pycache__/user.cpython-312.pyc differ
 
app/__pycache__/utils.cpython-312.pyc CHANGED
Binary files a/app/__pycache__/utils.cpython-312.pyc and b/app/__pycache__/utils.cpython-312.pyc differ
 
app/assistants.py CHANGED
@@ -382,7 +382,7 @@ class Assistant:
382
  return run, just_finished_intro, message
383
 
384
  elif run.status == 'failed':
385
- raise OpenAIRequestError(user_id=self.cm.user.id, message="Run failed", run_id=run.id)
386
 
387
  elif run.status == 'requires_action':
388
  reccursion = 0
 
382
  return run, just_finished_intro, message
383
 
384
  elif run.status == 'failed':
385
+ raise OpenAIRequestError(user_id=self.cm.user.user_id, message="Run failed", run_id=run.id)
386
 
387
  elif run.status == 'requires_action':
388
  reccursion = 0
app/conversation_manager.py CHANGED
@@ -9,8 +9,12 @@ from app.exceptions import BaseOurcoachException, ConversationManagerError, Open
9
  from datetime import datetime
10
 
11
  import dotenv
 
 
12
  dotenv.load_dotenv()
13
 
 
 
14
  logger = logging.getLogger(__name__)
15
 
16
  def get_current_datetime():
@@ -62,12 +66,17 @@ class ConversationManager:
62
  thread = self.client.beta.threads.create()
63
  self.system_message = self.add_message_to_thread(thread.id, "assistant",
64
  f"""
 
 
 
 
65
  You are coaching:
66
  \n\n{user_interaction_guidelines}\n\n\
67
  Be mindful of this information at all times in order to
68
  be as personalised as possible when conversing. Ensure to
69
  follow the conversation guidelines and flow templates. Use the
70
  current state of the conversation to adhere to the flow. Do not let the user know about any transitions.\n\n
 
71
  ** Today is {self.state['date']}.\n\n **
72
  ** You are now in the INTRODUCTION STATE. **
73
  """)
@@ -185,7 +194,7 @@ class ConversationManager:
185
  # OPENAI LIMITATION: Can only attach a maximum of 32 messages when creating a new thread
186
  messages = self._get_current_thread_history(remove_system_message=False)
187
  if len(messages) >= 29:
188
- messages = [{"content": """ Remember who you are coaching.
189
  Be mindful of this information at all times in order to
190
  be as personalised as possible when conversing. Ensure to
191
  follow the conversation guidelines and flow provided.""", "role":"assistant"}] + messages[-29:]
 
9
  from datetime import datetime
10
 
11
  import dotenv
12
+
13
+ from app.utils import id_to_persona
14
  dotenv.load_dotenv()
15
 
16
+ OURCOACH_DASHBOARD_URL = os.getenv("OURCOACH_DASHBOARD_URL")
17
+
18
  logger = logging.getLogger(__name__)
19
 
20
  def get_current_datetime():
 
66
  thread = self.client.beta.threads.create()
67
  self.system_message = self.add_message_to_thread(thread.id, "assistant",
68
  f"""
69
+ You are:
70
+ {id_to_persona(self.user.asst_id)}, always adhere to your choosen persona by incorporating it conversationally.
71
+ You represent a coach at ourcoach. You may refer to you knowledgebase for all information related to ourcoach.
72
+ -------------------------------------------
73
  You are coaching:
74
  \n\n{user_interaction_guidelines}\n\n\
75
  Be mindful of this information at all times in order to
76
  be as personalised as possible when conversing. Ensure to
77
  follow the conversation guidelines and flow templates. Use the
78
  current state of the conversation to adhere to the flow. Do not let the user know about any transitions.\n\n
79
+ Whenever you reference the dashboard or Revelation Dashboard, inlcue the link: {OURCOACH_DASHBOARD_URL} .
80
  ** Today is {self.state['date']}.\n\n **
81
  ** You are now in the INTRODUCTION STATE. **
82
  """)
 
194
  # OPENAI LIMITATION: Can only attach a maximum of 32 messages when creating a new thread
195
  messages = self._get_current_thread_history(remove_system_message=False)
196
  if len(messages) >= 29:
197
+ messages = [{"content": """ Remember who you are and who you are coaching.
198
  Be mindful of this information at all times in order to
199
  be as personalised as possible when conversing. Ensure to
200
  follow the conversation guidelines and flow provided.""", "role":"assistant"}] + messages[-29:]
app/flows.py CHANGED
@@ -483,11 +483,14 @@ Objective: To summarize the user's progress and achievements during the coaching
483
  Users Goal: {{}}
484
  The user is currently on day {{}}/{{}} of their journey.
485
 
 
 
 
486
  ## ** GUIDELINE ** :
487
 
488
  ## What Makes a Good Interaction:
489
 
490
- - Highlight the user's progress and achievements precisely and concisely. Use bullet points to list down your items.
491
 
492
  - Explain to the user that coaching is a continuous journey, so the user has the option to either continue with the same goal or create a new plan.
493
 
@@ -505,13 +508,14 @@ The user is currently on day {{}}/{{}} of their journey.
505
 
506
  - Congratulate the user for completing the growth plan until the last day (mention the current day, e.g. day 4)
507
 
508
- - Highlight the user's progress and achievements in bullet points. And tell them to check out their progress in the Revelation Dashboard here: https://app.staging.ourcoach.ai/
509
-
510
- - Ask the user whether they want to meet their Growth Guide to plan what's next! (Only ask this question first)
511
 
 
 
 
512
  - Wait for the user's response.
513
 
514
- - **IF** the user answer with a Yes, you reply with this message:
515
 
516
  Amazing! 🎉
517
 
 
483
  Users Goal: {{}}
484
  The user is currently on day {{}}/{{}} of their journey.
485
 
486
+ User's Last Growth Guide Session:
487
+ {{}}
488
+
489
  ## ** GUIDELINE ** :
490
 
491
  ## What Makes a Good Interaction:
492
 
493
+ - Highlight the user's progress and achievements precisely and concisely. IF the user has completed a growth guide session (see above), incorporate it into your response and reference that it was acheived during their growth guide session. Use bullet points to list down your items.
494
 
495
  - Explain to the user that coaching is a continuous journey, so the user has the option to either continue with the same goal or create a new plan.
496
 
 
508
 
509
  - Congratulate the user for completing the growth plan until the last day (mention the current day, e.g. day 4)
510
 
511
+ - Highlight the user's progress and achievements in bullet points. IF the user has completed a growth guide session (see above), incorporate it into your response and reference that it was acheived during their growth guide session. And tell them to check out their progress in the Revelation Dashboard here: https://app.staging.ourcoach.ai/
 
 
512
 
513
+ - IF the user has not completed a growth guide session yet (see above), encourage the user to book a Growth Guide session and explain its benefits. Really upsell this by being like a Growth Guide salesman!
514
+ - ELSE IF the user has booked a growth guide session (see above), tell them you hope it went well and they found it beneficial and let the use know that they could also book another via their Revelation Dashboard: https://app.staging.ourcoach.ai/
515
+
516
  - Wait for the user's response.
517
 
518
+ - **IF** the user says they want to book a growth guide session, you reply with this message:
519
 
520
  Amazing! 🎉
521
 
app/main.py CHANGED
@@ -257,8 +257,6 @@ class LoggingMiddleware(BaseHTTPMiddleware):
257
  raise
258
 
259
  # OpenAI Client
260
- # GENERAL_ASSISTANT = os.getenv('OPENAI_GENERAL_ASSISTANT')
261
- GENERAL_ASSISTANT = "asst_vnucWWELJlCWadfAARwyKkCW"
262
 
263
  # Initialize Logging (optional)
264
  # logging.basicConfig(filename='app.log', level=logging.INFO)
@@ -485,7 +483,7 @@ async def migrate_user(
485
 
486
  with open(user_file, 'rb') as f:
487
  old_user_object = pickle.load(f)
488
- user = User(request.user_id, old_user_object.user_info, client, GENERAL_ASSISTANT)
489
  user.conversations.current_thread = old_user_object.conversations.current_thread
490
  user.conversations.intro_done = True
491
  user.done_first_reflection = old_user_object.done_first_reflection
@@ -718,8 +716,29 @@ async def create_user(
718
  if os.path.exists(f'users/data/{request.user_id}.pkl'):
719
  return {"message": f"[OK] User already exists: {request.user_id}"}
720
 
721
- user_info, _ = get_user_info(request.user_id)
722
- user = User(request.user_id, user_info, client, GENERAL_ASSISTANT)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
723
  folder_path = os.path.join("mementos", "to_upload", request.user_id)
724
  os.makedirs(folder_path, exist_ok=True)
725
 
@@ -876,7 +895,10 @@ async def get_summary_by_id(
876
  ):
877
  print_log("INFO", "Getting user's summary", extra={"user_id": user_id, "endpoint": "/get_user_summary"})
878
  logger.info("Getting user's summary", extra={"user_id": user_id, "endpoint": "/get_user_summary"})
879
- user_summary = get_user_summary(user_id)
 
 
 
880
  print_log("INFO", "Successfully generated summary", extra={"user_id": user_id, "endpoint": "/get_user_summary"})
881
  logger.info("Successfully generated summary", extra={"user_id": user_id, "endpoint": "/get_user_summary"})
882
  return user_summary
 
257
  raise
258
 
259
  # OpenAI Client
 
 
260
 
261
  # Initialize Logging (optional)
262
  # logging.basicConfig(filename='app.log', level=logging.INFO)
 
483
 
484
  with open(user_file, 'rb') as f:
485
  old_user_object = pickle.load(f)
486
+ user = User(request.user_id, old_user_object.user_info, client, old_user_object.asst_id)
487
  user.conversations.current_thread = old_user_object.conversations.current_thread
488
  user.conversations.intro_done = True
489
  user.done_first_reflection = old_user_object.done_first_reflection
 
716
  if os.path.exists(f'users/data/{request.user_id}.pkl'):
717
  return {"message": f"[OK] User already exists: {request.user_id}"}
718
 
719
+ user_info, persona = get_user_info(request.user_id)
720
+ # Persona is one of ["Coach Steve", "Coach Aris", "Coach Teresa"]
721
+ # we map each of the above to assistant_ids = ["asst_mUm6MBcW544p1iVov9mwIC96", "asst_4WcktKgYdDnXA1QUlWvrNfWV", "asst_4UVkFK6r2pbz6NK6kNzG4sTW"]
722
+ persona_to_assistant = {
723
+ "Coach Steve": "asst_mUm6MBcW544p1iVov9mwIC96",
724
+ "Coach Aris": "asst_4WcktKgYdDnXA1QUlWvrNfWV",
725
+ "Coach Teresa": "asst_4UVkFK6r2pbz6NK6kNzG4sTW"
726
+ }
727
+
728
+ if persona not in persona_to_assistant:
729
+ logger.warning(f"Invalid persona: {persona}, defaulting to: Coach Steve", extra={"user_id": request.user_id, "endpoint": "/create_user"})
730
+ # For testing we default to steve
731
+ persona = "Coach Steve"
732
+ # raise FastAPIError(
733
+ # message="Invalid persona",
734
+ # e="Persona must be one of ['Coach Steve', 'Coach Aris', 'Coach Teresa']"
735
+ # )
736
+
737
+ selected_persona = persona_to_assistant[persona]
738
+
739
+ logger.info(f"Creating user with persona {persona}:{selected_persona}", extra={"user_id": request.user_id, "endpoint": "/create_user"})
740
+
741
+ user = User(request.user_id, user_info, client, selected_persona)
742
  folder_path = os.path.join("mementos", "to_upload", request.user_id)
743
  os.makedirs(folder_path, exist_ok=True)
744
 
 
895
  ):
896
  print_log("INFO", "Getting user's summary", extra={"user_id": user_id, "endpoint": "/get_user_summary"})
897
  logger.info("Getting user's summary", extra={"user_id": user_id, "endpoint": "/get_user_summary"})
898
+
899
+ # NOTE: This call will also update the users recommended topics to discuss with GG.
900
+ # This is so that the AI response will align with the dashboard.
901
+ user_summary = get_user_summary(user_id, update_rec_topics=True)
902
  print_log("INFO", "Successfully generated summary", extra={"user_id": user_id, "endpoint": "/get_user_summary"})
903
  logger.info("Successfully generated summary", extra={"user_id": user_id, "endpoint": "/get_user_summary"})
904
  return user_summary
app/user.py CHANGED
@@ -19,7 +19,7 @@ from app.flows import FINAL_SUMMARY_STATE, FINAL_SUMMARY_STATE, MICRO_ACTION_STA
19
  from pydantic import BaseModel
20
  from datetime import datetime
21
 
22
- from app.utils import generate_uuid, update_growth_guide_summary
23
 
24
  import dotenv
25
  import re
@@ -97,7 +97,7 @@ class User:
97
  },
98
  {
99
  "day": 3,
100
- "coachingTheme": "OPEN_DISCUSSION_STATE"
101
  },
102
  {
103
  "day": 4,
@@ -107,8 +107,7 @@ class User:
107
  "day": 5,
108
  "coachingTheme": "FINAL_SUMMARY_STATE"
109
  }
110
- ]
111
- }
112
 
113
 
114
  self.growth_plan = CircularQueue(array=growth_plan['growthPlan'], user_id=self.user_id)
@@ -189,7 +188,7 @@ class User:
189
  def add_recent_wins(self, wins, context = None):
190
  prompt = f"""
191
  ## Role
192
- You are an expert in writing achievement message and progress notification. Your task is to use the user's achievement and context to formulate a short and creative achievement message/progress notification. The output must be a one sentence short message (less than 15 words) in this JSON output schema:
193
 
194
  ```json
195
  {{
@@ -206,7 +205,7 @@ class User:
206
  Output:
207
  ```
208
  {{
209
- achievement_message: You crushed it! Completing that 10k run is a huge milestone—way to go!
210
  }}
211
  ```
212
 
@@ -630,7 +629,10 @@ class User:
630
  elif theme == "PROGRESS_SUMMARY_STATE":
631
  formatted_message = PROGRESS_SUMMARY_STATE.format(self.get_current_goal(), day, len(self.growth_plan.array))
632
  elif theme == "FINAL_SUMMARY_STATE":
633
- formatted_message = FINAL_SUMMARY_STATE.format(self.get_current_goal(), day, len(self.growth_plan.array))
 
 
 
634
  elif theme == "EDUCATION_STATE":
635
  formatted_message = EDUCATION_STATE.format(self.get_current_goal(), day, len(self.growth_plan.array))
636
  elif theme == "FOLLUP_ACTION_STATE":
@@ -692,6 +694,8 @@ class User:
692
 
693
  8. You **MUST** call the process_reminder() function if the user wants to postpone their micro-action
694
 
 
 
695
  Today's Theme:
696
  {formatted_message}
697
  """
@@ -794,7 +798,7 @@ class User:
794
  logger.info(f"Summarizing zoom ai summary", extra={"user_id": self.user_id, "endpoint": "summarize_zoom"})
795
  # make an api call to gpt4o to summarize the zoom_ai_summary and produce a text with a focus on the most amount of user insight and info extracted
796
  system_prompt = f"""You are an expert at summarizing AI-generated Zoom transcripts concisely, focusing on extracting key user insights to enhance personalization in future interactions. Note that the zoom ai transcript may get the user's name wrong. Replace it with the actual user's name: {self.user_info}. Refer to the coach/guide as 'the Growth Guide'."""
797
- prompt = f"Please summarize the following AI-generated Zoom transcript **in one short paragraph only** !!, emphasizing the most significant user insights and information:\n\n{zoom_ai_summary}"
798
 
799
  response = self.client.chat.completions.create(
800
  model="gpt-4o",
@@ -802,10 +806,32 @@ class User:
802
  {"role": "system", "content": system_prompt},
803
  {"role": "user", "content": prompt}
804
  ],
805
- temperature=0.2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
806
  )
807
- logger.info(f"Summary: {response.choices[0].message.content}", extra={"user_id": self.user_id, "endpoint": "summarize_zoom"})
808
- return {'overview': response.choices[0].message.content}
 
 
809
 
810
  @catch_error
811
  def _update_user_data(self, data_type, text_input, extra_text=""):
@@ -996,12 +1022,15 @@ class User:
996
  if completed_micro_action:
997
  self.micro_actions[-1].status = "COMPLETE"
998
  self.micro_actions[-1].updated_at = pd.Timestamp.now(tz='UTC').strftime("%d-%m-%Y %a %H:%M:%S")
 
999
 
1000
  num_of_micro_actions_completed = sum(1 for item in self.micro_actions if item.status == 'COMPLETE')
1001
 
1002
  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):
1003
  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")
1004
- self.add_recent_wins(wins = "You have completed a micro action!", context= self.micro_actions[-1]['content'])
 
 
1005
 
1006
  @catch_error
1007
  def trigger_deep_reflection_point(self, area_of_deep_reflection):
 
19
  from pydantic import BaseModel
20
  from datetime import datetime
21
 
22
+ from app.utils import generate_uuid, get_growth_guide_summary, update_growth_guide_summary
23
 
24
  import dotenv
25
  import re
 
97
  },
98
  {
99
  "day": 3,
100
+ "coachingTheme": "FINAL_SUMMARY_STATE"
101
  },
102
  {
103
  "day": 4,
 
107
  "day": 5,
108
  "coachingTheme": "FINAL_SUMMARY_STATE"
109
  }
110
+ ]}
 
111
 
112
 
113
  self.growth_plan = CircularQueue(array=growth_plan['growthPlan'], user_id=self.user_id)
 
188
  def add_recent_wins(self, wins, context = None):
189
  prompt = f"""
190
  ## Role
191
+ You are an expert in writing achievement message and progress notification. Your task is to use the user's achievement and context to formulate a short achievement message/progress notification. The output must be a one sentence short message (less than 15 words) in this JSON output schema:
192
 
193
  ```json
194
  {{
 
205
  Output:
206
  ```
207
  {{
208
+ achievement_message: You have completed a 10k run!
209
  }}
210
  ```
211
 
 
629
  elif theme == "PROGRESS_SUMMARY_STATE":
630
  formatted_message = PROGRESS_SUMMARY_STATE.format(self.get_current_goal(), day, len(self.growth_plan.array))
631
  elif theme == "FINAL_SUMMARY_STATE":
632
+ gg_summary = "<User has not had a Growth Guide session yet>"
633
+ if self.last_gg_session:
634
+ gg_summary = get_growth_guide_summary(self.user_id, self.last_gg_session)
635
+ formatted_message = FINAL_SUMMARY_STATE.format(self.get_current_goal(), day, len(self.growth_plan.array), gg_summary)
636
  elif theme == "EDUCATION_STATE":
637
  formatted_message = EDUCATION_STATE.format(self.get_current_goal(), day, len(self.growth_plan.array))
638
  elif theme == "FOLLUP_ACTION_STATE":
 
694
 
695
  8. You **MUST** call the process_reminder() function if the user wants to postpone their micro-action
696
 
697
+ 9. When talking about Growth Guide, you must try to upsell the growth guide. Meaning that you are always encouraging the user to book a Growth Guide session and explain it benefits. Be like the Growth Guide's salesman!
698
+
699
  Today's Theme:
700
  {formatted_message}
701
  """
 
798
  logger.info(f"Summarizing zoom ai summary", extra={"user_id": self.user_id, "endpoint": "summarize_zoom"})
799
  # make an api call to gpt4o to summarize the zoom_ai_summary and produce a text with a focus on the most amount of user insight and info extracted
800
  system_prompt = f"""You are an expert at summarizing AI-generated Zoom transcripts concisely, focusing on extracting key user insights to enhance personalization in future interactions. Note that the zoom ai transcript may get the user's name wrong. Replace it with the actual user's name: {self.user_info}. Refer to the coach/guide as 'the Growth Guide'."""
801
+ prompt = f"Please summarize the following AI-generated Zoom transcript **in one short paragraph only, around 50 completion tokens maximum** !!, emphasizing the most significant user insights and information:\n\n{zoom_ai_summary}"
802
 
803
  response = self.client.chat.completions.create(
804
  model="gpt-4o",
 
806
  {"role": "system", "content": system_prompt},
807
  {"role": "user", "content": prompt}
808
  ],
809
+ response_format = {
810
+ "type": "json_schema",
811
+ "json_schema": {
812
+ "name": "summarized_overview",
813
+ "strict": True,
814
+ "schema": {
815
+ "type": "object",
816
+ "properties": {
817
+ "summary": {
818
+ "type": "string",
819
+ "description": "The summary of the zoom transcript"
820
+ }
821
+ },
822
+ "required": [
823
+ "summary"
824
+ ],
825
+ "additionalProperties": False
826
+ }
827
+ }
828
+ },
829
+ temperature=0.5
830
  )
831
+
832
+ overview_summary = json.loads(response.choices[0].message.content)['summary']
833
+ logger.info(f"Summary: {overview_summary}", extra={"user_id": self.user_id, "endpoint": "summarize_zoom"})
834
+ return {'overview': overview_summary}
835
 
836
  @catch_error
837
  def _update_user_data(self, data_type, text_input, extra_text=""):
 
1022
  if completed_micro_action:
1023
  self.micro_actions[-1].status = "COMPLETE"
1024
  self.micro_actions[-1].updated_at = pd.Timestamp.now(tz='UTC').strftime("%d-%m-%Y %a %H:%M:%S")
1025
+ logger.info("Micro action status updated, checking number of actions completed...", extra={"user_id": self.user_id, "endpoint": "update_micro_action_status"})
1026
 
1027
  num_of_micro_actions_completed = sum(1 for item in self.micro_actions if item.status == 'COMPLETE')
1028
 
1029
  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):
1030
  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")
1031
+ self.add_recent_wins(wins = "You have completed a micro action!", context= self.micro_actions[-1].content)
1032
+ logger.info("Added life score points based on number of actions completed.", extra={"user_id": self.user_id, "endpoint": "update_micro_action_status"})
1033
+ logger.info("Process done.", extra={"user_id": self.user_id, "endpoint": "update_micro_action_status"})
1034
 
1035
  @catch_error
1036
  def trigger_deep_reflection_point(self, area_of_deep_reflection):
app/utils.py CHANGED
@@ -1,14 +1,13 @@
1
  import logging
2
  import boto3
3
- from botocore.exceptions import ClientError, NoCredentialsError, PartialCredentialsError
4
  import os
5
  from dotenv import load_dotenv
6
- from fastapi import FastAPI, HTTPException, Security, Query, status
7
  from fastapi.security import APIKeyHeader
8
  from openai import OpenAI
9
  import openai
10
  import pandas as pd
11
- from pydantic import BaseModel
12
  import os
13
  import logging
14
  import json
@@ -17,17 +16,11 @@ from psycopg2 import sql
17
  import os
18
  from dotenv import load_dotenv
19
  from datetime import datetime, timezone
20
- import threading
21
  import pickle # Replace dill with pickle
22
- from cachetools import TTLCache
23
- import threading
24
- import time
25
  import uuid
26
  from app.cache import CustomTTLCache, upload_file_to_s3
27
  import pdfkit
28
  import PyPDF2
29
- import secrets
30
- import string
31
 
32
  from app.exceptions import BaseOurcoachException, DBError, OpenAIRequestError, UtilsError
33
 
@@ -346,7 +339,7 @@ def generate_html(json_data, coach_name='Growth Guide', booking_id = None):
346
  raise DBError(user_id="no-user", message="Error uploading file to S3", code="S3Error")
347
 
348
  @catch_error
349
- def get_user_summary(user_id):
350
  function_name = get_user_summary.__name__
351
  logger.info(f"Generating user summary for user {user_id}", extra={'user_id': user_id, 'endpoint': function_name})
352
 
@@ -819,7 +812,8 @@ def get_user_summary(user_id):
819
  # reports['html_report'] = html_output
820
 
821
  # Store users_growth_guide_preparation_brief in the User object
822
- user.set_recommened_gg_topics(reports['users_growth_guide_preparation_brief'])
 
823
 
824
  # Step 4: Return the JSON reports
825
  logger.info(f"User summary generated successfully for user {user_id}", extra={'user_id': user_id, 'endpoint': function_name})
@@ -1043,7 +1037,6 @@ def get_user_info(user_id):
1043
  {user_data_clean.get('firstName', '')}'s challenges (You **must** use this information for the PLANNING STATE):
1044
  {challenges}
1045
 
1046
- {user_data_clean.get('firstName', '')}'s Legendary Persona: {user_data_clean.get('legendPersona', '')}
1047
  Pronouns: {user_data_clean.get('pronouns', '')}
1048
  Birthday: {user_data_clean.get('birthDate', '')}
1049
  {user_data_clean.get('firstName', '')}'s MBTI: {user_data_clean.get('mbti', '')}
@@ -1062,7 +1055,7 @@ def get_user_info(user_id):
1062
  {whoImportant}
1063
  """
1064
  logger.info(f"User info retrieved successfully for {user_id}", extra={'user_id': user_id, 'endpoint': function_name})
1065
- return user_data_formatted, user_data_clean.get('mattersMost', ['', '', '', '', ''])
1066
  else:
1067
  logger.warning(f"No user info found for {user_id}", extra={'user_id': user_id, 'endpoint': function_name})
1068
  raise DBError(user_id=user_id, message="Error retrieving user info", code="NoOnboardingError", e=str(e))
@@ -1402,6 +1395,22 @@ def get_users_mementos(user_id, date):
1402
  finally:
1403
  return mementos
1404
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1405
  @catch_error
1406
  def get_user_subscriptions(user_id):
1407
  function_name = get_user_subscriptions.__name__
 
1
  import logging
2
  import boto3
3
+ from botocore.exceptions import NoCredentialsError, PartialCredentialsError
4
  import os
5
  from dotenv import load_dotenv
6
+ from fastapi import HTTPException, Security, Query, status
7
  from fastapi.security import APIKeyHeader
8
  from openai import OpenAI
9
  import openai
10
  import pandas as pd
 
11
  import os
12
  import logging
13
  import json
 
16
  import os
17
  from dotenv import load_dotenv
18
  from datetime import datetime, timezone
 
19
  import pickle # Replace dill with pickle
 
 
 
20
  import uuid
21
  from app.cache import CustomTTLCache, upload_file_to_s3
22
  import pdfkit
23
  import PyPDF2
 
 
24
 
25
  from app.exceptions import BaseOurcoachException, DBError, OpenAIRequestError, UtilsError
26
 
 
339
  raise DBError(user_id="no-user", message="Error uploading file to S3", code="S3Error")
340
 
341
  @catch_error
342
+ def get_user_summary(user_id, update_rec_topics=False):
343
  function_name = get_user_summary.__name__
344
  logger.info(f"Generating user summary for user {user_id}", extra={'user_id': user_id, 'endpoint': function_name})
345
 
 
812
  # reports['html_report'] = html_output
813
 
814
  # Store users_growth_guide_preparation_brief in the User object
815
+ if update_rec_topics:
816
+ user.set_recommened_gg_topics(reports['users_growth_guide_preparation_brief'])
817
 
818
  # Step 4: Return the JSON reports
819
  logger.info(f"User summary generated successfully for user {user_id}", extra={'user_id': user_id, 'endpoint': function_name})
 
1037
  {user_data_clean.get('firstName', '')}'s challenges (You **must** use this information for the PLANNING STATE):
1038
  {challenges}
1039
 
 
1040
  Pronouns: {user_data_clean.get('pronouns', '')}
1041
  Birthday: {user_data_clean.get('birthDate', '')}
1042
  {user_data_clean.get('firstName', '')}'s MBTI: {user_data_clean.get('mbti', '')}
 
1055
  {whoImportant}
1056
  """
1057
  logger.info(f"User info retrieved successfully for {user_id}", extra={'user_id': user_id, 'endpoint': function_name})
1058
+ return user_data_formatted, user_data_clean.get('legendPersona', '')
1059
  else:
1060
  logger.warning(f"No user info found for {user_id}", extra={'user_id': user_id, 'endpoint': function_name})
1061
  raise DBError(user_id=user_id, message="Error retrieving user info", code="NoOnboardingError", e=str(e))
 
1395
  finally:
1396
  return mementos
1397
 
1398
+ @catch_error
1399
+ def id_to_persona(assistant_id):
1400
+ # persona_to_assistant = {
1401
+ # "Coach Steve": "asst_mUm6MBcW544p1iVov9mwIC96",
1402
+ # "Coach Aris": "asst_4WcktKgYdDnXA1QUlWvrNfWV",
1403
+ # "Coach Teresa": "asst_4UVkFK6r2pbz6NK6kNzG4sTW"
1404
+ # }
1405
+
1406
+ assistant_to_persona = {
1407
+ "asst_mUm6MBcW544p1iVov9mwIC96": "Coach Steve, based on the persona of Steve Jobs",
1408
+ "asst_4WcktKgYdDnXA1QUlWvrNfWV": "Coach Aris, based on the persona of Aristotle",
1409
+ "asst_4UVkFK6r2pbz6NK6kNzG4sTW": "Coach Teresa, based on the persona of Mother Teresa"
1410
+ }
1411
+
1412
+ return assistant_to_persona.get(assistant_id, "Coach Steve, based on the persona of Steve Jobs")
1413
+
1414
  @catch_error
1415
  def get_user_subscriptions(user_id):
1416
  function_name = get_user_subscriptions.__name__