Spaces:
Sleeping
Sleeping
| 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() | |