Many individuals hit the gym with passion and believe they are on the right path to achieving their fitness goals. But the results aren’t there due to poor diet planning and a lack of direction. Hiring a personal trainer along with an expensive gym stack isn’t always an option. That is why I have created this blog post to show you how to build your fitness coach using the power of LangChain. With this, you can now get workout and diet advice customized to your goals with minimal cost. Let’s get started with taking some amazing tech and turning it into your fitness co-pilot!
Langchain enables you to do much more when building advanced AI applications by combining large language models (LLMs) with tools, data sources, and memory. Instead of invoking the LLM with a plain text prompt, you can create agents that invoke functions, query information, and manage conversations with state. For a fitness coach, Langchain allows you to combine LLM intelligence with custom logic – for example, create workout suggestions, track progress, and get health data – so you can be a smarter interactive coach without having to figure that all out yourself.
To create your fitness coach using LangChain, you’ll need:
That’s all, you are now ready to get started.
In this section, I will demonstrate how to make your fitness coach using a Langchain agent. Ensure you have everything prepared according to the prerequisites. I will walk you through the step-by-step process of building the solution and explain the role each step plays in achieving the outcome.
FitCoach AI is a conversational fitness coach that collects user data consistently and generates personalized workout and diet plans using LangChain agents with OpenAI.
To install all the libraries required for building the fitness agent, run the following command in your command line:
pip install gradio langchain openai serper-dev python-doten
Once all the dependencies are in place, we’d start by importing all the relevant modules for the task:
import os
import gradio as gr
import traceback
import datetime
from typing import List, Tuple, Optional
from langchain_openai import ChatOpenAI
from langchain.memory import ConversationBufferMemory
from langchain.agents import initialize_agent, AgentType
from langchain.tools import BaseTool
import json
import requests
import dotenv
# Load environment variables
dotenv.load_dotenv()
Functionality: Provides the ability to have real-time web search capabilities for up-to-date fitness/nutrition information.
Main features:
# ----------- SERPER SEARCH TOOL ------------
class SerperSearchTool(BaseTool):
name: str = "search_web"
description: str = "Searches the web for real-time information and returns structured results"
def _run(self, query: str) -> str:
"""Search the web using Serper API"""
try:
api_key = os.getenv("SERPER_API_KEY")
if not api_key:
return "Error: SERPER_API_KEY not found in environment variables"
url = "https://google.serper.dev/search"
payload = json.dumps({"q": query})
headers = {
'X-API-KEY': api_key,
'Content-Type': 'application/json'
}
response = requests.post(url, headers=headers, data=payload, timeout=10)
response.raise_for_status()
search_results = response.json()
# Extract and format organic results
results = []
if 'organic' in search_results:
for item in search_results['organic'][:5]: # Limit to top 5 results
results.append({
"title": item.get('title', ''),
"link": item.get('link', ''),
"snippet": item.get('snippet', '')
})
# Format results in a readable way
if results:
formatted_results = "Search Results:\n\n"
for i, result in enumerate(results, 1):
formatted_results += f"{i}. {result['title']}\n"
formatted_results += f" {result['snippet']}\n"
formatted_results += f" URL: {result['link']}\n\n"
return formatted_results
else:
return "No search results found."
except requests.exceptions.RequestException as e:
return f"Error performing search - Network issue: {str(e)}"
except Exception as e:
return f"Error performing search: {str(e)}"
async def _arun(self, query: str) -> str:
"""Async version of search"""
return self._run(query)
Functionality: Get all necessary information before creating any fitness plans
Required Data Fields (in order):
Fitness goal (weight loss, muscle gain, etc.)
Age (in range 10-100 validation)
Gender (male/female/other)
Weight (in units, - kg/lbs)
Height (in cm or feet/inches)
Activity Level (5 predefined levels)
Diet Preferences (vegetarian, vegan, etc.)
Diet Restrictions/allergy
Workout-Preferencing & limitations
Main Features:
# ----------- USER DATA TRACKER CLASS ------------
class UserDataTracker:
def __init__(self):
self.data = {}
# Define required fields with their validation functions and question prompts
self.required_fields = {
'fitness_goal': {
'question': "What is your primary fitness goal? (e.g., weight loss, muscle gain, general fitness)",
'validate': self._validate_fitness_goal
},
'age': {
'question': "How old are you? (Must be between 10-100)",
'validate': self._validate_age
},
'gender': {
'question': "What is your gender? (male/female/other)",
'validate': self._validate_gender
},
'weight': {
'question': "What is your current weight? (e.g., 150 lbs or 68 kg)",
'validate': self._validate_weight
},
'height': {
'question': "What is your height? (e.g., 5'10\" or 178 cm)",
'validate': self._validate_height
},
'activity_level': {
'question': "What is your activity level? (sedentary, lightly active, moderately active, very active, extremely active)",
'validate': self._validate_activity_level
},
'dietary_preferences': {
'question': "Do you follow any specific diet? (e.g., vegetarian, vegan, keto, none)",
'validate': self._validate_dietary_preferences
},
'dietary_restrictions': {
'question': "Any food allergies or dietary restrictions? (e.g., nuts, dairy, gluten, none)",
'validate': self._validate_dietary_restrictions
},
'workout_preferences': {
'question': "What are your workout preferences? (e.g., gym, home workouts, equipment available, any injuries?)",
'validate': self._validate_workout_preferences
},
}
self.current_step = 0
Agent Initialization:
The initialize_fitcoach_agent
function configures FitCoach, a Langchain conversational agent that serves as a virtual fitness and nutrition coach. It connects to the language model GPT-4o-mini, is potentially augmented by web search tools, and keeps track of conversation memory for context. The agent follows a stringent, rule-based dialogue continuity: it asks users specific questions one at a time to extract all important information regarding fitness goals, age, body metrics, food habits, and medical history, among others. Only after all you needed to know has been gathered and confirmed, the agent will commit to not generating any fitness or diet plans. This way, the agent allows for the safe, accurate, and personalized instructions that users want in an agent. Once all the necessary information has been gathered, FitCoach generates comprehensive workout routines and meal plans based on the user, while offering an interactive and engaging coaching plan.
# ----------- LANGCHAIN AGENT SETUP ------------
def initialize_fitcoach_agent():
"""Initialize the FitCoach agent with error handling"""
try:
# Check for OpenAI API key
openai_key = os.getenv("OPENAI_API_KEY")
if not openai_key:
raise ValueError("OPENAI_API_KEY not found in environment variables")
# Initialize the language model with correct model name
llm = ChatOpenAI(
model="gpt-4o-mini",
temperature=0.3,
openai_api_key=openai_key
)
# Initialize tools
tools = []
try:
if os.getenv("SERPER_API_KEY"):
search_tool = SerperSearchTool()
tools.append(search_tool)
print("✅ Search tool initialized successfully")
else:
print("⚠️ SERPER_API_KEY not found - search functionality will be limited")
except Exception as e:
print(f"⚠️ Could not initialize search tool: {e}")
# Initialize memory
memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)
----------- GRADIO CHATBOT LOGIC ------------
def is_plan_content(text: str) -> bool:
"""Check if the text contains a fitness plan with detailed content"""
if not text or len(text.strip()) < 100: # Too short to be a complete plan
return False
# Check for common plan indicators
plan_indicators = [
'workout plan', 'exercise routine', 'training program',
'meal plan', 'nutrition plan', 'diet plan', 'weekly schedule',
'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday',
'sets x reps', 'rest between sets', 'warm up', 'cool down',
'day 1', 'day 2', 'day 3', 'day 4', 'day 5', 'day 6', 'day 7',
'breakfast', 'lunch', 'dinner', 'snacks', 'meals', 'nutrition',
'exercise', 'workout', 'training', 'routine', 'program', 'plan'
]
# Check for multiple indicators to reduce false positives
text_lower = text.lower()
matching_indicators = [ind for ind in plan_indicators if ind in text_lower]
# Require at least 3 matching indicators to consider it a plan
return len(matching_indicators) >= 3
Note: I have shown only parts of the code in the article. My full code is available here.
When it comes to the user interface, you could use solutions like Streamlit or Gradio to keep it simple. I used Gradio since it allows me to create a polished web app with a custom design, automatic updates, and a quick, responsive interface that suits health and fitness applications. Click here to view the source code.
When it’s all said and done, AI isn’t all about tech; it’s about the inner workings of how to leverage technology as a power to improve our everyday lives! Whether it be to get in shape, eat well, or stay motivated, designing your own unique personal fitness coach is a perfect example of how AI can support and motivate, yet still keep us accountable for our actions to meet our goals. And the best part is you don’t have to be a tech wizard to start building your application! There are a number of tools like LangChain for development, OpenAI for AI capabilities, and Gradio for deploying your smart application, just to mention a few, that can help anyone build smart and unique applications for themselves. The future of fitness, as well as many other areas of life, is available to us!