yhng2525's picture
Upload 4 files
3692b0f verified
import os
import gradio as gr
from dotenv import load_dotenv
from crewai import Agent, Task, Crew
# Firecrawl tool (from crewai tools package)
from crewai_tools import FirecrawlSearchTool
# -----------------------------
# Load environment variables
# -----------------------------
load_dotenv() # reads local .env (HF Spaces uses Secrets as env vars)
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY", "").strip()
FIRECRAWL_API_KEY = os.getenv("FIRECRAWL_API_KEY", "").strip()
def _validate_env():
missing = []
if not OPENAI_API_KEY:
missing.append("OPENAI_API_KEY")
if not FIRECRAWL_API_KEY:
missing.append("FIRECRAWL_API_KEY")
if missing:
return (
"❌ Missing environment variables: "
+ ", ".join(missing)
+ "\n\n"
"On Hugging Face Spaces:\n"
"Space → Settings → Secrets → add them as:\n"
"- OPENAI_API_KEY\n"
"- FIRECRAWL_API_KEY\n"
)
return None
# -----------------------------
# Build CrewAI setup
# -----------------------------
def build_crew():
"""
Builds tools, agents, tasks, and the crew.
"""
# Tool
travel_search_tool = FirecrawlSearchTool(api_key=FIRECRAWL_API_KEY)
# Agents
flights_agent = Agent(
role="Flight Search Specialist",
goal="Find round-trip flight options that balance price, duration, and convenience.",
backstory="Expert in comparing flights across airlines, booking sites, and schedules.",
tools=[travel_search_tool],
allow_delegation=False,
)
hotels_agent = Agent(
role="Hotel Research Specialist",
goal="Find good hotel options near destination city center, balancing price, reviews, and amenities.",
backstory="Knows how to compare hotels on different sites and summarize top picks.",
tools=[travel_search_tool],
allow_delegation=False,
)
info_agent = Agent(
role="Destination Info Specialist",
goal="Collect useful information about attractions, safety tips, and transport options in the destination.",
backstory="Experienced in giving local insights to travelers, focusing on practical tips.",
tools=[travel_search_tool],
allow_delegation=False,
)
consultant_agent = Agent(
role="Travel Consultant",
goal="Summarize all findings (flights, hotels, destination info) into a final travel plan.",
backstory="Expert travel planner who creates easy-to-follow itineraries.",
allow_delegation=False,
)
# Tasks
search_flights = Task(
description=(
"Search for round-trip flights from {origin} to {destination}, departing around {departure_date} "
"and returning around {return_date}, within budget {budget}."
),
expected_output="""
Top 3 round-trip flight options:
1) Airline/Provider: ..., Route: ..., Depart/Arrive: ..., Return: ..., Total duration: ..., Stops: ..., Price: ...
2) ...
3) ...
""",
agent=flights_agent,
)
search_hotels = Task(
description=(
"Find 3-4 hotel options in {destination}, near city center, within nightly budget {hotel_budget}. "
"Include hotel name, location, rating, and price per night."
),
expected_output="""
Top hotel options:
1) Name: ..., Area: ..., Rating: ..., Price/night: ..., Why it’s good: ...
2) ...
3) ...
4) ...
""",
agent=hotels_agent,
)
get_destination_info = Task(
description=(
"Gather key travel info for {destination}: top attractions, safety advice, and transport options "
"from airport to city center."
),
expected_output="""
Destination info:
- Attractions: ...
- Safety: ...
- Transport (airport -> city): ...
- Local tips: ...
""",
agent=info_agent,
)
create_summary = Task(
description="Summarize the results from flights, hotels, and destination info into a structured final travel plan.",
expected_output="""
Final Travel Plan:
✈️ Flights:
- ...
🏨 Hotels:
- ...
📍 Destination Tips:
- ...
""",
agent=consultant_agent,
)
crew = Crew(
agents=[flights_agent, hotels_agent, info_agent, consultant_agent],
tasks=[search_flights, search_hotels, get_destination_info, create_summary],
verbose=True,
)
return crew
def run_travel_planner(origin, destination, departure_date, return_date, trip_budget, hotel_budget):
env_error = _validate_env()
if env_error:
return env_error
# Some light cleanup
origin = (origin or "").strip()
destination = (destination or "").strip()
departure_date = (departure_date or "").strip()
return_date = (return_date or "").strip()
trip_budget = (trip_budget or "").strip()
hotel_budget = (hotel_budget or "").strip()
if not all([origin, destination, departure_date, return_date, trip_budget, hotel_budget]):
return "❗ Please fill in all fields before running."
try:
crew = build_crew()
result = crew.kickoff(
inputs={
"origin": origin,
"destination": destination,
"departure_date": departure_date,
"return_date": return_date,
"budget": trip_budget,
"hotel_budget": hotel_budget,
}
)
# CrewAI may return a string or richer object; stringify safely
return str(result)
except Exception as e:
return f"❌ Error while running the crew:\n{type(e).__name__}: {e}"
# -----------------------------
# Gradio UI
# -----------------------------
with gr.Blocks(title="CrewAI Multi-Agent Travel Planner") as demo:
gr.Markdown(
"# ✈️🏨 CrewAI Multi-Agent Travel Planner\n"
"Enter your trip details and run the multi-agent workflow (Flights + Hotels + Destination Info → Final Plan)."
)
with gr.Row():
origin = gr.Textbox(label="Origin", value="Singapore")
destination = gr.Textbox(label="Destination", value="Tokyo")
with gr.Row():
departure_date = gr.Textbox(label="Departure Date", value="Mar 15th, 2026")
return_date = gr.Textbox(label="Return Date", value="Mar 30th, 2026")
with gr.Row():
trip_budget = gr.Textbox(label="Trip Budget (total flights budget)", value="$2000")
hotel_budget = gr.Textbox(label="Hotel Budget (per night)", value="$150")
run_btn = gr.Button("Run Multi-Agent Planner", variant="primary")
output = gr.Textbox(label="Result", lines=22)
run_btn.click(
fn=run_travel_planner,
inputs=[origin, destination, departure_date, return_date, trip_budget, hotel_budget],
outputs=[output],
)
gr.Markdown(
"### 🔐 Secrets needed on Hugging Face\n"
"- `OPENAI_API_KEY`\n"
"- `FIRECRAWL_API_KEY`\n"
)
if __name__ == "__main__":
demo.launch()