
ChatGPT Is My New Personal Trainer
I'm a bit of a fitness guy.
In college, I worked at a running store. I built relationships with people in the fitness industry and got my toes wet with coaching. I trained people for years to build speed and endurance and helped them get comfortable with running.
When I graduated college and started working in the tech industry, I continued to coach for a couple more years. Eventually, that tapered off as I focused on work. However, I ended up leading a strength-training group at my company for about 6 years until the pandemic hit.
Once we all started working from home, I built a mobile app to continue sending out workouts remotely so we could train virtually and do the same workouts together.
But again, that tapered off after a couple of years and now I just train myself. I have over a decade of experience building personalized training plans. But that's a lot of work, especially if it's just for me. I now have two kids, a small farm,work at a startup, and runReady, Set, Cloud where I write weekly blog posts and newsletters, and release a biweekly podcast.
I'm a bit busy.
But not working out isn't an option. It's part of mymorning routine.
Inepisode 2 of my podcast, I talk withRan Isenberg about platform engineering. Ran says part of the responsibilities of a platform engineering team is toreduce cognitive load from developers. That sounded exactly like what I needed with my fitness routine. I needed someone, or something, to make it easier on me when building my workout schedule.
ChatGPT is trending right now. Itconsolidates information from all over the internet to build a legitimate learning model. Why not use it to reduce cognitive load and build my workouts?
Wouldn't hurt to give it a try, right?
tl;dr - you can skip straightto the GitHub repo if you want to try it yourself!
Workout Variance
Every winter I go through a strength training phase. I lift weights five days a week and work a different muscle group every day. I cycle through arms, chest, back, shoulders, and legs. I also throw in a cardio-based warmup and cooldown into the mix and always try to get in some abs.
At first, I wanted to see how well ChatGPT could come up with a workout. So I went to the website and asked it to write me one.
This answer got me very excited. It was as good (if not better than) a workout I would have come up with, and it only took a few seconds to create exactly what I was looking for!
One thing I've learned about exercise is that variety is the spice of life. Not only does it help to keep you mentally fresh but changing up the workout routine can also have dramatic results physically bypreventing you from plateauing. With this in mind, I decided to add some variance to the query I sent ChatGPT.
I wanted the ability to have a workout randomly generated that was either a circuit, superset, or standard workout. On top of that, I wanted a workout that would randomly pick from the equipment I had available. One day I could be using kettlebells and the next I could be using barbells.
So I parameterized the workout types and available equipment and built a small randomizer that would pick and choose a workout type and subset of equipment every day. Ultimately my query to ChatGPT ended up looking like this:
let muscleGroups = ['chest', 'arm', 'shoulder', 'back', 'leg'];let workoutTypes = ['as a circuit', 'in supersets', 'as a standard workout'];let equipment = [{ type: 'barbells', threshold: .9 }, { type: 'dumbbells', threshold: .75 }, { type: 'kettlebells', threshold: .45 }];// Logic to randomly pick a muscle group, workout type, and set of equipment omitted for brevityconst request = `Create a ${muscleGroup} workout for strength training that uses ${joinWithAnd(equipmentToUse)} structured ${workoutType}.`;
For randomly selecting equipment, I had a random number generated between 0 and 1. If that random number was lower than the provided threshold, it was included in the workout.
With all this in place, I had a great way to build high-quality workouts that cycled through all my available equipment and gave me some much-needed variance.
Let's talk a bit about how it works.
Serverless Solution
Since Itend to do everything serverless, it made sense to build a solution powered by Lambda, DynamoDB, EventBridge, and Step Functions. These services give me an event-driven architecture that could scale up if I decided to turn this into a SaaS offering. For now, I'll settle with thefree-scale nature of the application where usage is so little I will never get charged for anything.
This solution is powered by two Step Functions:
- Generate Weekly Schedule - Randomizes which muscle groups, workout types, and equipment will be on each day and gets the workout from ChatGPT
- Daily Workout Notifier - Sends me an email in the evening with the workout details for the next day
Every Sunday the weekly scheduler will run, randomly decide what the workouts will be, ask ChatGPT to generate them, and save them to the DynamoDB. I then get an email so I know what to expect in the upcoming week.
Every weekday the workout notifier runs, "pops" a workout from DynamoDB (more on this in a sec), and sends the details in an email so I have it for the next day. All I have to do is open up the email in the morning and I'm good to go!
Data Model
I was recently educated byPete Naylor in his blog post aboutoptimizing DynamoDB secondary indexes. It was a real eye-opener that made me wonder if I've been doing things wrong for a long time.
A practice I am trying to shy away from is "GSI overloading" where you shove everything in a GSI and hope for the best. That feels (and is) confusing to maintain over time and doesn't provide any real benefits. So I came up with this data model for the workout schedule.
The partition key is the date and the sort key is eitherworkout
orschedule
to reflect which entity they represent. I have a GSI namedFutureSchedule
with hash key ofIsScheduledInFuture
and range key ofScheduledDate
.
This GSI is intended to besparse, meaning not everything is going to be projected into it. Only records that are scheduled in the future will show up, making it a breeze to figure out what the next workout is.
To get tomorrow's workout, I have a query in my state machine that looks like this:
"Get Next Workout": { "Type": "Task", "Parameters": { "TableName": "${TableName}", "IndexName": "FutureSchedule", "KeyConditionExpression": "#future = :future", "ExpressionAttributeNames": { "#future": "IsScheduledInFuture" }, "ExpressionAttributeValues": { ":future": { "S": "true" } }, "Limit": 1 }, "Resource": "${DynamodbQuery}", "Next": "Has Next Workout?"}
This pulls the first item (seeLimit: 1
) out of the GSI. All items in this index are sorted by the scheduled date, so the first item to be returned is the one for tomorrow!
Now, before you tell me this pattern creates a hot partition, I am aware that itcould. But it won't. The data is accessed once per day and is scoped to a single record. You start having issues with hot partitionswhen you cross 3000 RCUs or 1000 WCUs per second.
After loading the data in the state machine and sending out the email, I remove theIsScheduledInFuture
andScheduledDate
values from the workout record so it is removed from the GSI and doesn't return in a future query. Easy!
3rd Party APIs
This entire solution runs on some outstanding 3rd party APIs. First, of course, is theOpenAI API that enables us to communicate with ChatGPT. This API allows a decent amount of configuration to fine-tune the results you get back from the next-gen AI. You can adjust the level of creativity (I think of it as workout difficulty) with thetemperature
setting. The higher the temperature, the more creative of an answer you receive.
You also can limit the number oftokens in your response. The OpenAI API is not free. Depending on the AI model you use, you are charged anywhere from $0.0004 to $0.02 per 1000 tokens. Tokens are pieces of words and depending on how wordy your response is you could use anywhere from 30 to 1500 tokens in a single call. So we want to limit how much it's charging you per request by providing a value in themax_tokens
parameter.
The workout generator uses the most powerful AI model available via the API -Davinci. This model is close to (but not exactly) the one you use when you interact with ChatGPTon the website. This ends up being the most expensive part of the entire solution.
Since the OpenAI API is the most expensive part, I don't want to run unnecessary queries. We already know that "everything fails all the time," so when Ibuilt the state machines for retry I opted to useMomento to cache the ChatGPT responses. This enables me to omit an expensive query by implementing a read-aside (more like query-aside) cache.
First, I check my cache in Momento to see if I've queried OpenAI for a specific workout. If I have, great! I short-circuit the call and return the cached response. If I haven't, then I make the call to the OpenAI API. Momento has a50GB free tier per month so I pay nothing to use this serverless caching service.
Finally, I use theSendGrid API to send the workout email to myself. I could have usedAmazon SES, but I already had SendGrid fully functional and configured to send emails in response to an EventBridge event aspart of my newsletter platform. I just useputEvents
with a DetailType ofSend Email, pass thehtml
,subject
, andto
fields in the Detail, and boom - email sent. SendGrid also has agreat free tier that allows me to send up to 100 emails per day at no charge.
Summary
The world we live in today is amazing. I had an idea to offload workout creation to AI and two days later I was receiving automated emails with high-quality, high-variance workouts using equipment I have in my home gym.
I was able to move quickly by going serverless, but not so fastwhere I can't maintain it in the future. I've also left the door open for this to be a fully viable SaaS offering. It wouldn't be too much work to add Cognito into the mix, add configurable user settings in DynamoDB, and toss in EventBridge Schedules to dynamically send workouts at a configurable time to anyone who wants to sign up.
Software today is highly composable, whether you're sticking completely with your cloud vendor services, using 3rd party offerings like OpenAI, Momento, or Sendgrid, or even writing your own modules. With APIs, you can link together a wealth of services to build any crazy integration you think of.
I am thrilled to take "workout building" off my plate. It's something I've enjoyed for a long time but I'm ready to have someone else do it for me. This was a fun project to build and I hope you take it and run with it. It'sfully open-source and available for a PR!
Happy coding!
Top comments(4)

- LocationNovi Sad, Serbia
- Joined
Allen, this is absolutely awesome!

- LocationTexas
- WorkEcosystem Engineer at Momento
- Joined
Thank you very much!

- Joined
Love this idea Allen!

- LocationChennai,India
- EducationUniversity of Madras
- WorkSoftware Consultant
- Joined
Fantastic Allen...How you took a real problem and imparted Technology to it in a pretty logical fashion...Your thought process is pretty good...A lot of takeaways from this post!
For further actions, you may consider blocking this person and/orreporting abuse