Skip to content

Commit

Permalink
works well enough for deploy
Browse files Browse the repository at this point in the history
  • Loading branch information
voynow committed Aug 17, 2024
1 parent 86c6088 commit 0bbe641
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 78 deletions.
5 changes: 3 additions & 2 deletions src/training_week_generation/lambda_function.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@
get_weekly_summaries,
)
from src.auth_manager import get_strava_client
from src.constants import COACH_ROLE
from src.email_manager import send_email, training_week_to_html
from src.supabase_client import upsert_training_week_with_coaching
from src.training_week_generation.training_week import generate_training_week


def lambda_handler(event, context):
client_preferences = "A) Training for a marathon B) This will be my second marathon C) Prefer workouts on Wednesdays and long runs on Saturdays"

sysmsg_base = f"{COACH_ROLE}\nYour client has included the following preferenced: {client_preferences}\n"
# activities setup
athlete_id = os.environ["JAMIES_ATHLETE_ID"]
strava_client = get_strava_client(athlete_id)
Expand All @@ -23,7 +24,7 @@ def lambda_handler(event, context):
day_of_week_summaries = get_day_of_week_summaries(activities_df)
weekly_summaries = get_weekly_summaries(activities_df)
training_week_with_coaching = generate_training_week(
client_preferences=client_preferences,
sysmsg_base=sysmsg_base,
weekly_summaries=weekly_summaries,
day_of_week_summaries=day_of_week_summaries,
)
Expand Down
7 changes: 1 addition & 6 deletions src/training_week_generation/training_week.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from typing import List

from src.constants import COACH_ROLE
from src.llm import get_completion, get_completion_json
from src.types.day_of_week_summary import DayOfWeekSummary
from src.types.training_week import (
Expand Down Expand Up @@ -54,14 +53,10 @@ def get_training_week(


def generate_training_week(
client_preferences: str,
sysmsg_base: str,
day_of_week_summaries: List[DayOfWeekSummary],
weekly_summaries: List[WeekSummary],
) -> TrainingWeekWithCoaching:

sysmsg_base = f"""{COACH_ROLE}
Your client has included the following preferenced: {client_preferences}\n"""

typical_week_training_review = get_typical_week_training_review(
sysmsg_base=sysmsg_base, day_of_week_summaries=day_of_week_summaries
)
Expand Down
4 changes: 4 additions & 0 deletions src/types/training_week.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ class TrainingWeekWithCoaching(BaseModel):
training_week: List[TrainingSession]
"""Client's recommended training week"""

@property
def total_weekly_mileage(self) -> float:
return sum(session.distance for session in self.training_week)

def __str__(self):
return f"{self.typical_week_training_review=}\n{self.weekly_mileage_target=}\n{self.training_week_planning=}\n{self.training_week=}"

Expand Down
164 changes: 94 additions & 70 deletions test.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@
},
{
"cell_type": "code",
"execution_count": 13,
"execution_count": 92,
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"from typing import List\n",
"from datetime import datetime\n",
"\n",
"import polars as pl\n",
"from freezegun import freeze_time\n",
Expand All @@ -27,11 +27,14 @@
" get_day_of_week_summaries,\n",
" get_weekly_summaries,\n",
")\n",
"from src.types.training_week import TrainingWeekWithCoaching, TrainingSession\n",
"from pydantic import BaseModel\n",
"from src.constants import COACH_ROLE\n",
"from typing import List\n",
"from src.auth_manager import get_strava_client\n",
"from src.email_manager import send_email, training_week_to_html\n",
"from src.supabase_client import upsert_training_week_with_coaching, get_training_week_with_coaching\n",
"from src.training_week_generation.training_week import generate_training_week"
"from src.training_week_generation.training_week import generate_training_week\n",
"from src.types.training_week import TrainingSession"
]
},
{
Expand Down Expand Up @@ -71,6 +74,7 @@
" return get_activities_df(strava_client)\n",
"\n",
"client_preferences = \"A) Training for a marathon B) This will be my second marathon C) Prefer workouts on Wednesdays and long runs on Saturdays\"\n",
"sysmsg_base = f\"{COACH_ROLE}\\nYour client has included the following preferenced: {client_preferences}\\n\"\n",
"\n",
"# activities setup\n",
"athlete_id = os.environ[\"JAMIES_ATHLETE_ID\"]\n",
Expand All @@ -81,7 +85,7 @@
"day_of_week_summaries = get_day_of_week_summaries(activities_df)\n",
"weekly_summaries = get_weekly_summaries(activities_df)\n",
"training_week_with_coaching = generate_training_week(\n",
" client_preferences=client_preferences,\n",
" sysmsg_base=sysmsg_base,\n",
" weekly_summaries=weekly_summaries,\n",
" day_of_week_summaries=day_of_week_summaries,\n",
")\n",
Expand All @@ -105,115 +109,135 @@
},
{
"cell_type": "code",
"execution_count": 67,
"execution_count": 59,
"metadata": {},
"outputs": [],
"source": [
"import datetime\n",
"\n",
"@freeze_time(\"2024-08-13 20:00:00\")\n",
"def mock_get_activities_df(strava_client, num_weeks=8):\n",
" return get_activities_df(strava_client, num_weeks)\n",
"\n",
"\n",
"@freeze_time(\"2024-08-13 20:00:00\")\n",
"def mock_time_now():\n",
" return datetime.datetime.now()\n",
" return datetime.now()\n",
"\n",
"\n",
"def get_day_of_week():\n",
" return mock_time_now().strftime(\"%A\")\n",
"\n",
"\n",
"def get_weekday_num():\n",
" return mock_time_now().weekday()\n",
"\n",
"\n",
"def get_concise_activities(strava_client, num_weeks=8) -> pl.DataFrame:\n",
"class ActivitySummary(BaseModel):\n",
" date_and_time: str\n",
" \"\"\"Datetime formatted as 'Monday, August 13, 2024 08:00 PM'\"\"\"\n",
"\n",
" distance_in_miles: float\n",
" elevation_gain_in_feet: float\n",
" pace_minutes_per_mile: float\n",
"\n",
"\n",
"def get_activity_summaries(strava_client, num_weeks=8) -> pl.DataFrame:\n",
" df = mock_get_activities_df(strava_client, num_weeks)\n",
" return df.with_columns(\n",
" pl.col('start_date_local').apply(lambda x: x.strftime(\"%A, %B %d, %Y %I:%M %p\")),\n",
" concise_activities_df = df.with_columns(\n",
" pl.col('start_date_local').apply(lambda x: x.strftime(\"%A, %B %d, %Y %I:%M %p\")).alias('date_and_time'),\n",
" pl.col('distance_in_miles').apply(lambda x: round(x, 2)),\n",
" pl.col('elevation_gain_in_feet').apply(lambda x: round(x, 2)),\n",
" pl.col('pace_minutes_per_mile').apply(lambda x: round(x, 2)),\n",
" ).drop('id', 'name', 'day_of_week', 'week_of_year', 'year', 'moving_time_in_minutes')\n",
"\n",
"\n",
"def get_mid_week_delta(\n",
" training_week_with_coaching: TrainingWeekWithCoaching,\n",
" activities: pl.DataFrame\n",
") -> float:\n",
" \"\"\"\n",
" Assumes that activities is truncated to the current week, calculating the \n",
" difference between target mileage and actual mileage thus far this week\n",
"\n",
" :param training_week_with_coaching: instance TrainingWeekWithCoaching\n",
" :param activities: DataFrame of activities thus far this week\n",
" :return: The mileage delta as a float\n",
" \"\"\"\n",
" actual_mileage = activities['distance_in_miles'].sum()\n",
" weekly_target = sum(sess.distance for sess in training_week_with_coaching.training_week)\n",
" mileage_delta = weekly_target - actual_mileage\n",
"\n",
" return mileage_delta"
" ).drop('id', 'name', 'day_of_week', 'week_of_year', 'year', 'moving_time_in_minutes', 'start_date_local') \n",
" return [ActivitySummary(**row) for row in concise_activities_df.rows(named=True)]"
]
},
{
"cell_type": "code",
"execution_count": 68,
"execution_count": 47,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"athlete_id='98390356' token still valid until 2024-08-17 05:16:28+00:00\n"
"athlete_id='98390356' token still valid until 2024-08-17 22:38:15+00:00\n"
]
}
],
"source": [
"\n",
"athlete_id = os.environ[\"JAMIES_ATHLETE_ID\"]\n",
"strava_client = get_strava_client(athlete_id)\n",
"training_week_with_coaching = get_training_week_with_coaching(athlete_id)\n",
"activities = get_concise_activities(strava_client, num_weeks=1)"
"activities = get_activity_summaries(strava_client, num_weeks=1)"
]
},
{
"cell_type": "code",
"execution_count": 69,
"execution_count": 77,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div><style>\n",
".dataframe > thead > tr,\n",
".dataframe > tbody > tr {\n",
" text-align: right;\n",
" white-space: pre-wrap;\n",
"}\n",
"</style>\n",
"<small>shape: (2, 4)</small><table border=\"1\" class=\"dataframe\"><thead><tr><th>start_date_local</th><th>distance_in_miles</th><th>elevation_gain_in_feet</th><th>pace_minutes_per_mile</th></tr><tr><td>str</td><td>f64</td><td>f64</td><td>f64</td></tr></thead><tbody><tr><td>&quot;Monday, August 12, 2024 06:06 …</td><td>8.01</td><td>183.73</td><td>9.43</td></tr><tr><td>&quot;Tuesday, August 13, 2024 06:15…</td><td>4.01</td><td>52.49</td><td>10.64</td></tr></tbody></table></div>"
],
"text/plain": [
"shape: (2, 4)\n",
"┌──────────────────────────┬───────────────────┬────────────────────────┬───────────────────────┐\n",
"│ start_date_local ┆ distance_in_miles ┆ elevation_gain_in_feet ┆ pace_minutes_per_mile │\n",
"│ --- ┆ --- ┆ --- ┆ --- │\n",
"│ str ┆ f64 ┆ f64 ┆ f64 │\n",
"╞══════════════════════════╪═══════════════════╪════════════════════════╪═══════════════════════╡\n",
"│ Monday, August 12, 2024 ┆ 8.01 ┆ 183.73 ┆ 9.43 │\n",
"│ 06:06 … ┆ ┆ ┆ │\n",
"│ Tuesday, August 13, 2024 ┆ 4.01 ┆ 52.49 ┆ 10.64 │\n",
"│ 06:15… ┆ ┆ ┆ │\n",
"└──────────────────────────┴───────────────────┴────────────────────────┴───────────────────────┘"
]
},
"execution_count": 69,
"metadata": {},
"output_type": "execute_result"
}
],
"outputs": [],
"source": [
"activities"
"\n",
"class MidWeekAnalysis(BaseModel):\n",
" activities: list[ActivitySummary]\n",
" training_week: List[TrainingSession]\n",
" \n",
" @property\n",
" def training_week_future(self):\n",
" return self.training_week[get_weekday_num() + 1:]\n",
" \n",
" @property\n",
" def miles_ran(self):\n",
" return sum(activity.distance_in_miles for activity in self.activities)\n",
" \n",
" @property\n",
" def miles_target(self):\n",
" return sum(session.distance for session in self.training_week)\n",
" \n",
" @property\n",
" def miles_remaining(self):\n",
" return self.miles_target - self.miles_ran\n",
" \n",
" @property\n",
" def future_miles_planned(self):\n",
" return sum(session.distance for session in self.training_week_future)"
]
},
{
"cell_type": "code",
"execution_count": 80,
"metadata": {},
"outputs": [],
"source": [
"mid_week_analysis = MidWeekAnalysis(activities=activities, training_week=training_week_with_coaching.training_week)"
]
},
{
"cell_type": "code",
"execution_count": 94,
"metadata": {},
"outputs": [],
"source": [
"from src.llm import get_completion_json\n",
"from src.types.training_week import TrainingWeekWithPlanning\n",
"\n",
"client_preferences = \"A) Training for a marathon B) This will be my second marathon C) Prefer workouts on Wednesdays and long runs on Saturdays\"\n",
"sysmsg_base = f\"{COACH_ROLE}\\nYour client has included the following preferenced: {client_preferences}\\n\"\n",
"\n",
"msg = sysmsg_base + f\"\"\"\\nThe original plan for this week targeted {mid_week_analysis.miles_target} miles. Your client has run {mid_week_analysis.miles_ran} miles so far (and they have {mid_week_analysis.miles_remaining} miles left to run this week), but the plan for the rest of the week includes {mid_week_analysis.future_miles_planned} miles. Adjust the plan accordingly given the following information:\n",
"\n",
"Here is your client's progress so far this week:\n",
"{mid_week_analysis.activities}\n",
"\n",
"Here is the plan for the rest of the week:\n",
"{mid_week_analysis.training_week_future}\n",
"\n",
"What changes need to be made so that your client runs {mid_week_analysis.miles_remaining} more miles this week?\"\"\"\n",
"\n",
"response = get_completion_json(\n",
" message=msg,\n",
" response_model=TrainingWeekWithPlanning,\n",
" )"
]
},
{
Expand Down

0 comments on commit 0bbe641

Please sign in to comment.