import streamlit as st from langchain.llms import HuggingFaceHub from langchain.memory import ConversationBufferMemory import os from datetime import datetime, timedelta from dotenv import load_dotenv # Print version information for debugging try: import langchain_community print(f"langchain_community version: {langchain_community.__version__}") except Exception as e: print(f"Error getting version info: {e}") # Load environment variables - MUST be at the top load_dotenv('.env') # Explicitly load from .env file # Configure page st.set_page_config( page_title="Tourism Chatbot", page_icon="🌍", layout="wide" ) # Title with better styling st.markdown("""

Tourism Assistant - مساعد السياحة

""", unsafe_allow_html=True) # Initialize session states if "memory" not in st.session_state: st.session_state.memory = ConversationBufferMemory( return_messages=True, memory_key="chat_history" ) if "messages" not in st.session_state: st.session_state.messages = [] if "last_request" not in st.session_state: st.session_state.last_request = datetime.now() - timedelta(seconds=10) # Language selector language = st.selectbox( "Choose Language / اختر اللغة", ["English", "العربية"], key="lang_select" ) # Get token from environment token = os.environ.get("HUGGINGFACEHUB_API_TOKEN") # For development, allow manual token entry if not found in environment if not token: st.warning("API token not found in environment variables.") token = st.text_input("Enter your Hugging Face API token:", type="password") if not token: st.error("Token is required to proceed.") st.stop() # Enhanced model configuration model_config = { "English": { "repo_id": "google/flan-t5-base", # Using a smaller model for testing "params": { "temperature": 0.7, "max_length": 512 } }, "العربية": { "repo_id": "aubmindlab/aragpt2-medium", # Using a smaller model for testing "params": { "temperature": 0.6, "max_length": 1024 } } } # Initialize the language model with enhanced error handling try: # Simple initialization - let the library handle the token from env vars llm = HuggingFaceHub( repo_id=model_config[language]["repo_id"], model_kwargs=model_config[language]["params"] ) conversation = ConversationChain( llm=llm, memory=st.session_state.memory, verbose=False ) st.success("Model connected successfully!") except Exception as e: error_msg = str(e) st.error(f"Error initializing model: {error_msg}") if "token" in error_msg.lower() or "api" in error_msg.lower(): st.info(""" Make sure the token is set correctly: 1. Create a Hugging Face account and get a token 2. Set it as an environment variable: `setx HUGGINGFACEHUB_API_TOKEN "your_token"` 3. Restart your terminal after setting the environment variable """) st.stop() # Display chat history with improved formatting for message in st.session_state.messages: avatar = "🧑" if message["role"] == "user" else "🌍" with st.chat_message(message["role"], avatar=avatar): if language == "العربية": st.markdown(f"
{message['content']}
", unsafe_allow_html=True) else: st.markdown(message["content"]) # Enhanced rate limiting if (datetime.now() - st.session_state.last_request).seconds < 3: st.warning("Please wait a moment before sending another message." if language == "English" else "الرجاء الانتظار قليلاً قبل إرسال رسالة أخرى") st.stop() # User input with better placeholder handling prompt_placeholder = { "English": "Ask about destinations, culture, or safety tips...", "العربية": "اسأل عن الوجهات، الثقافة، أو نصائح السلامة..." } prompt = st.chat_input(prompt_placeholder[language]) if prompt: st.session_state.last_request = datetime.now() st.session_state.messages.append({"role": "user", "content": prompt}) with st.chat_message("user", avatar="🧑"): st.markdown(prompt) with st.chat_message("assistant", avatar="🌍"): with st.spinner("Generating response..." if language == "English" else "جارٍ تحضير الرد..."): try: # Enhanced prompt engineering if language == "English": full_prompt = """You are an expert tourism assistant specializing in: - Detailed travel destination information - Cultural norms and etiquette - Safety recommendations - Local transportation options - Authentic dining experiences Question: {prompt} Answer in clear, detailed points:""".format(prompt=prompt) else: full_prompt = """أنت مساعد سياحي خبير متخصص في: - معلومات مفصلة عن الوجهات السياحية - الأعراف الثقافية وآداب السلوك - توصيات السلامة - خيارات النقل المحلي - تجارب تناول الطعام الأصيلة السؤال: {prompt} الجواب بنقاط واضحة ومفصلة:""".format(prompt=prompt) response = conversation.predict(input=full_prompt) # Post-process response cleaned_response = response.strip() if language == "العربية": cleaned_response = f"
{cleaned_response}
" st.markdown(cleaned_response, unsafe_allow_html=True) st.session_state.messages.append({"role": "assistant", "content": cleaned_response}) except Exception as e: error_response = { "English": f"Sorry, I encountered an error: {str(e)}. Please try again later.", "العربية": f"عذرًا، حدث خطأ: {str(e)}. يرجى المحاولة مرة أخرى لاحقًا." } st.error(error_response[language]) st.session_state.messages.append({ "role": "assistant", "content": error_response[language] }) # Sidebar with deployment-ready information with st.sidebar: st.header("ℹ️ " + ("About" if language == "English" else "حول")) about_text = { "English": """ **Tourism Expert Chatbot** • Provides detailed travel information • Offers cultural insights • Available in English/Arabic • Remembers conversation history """, "العربية": """ **مساعد سياحي خبير** • يقدم معلومات سفر مفصلة • يوفر رؤى ثقافية • متاح باللغتين الإنجليزية والعربية • يحفظ تاريخ المحادثة """ } st.markdown(about_text[language]) # Add reset button to clear conversation if st.button("Reset Conversation" if language == "English" else "إعادة ضبط المحادثة"): st.session_state.messages = [] st.session_state.memory.clear() st.experimental_rerun() # Add a manual token entry option in sidebar for easy updating st.subheader("API Configuration") new_token = st.text_input("Update API Token:", type="password") if st.button("Save Token"): os.environ["HUGGINGFACEHUB_API_TOKEN"] = new_token st.success("Token updated! Restart the app to apply.")