Spaces:
Sleeping
Sleeping
File size: 13,466 Bytes
de7999b f910d32 de7999b 3a7be99 de7999b 3a7be99 de7999b 3a7be99 de7999b 515dd18 de7999b 515dd18 de7999b |
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 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 |
import gradio as gr
import json
import os
import requests
import sys
from gradio.themes.utils import colors
# === Environment Setup ===
GROQ_API_KEY = os.getenv("GROQ_API_KEY")
if not GROQ_API_KEY:
print("β οΈ GROQ_API_KEY not set. Set it in Hugging Face Secrets.")
GROQ_API_KEY = "gsk-fake-for-testing" # Fallback for local testing
# === File Definitions for Persistence ===
HISTORY_FILE_TEMPLATE = "chat_history_{}.json"
USER_PROFILE_FILE = "user_profiles.json"
# --- Personalized History Management ---
def get_history_filename(user_id):
return HISTORY_FILE_TEMPLATE.format(user_id)
def save_history(history, user_id):
filename = get_history_filename(user_id)
with open(filename, 'w', encoding='utf-8') as f:
json.dump(history, f, ensure_ascii=False, indent=2)
def load_history(history, user_id):
filename = get_history_filename(user_id)
if os.path.exists(filename):
with open(filename, 'r', encoding='utf-8') as f:
return json.load(f)
return []
def clear_history_file(user_id):
if not isinstance(user_id, str): # Ensure user_id is a valid string
print(f"β Invalid user_id format: {user_id}")
user_id = "anonymous" # Fallback to prevent file errors
filename = get_history_filename(user_id) # Generates correct file name
print(f"π Clearing chat history for {user_id}, file: {filename}")
try:
with open(filename, 'w', encoding='utf-8') as f:
json.dump([], f, ensure_ascii=False, indent=2)
except Exception as e:
print(f"β Failed to clear chat history: {e}")
# === GROQ API Config ===
GROQ_API_URL = "https://api.groq.com/openai/v1/chat/completions"
MODEL_NAME = "llama3-8b-8192"
def query_groq(message, history):
if not GROQ_API_KEY or not GROQ_API_KEY.startswith("gsk_"):
print("π« GROQ_API_KEY is missing or invalid.", file=sys.stderr)
return "GROQ_API_KEY is missing or invalid. Please check Hugging Face Secrets."
headers = {
"Authorization": f"Bearer {GROQ_API_KEY}",
"Content-Type": "application/json"
}
payload = {
"model": MODEL_NAME,
"messages": history,
"temperature": 0.7
}
try:
response = requests.post(GROQ_API_URL, headers=headers, json=payload)
if response.status_code == 200:
return response.json()["choices"][0]["message"]["content"].strip()
else:
return f"β GROQ API Error {response.status_code}: {response.text}"
except Exception as e:
return f"β οΈ Failed to call GROQ API: {str(e)}"
# === Chatbot Response Function ===
def respond_chat(message, history, user_id, profile):
if history is None or not history:
history = load_history(user_id, profile) # Load user-specific past history
user_profile = update_user_profile(user_id, message)
system_message = {
"role": "system",
"content": f"You are a friendly travel assistant named Sky. User profile: {user_profile}"
}
# Include conversation history in API request
messages_for_api = history + [system_message, {"role": "user", "content": message}]
response_text = query_groq(message, messages_for_api)
history.append({"role": "user", "content": message})
history.append({"role": "assistant", "content": response_text})
save_history(history, user_id) # Save chat history after each interaction
return history, history # Persist chat history in Gradio UI
# === User Profile Management ===
def save_user_profile(user_id, profile_data):
profiles = load_user_profiles()
profiles[user_id] = profile_data
with open(USER_PROFILE_FILE, 'w', encoding='utf-8') as f:
json.dump(profiles, f, ensure_ascii=False, indent=2)
def load_user_profiles():
if os.path.exists(USER_PROFILE_FILE):
with open(USER_PROFILE_FILE, 'r', encoding='utf-8') as f:
return json.load(f)
return {}
def update_user_profile(user_id, user_msg):
profiles = load_user_profiles()
profile = profiles.get(user_id, {
"name": user_id,
"preferences": {},
"past_trips": [],
"travel_style": "Unknown"
})
keywords = ["beach", "mountain", "budget", "luxury", "adventure", "relaxation"]
for word in keywords:
if word in user_msg.lower():
profile["preferences"][word] = True
save_user_profile(user_id, profile)
return profile
# === Function to Update Preferences from Sidebar ===
def update_preferences(budget, language, destination, current_location, days, traveling_alone, diet):
user_id = "anonymous"
profiles = load_user_profiles()
profile = profiles.get(user_id, {
"name": user_id,
"preferences": {},
"past_trips": [],
"travel_style": "Unknown"
})
profile["budget"] = budget
profile["language"] = language
profile["destination"] = destination
profile["travel_days"] = days
profile["traveling_alone"] = traveling_alone
profile["current_location"] = current_location
profile["dietary_restrictions"] = diet
save_user_profile(user_id, profile)
return f"Travel preferences updated for user {user_id}."
# === Function to Clear Chat History ===
def clear_chat_history(user_id):
print(f"π Clearing chat history for user: {user_id}") # Debugging
clear_history_file(user_id) # Delete chat history file
return [], [] # Reset displayed chatbot conversation
# Function to generate a receipt for budget tab
def generate_receipt(expenses):
categories = {
"Food": 0,
"Transportation": 0,
"Accommodation": 0,
"Other": 0
}
total_cost = 0
for item in expenses:
category = item.get("category", "Other")
amount = item.get("amount", 0)
categories[category] += amount
total_cost += amount
receipt = "**Receipt:**\n\n"
for category, amount in categories.items():
receipt += f"{category}: ${amount}\n"
receipt += f"\n**Total Cost:** ${total_cost}\n"
return receipt
# Function to generate an itinerary based on number of days and solo travel
def create_itinerary(days, traveling_alone):
itinerary = "**Your Trip Itinerary:**\n\n"
for day in range(1, days + 1):
if traveling_alone == "Yes":
itinerary += f"Day {day}: Explore local attractions, enjoy a quiet meal, and relax.\n"
else:
itinerary += f"Day {day}: Group tour, shared meals, and adventure activities.\n"
return itinerary
#Theme stuff
travelwise_purple = colors.Color(
name="travelwise_purple",
c50="#f4f0f8",
c100="#e3d9ee",
c200="#c7b3dc",
c300="#ab8dca",
c400="#8f67b8",
c500="#947EB0", # main color
c600="#7e5f97",
c700="#5e476f",
c800="#3f2f47",
c900="#1f1820",
c950="#0f0c10"
)
light_neutral = colors.Color(
name="light_neutral",
c50="#ffffff",
c100="#f9f9f9",
c200="#f3f3f3",
c300="#eaeaea",
c400="#d9d9d9",
c500="#c0c0c0",
c600="#a7a7a7",
c700="#8e8e8e",
c800="#757575",
c900="#5c5c5c",
c950="#3c3c3c"
)
my_theme = gr.themes.Soft(
primary_hue= travelwise_purple,
neutral_hue= light_neutral, # optional
).set(
body_background_fill="#f1eeccff",
button_secondary_background_fill="#ABA8A6",
button_primary_text_color="#004643"
)
def generate_receipt(expenses):
categories = {
"Food": 0,
"Transportation": 0,
"Accommodation": 0,
"Other": 0
}
total_cost = 0
for item in expenses:
category = item.get("category", "Other")
amount = item.get("amount", 0)
# If a category is not predefined, accumulate it under 'Other'
if category not in categories:
categories["Other"] += amount
else:
categories[category] += amount
total_cost += amount
receipt = "**Receipt:**\n\n"
for cat, amt in categories.items():
receipt += f"{cat}: ${amt}\n"
receipt += f"\n**Total Cost:** ${total_cost}\n"
return receipt
def parse_expenses(user_input):
"""
Parses a string of expenses in the format:
"Food - 20, Transportation - 15, Accommodation - 100"
into a list of dictionaries required by generate_receipt.
"""
expenses = []
if not user_input.strip():
return "β οΈ Please enter some expenses."
entries = user_input.split(",")
for entry in entries:
try:
category, amount = entry.strip().split("-")
expenses.append({
"category": category.strip().title(),
"amount": float(amount.strip())
})
except ValueError:
return ("β οΈ Please ensure each expense is entered in the format: "
"Category - Amount (e.g., Food - 20, Transportation - 15)")
return generate_receipt(expenses)
# Gradio UI
# === Gradio UI Setup ===
# === Gradio UI Setup ===
with gr.Blocks(theme=my_theme) as demo:
chat_history = gr.State([]) # Maintain chat history across interactions
# πΉ Add `user_id_input` to store user identity across sessions πΉ
user_id_input = gr.Textbox(value="anonymous", interactive=False, visible=False)
with gr.Tabs():
with gr.TabItem("Chatbot"):
with gr.Row():
with gr.Column(scale=2):
gr.Image(
value="logo.png",
width=400,
show_label=False,
show_download_button=False,
container=False,
show_share_button=False,
interactive=False
)
gr.Markdown("Plan your perfect trip with ease! Travelwise helps you customize itineraries, explore budgeting options, and get personalized tipsβall based on your travel style and preferences. Whether you're going solo or in a group, relaxing or adventuring, the bot adapts to your needs in real time.")
with gr.Row():
with gr.Column(scale=2):
gr.Markdown("## Chatbot")
chatbot = gr.Chatbot(type="messages") # Display chat conversation
chat_input = gr.Textbox(label="Your Message") # User input field
chat_button = gr.Button("Send Message") # Send message button
clear_history_btn = gr.Button("Clear Chat History") # Reset conversation button
with gr.Column(scale=1):
gr.Markdown("### βοΈ Travel Preferences")
budget = gr.Textbox(label="π° Budget")
language = gr.Dropdown(
label="π Language",
choices=["English", "Korean", "Japanese", "French", "Spanish", "Chinese", "Italian"]
)
destination = gr.Textbox(label="πΊοΈ Travel Location")
current_location = gr.Textbox(label="π Current Location")
days = gr.Slider(minimum=1, maximum=200, step=1, label="π Days Traveling")
traveling_alone = gr.Dropdown(label="Traveling Alone?", choices=["Yes", "No"], value="No")
diet = gr.Textbox(label="π₯ Dietary Restrictions")
pref_button = gr.Button("Update Preferences")
pref_confirmation = gr.Textbox(label="Preference Update Confirmation")
with gr.TabItem("Budget"):
gr.Markdown("### Enter your expenses in the format: `Category - Amount`, separated by commas.")
expense_input = gr.Textbox(
placeholder="Food - 20, Transportation - 15, Accommodation - 100",
label="Expenses"
)
generate_button = gr.Button("Generate Receipt")
receipt_output = gr.Markdown()
generate_button.click(
fn=parse_expenses,
inputs=[expense_input],
outputs=[receipt_output]
)
with gr.TabItem("Itinerary"):
days_input = gr.Slider(1, 14, step=1, label="Number of Days")
solo_input = gr.Dropdown(["Yes", "No"], label="Traveling Alone?")
generate_itinerary_button = gr.Button("Generate Itinerary")
itinerary_output = gr.Markdown()
generate_itinerary_button.click(
fn=create_itinerary,
inputs=[days_input, solo_input],
outputs=[itinerary_output]
)
# πΉ Fix: Ensure user ID is passed correctly πΉ
chat_button.click(
fn=respond_chat,
inputs=[chat_input, chat_history, user_id_input], # β
Ensure correct user ID is used
outputs=[chatbot, chat_history]
)
# πΉ Fix: Correctly clear history by passing `user_id_input` πΉ
clear_history_btn.click(
fn=clear_chat_history,
inputs=[user_id_input], # β
Pass stored user ID correctly
outputs=[chatbot, chat_history]
)
# testing with token
# Bind the sidebar button for updating travel preferences.
pref_button.click(
fn=update_preferences,
inputs=[budget, language, destination, current_location, days, traveling_alone, diet],
outputs=pref_confirmation
)
demo.launch(debug=True)
|