File size: 9,217 Bytes
1d2cc0e
 
 
 
 
 
 
 
31c0684
 
 
 
 
1d2cc0e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
import streamlit as st
from groq import Groq, APITimeoutError
import os

# Set up the page configuration
st.set_page_config(page_title="Fitness and Nutrition Coaching Chatbot", page_icon="🏋️‍♂️")

# Read the API key from environment variables or Streamlit secrets
# groq_api_key = st.secrets["GROQ_API_KEY"]

# client = Groq(api_key=groq_api_key, timeout=60)

groq_api_key = st.secrets["groq"]["api_key"]

client = Groq(api_key=groq_api_key, timeout=60)

# Session state for chats and editing
if "chats" not in st.session_state:
    # Start with one empty chat
    st.session_state.chats = [{"first_query": None, "history": []}]

if "current_chat_index" not in st.session_state:
    st.session_state.current_chat_index = 0  # Start with the first chat

if "editing_query_index" not in st.session_state:
    st.session_state.editing_query_index = None  # Initialize editing mode

# Helper function to truncate long text with ellipsis
def truncate_query(query, max_len=40):
    if len(query) > max_len:
        # Show only the first 'max_len' characters, followed by ellipsis
        return query[:max_len] + "..."
    return query

def handle_submit(user_input, is_edit=False):
    if user_input:
        current_chat = st.session_state.chats[st.session_state.current_chat_index]

        # Generate the response using Groq
        try:
            chat_completion = client.chat.completions.create(
                messages=[
                    {
                        "role": "system",
                        "content": """You are a knowledgeable, friendly, and professional Fitness and Nutrition Coach. Your goal is to provide evidence-based, practical, and personalized advice on fitness, nutrition, and overall health. Follow these guidelines:

Expertise: Offer accurate, science-backed information on topics like workout routines, diet plans, macronutrients (proteins, fats, carbs), micronutrients (vitamins, minerals), calorie intake, hydration, and healthy lifestyle habits.

Personalization: Tailor your responses to the user's goals (e.g., muscle gain, fat loss, endurance training, general health). Ask clarifying questions if needed to provide better advice. However, avoid giving medical advice or diagnosing conditions.

Encouragement: Motivate users with positive reinforcement and celebrate their progress, no matter how small. Help them stay consistent and focused on their goals.

Clarity: Explain complex concepts in simple, easy-to-understand language. Avoid jargon unless you define it clearly.

Safety: Always emphasize the importance of consulting a healthcare professional, registered dietitian, or certified trainer before making significant changes to diet, exercise, or lifestyle—especially for users with pre-existing conditions or specific health concerns.

Relevance: Stay focused on fitness and nutrition topics. If the user asks unrelated questions, politely guide the conversation back to health and wellness.

Balance: Promote a balanced approach to fitness and nutrition. Avoid extreme diets or workout regimens unless scientifically justified and safe.

Ethics: Do not promote unhealthy behaviors, fad diets, or unverified supplements. Always prioritize the user's long-term health and well-being.

Your role is to educate, inspire, and support users in achieving their fitness and nutrition goals while fostering a positive and sustainable approach to health."""
                    },
                    {
                        "role": "user",
                        "content": user_input,
                    }
                ],
                model="Llama3-8b-8192",  # Default model
            )
            response = chat_completion.choices[0].message.content

        except APITimeoutError as e:
            st.write("API Timeout Error! Try again sometimes.")
            st.stop()

        if is_edit:
            # Update existing query and response
            original_response = current_chat["history"][st.session_state.editing_query_index]["response"]
            current_chat["history"][st.session_state.editing_query_index]["query"] = user_input
            current_chat["history"][st.session_state.editing_query_index]["response"] = response
            current_chat["history"][st.session_state.editing_query_index]["original_response"] = original_response
            st.session_state.editing_query_index = None  # Reset edit mode
        else:
            # Add new query and response
            current_chat["history"].append(
                {"query": user_input, "response": response})

            # Set the first query and rerun to update the chat title
            if current_chat["first_query"] is None:
                current_chat["first_query"] = user_input
                st.rerun()

# Function to create a new chat
def create_new_chat():
    st.session_state.chats.append({"first_query": None, "history": []})
    st.session_state.current_chat_index = len(st.session_state.chats) - 1

# Function to switch to a chat
def switch_chat(index):
    st.session_state.current_chat_index = index

# Function to delete a chat
def delete_chat(index):
    del st.session_state.chats[index]
    if st.session_state.current_chat_index >= len(st.session_state.chats):
        st.session_state.current_chat_index = len(st.session_state.chats) - 1
    st.rerun()

# Function to delete a message
def delete_message(chat_index, message_index):
    del st.session_state.chats[chat_index]["history"][message_index]
    st.rerun()

# Sidebar for user instructions
st.sidebar.header("Instructions")
st.sidebar.markdown("""
Welcome to the Fitness and Nutrition Coaching AI Chatbot!
- Ask any fitness or nutrition-related questions.
- Get personalized advice and tips.
""")

# Sidebar buttons for creating new chats and displaying existing chats
st.sidebar.title("Chats")
if st.sidebar.button("Create New Chat", key="create_new_chat"):
    create_new_chat()

for i, chat in enumerate(st.session_state.chats):
    chat_title = chat["first_query"] if chat["first_query"] else f"Chat {i + 1}"
    truncated_chat_title = truncate_query(chat_title)
    col1, col2 = st.sidebar.columns([1, 1])
    with col1:
        if st.button(truncated_chat_title, key=f'chat_{i}', help="Switch to this chat"):
            switch_chat(i)
    with col2:
        if st.button("🗑️", key=f'delete_chat_{i}', help="Delete this chat"):
            delete_chat(i)

# Search input for search history
search_query = st.sidebar.text_input("Search History", "")

# Display search history in the sidebar
st.sidebar.title("Search History")
current_chat = st.session_state.chats[st.session_state.current_chat_index]
filtered_history = [entry for entry in current_chat["history"] if search_query.lower() in entry["query"].lower()]

for i, entry in enumerate(filtered_history):
    query = entry["query"]
    truncated_query = truncate_query(query)
    col1, col2 = st.sidebar.columns([1, 1])
    with col1:
        if st.button(truncated_query, key=f'history_{i}', help="Edit this query"):
            st.session_state.editing_query_index = i
            st.rerun()  # Trigger rerun to show the edit input
    with col2:
        if st.button("🗑️", key=f'delete_message_{i}', help="Delete this message"):
            delete_message(st.session_state.current_chat_index, i)

# Handle query input and edit mode
if st.session_state.editing_query_index is not None:
    editing_index = st.session_state.editing_query_index
    current_chat = st.session_state.chats[st.session_state.current_chat_index]
    if editing_index < len(current_chat["history"]):
        edited_query = st.text_input(
            "Edit your query:", value=current_chat["history"][editing_index]["query"], key=f'edit_query_{editing_index}')
        if st.button("Submit Edit", key=f'submit_edit_{editing_index}', help="Submit the edited query"):
            handle_submit(edited_query, is_edit=True)
            st.rerun()  # Rerun to update the view and exit edit mode
    else:
        st.session_state.editing_query_index = None  # Reset edit mode if index is out of range
else:
    user_input = st.chat_input("Ask something!")
    if user_input:
        handle_submit(user_input)

# Display the chat history
current_chat = st.session_state.chats[st.session_state.current_chat_index]["history"]

# Display chat history with edit options
for i, entry in enumerate(current_chat):
    if i == st.session_state.editing_query_index:
        continue  # Skip displaying the entry currently being edited

    # Display query and response
    with st.chat_message("user"):
        st.markdown(entry["query"])
    with st.chat_message("assistant"):
        st.markdown(entry["response"])
        if "original_response" in entry:
            st.markdown(f"**Original Response:** {entry['original_response']}")
    col1, col2 = st.columns([1, 1])
    with col1:
        if st.button("✏️", key=f'edit_{i}', help="Edit this query"):
            st.session_state.editing_query_index = i
            st.rerun()  # Trigger rerun to show the edit input
    with col2:
        if st.button("🗑️", key=f'delete_{i}', help="Delete this message"):
            delete_message(st.session_state.current_chat_index, i)