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)