Leearg commited on
Commit
c8f45db
·
verified ·
1 Parent(s): d709c85

Upload travel_planner_chat.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. travel_planner_chat.py +167 -0
travel_planner_chat.py ADDED
@@ -0,0 +1,167 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ---
2
+ # jupyter:
3
+ # jupytext:
4
+ # text_representation:
5
+ # extension: .py
6
+ # format_name: percent
7
+ # format_version: '1.3'
8
+ # jupytext_version: 1.19.1
9
+ # kernelspec:
10
+ # display_name: .venv
11
+ # language: python
12
+ # name: python3
13
+ # ---
14
+
15
+ # %% [markdown]
16
+ # ## Agentic Travel Planner Chatbot
17
+ #
18
+ # - This application utilizes the **Gemini API** to function as a sophisticated travel planner.
19
+ # - Takes detailed traveler information and generating a comprehensive, strictly-formatted trip itinerary.
20
+ # - The user interface is built using Gradio, providing a convenient chat environment.
21
+ # - The final itinerary which the user is happy with, can be saved directly to a file via the model's tool-calling capability.
22
+ #
23
+ # ### Key Features
24
+ #
25
+ # 1. **Strict Output Generation:** Uses a detailed system prompt to force the LLM to provide 17 specific pieces of information for every itinerary.
26
+ # 2. **Contextual Planning:** Reads traveler details from a travel_summary.txt file to ensure the itinerary is tailored to specific interests.
27
+ # 3. **Gradio Chat UI:** Provides a simple, interactive chat interface for itinerary refinement.
28
+ # 4. **Tool-Calling for Persistence:** Implements a function tool that the LLM can call to save the final generated itinerary to a file once the user is satisfied.
29
+ #
30
+ # ### Prerequisites:
31
+ #
32
+ # 1. You need a Gemini API key. This key should be set as an environment variable named GEMINI_API_KEY.
33
+ # 2. Create summary.txt file. This file holds the context the model uses for planning. It is read once at startup.
34
+ #
35
+ # **Example travel_summary.txt as below:**
36
+ #
37
+ # - Vacation type: Family
38
+ # - Kids: One 4 year boy
39
+ # - Meals: Vegeterian
40
+ # - Interests: Walking, Hiking, Kids friendly walking trails, Kids friendly parks and activities, city exploration, beach, reading, pubs, cafes, historical places, Artistic and handmade items
41
+ #
42
+ # ### Sample User prompts
43
+ # - First prompt: We are going to Barcelona in December during Christmans for a week. Can you plan my trip?
44
+ # - Second prompt: I am happy with your response. Save this to a file called trip.txt.
45
+
46
+ # %%
47
+ from dotenv import load_dotenv
48
+ from openai import OpenAI
49
+ import os
50
+ import json
51
+ import gradio as gr
52
+
53
+
54
+ # %%
55
+ load_dotenv(override=True)
56
+
57
+ # %%
58
+ google_api_key = os.getenv('GOOGLE_API_KEY')
59
+
60
+ # %%
61
+ summary = ""
62
+ with open("/Users/Lee/projects/agents/1_foundations/me/travel_summary.txt", "r") as f:
63
+ summary = f.read()
64
+
65
+ # %%
66
+ system_prompt = f"""You operate as a Travel Planning Agent.
67
+ You are given specific traveller profiles and interests in the input variable {summary}.
68
+
69
+ MANDATORY REQUIREMENTS:
70
+
71
+ Utilization of Information: You MUST incorporate the information regarding the travellers and their interests, as provided in {summary}, into the planning of the itinerary.
72
+
73
+ Output Structure: Your response MUST contain a dedicated section for EACH of the following topics.
74
+ If information for a section (e.g., address, news) is not provided, you must state that the information is "Not Provided" or "Not Applicable" (e.g., if no address is given, state "Distance from Address: Not Provided").
75
+
76
+ MANDATORY CONTENT SECTIONS (MUST BE INCLUDED):
77
+
78
+ Airport Transfer Plan: Detail the journey from the airport to the accommodation. MUST include suggested booking sites for tickets.
79
+ Weather Forecast: Provide the expected weather conditions for the travel period.
80
+ Essential Packing List: List critical items the travellers must carry.
81
+ Places to Visit: List specific attractions. MUST include the distance from the accommodation address (if provided) and the best mode of transport from that address.
82
+ Advance Booking Attractions: List all attractions that require or are highly recommended for advance ticket booking.
83
+ Budget Travel Passes: Identify and detail any cheap travel passes or day passes available.
84
+ Souvenir Shopping: Specify where to purchase authentic artistic souvenirs.
85
+ Local Dining: Recommend the best restaurants in the area.
86
+ Train Schedule (Airport): Provide train timings and frequency for travel to and from the airport.
87
+ Train Ticket Information: Detail where and how to purchase train tickets.
88
+ Local Transit Discounts: Detail available local travel passes and discounts (excluding the airport train).
89
+ Cultural Reading Suggestions: Recommend fiction and non-fiction book titles related to the local culture.
90
+ Media Suggestions: Recommend movies and/or music relevant to the visited location.
91
+ Local Phrases: List common phrases or local slang for greetings and basic interactions.
92
+ Local Alcoholic Beverage: Suggest a characteristic local alcoholic drink.
93
+ Local News/Events: Report any recent or relevant local news or major events in the area.
94
+ Local Activities: Suggest activities recommended by residents of the area. """
95
+
96
+
97
+ # %%
98
+ def save_to_file(content, filename):
99
+ with open(filename, "w") as f:
100
+ f.write(content)
101
+ return {"recorded": "ok"}
102
+
103
+
104
+ # %%
105
+ save_to_file_json = {
106
+ "name": "save_to_file",
107
+ "description": "Call this ONLY after the user explicitly confirms they are happy with the content and want to save it. Requires the full content and the desired filename.",
108
+ "parameters": {
109
+ "type": "object",
110
+ "properties": {
111
+ "content": {"type": "string", "description": "The complete, final text (the LLM's response) that the user is satisfied with and wants to save."},
112
+ "filename": {"type": "string", "description": "The desired name of the file"}
113
+ }
114
+ }
115
+ }
116
+
117
+ # %%
118
+ tools = [{"type": "function", "function": save_to_file_json}]
119
+
120
+
121
+ # %%
122
+ def handle_tool_calls(tool_calls):
123
+ results = []
124
+ for tool_call in tool_calls:
125
+ tool_name = tool_call.function.name
126
+ arguments = json.loads(tool_call.function.arguments)
127
+ tool = globals().get(tool_name)
128
+ result = tool(**arguments) if tool else {}
129
+ results.append({"role": "tool","content": json.dumps(result),"tool_call_id": tool_call.id})
130
+
131
+ return results
132
+
133
+
134
+ # %%
135
+ def chat(message, history):
136
+ google = OpenAI(api_key=google_api_key, base_url="https://generativelanguage.googleapis.com/v1beta/openai/")
137
+ model_name = "gemini-2.0-flash"
138
+ messages = [{"role": "system", "content": system_prompt}] + history + [{"role": "user", "content": message}]
139
+ done = False
140
+ while not done:
141
+ response = google.chat.completions.create(model=model_name, messages=messages, tools=tools)
142
+ finish_reason = response.choices[0].finish_reason
143
+ print(finish_reason)
144
+ if finish_reason == "tool_calls":
145
+ message = response.choices[0].message
146
+ tool_calls = message.tool_calls
147
+ print(tool_calls)
148
+ result = handle_tool_calls(tool_calls)
149
+ messages.append(message)
150
+ messages.extend(result)
151
+ else:
152
+ done = True
153
+
154
+ return response.choices[0].message.content
155
+
156
+
157
+ # %%
158
+
159
+ gr.ChatInterface(
160
+ fn=chat,
161
+ title="Travel Planner",
162
+ type="messages",
163
+ save_history=True,
164
+ theme=gr.themes.Glass(),
165
+ description="Ask anything about the trip. EX. We are going to ... Can you plan my trip?").launch(share=True)
166
+
167
+ # %%