matthew.farant commited on
Commit
bead928
·
1 Parent(s): f22f2db

Add cumulative days & GG name to intro msg

Browse files
Files changed (5) hide show
  1. app/assistants.py +2 -1
  2. app/flows.py +6 -6
  3. app/main.py +3 -1
  4. app/user.py +22 -9
  5. app/utils.py +2 -1
app/assistants.py CHANGED
@@ -617,7 +617,8 @@ class Assistant:
617
 
618
  # switch back to the intro assistant, so we set just_finish_intro to False again
619
  just_finish_intro = False
620
-
 
621
  # cancel current run
622
  run = self.cancel_run(run, thread)
623
  run = PseudoRun(status="cancelled", metadata={"message": "change_goal"})
 
617
 
618
  # switch back to the intro assistant, so we set just_finish_intro to False again
619
  just_finish_intro = False
620
+ self.cm.user.reset_cumulative_plan_day()
621
+
622
  # cancel current run
623
  run = self.cancel_run(run, thread)
624
  run = PseudoRun(status="cancelled", metadata={"message": "change_goal"})
app/flows.py CHANGED
@@ -137,7 +137,7 @@ Step 1:
137
  - **One Micro-Action Only:** Suggest only one action per day.
138
  - **Minimal Questions:** Use questions only when absolutely necessary and limit to one question in total per day.
139
  - **Avoid Over-Questioning:** Keep questions minimal to prevent overwhelming the user.
140
- - **Lists:** Provide a maximum of three items in any list.
141
 
142
  ---
143
 
@@ -239,7 +239,7 @@ Step 1:
239
 
240
  - **Avoid Over-Questioning:** Keep questions creative and sparing; avoid overwhelming the user.
241
 
242
- - **Lists:** Provide a maximum of three items in any list.
243
 
244
  - **Quoting your persona:**
245
  - Do **not** mention the name of your persona when quoting.
@@ -279,7 +279,7 @@ User’s Context
279
  2. Ask no more than **three questions** per day. Limit to **one question per message** and encapsulate it with asterisks (*).
280
  3. Avoid overwhelming the user; keep your suggestions conversational and focused.
281
  4. Always guide the user with specific suggestions rather than seeking ideas from them.
282
- 5. Limit lists to a maximum of three items.
283
  6. Structure responses as if texting: short, friendly, and actionable.
284
  """
285
 
@@ -318,7 +318,7 @@ Objective: Assist users in reflecting on their progress, recognizing strengths,
318
  - **Encapsulate questions with asterisks:** like this *question* (Replace "question" with the actual question.)
319
 
320
  - **Guided Coaching:** Provide suggestions assertively rather than asking for the user's ideas or plans. Remember, you are the coach!
321
- - **Lists:** When listing actions or insights, limit to no more than three items.
322
 
323
  ---
324
 
@@ -400,7 +400,7 @@ Important Rules
400
  • Never explicitly tell the function that you are calling to the user (just do the function calling in the background)
401
  • Question Format: When you ask a question, encapsulate it with asterisks (e.g., What’s one thing you can commit to today?). Use only one question mark per message.
402
  • Avoid Over-Questioning: Keep questions creative, sparing, and avoid overwhelming the user.
403
- • Lists: Provide a maximum of three items in any list.
404
 
405
  When you want to mention a quote from your persona, you must not say the name of your persona. You should paraphrase the quote and say it like it's your own message!
406
  Bad Example: Hey <user name>! As <your persona> said, "<quote>"
@@ -573,7 +573,7 @@ Important Rules
573
  • Never explicitly tell the function that you are calling to the user (just do the function calling in the background)
574
  • Question Format: When you ask a question, encapsulate it with asterisks (e.g., What’s one thing you can commit to today?). Use only one question mark per message.
575
  • Avoid Over-Questioning: Keep questions creative, sparing, and avoid overwhelming the user.
576
- • Lists: Provide a maximum of three items in any list.
577
  • Be concise! Use Whatsapp texting length!
578
 
579
  When you want to mention a quote from your persona, you must not say the name of your persona. You should paraphrase the quote and say it like it's your own message!
 
137
  - **One Micro-Action Only:** Suggest only one action per day.
138
  - **Minimal Questions:** Use questions only when absolutely necessary and limit to one question in total per day.
139
  - **Avoid Over-Questioning:** Keep questions minimal to prevent overwhelming the user.
140
+ - **Lists:** Provide a maximum of three items in any list. Use italic (single asterisk) instead of bold (double asterisk) in your list!
141
 
142
  ---
143
 
 
239
 
240
  - **Avoid Over-Questioning:** Keep questions creative and sparing; avoid overwhelming the user.
241
 
242
+ - **Lists:** Provide a maximum of three items in any list. Use italic (single asterisk) instead of bold (double asterisk) in your list!
243
 
244
  - **Quoting your persona:**
245
  - Do **not** mention the name of your persona when quoting.
 
279
  2. Ask no more than **three questions** per day. Limit to **one question per message** and encapsulate it with asterisks (*).
280
  3. Avoid overwhelming the user; keep your suggestions conversational and focused.
281
  4. Always guide the user with specific suggestions rather than seeking ideas from them.
282
+ 5. Limit lists to a maximum of three items. Use italic (single asterisk) instead of bold (double asterisk) in your list!
283
  6. Structure responses as if texting: short, friendly, and actionable.
284
  """
285
 
 
318
  - **Encapsulate questions with asterisks:** like this *question* (Replace "question" with the actual question.)
319
 
320
  - **Guided Coaching:** Provide suggestions assertively rather than asking for the user's ideas or plans. Remember, you are the coach!
321
+ - **Lists:** When listing actions or insights, limit to no more than three items. Use italic (single asterisk) instead of bold (double asterisk) in your list!
322
 
323
  ---
324
 
 
400
  • Never explicitly tell the function that you are calling to the user (just do the function calling in the background)
401
  • Question Format: When you ask a question, encapsulate it with asterisks (e.g., What’s one thing you can commit to today?). Use only one question mark per message.
402
  • Avoid Over-Questioning: Keep questions creative, sparing, and avoid overwhelming the user.
403
+ • Lists: Provide a maximum of three items in any list. Use italic (single asterisk) instead of bold (double asterisk) in your list!
404
 
405
  When you want to mention a quote from your persona, you must not say the name of your persona. You should paraphrase the quote and say it like it's your own message!
406
  Bad Example: Hey <user name>! As <your persona> said, "<quote>"
 
573
  • Never explicitly tell the function that you are calling to the user (just do the function calling in the background)
574
  • Question Format: When you ask a question, encapsulate it with asterisks (e.g., What’s one thing you can commit to today?). Use only one question mark per message.
575
  • Avoid Over-Questioning: Keep questions creative, sparing, and avoid overwhelming the user.
576
+ • Lists: Provide a maximum of three items in any list. Use italic (single asterisk) instead of bold (double asterisk) in your list!
577
  • Be concise! Use Whatsapp texting length!
578
 
579
  When you want to mention a quote from your persona, you must not say the name of your persona. You should paraphrase the quote and say it like it's your own message!
app/main.py CHANGED
@@ -512,6 +512,7 @@ async def migrate_user(
512
  if hasattr(old_user_object, "growth_plan"): setattr(user, "growth_plan", old_user_object.growth_plan)
513
  if hasattr(old_user_object, "user_interaction_guidelines"): setattr(user, "user_interaction_guidelines", old_user_object.user_interaction_guidelines)
514
  if hasattr(old_user_object, "score_history"): setattr(user, "score_history", old_user_object.score_history)
 
515
 
516
  api_response = {
517
  "user": user.user_info,
@@ -531,7 +532,8 @@ async def migrate_user(
531
  "recommended_gg_topics": user.recommended_gg_topics,
532
  "growth_plan": user.growth_plan,
533
  "user_interaction_guidelines": user.user_interaction_guidelines,
534
- "score_history": user.score_history
 
535
  }
536
 
537
  add_to_cache(user)
 
512
  if hasattr(old_user_object, "growth_plan"): setattr(user, "growth_plan", old_user_object.growth_plan)
513
  if hasattr(old_user_object, "user_interaction_guidelines"): setattr(user, "user_interaction_guidelines", old_user_object.user_interaction_guidelines)
514
  if hasattr(old_user_object, "score_history"): setattr(user, "score_history", old_user_object.score_history)
515
+ if hasattr(old_user_object, "cumulative_plan_day"): setattr(user, "cumulative_plan_day", old_user_object.cumulative_plan_day)
516
 
517
  api_response = {
518
  "user": user.user_info,
 
532
  "recommended_gg_topics": user.recommended_gg_topics,
533
  "growth_plan": user.growth_plan,
534
  "user_interaction_guidelines": user.user_interaction_guidelines,
535
+ "score_history": user.score_history,
536
+ "cumulative_plan_day": user.cumulative_plan_day
537
  }
538
 
539
  add_to_cache(user)
app/user.py CHANGED
@@ -23,6 +23,7 @@ from app.utils import generate_uuid, get_booked_gg_sessions, get_growth_guide_su
23
 
24
  import dotenv
25
  import re
 
26
  dotenv.load_dotenv()
27
 
28
  OURCOACH_DASHBOARD_URL = os.getenv("OURCOACH_DASHBOARD_URL")
@@ -126,6 +127,7 @@ class User:
126
  self.conversations = ConversationManager(client, self, asst_id)
127
 
128
  self.score_history = []
 
129
 
130
  @catch_error
131
  def extend_growth_plan(self):
@@ -195,6 +197,11 @@ class User:
195
  logger.info(f"Success.", extra={"user_id": self.user_id, "endpoint": "extend_growth_plan"})
196
  return True
197
 
 
 
 
 
 
198
  @catch_error
199
  def add_recent_wins(self, wins, context = None):
200
  prompt = f"""
@@ -616,6 +623,10 @@ class User:
616
  def do_theme(self, theme, date, day, last_msg_is_answered = True):
617
  logger.info(f"Doing theme: {theme}", extra={"user_id": self.user_id, "endpoint": "do_theme"})
618
 
 
 
 
 
619
  if self.reminders is not None and len(self.reminders):
620
  logger.info(f"ALL Upcoming Reminders: {self.reminders}", extra={"user_id": self.user_id, "endpoint": "do_theme"})
621
  reminders = list(filter(lambda x : x['recurrence'] == 'postponed', self.reminders))
@@ -635,40 +646,40 @@ class User:
635
  logger.info(f"No reminders found for today ({pd.to_datetime(date).date()})", extra={"user_id": self.user_id, "endpoint": "do_theme"})
636
 
637
  if theme == "MOTIVATION_INSPIRATION_STATE":
638
- formatted_message = MOTIVATION_INSPIRATION_STATE.format(self.get_current_goal(), day, len(self.growth_plan.array))
639
  elif theme == "PROGRESS_REFLECTION_STATE":
640
- formatted_message = PROGRESS_REFLECTION_STATE.format(self.get_current_goal(), day, len(self.growth_plan.array))
641
  if len(self.challenges):
642
  challenge = self.challenges.pop(0)
643
  formatted_message += f"\n\n** IMPORTANT: Today, reflect on the users' challenge of: {challenge.content}, which they brought up during their growth guide session (let the user know we are bringing it up because of this) **"
644
  elif theme == "MICRO_ACTION_STATE":
645
  reminder_message = "\n".join([f"{i+1}. {reminder}" for i, reminder in enumerate(reminders)]) if reminders else "User has no postponed micro-actions"
646
 
647
- formatted_message = MICRO_ACTION_STATE.format(self.get_current_goal(), day, len(self.growth_plan.array), reminder_message)
648
  if len(self.recommended_micro_actions):
649
  todays_micro_action = self.recommended_micro_actions.pop(0)
650
  formatted_message += f"\n\n** IMPORTANT: Today's Micro Action is: {todays_micro_action.content}, which was recommended during their growth guide session (let the user know we are bringing it up because of this) **"
651
  elif theme == "OPEN_DISCUSSION_STATE":
652
- formatted_message = OPEN_DISCUSSION_STATE.format(self.get_current_goal(), day, len(self.growth_plan.array))
653
  if len(self.other_focusses):
654
  focus = self.other_focusses.pop(0)
655
  formatted_message += f"\n\n** IMPORTANT: Today, focus the discussion on: {focus.content}, which they discussed during their growth guide session (let the user know we are bringing it up because of this) **"
656
  elif theme == "PROGRESS_SUMMARY_STATE":
657
- formatted_message = PROGRESS_SUMMARY_STATE.format(self.get_current_goal(), day, len(self.growth_plan.array))
658
  elif theme == "FINAL_SUMMARY_STATE":
659
  gg_summary = "<User has not had a Growth Guide session yet>"
660
  if self.last_gg_session:
661
  gg_summary = get_growth_guide_summary(self.user_id, self.last_gg_session)
662
- formatted_message = FINAL_SUMMARY_STATE.format(self.get_current_goal(), day, len(self.growth_plan.array), gg_summary)
663
  elif theme == "EDUCATION_STATE":
664
- formatted_message = EDUCATION_STATE.format(self.get_current_goal(), day, len(self.growth_plan.array))
665
  elif theme == "FOLLUP_ACTION_STATE":
666
  reminder_message = "\n".join([f"{i+1}. {reminder}" for i, reminder in enumerate(reminders)]) if reminders else "User has no postponed micro-actions"
667
- formatted_message = FOLLUP_ACTION_STATE.format(self.get_current_goal(), day, len(self.growth_plan.array), reminder_message)
668
  elif theme == "FUNFACT_STATE":
669
  topics = ["Fun Fact about the User's Goal", "How Personality Type is affecting/shaping their behaviour towards the goal", "How Love Language may impact and be relevant toward the goal"]
670
  randomized_topic = random.choice(topics)
671
- formatted_message = FUNFACT_STATE.format(self.get_current_goal(), day, len(self.growth_plan.array), randomized_topic)
672
 
673
  # prompt = f"""** It is a new day: {date} **
674
  # Additional System Instruction:
@@ -709,6 +720,8 @@ class User:
709
  If the answer above is "False", you must immediately ask something like (but warmer) "Hey <user name>, I've noticed that you haven't answered my latest question. Do you still want to continue the growth plan?". If the user says "no", then ask if they want to set a new goal (therefore later, call the change_goal() function)
710
  But if the user says "yes", then proceed to do the instruction below.
711
 
 
 
712
  Today's Theme:
713
  {formatted_message}
714
  """
 
23
 
24
  import dotenv
25
  import re
26
+ import math
27
  dotenv.load_dotenv()
28
 
29
  OURCOACH_DASHBOARD_URL = os.getenv("OURCOACH_DASHBOARD_URL")
 
127
  self.conversations = ConversationManager(client, self, asst_id)
128
 
129
  self.score_history = []
130
+ self.cumulative_plan_day = 0
131
 
132
  @catch_error
133
  def extend_growth_plan(self):
 
197
  logger.info(f"Success.", extra={"user_id": self.user_id, "endpoint": "extend_growth_plan"})
198
  return True
199
 
200
+ @catch_error
201
+ def reset_cumulative_plan_day(self):
202
+ logger.info(f"Reseting cumulative_plan_day", extra={"user_id": self.user_id, "endpoint": "reset_cumulative_plan_day"})
203
+ self.cumulative_plan_day = 0
204
+
205
  @catch_error
206
  def add_recent_wins(self, wins, context = None):
207
  prompt = f"""
 
623
  def do_theme(self, theme, date, day, last_msg_is_answered = True):
624
  logger.info(f"Doing theme: {theme}", extra={"user_id": self.user_id, "endpoint": "do_theme"})
625
 
626
+ # Add 1 day to cumulative_plan_day
627
+ self.cumulative_plan_day += 1
628
+ final_day = (math.ceil((self.cumulative_plan_day+7)/14) * 14) - 7
629
+
630
  if self.reminders is not None and len(self.reminders):
631
  logger.info(f"ALL Upcoming Reminders: {self.reminders}", extra={"user_id": self.user_id, "endpoint": "do_theme"})
632
  reminders = list(filter(lambda x : x['recurrence'] == 'postponed', self.reminders))
 
646
  logger.info(f"No reminders found for today ({pd.to_datetime(date).date()})", extra={"user_id": self.user_id, "endpoint": "do_theme"})
647
 
648
  if theme == "MOTIVATION_INSPIRATION_STATE":
649
+ formatted_message = MOTIVATION_INSPIRATION_STATE.format(self.get_current_goal(), self.cumulative_plan_day, final_day)
650
  elif theme == "PROGRESS_REFLECTION_STATE":
651
+ formatted_message = PROGRESS_REFLECTION_STATE.format(self.get_current_goal(), self.cumulative_plan_day, final_day)
652
  if len(self.challenges):
653
  challenge = self.challenges.pop(0)
654
  formatted_message += f"\n\n** IMPORTANT: Today, reflect on the users' challenge of: {challenge.content}, which they brought up during their growth guide session (let the user know we are bringing it up because of this) **"
655
  elif theme == "MICRO_ACTION_STATE":
656
  reminder_message = "\n".join([f"{i+1}. {reminder}" for i, reminder in enumerate(reminders)]) if reminders else "User has no postponed micro-actions"
657
 
658
+ formatted_message = MICRO_ACTION_STATE.format(self.get_current_goal(), self.cumulative_plan_day, final_day, reminder_message)
659
  if len(self.recommended_micro_actions):
660
  todays_micro_action = self.recommended_micro_actions.pop(0)
661
  formatted_message += f"\n\n** IMPORTANT: Today's Micro Action is: {todays_micro_action.content}, which was recommended during their growth guide session (let the user know we are bringing it up because of this) **"
662
  elif theme == "OPEN_DISCUSSION_STATE":
663
+ formatted_message = OPEN_DISCUSSION_STATE.format(self.get_current_goal(), self.cumulative_plan_day, final_day)
664
  if len(self.other_focusses):
665
  focus = self.other_focusses.pop(0)
666
  formatted_message += f"\n\n** IMPORTANT: Today, focus the discussion on: {focus.content}, which they discussed during their growth guide session (let the user know we are bringing it up because of this) **"
667
  elif theme == "PROGRESS_SUMMARY_STATE":
668
+ formatted_message = PROGRESS_SUMMARY_STATE.format(self.get_current_goal(), self.cumulative_plan_day, final_day)
669
  elif theme == "FINAL_SUMMARY_STATE":
670
  gg_summary = "<User has not had a Growth Guide session yet>"
671
  if self.last_gg_session:
672
  gg_summary = get_growth_guide_summary(self.user_id, self.last_gg_session)
673
+ formatted_message = FINAL_SUMMARY_STATE.format(self.get_current_goal(), self.cumulative_plan_day, final_day, gg_summary)
674
  elif theme == "EDUCATION_STATE":
675
+ formatted_message = EDUCATION_STATE.format(self.get_current_goal(), self.cumulative_plan_day, final_day)
676
  elif theme == "FOLLUP_ACTION_STATE":
677
  reminder_message = "\n".join([f"{i+1}. {reminder}" for i, reminder in enumerate(reminders)]) if reminders else "User has no postponed micro-actions"
678
+ formatted_message = FOLLUP_ACTION_STATE.format(self.get_current_goal(), self.cumulative_plan_day, final_day, reminder_message)
679
  elif theme == "FUNFACT_STATE":
680
  topics = ["Fun Fact about the User's Goal", "How Personality Type is affecting/shaping their behaviour towards the goal", "How Love Language may impact and be relevant toward the goal"]
681
  randomized_topic = random.choice(topics)
682
+ formatted_message = FUNFACT_STATE.format(self.get_current_goal(), self.cumulative_plan_day, final_day, randomized_topic)
683
 
684
  # prompt = f"""** It is a new day: {date} **
685
  # Additional System Instruction:
 
720
  If the answer above is "False", you must immediately ask something like (but warmer) "Hey <user name>, I've noticed that you haven't answered my latest question. Do you still want to continue the growth plan?". If the user says "no", then ask if they want to set a new goal (therefore later, call the change_goal() function)
721
  But if the user says "yes", then proceed to do the instruction below.
722
 
723
+ Today is day {self.cumulative_plan_day} of the user's growth journey (out of {final_day} days). You may (or may not) mention this occasionally in your first message of the day.
724
+
725
  Today's Theme:
726
  {formatted_message}
727
  """
app/utils.py CHANGED
@@ -1088,7 +1088,7 @@ def get_user_info(user_id):
1088
  try:
1089
  with psycopg2.connect(**db_params) as conn:
1090
  with conn.cursor() as cursor:
1091
- query = sql.SQL("SELECT * FROM {table} WHERE id = %s").format(table=sql.Identifier('public', 'users'))
1092
  cursor.execute(query, (user_id,))
1093
  row = cursor.fetchone()
1094
  if (row):
@@ -1104,6 +1104,7 @@ def get_user_info(user_id):
1104
  ### USER PROFILE ###
1105
 
1106
  Name: {user_data_clean.get('firstName', '')}
 
1107
  {user_data_clean.get('firstName', '')}'s challenges (You **must** use this information for the PLANNING STATE):
1108
  {challenges}
1109
  Persona:
 
1088
  try:
1089
  with psycopg2.connect(**db_params) as conn:
1090
  with conn.cursor() as cursor:
1091
+ query = sql.SQL("SELECT left(onboarding,length(onboarding)-1)||',\"growth_guide_name\":\"'||coalesce(b.full_name,'')||'\"}}' onboarding FROM {table} a LEFT JOIN {coach_tbl} b ON a.assign_coach_id = b.id WHERE a.id = %s").format(table=sql.Identifier('public', 'users'), coach_tbl = sql.Identifier('public','coach'))
1092
  cursor.execute(query, (user_id,))
1093
  row = cursor.fetchone()
1094
  if (row):
 
1104
  ### USER PROFILE ###
1105
 
1106
  Name: {user_data_clean.get('firstName', '')}
1107
+ Growth Guide Name: {user_data_clean.get('growth_guide_name', '')}
1108
  {user_data_clean.get('firstName', '')}'s challenges (You **must** use this information for the PLANNING STATE):
1109
  {challenges}
1110
  Persona: