-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathdemo.py
317 lines (276 loc) · 11.4 KB
/
demo.py
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
import streamlit as st
from taskflowai import Agent, OpenrouterModels, Task, AmadeusTools, OpenaiModels, WikipediaTools, WebTools, set_verbosity
import os
from dotenv import load_dotenv
import re
# Must be the first Streamlit command
st.set_page_config(
page_title="Travel Planning Assistant",
layout="wide",
initial_sidebar_state="collapsed"
)
# Set verbosity for debugging purposes
set_verbosity(True)
# Load environment variables
load_dotenv()
# First, simplify the CSS by removing the white backgrounds and fixing contrast
st.markdown("""
<style>
/* Container styling */
.block-container {
padding: 1rem;
max-width: 960px;
margin: 0 auto;
}
/* Section styling */
.section-header {
margin: 1.5rem 0 1rem;
padding: 0.5rem;
background-color: #1e3a8a;
color: white;
border-radius: 0.3rem;
}
/* Content sections */
.content-section {
padding: 1.5rem;
border-radius: 0.5rem;
margin-bottom: 1.5rem;
border: 1px solid #e5e7eb;
background-color: #1e293b;
color: white;
}
/* Form styling */
.stTextInput {
margin-bottom: 0.5rem;
}
/* Button styling */
.stButton button {
margin: 1rem 0;
}
/* Message styling */
.stSuccess, .stError, .stWarning {
padding: 0.75rem;
border-radius: 0.3rem;
margin: 1rem 0;
}
</style>
""", unsafe_allow_html=True)
# Validate required API keys
required_keys = [
"WEATHER_API_KEY",
"SERPER_API_KEY",
"AMADEUS_API_KEY",
"AMADEUS_API_SECRET",
"GROQ_API_KEY",
"GEMINI_API_KEY"
"OPENAI_API_KEY"
]
# Check for missing keys
missing_keys = [key for key in required_keys if not os.getenv(key)]
if missing_keys:
raise ValueError(f"Missing required API keys: {', '.join(missing_keys)}")
# Define agents
web_research_agent = Agent(
role="Web Research Agent",
goal="Research destinations and find relevant images",
attributes="diligent, thorough, comprehensive, visual-focused",
llm=OpenaiModels.gpt_3_5_turbo,
tools=[WebTools.serper_search, WikipediaTools.search_articles, WikipediaTools.search_images]
)
travel_agent = Agent(
role="Travel Agent",
goal="Assist travelers with their queries",
attributes="friendly, hardworking, and detailed in reporting back to users",
llm=OpenaiModels.gpt_3_5_turbo,
tools=[AmadeusTools.search_flights, WebTools.get_weather_data]
)
reporter_agent = Agent(
role="Travel Report Agent",
goal="Write comprehensive travel reports with visual elements",
attributes="friendly, hardworking, visual-oriented, and detailed in reporting",
llm=OpenaiModels.gpt_3_5_turbo
)
# Then, simplify the image formatting function to preserve markdown
def format_markdown_images(markdown_text):
"""
Keep markdown image syntax intact and just ensure URLs are properly formatted
"""
import re
# Only process markdown images without converting to HTML
img_pattern = r'!\[(.*?)\]\((.*?)\)'
def fix_url(match):
alt_text, url = match.groups()
url = url.strip()
if not url.startswith(('http://', 'https://')):
url = f"https:{url}" if url.startswith('//') else f"https://{url}"
return f'![{alt_text}]({url})'
return re.sub(img_pattern, fix_url, markdown_text)
def research_destination(destination, interests):
"""Research destination with enhanced image handling"""
instruction = (
f"Create a comprehensive report about {destination} with the following:\n"
f"1. Use Wikipedia tools to find and include 2-3 high-quality images of key attractions\n"
f"2. Ensure images are full URLs starting with http:// or https://\n"
f"3. Format images as: ![Description](https://full-image-url)\n"
f"4. Include a brief caption for each image\n"
f"5. Research attractions and activities related to: {interests}\n"
f"6. Organize the report with proper headings and sections\n"
f"7. Place images naturally throughout the content where relevant\n"
f"8. Include practical visitor information\n"
f"Format the entire response in clean markdown"
)
return Task.create(
agent=web_research_agent,
context=f"User Destination: {destination}\nUser Interests: {interests}",
instruction=instruction
)
def research_events(destination, dates, interests):
"""Research events with enhanced image handling"""
instruction = (
f"Research events in {destination} during {dates} that match these interests: {interests}.\n\n"
f"For each event, include:\n"
f"- Event name\n"
f"- Date and time\n"
f"- Venue/location\n"
f"- Ticket information (if applicable)\n"
f"- A short description of the event\n"
f"- Format event images as: ![Event Name](https://full-image-url)\n"
f"- Format images as: ![Description](https://full-image-url)\n"
f"- Ensure images are full URLs starting with http:// or https://\n"
f"- Information is accurate and up-to-date\n"
f"- Place images naturally throughout the content where relevant\n"
f"- Format the entire response in clean markdown"
)
return Task.create(
agent=web_research_agent,
context=f"Destination: {destination}\nDates: {dates}\nInterests: {interests}",
instruction=instruction
)
def research_weather(destination, dates):
"""Research weather information"""
return Task.create(
agent=travel_agent,
context=f"Destination: {destination}\nDates: {dates}",
instruction=(
"Provide detailed weather information including:\n"
"1. Temperature ranges\n"
"2. Precipitation chances\n"
"3. General weather patterns\n"
"4. Recommended clothing/gear"
)
)
def search_flights(current_location, destination, dates):
"""Search flight options"""
return Task.create(
agent=travel_agent,
context=f"Flights from {current_location} to {destination} on {dates}",
instruction="Find top 3 affordable and convenient flight options and provide concise bullet-point information"
)
def write_travel_report(destination_report, events_report, weather_report, flight_report):
"""Create final travel report"""
instruction = (
"Create a comprehensive travel report that:\n"
"1. Maintains all images from the destination and events reports\n"
"2. Organizes information in a clear, logical structure\n"
"3. Keeps all markdown formatting intact\n"
"4. Ensures images are properly displayed with captions\n"
"5. Includes all key information from each section"
)
return Task.create(
agent=reporter_agent,
context=f"Destination Report: {destination_report}\n\n"
f"Events Report: {events_report}\n\n"
f"Weather Report: {weather_report}\n\n"
f"Flight Report: {flight_report}",
instruction=instruction
)
def main():
st.title("✈️ Travel Planning Assistant")
with st.container():
st.subheader("📝 Trip Details")
col1, col2 = st.columns(2)
with col1:
current_location = st.text_input(
"Departure City",
placeholder="Enter your starting point"
)
destination = st.text_input(
"Destination City",
placeholder="Enter your destination"
)
with col2:
dates = st.text_input(
"Travel Dates",
placeholder="Dec 20-25, 2024"
)
interests = st.text_input(
"Your Interests",
placeholder="museums, food, hiking..."
)
plan_button = st.button("🚀 Plan My Trip", type="primary", use_container_width=True)
if plan_button:
if current_location and destination and dates:
try:
st.success("🎈 Starting your travel planning journey!")
st.balloons()
sections = {
"destination": ("📍 Destination Information", research_destination),
"events": ("🎯 Events & Activities", research_events),
"weather": ("☀️ Weather Forecast", research_weather),
"flights": ("✈️ Flight Options", search_flights)
}
reports = {}
for key, (title, func) in sections.items():
with st.container():
st.markdown(f"<div class='section-header'><h3>{title}</h3></div>",
unsafe_allow_html=True)
with st.spinner(f"Loading {title.lower()}..."):
if key == "destination":
reports[key] = func(destination, interests)
elif key == "events":
reports[key] = func(destination, dates, interests)
elif key == "weather":
reports[key] = func(destination, dates)
else: # flights
reports[key] = func(current_location, destination, dates)
try:
formatted_content = format_markdown_images(reports[key])
st.markdown(formatted_content) # Just use regular markdown
except Exception as e:
st.error(f"Error displaying content: {str(e)}")
st.markdown(reports[key])
st.markdown("<div class='section-header'><h3>📋 Complete Travel Plan</h3></div>",
unsafe_allow_html=True)
with st.spinner("Creating final report..."):
final_report = write_travel_report(
reports["destination"],
reports["events"],
reports["weather"],
reports["flights"]
)
# And for the final report:
try:
formatted_final_report = format_markdown_images(final_report)
st.markdown(formatted_final_report) # Just use regular markdown
except Exception as e:
st.error(f"Error displaying final report: {str(e)}")
st.markdown(final_report)
st.download_button(
label="📥 Download Complete Travel Plan",
data=final_report,
file_name=f"travel_plan_{destination.lower().replace(' ', '_')}.md",
mime="text/markdown",
use_container_width=True
)
except Exception as e:
st.error(f"🚨 An error occurred: {str(e)}")
print(f"Debug - Error details: {str(e)}")
else:
st.warning("🔔 Please fill in all required fields")
st.markdown("""
<p style='text-align: center; color: #666666; margin-top: 2rem;'>
Happy Travels! 🌟
</p>
""", unsafe_allow_html=True)
if __name__ == "__main__":
main()