Spaces:
Sleeping
Sleeping
import gradio as gr | |
from huggingface_hub import InferenceClient | |
import json | |
from typing import Dict, List, Tuple | |
# Hotel data | |
HOTELS = [ | |
{ | |
"name": "Azure Haven", | |
"pricingPerDay": 250, | |
"roomTypes": ["Single Room", "Double Room", "Suite"], | |
"description": "Azure Haven is a tranquil getaway offering breathtaking ocean views and luxurious amenities. Ideal for a peaceful escape or a romantic retreat." | |
}, | |
{ | |
"name": "Golden Sands Resort", | |
"pricingPerDay": 300, | |
"roomTypes": ["Standard Room", "Deluxe Room", "Family Suite"], | |
"description": "Nestled on a pristine beach, Golden Sands Resort is perfect for family vacations and adventure seekers. Enjoy watersports, beachside dining, and more." | |
}, | |
{ | |
"name": "Mountain Bliss Lodge", | |
"pricingPerDay": 220, | |
"roomTypes": ["Cabin", "Deluxe Cabin", "Mountain Suite"], | |
"description": "Mountain Bliss Lodge offers cozy cabins and stunning mountain views. A perfect destination for nature lovers and outdoor enthusiasts." | |
}, | |
{ | |
"name": "Urban Oasis Hotel", | |
"pricingPerDay": 280, | |
"roomTypes": ["Single Room", "Double Room", "Executive Suite"], | |
"description": "Located in the heart of the city, Urban Oasis Hotel combines modern luxury with convenient access to top attractions, dining, and entertainment." | |
}, | |
{ | |
"name": "Lakeside Retreat", | |
"pricingPerDay": 270, | |
"roomTypes": ["Single Room", "Double Room", "Lakeside Suite"], | |
"description": "Lakeside Retreat offers serene lakeside accommodations with a focus on relaxation and rejuvenation. Enjoy spa treatments, boating, and picturesque views." | |
} | |
] | |
# Cost constants | |
COST_FACTORS = { | |
"local_transport_per_day": { | |
"Budget Backpacking": 10, | |
"Cultural & Sightseeing": 20, | |
"Adventure & Outdoor": 25, | |
"Food & Culinary": 20, | |
"Relaxation & Wellness": 15, | |
"Luxury & High-End": 50, | |
"Family-Friendly": 30 | |
}, | |
"food_cost_per_day": { | |
"Budget Backpacking": 30, | |
"Cultural & Sightseeing": 50, | |
"Adventure & Outdoor": 45, | |
"Food & Culinary": 80, | |
"Relaxation & Wellness": 60, | |
"Luxury & High-End": 120, | |
"Family-Friendly": 70 | |
}, | |
"activities_cost_per_day": { | |
"Budget Backpacking": 20, | |
"Cultural & Sightseeing": 40, | |
"Adventure & Outdoor": 60, | |
"Food & Culinary": 45, | |
"Relaxation & Wellness": 80, | |
"Luxury & High-End": 150, | |
"Family-Friendly": 70 | |
} | |
} | |
client = InferenceClient("HuggingFaceH4/zephyr-7b-beta") | |
def calculate_flight_cost(origin: str, destination: str, budget: int) -> float: | |
"""Estimate flight cost based on budget and journey type.""" | |
# Basic estimation - can be enhanced with actual flight data API | |
if budget < 2000: | |
return budget * 0.3 # 30% of budget for budget trips | |
elif budget < 5000: | |
return budget * 0.35 # 35% for mid-range trips | |
else: | |
return budget * 0.4 # 40% for luxury trips | |
def calculate_daily_costs(holiday_type: str) -> Dict[str, float]: | |
"""Calculate daily costs based on holiday type.""" | |
return { | |
"local_transport": COST_FACTORS["local_transport_per_day"][holiday_type], | |
"food": COST_FACTORS["food_cost_per_day"][holiday_type], | |
"activities": COST_FACTORS["activities_cost_per_day"][holiday_type] | |
} | |
def get_suitable_hotels(budget_per_day: float, holiday_type: str) -> List[Dict]: | |
"""Get suitable hotels based on daily budget and holiday type.""" | |
max_hotel_budget = budget_per_day * 0.4 # 40% of daily budget for accommodation | |
suitable_hotels = [] | |
for hotel in HOTELS: | |
if hotel["pricingPerDay"] <= max_hotel_budget: | |
match_score = 0 | |
# Score hotels based on type match | |
if holiday_type == "Relaxation & Wellness" and ("Haven" in hotel["name"] or "Retreat" in hotel["name"]): | |
match_score += 2 | |
elif holiday_type == "Adventure & Outdoor" and ("Mountain" in hotel["name"] or "Sands" in hotel["name"]): | |
match_score += 2 | |
elif holiday_type == "Cultural & Sightseeing" and "Urban" in hotel["name"]: | |
match_score += 2 | |
elif holiday_type == "Family-Friendly" and "Family" in str(hotel["roomTypes"]): | |
match_score += 2 | |
suitable_hotels.append({"hotel": hotel, "match_score": match_score}) | |
# Sort by match score and then price | |
sorted_hotels = sorted(suitable_hotels, key=lambda x: (-x["match_score"], x["hotel"]["pricingPerDay"])) | |
return [hotel["hotel"] for hotel in sorted_hotels] | |
def calculate_total_costs( | |
origin: str, | |
destination: str, | |
budget: int, | |
num_days: int, | |
holiday_type: str, | |
selected_hotel: Dict | |
) -> Dict[str, float]: | |
"""Calculate detailed cost breakdown.""" | |
flight_cost = calculate_flight_cost(origin, destination, budget) | |
daily_costs = calculate_daily_costs(holiday_type) | |
accommodation_cost = selected_hotel["pricingPerDay"] * num_days | |
local_transport_cost = daily_costs["local_transport"] * num_days | |
food_cost = daily_costs["food"] * num_days | |
activities_cost = daily_costs["activities"] * num_days | |
total_cost = ( | |
flight_cost + | |
accommodation_cost + | |
local_transport_cost + | |
food_cost + | |
activities_cost | |
) | |
return { | |
"flight": flight_cost, | |
"accommodation": accommodation_cost, | |
"local_transport": local_transport_cost, | |
"food": food_cost, | |
"activities": activities_cost, | |
"total": total_cost, | |
"per_day": total_cost / num_days | |
} | |
def format_cost_breakdown(costs: Dict[str, float]) -> str: | |
"""Format cost breakdown for display.""" | |
return f"""Cost Breakdown: | |
- Flight: ${costs['flight']:,.2f} | |
- Accommodation: ${costs['accommodation']:,.2f} | |
- Local Transportation: ${costs['local_transport']:,.2f} | |
- Food & Dining: ${costs['food']:,.2f} | |
- Activities & Entertainment: ${costs['activities']:,.2f} | |
Total Cost: ${costs['total']:,.2f} | |
Average Daily Cost: ${costs['per_day']:,.2f}""" | |
def generate_itinerary( | |
destination: str, | |
origin: str, | |
budget: int, | |
num_days: int, | |
holiday_type: str, | |
system_message: str, | |
max_tokens: int, | |
temperature: float, | |
top_p: float, | |
) -> str: | |
# Calculate initial costs and get hotel recommendations | |
recommended_hotels = get_suitable_hotels(budget/num_days, holiday_type) | |
if not recommended_hotels: | |
return "Error: No suitable hotels found for your budget. Please increase your budget or reduce the number of days." | |
selected_hotel = recommended_hotels[0] | |
costs = calculate_total_costs(origin, destination, budget, num_days, holiday_type, selected_hotel) | |
if costs["total"] > budget: | |
return f"""Warning: The estimated total cost (${costs['total']:,.2f}) exceeds your budget (${budget:,.2f}). | |
Please consider: | |
1. Increasing your budget | |
2. Reducing the number of days | |
3. Choosing a more budget-friendly holiday type | |
4. Selecting different destinations | |
{format_cost_breakdown(costs)}""" | |
# Construct prompt with accurate cost information | |
prompt = f"""Create a detailed {num_days}-day travel itinerary for a trip: | |
From: {origin} | |
To: {destination} | |
Budget Breakdown: {format_cost_breakdown(costs)} | |
Holiday Type: {holiday_type} | |
Recommended Accommodation: | |
{selected_hotel['name']} (${selected_hotel['pricingPerDay']}/night) | |
{selected_hotel['description']} | |
Please provide: | |
1. Day-by-day itinerary with specific activities and timing | |
2. Daily budget allocation matching the cost breakdown above | |
3. Specific local transportation recommendations | |
4. Restaurant suggestions within the food budget (${costs['food']/num_days:.2f}/day) | |
5. Activity recommendations within the activities budget (${costs['activities']/num_days:.2f}/day) | |
Format as a clear day-by-day breakdown with budgets for each activity.""" | |
messages = [ | |
{"role": "system", "content": system_message}, | |
{"role": "user", "content": prompt} | |
] | |
response = "" | |
for message in client.chat_completion( | |
messages, | |
max_tokens=max_tokens, | |
stream=True, | |
temperature=temperature, | |
top_p=top_p, | |
): | |
token = message.choices[0].delta.content | |
response += token | |
yield response | |
# [Previous Gradio interface code remains the same, just update the button click handler to use the new generate_itinerary function] | |
# Create the Gradio interface | |
with gr.Blocks(theme=gr.themes.Soft()) as demo: | |
gr.Markdown("# 🌎 AI Travel Itinerary Generator ✈️") | |
gr.Markdown("Enter your travel details for a customized itinerary with accurate cost calculations!") | |
with gr.Row(): | |
with gr.Column(): | |
origin = gr.Textbox(label="Starting Location", placeholder="e.g., New York, USA") | |
destination = gr.Textbox(label="Destination", placeholder="e.g., Paris, France") | |
budget = gr.Slider(minimum=1000, maximum=15000, value=3000, step=100, label="Total Budget (USD)") | |
num_days = gr.Slider(minimum=1, maximum=14, value=3, step=1, label="Number of Days") | |
holiday_type = gr.Dropdown( | |
choices=list(COST_FACTORS["local_transport_per_day"].keys()), | |
label="Type of Holiday", | |
value="Cultural & Sightseeing" | |
) | |
with gr.Accordion("Advanced Settings", open=False): | |
system_message = gr.Textbox( | |
value="You are an experienced travel planner. Provide detailed itineraries that strictly adhere to the given budget constraints and cost breakdown.", | |
label="System Message", | |
lines=3 | |
) | |
max_tokens = gr.Slider(minimum=1, maximum=2048, value=1024, step=1, label="Max Tokens") | |
temperature = gr.Slider(minimum=0.1, maximum=1.0, value=0.7, step=0.1, label="Temperature") | |
top_p = gr.Slider(minimum=0.1, maximum=1.0, value=0.95, step=0.05, label="Top-p") | |
with gr.Row(): | |
generate_button = gr.Button("Generate Itinerary", variant="primary") | |
output = gr.Textbox(label="Your Custom Itinerary", lines=20, show_copy_button=True) | |
generate_button.click( | |
fn=generate_itinerary, | |
inputs=[ | |
destination, | |
origin, | |
budget, | |
num_days, | |
holiday_type, | |
system_message, | |
max_tokens, | |
temperature, | |
top_p, | |
], | |
outputs=output, | |
) | |
if __name__ == "__main__": | |
demo.launch() |