DrishtiSharma commited on
Commit
7ef4406
ยท
verified ยท
1 Parent(s): 164020e

Upload 6 files

Browse files
Files changed (6) hide show
  1. agents.py +188 -0
  2. app.py +82 -0
  3. config.py +6 -0
  4. tools.py +30 -0
  5. user.png +0 -0
  6. workflow.py +37 -0
agents.py ADDED
@@ -0,0 +1,188 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import functools
2
+ from langchain.agents import AgentExecutor, create_openai_tools_agent
3
+ from langchain_core.messages import HumanMessage
4
+ from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
5
+ from langchain_openai import ChatOpenAI
6
+ from langchain.output_parsers.openai_functions import JsonOutputFunctionsParser
7
+ import tools
8
+ from tools import tools
9
+ import os
10
+ import config
11
+
12
+
13
+ os.environ["OPENAI_API_KEY"] = config.config("OPENAI_API_KEY")
14
+
15
+ # initializing the GPT-4 Turbo model with no temperature variation
16
+ llm = ChatOpenAI(temperature=0, model="gpt-4-turbo-preview")
17
+
18
+ def create_agents(llm:ChatOpenAI, tools:list, system_prompt:str)->AgentExecutor:
19
+ # creating a chat prompt template
20
+ prompt = ChatPromptTemplate.from_messages([
21
+ ('system', system_prompt),
22
+ MessagesPlaceholder(variable_name='messages'),
23
+ MessagesPlaceholder(variable_name="agent_scratchpad")
24
+ ])
25
+
26
+ # creating an agent with specified tools and prompting template
27
+ agent = create_openai_tools_agent(llm, tools, prompt)
28
+ executor = AgentExecutor(agent=agent, tools=tools)
29
+ return executor
30
+
31
+ # function to handle the agent invocation and return formatted state
32
+ def agent_node(state, agent, name):
33
+ result = agent.invoke(state)
34
+ return {"messages": [HumanMessage(content=result["output"], name=name)]}
35
+
36
+ # list of agents representing different coaching roles
37
+ members = ["nutritionist", "workout_coach", "mental_health_coach","sleep_coach","hydration_coach",
38
+ "posture_and_ergonomics_coach","injury_prevention_and_recovery_coach"]
39
+
40
+ # system prompt explaining the FIT.AI role and its tasks
41
+ system_prompt = (
42
+ """
43
+ TASK:
44
+ You are "FIT.AI", an intelligent chatbot that answers questions about fitness and overall health.
45
+ You also supervise and coordinate tasks among seven workers: {members}.
46
+ Based on the user's request, determine which worker should take the next action.
47
+ Each worker is responsible for executing specific tasks and reporting back their findings and progress.
48
+
49
+ Example session :
50
+
51
+ User question : Hello, help me with a fitness and diet plan.
52
+ Thought : I should first ask the user their daily routine and then
53
+ search the web for the most optimal fitness and diet plan first.
54
+ Action : Search the web for optimal results.
55
+ Pause : You will take some time to think
56
+ You then output : Please provide your daily routine so as to tailor the plan accordingly.
57
+ """
58
+ )
59
+
60
+ # options for routing the next step in the flow
61
+ options = ['FINISH'] + members
62
+
63
+ # function definition for routing the tasks to agents
64
+ function_def = {
65
+ "name": "route",
66
+ "description": "Select the next role.",
67
+ "parameters": {
68
+ "title": "routeSchema",
69
+ "type": "object",
70
+ "properties": {"next": {"title": "Next", "anyOf": [{"enum": options}]}},
71
+ "required": ["next"]
72
+ }
73
+ }
74
+
75
+ # creating the supervisor chain using the specified LLM and function definitions
76
+ prompt = ChatPromptTemplate.from_messages(
77
+ [
78
+ ("system", system_prompt),
79
+ MessagesPlaceholder(variable_name="messages"),
80
+ (
81
+ "system",
82
+ "Given the conversation above, who should act next?"
83
+ " Or should we FINISH? Select one of: {options}",
84
+ ),
85
+ ]).partial(options=str(options), members=", ".join(members))
86
+
87
+ supervisor_chain = (
88
+ prompt
89
+ | llm.bind_functions(functions=[function_def], function_call="route")
90
+ | JsonOutputFunctionsParser()
91
+ )
92
+
93
+ # creating agents for each coach role with specified prompts and tools
94
+ nutritionist_agent = create_agents(
95
+ llm,
96
+ tools,
97
+ """Your role is to act as a knowledgeable nutritionist. Provide practical dietary
98
+ advice and create meal plans. Research the latest nutritional information and trends,
99
+ and give personalized recommendations based on the user's needs and country of choice.
100
+ Utilize information from the workout coach to suggest a diet plan. Always mention any web/mobile applications for tracking
101
+ calorie intake and identify potential food allergies. If no applications are found,
102
+ provide useful tips. Respond in a friendly, informal tone."""
103
+ )
104
+
105
+ workout_coach_agent = create_agents(
106
+ llm,
107
+ tools,
108
+ """You are a workout coach. Based on the user's fitness goals and nutritionist's suggestions,
109
+ create tailored workout plans. Provide exercise routines, tips for proper form, and motivation.
110
+ Suggest home workout equipment along with online links to purchase them and useful fitness tracking applications or websites.
111
+ Respond in a friendly, informal tone, offering positive affirmations and practical
112
+ timelines for achieving goals."""
113
+ )
114
+
115
+ mental_health_coach_agent = create_agents(
116
+ llm,
117
+ tools,
118
+ """You are a mental health coach. Provide support and mindfulness strategies to improve
119
+ mental well-being taking into account the user's dietary and workout plans. Research techniques
120
+ and practices to help with mental health and offer insights into mental health disorders if queried.
121
+ Reccommend home tips based in the user's activity level.
122
+ Suggest useful apps for maintaining mental stability. Respond in a friendly, informal tone."""
123
+ )
124
+
125
+ sleep_coach_agent = create_agents(
126
+ llm,
127
+ tools,
128
+ """You are a sleep coach. Provide tips for better sleep hygiene, suggest tools and techniques
129
+ to improve sleep quality, and offer advice on optimizing sleep habits based on the
130
+ user's daily routine and age . Mention any web or mobile applications for tracking sleep
131
+ patterns and provide relaxation techniques. Respond in a friendly, informal tone."""
132
+ )
133
+
134
+ hydration_coach_agent = create_agents(
135
+ llm,
136
+ tools,
137
+ """You are a hydration coach. Help users maintain proper hydration levels by providing advice on water intake
138
+ and the importance of staying hydrated. Suggest tools and techniques for tracking water consumption and offer
139
+ tips for improving hydration habits based on the user's daily routine. Also, gives hydration advice, complementing the meal and workout plans results provided
140
+ by the nutritionist and workout coach. Always ask users to drink water based on the gender.
141
+ Respond in a friendly, informal tone."""
142
+ )
143
+
144
+ posture_and_ergonomics_coach_agent = create_agents(
145
+ llm,
146
+ tools,
147
+ """You are a posture and ergonomics coach. Provide guidance on maintaining good posture, especially for individuals
148
+ who spend long hours sitting, and recommend ergonomic adjustments depending on the workspace. Suggest tools and
149
+ techniques for tracking and improving posture. Respond in a friendly, informal tone."""
150
+ )
151
+
152
+ injury_prevention_and_recovery_coach_agent = create_agents(
153
+ llm,
154
+ tools,
155
+ """You are an injury prevention and recovery coach. Help users prevent injuries by providing exercises
156
+ and tips for proper form and recovery strategies if an injury occurs. If user is injured provide quick and
157
+ relevant solutions for the particular injury. Always reccommend seeking a doctor.
158
+ Suggest tools and techniques for tracking and managing recovery. Respond in a friendly, informal tone."""
159
+ )
160
+
161
+
162
+ nutritionist_node = functools.partial(
163
+ agent_node, agent=nutritionist_agent, name="nutritionist"
164
+ )
165
+
166
+ workout_coach_node = functools.partial(
167
+ agent_node, agent=workout_coach_agent, name="workout_coach"
168
+ )
169
+
170
+ mental_health_coach_node = functools.partial(
171
+ agent_node, agent=mental_health_coach_agent, name="mental_health_coach"
172
+ )
173
+
174
+ sleep_coach_node = functools.partial(
175
+ agent_node, agent=sleep_coach_agent, name="sleep_coach"
176
+ )
177
+
178
+ hydration_coach_node = functools.partial(
179
+ agent_node, agent=hydration_coach_agent, name="hydration_coach"
180
+ )
181
+
182
+ posture_and_ergonomics_coach_node = functools.partial(
183
+ agent_node, agent=posture_and_ergonomics_coach_agent, name="posture_and_ergonomics_coach"
184
+ )
185
+
186
+ injury_prevention_and_recovery_coach_node = functools.partial(
187
+ agent_node, agent=injury_prevention_and_recovery_coach_agent, name="injury_prevention_and_recovery_coach"
188
+ )
app.py ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from langchain_core.messages import HumanMessage
3
+ from config import *
4
+ from tools import tools
5
+ from agents import *
6
+ from workflow import create_workflow
7
+
8
+ graph = create_workflow()
9
+
10
+ def run_graph(input_message, history):
11
+ try:
12
+ # relevant fitness-related keywords to handle irrelevant user prompts
13
+ relevant_keywords = [
14
+ "workout", "training", "exercise", "cardio", "strength training", "hiit (high-intensity interval training)",
15
+ "flexibility", "yoga", "pilates", "aerobics", "crossfit", "bodybuilding", "endurance", "running",
16
+ "cycling", "swimming", "martial arts", "stretching", "warm-up", "cool-down",
17
+ "diet plan", "meal plan", "macronutrients", "micronutrients", "vitamins", "minerals", "protein",
18
+ "carbohydrates", "fats", "calories", "calorie", "daily", "nutrition", "supplements", "hydration", "weightloss",
19
+ "weight gain", "healthy eating","health", "fitness", "intermittent fasting", "keto diet", "vegan diet", "paleo diet",
20
+ "mediterranean diet", "gluten-free", "low-carb", "high-protein", "bmi", "calculate", "body mass index", 'calculator'
21
+ "mental health", "mindfulness", "meditation", "stress management", "anxiety relief", "depression",
22
+ "positive thinking", "motivation", "self-care", "relaxation", "sleep hygiene", "therapy",
23
+ "counseling", "cognitive-behavioral therapy (cbt)", "mood tracking", "mental", "emotional well-being",
24
+ "healthy lifestyle", "fitness goals", "health routines", "daily habits", "ergonomics",
25
+ "posture", "work-life balance", "workplace", "habit tracking", "goal setting", "personal growth",
26
+ "injury prevention", "recovery", "rehabilitation", "physical therapy", "sports injuries",
27
+ "pain management", "recovery techniques", "foam rolling", "stretching exercises",
28
+ "injury management", "injuries", "apps", "health tracking", "wearable technology", "equipment",
29
+ "home workouts", "gym routines", "outdoor activities", "sports", "wellness tips", "water", "adult", "adults"
30
+ "child", "children", "infant", "sleep", "habit", "habits", "routine", "loose", "weight", "fruits", "vegetables",
31
+ "chicken", "veg", "vegetarian", "non-veg", "non-vegetarian", "plant", "plant-based", "plant based", "fat", "resources",
32
+ "help", "cutting", "bulking", "link", "links", "website", "online", "websites", "peace", "mind", "equipments", "equipment",
33
+ "watch", "tracker", "watch", "band", "height", "injured", "quick", "remedy", "solution", "solutions", "pain", "male", "female"
34
+ ]
35
+
36
+ greetings=["hello", "hi", "how are you doing"]
37
+
38
+ # Check if the input message contains any relevant keywords
39
+ if any(keyword in input_message.lower() for keyword in relevant_keywords):
40
+ response = graph.invoke({
41
+ "messages": [HumanMessage(content=input_message)]
42
+ })
43
+ return response['messages'][1].content
44
+
45
+ elif any(keyword in input_message.lower() for keyword in greetings):
46
+ return "Hi there, I am FIT bot, your personal wellbeing coach "
47
+
48
+ else:
49
+ return "I'm here to assist with fitness, nutrition, mental health, and related topics. Please ask questions related to these areas."
50
+ except Exception as e:
51
+ return f"An error occurred while processing your request: {e}"
52
+
53
+
54
+
55
+ bot = gr.Chatbot(render=False,placeholder="<strong>Your Personal Assistant</strong><br>Ask Me Anything",
56
+ show_copy_button=True,
57
+ layout="bubble",
58
+ container=True,
59
+ label="FIT.AI",
60
+ show_label=True,
61
+ avatar_images=("user.png","bot.png"),
62
+ likeable=True)
63
+
64
+
65
+ demo = gr.ChatInterface(
66
+ fn=run_graph,
67
+ clear_btn="๐Ÿ—‘๏ธ Clear",
68
+ theme="soft",
69
+ undo_btn="Delete Previous",
70
+ autofocus=True,
71
+ textbox=gr.Textbox(placeholder="Ask away any fitness related questions", scale=7),
72
+ stop_btn="Stop",
73
+ show_progress="full",
74
+ description="<strong>An intelligent assistant for fitness, diet and mental health guidance.<strong>",
75
+ js="custom.js",
76
+ examples=["Provide health and fitness tips", "My daily Calorie intake",
77
+ "Better mental health","Best sleep habits","Water intake for a fully grown adult",
78
+ "Ergonomics in the workplace","Injuries Rehabilitation"],
79
+ chatbot=bot,
80
+ )
81
+
82
+ demo.launch(share=True)
config.py ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ import os
2
+ from decouple import config
3
+
4
+ # Set environment variables
5
+ os.environ["OPENAI_API_KEY"] = config("OPENAI_API_KEY")
6
+ os.environ["TAVILY_API_KEY"] = config("TAVILY_API_KEY")
tools.py ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import requests
2
+ from bs4 import BeautifulSoup
3
+ from langchain.tools import tool
4
+ from tavily import TavilyClient
5
+ import os
6
+
7
+ tavily_client = TavilyClient(api_key=os.getenv("TAVILY_API_KEY"))
8
+
9
+ # tool for processing web content
10
+ @tool("process_search_tool", return_direct=False)
11
+ def process_search_tool(url: str) -> str:
12
+ """Used to process content found on the internet."""
13
+ try:
14
+ response = requests.get(url=url)
15
+ soup = BeautifulSoup(response.content, "html.parser")
16
+ return soup.get_text()
17
+ except requests.exceptions.RequestException as e:
18
+ return f"Error processing the URL: {str(e)}"
19
+
20
+ # tool for internet searches
21
+ @tool("internet_search_tool", return_direct=False)
22
+ def internet_search_tool(query: str) -> str:
23
+ """Search user query on the internet using TavilyAPI."""
24
+ try:
25
+ response = tavily_client.qna_search(query=query, max_results=5)
26
+ return response if response else "No results found"
27
+ except requests.exceptions.HTTPError as e:
28
+ return f"HTTP Error: {str(e)}"
29
+
30
+ tools = [internet_search_tool, process_search_tool]
user.png ADDED
workflow.py ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import operator
2
+ from langchain_core.messages import BaseMessage
3
+ from langgraph.graph import StateGraph, END, START
4
+ from typing import TypedDict, Annotated, Sequence
5
+ from agents import supervisor_chain,nutritionist_node,workout_coach_node,mental_health_coach_node,members,sleep_coach_node,hydration_coach_node,posture_and_ergonomics_coach_node,injury_prevention_and_recovery_coach_node
6
+
7
+
8
+ # define the state structure for agents
9
+ class AgentState(TypedDict):
10
+ messages: Annotated[Sequence[BaseMessage], operator.add]
11
+ next: str
12
+
13
+ # function to create the workflow graph
14
+ def create_workflow():
15
+ workflow = StateGraph(AgentState)
16
+ workflow.add_node("supervisor", action=supervisor_chain) # addign nodes to the graph
17
+ workflow.add_node("nutritionist", action=nutritionist_node)
18
+ workflow.add_node("workout_coach", action=workout_coach_node)
19
+ workflow.add_node("mental_health_coach", action=mental_health_coach_node)
20
+ workflow.add_node("sleep_coach", action=sleep_coach_node)
21
+ workflow.add_node("hydration_coach", action=hydration_coach_node)
22
+ workflow.add_node("posture_and_ergonomics_coach", action=posture_and_ergonomics_coach_node)
23
+ workflow.add_node("injury_prevention_and_recovery_coach", action=injury_prevention_and_recovery_coach_node)
24
+
25
+ for member in members:
26
+ workflow.add_edge(start_key=member, end_key="supervisor")
27
+
28
+ conditional_map = {k: k for k in members}
29
+ conditional_map["FINISH"] = END
30
+
31
+
32
+ workflow.add_conditional_edges("supervisor", lambda x: x["next"], conditional_map)
33
+ workflow.add_edge(START, "supervisor")
34
+
35
+ graph= workflow.compile()
36
+
37
+ return graph