Wayne0102 commited on
Commit
fae165e
·
verified ·
1 Parent(s): da5e409

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +400 -30
app.py CHANGED
@@ -3,6 +3,8 @@ import gradio as gr
3
  import datetime
4
  import pytz
5
  import asyncio
 
 
6
 
7
  # Framework 1: LlamaIndex
8
  from llama_index.core.agent.workflow import AgentWorkflow
@@ -14,24 +16,202 @@ from smolagents import CodeAgent, DuckDuckGoSearchTool, tool, InferenceClientMod
14
 
15
  # 0. SHARED CONFIG
16
  HF_TOKEN = os.getenv("HF_TOKEN")
17
- # 7B is the sweet spot for free serverless inference in 2026
18
  MODEL_ID = "Qwen/Qwen2.5-7B-Instruct"
19
 
20
  # ==========================================
21
- # PART 1: LLAMAINDEX AGENT
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  # ==========================================
23
  li_llm = HuggingFaceInferenceAPI(
24
  model_name=MODEL_ID,
25
  token=HF_TOKEN,
26
- provider="together"
27
  )
28
 
29
- def get_tokyo_time() -> str:
30
- """Returns the current time in Tokyo, Japan."""
31
- tz = pytz.timezone('Asia/Tokyo')
32
- return f"The current time in Tokyo is {datetime.datetime.now(tz).strftime('%H:%M:%S')}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
 
34
- li_tools = [FunctionTool.from_defaults(fn=get_tokyo_time)]
 
 
 
 
 
 
35
 
36
  li_agent = AgentWorkflow.from_tools_or_functions(
37
  li_tools,
@@ -40,13 +220,32 @@ li_agent = AgentWorkflow.from_tools_or_functions(
40
 
41
  async def chat_llama(message, history):
42
  try:
 
 
 
 
43
  result = await li_agent.run(user_msg=message)
44
- return str(result)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
  except Exception as e:
46
- return f"LlamaIndex Error: {str(e)}"
47
 
48
  # ==========================================
49
- # PART 2: SMOLAGENTS
50
  # ==========================================
51
  smol_model = InferenceClientModel(
52
  model_id=MODEL_ID,
@@ -54,17 +253,9 @@ smol_model = InferenceClientModel(
54
  provider="together"
55
  )
56
 
57
- @tool
58
- def weather_tool(location: str) -> str:
59
- """Get the current weather for a location.
60
- Args:
61
- location: The city name.
62
- """
63
- return f"The weather in {location} is currently sunny and 22°C."
64
-
65
  smol_agent = CodeAgent(
66
  model=smol_model,
67
- tools=[weather_tool, DuckDuckGoSearchTool()]
68
  )
69
 
70
  def chat_smol(message, history):
@@ -72,20 +263,199 @@ def chat_smol(message, history):
72
  response = smol_agent.run(message)
73
  return str(response)
74
  except Exception as e:
75
- return f"Smolagents Error: {str(e)}"
76
 
77
  # ==========================================
78
- # PART 3: UNIFIED GRADIO UI
79
  # ==========================================
80
- with gr.Blocks(theme=gr.themes.Soft()) as demo:
81
- gr.Markdown("# 🤖 Consolidated AI Agent Space")
82
- gr.Markdown(f"Currently using **{MODEL_ID}** via Together AI Provider.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83
 
84
- with gr.Tab("LlamaIndex (Workflow)"):
85
- gr.ChatInterface(fn=chat_llama)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86
 
87
- with gr.Tab("smolagents (CodeAgent)"):
88
- gr.ChatInterface(fn=chat_smol)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
 
90
  if __name__ == "__main__":
91
- demo.launch()
 
 
 
 
 
 
3
  import datetime
4
  import pytz
5
  import asyncio
6
+ import requests
7
+ from typing import Dict, Any
8
 
9
  # Framework 1: LlamaIndex
10
  from llama_index.core.agent.workflow import AgentWorkflow
 
16
 
17
  # 0. SHARED CONFIG
18
  HF_TOKEN = os.getenv("HF_TOKEN")
19
+ WEATHER_API_KEY = os.getenv("WEATHER_API_KEY", "your-openweather-api-key") # Get from: https://openweathermap.org/api
20
  MODEL_ID = "Qwen/Qwen2.5-7B-Instruct"
21
 
22
  # ==========================================
23
+ # ENHANCED WEATHER FUNCTIONALITY
24
+ # ==========================================
25
+ class WeatherService:
26
+ def __init__(self, api_key: str = None):
27
+ self.api_key = api_key or WEATHER_API_KEY
28
+ self.base_url = "http://api.openweathermap.org/data/2.5/weather"
29
+
30
+ def get_weather(self, location: str) -> Dict[str, Any]:
31
+ """Get real weather data for a location"""
32
+ try:
33
+ params = {
34
+ 'q': location,
35
+ 'appid': self.api_key,
36
+ 'units': 'metric',
37
+ 'lang': 'en'
38
+ }
39
+
40
+ response = requests.get(self.base_url, params=params, timeout=10)
41
+ response.raise_for_status()
42
+ data = response.json()
43
+
44
+ return {
45
+ 'temperature': data['main']['temp'],
46
+ 'feels_like': data['main']['feels_like'],
47
+ 'humidity': data['main']['humidity'],
48
+ 'pressure': data['main']['pressure'],
49
+ 'description': data['weather'][0]['description'].title(),
50
+ 'wind_speed': data['wind']['speed'],
51
+ 'wind_direction': self.get_wind_direction(data['wind'].get('deg', 0)),
52
+ 'location': f"{data['name']}, {data['sys']['country']}",
53
+ 'icon': data['weather'][0]['icon'],
54
+ 'timestamp': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
55
+ }
56
+ except Exception as e:
57
+ # Fallback to mock data if API fails
58
+ return self.get_mock_weather(location)
59
+
60
+ def get_mock_weather(self, location: str) -> Dict[str, Any]:
61
+ """Fallback mock weather data"""
62
+ mock_temps = {
63
+ 'tokyo': 18, 'london': 12, 'new york': 15,
64
+ 'paris': 14, 'sydney': 22, 'dubai': 28
65
+ }
66
+ temp = mock_temps.get(location.lower(), 20)
67
+
68
+ return {
69
+ 'temperature': temp,
70
+ 'feels_like': temp + 2,
71
+ 'humidity': 65,
72
+ 'pressure': 1013,
73
+ 'description': 'Partly Cloudy',
74
+ 'wind_speed': 3.5,
75
+ 'wind_direction': 'NW',
76
+ 'location': location.title(),
77
+ 'icon': '03d',
78
+ 'timestamp': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
79
+ 'note': 'Using mock data (add real API key for live weather)'
80
+ }
81
+
82
+ def get_wind_direction(self, degrees: float) -> str:
83
+ """Convert wind degrees to cardinal direction"""
84
+ directions = ['N', 'NNE', 'NE', 'ENE', 'E', 'ESE', 'SE', 'SSE',
85
+ 'S', 'SSW', 'SW', 'WSW', 'W', 'WNW', 'NW', 'NNW']
86
+ index = round(degrees / 22.5) % 16
87
+ return directions[index]
88
+
89
+ def format_weather_report(self, weather_data: Dict[str, Any]) -> str:
90
+ """Format weather data into a readable report"""
91
+ emoji_map = {
92
+ 'Clear': '☀️', 'Clouds': '☁️', 'Rain': '🌧️',
93
+ 'Snow': '❄️', 'Thunderstorm': '⛈️', 'Drizzle': '🌦️',
94
+ 'Mist': '🌫️', 'Smoke': '💨', 'Haze': '😶‍🌫️'
95
+ }
96
+
97
+ description = weather_data['description']
98
+ emoji = emoji_map.get(description.split()[0], '🌈')
99
+
100
+ report = f"""
101
+ {emoji} **Weather Report for {weather_data['location']}** {emoji}
102
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
103
+ **Temperature:** {weather_data['temperature']:.1f}°C
104
+ **Feels Like:** {weather_data['feels_like']:.1f}°C
105
+ **Conditions:** {description}
106
+ **Humidity:** {weather_data['humidity']}%
107
+ **Pressure:** {weather_data['pressure']} hPa
108
+ **Wind:** {weather_data['wind_speed']} m/s {weather_data['wind_direction']}
109
+ **Updated:** {weather_data['timestamp']}
110
+ """
111
+ if 'note' in weather_data:
112
+ report += f"\n⚠️ *{weather_data['note']}*"
113
+
114
+ return report
115
+
116
+ weather_service = WeatherService()
117
+
118
+ # ==========================================
119
+ # ENHANCED TIME FUNCTIONS
120
+ # ==========================================
121
+ def get_tokyo_time() -> str:
122
+ """Returns the current time in Tokyo, Japan."""
123
+ tz = pytz.timezone('Asia/Tokyo')
124
+ current_time = datetime.datetime.now(tz)
125
+ return f"**Tokyo Time:** {current_time.strftime('%A, %B %d, %Y %H:%M:%S')} (JST)"
126
+
127
+ def get_world_time(city: str = None) -> str:
128
+ """Get current time for various cities"""
129
+ timezones = {
130
+ 'tokyo': 'Asia/Tokyo',
131
+ 'new york': 'America/New_York',
132
+ 'london': 'Europe/London',
133
+ 'paris': 'Europe/Paris',
134
+ 'sydney': 'Australia/Sydney',
135
+ 'dubai': 'Asia/Dubai',
136
+ 'singapore': 'Asia/Singapore',
137
+ 'mumbai': 'Asia/Kolkata'
138
+ }
139
+
140
+ if not city:
141
+ # Return all times
142
+ result = "🌍 **World Clock** 🌍\n━━━━━━━━━━━━━━━━━━━━━━━━━━\n"
143
+ for city_name, tz_str in timezones.items():
144
+ tz = pytz.timezone(tz_str)
145
+ current_time = datetime.datetime.now(tz)
146
+ result += f"• **{city_name.title()}:** {current_time.strftime('%H:%M:%S')}\n"
147
+ return result
148
+
149
+ city_lower = city.lower()
150
+ if city_lower in timezones:
151
+ tz = pytz.timezone(timezones[city_lower])
152
+ current_time = datetime.datetime.now(tz)
153
+ return f"**{city.title()} Time:** {current_time.strftime('%A, %B %d, %Y %H:%M:%S')}"
154
+ else:
155
+ return f"Sorry, I don't have timezone data for {city}. Available cities: {', '.join(timezones.keys())}"
156
+
157
+ # ==========================================
158
+ # PART 1: LLAMAINDEX AGENT (ENHANCED)
159
  # ==========================================
160
  li_llm = HuggingFaceInferenceAPI(
161
  model_name=MODEL_ID,
162
  token=HF_TOKEN,
163
+ provider="together"
164
  )
165
 
166
+ @tool
167
+ def enhanced_weather_tool(location: str) -> str:
168
+ """Get detailed weather information for any location worldwide.
169
+ Args:
170
+ location: City name (e.g., 'Tokyo', 'New York', 'London')
171
+ """
172
+ weather_data = weather_service.get_weather(location)
173
+ return weather_service.format_weather_report(weather_data)
174
+
175
+ @tool
176
+ def world_time_tool(city: str = None) -> str:
177
+ """Get current time for world cities.
178
+ Args:
179
+ city: Optional city name. If not provided, shows all major cities.
180
+ """
181
+ return get_world_time(city)
182
+
183
+ @tool
184
+ def calculator_tool(expression: str) -> str:
185
+ """Evaluate mathematical expressions.
186
+ Args:
187
+ expression: Mathematical expression to calculate (e.g., '2 + 2', 'sqrt(16)')
188
+ """
189
+ try:
190
+ # Safe evaluation
191
+ import math
192
+ allowed_names = {k: v for k, v in math.__dict__.items() if not k.startswith("_")}
193
+ allowed_names.update({'abs': abs, 'round': round})
194
+
195
+ # Compile the expression
196
+ code = compile(expression, "<string>", "eval")
197
+
198
+ # Check for disallowed names
199
+ for name in code.co_names:
200
+ if name not in allowed_names:
201
+ raise NameError(f"Use of {name} is not allowed")
202
+
203
+ result = eval(code, {"__builtins__": {}}, allowed_names)
204
+ return f"**Result:** {expression} = {result}"
205
+ except Exception as e:
206
+ return f"Calculation Error: {str(e)}. Please use valid mathematical expressions."
207
 
208
+ # Create LlamaIndex tools
209
+ li_tools = [
210
+ FunctionTool.from_defaults(fn=get_tokyo_time),
211
+ FunctionTool.from_defaults(fn=lambda location: enhanced_weather_tool(location)),
212
+ FunctionTool.from_defaults(fn=lambda city=None: world_time_tool(city)),
213
+ FunctionTool.from_defaults(fn=lambda expr: calculator_tool(expr))
214
+ ]
215
 
216
  li_agent = AgentWorkflow.from_tools_or_functions(
217
  li_tools,
 
220
 
221
  async def chat_llama(message, history):
222
  try:
223
+ # Add some thinking emoji
224
+ thinking_msg = "🤔 Thinking..."
225
+
226
+ # Process the message
227
  result = await li_agent.run(user_msg=message)
228
+
229
+ # Format response
230
+ response = str(result)
231
+ if "weather" in message.lower() and "tokyo" not in message.lower():
232
+ # Extract location from message
233
+ words = message.lower().split()
234
+ for word in words:
235
+ if word in ['weather', 'forecast', 'temperature']:
236
+ continue
237
+ # Try to find a location
238
+ weather_data = weather_service.get_weather(word)
239
+ if 'mock' not in str(weather_data.get('note', '')):
240
+ response = weather_service.format_weather_report(weather_data)
241
+ break
242
+
243
+ return response
244
  except Exception as e:
245
+ return f"LlamaIndex Error: {str(e)}"
246
 
247
  # ==========================================
248
+ # PART 2: SMOLAGENTS (ENHANCED)
249
  # ==========================================
250
  smol_model = InferenceClientModel(
251
  model_id=MODEL_ID,
 
253
  provider="together"
254
  )
255
 
 
 
 
 
 
 
 
 
256
  smol_agent = CodeAgent(
257
  model=smol_model,
258
+ tools=[enhanced_weather_tool, world_time_tool, calculator_tool, DuckDuckGoSearchTool()]
259
  )
260
 
261
  def chat_smol(message, history):
 
263
  response = smol_agent.run(message)
264
  return str(response)
265
  except Exception as e:
266
+ return f"Smolagents Error: {str(e)}"
267
 
268
  # ==========================================
269
+ # PART 3: ENHANCED GRADIO UI
270
  # ==========================================
271
+ def create_weather_component():
272
+ """Create a standalone weather component"""
273
+ with gr.Column(variant="panel"):
274
+ gr.Markdown("## 🌤️ Quick Weather Check")
275
+
276
+ with gr.Row():
277
+ location_input = gr.Textbox(
278
+ label="City Name",
279
+ placeholder="Enter city name...",
280
+ scale=4
281
+ )
282
+ get_weather_btn = gr.Button("Get Weather", variant="primary", scale=1)
283
+
284
+ weather_output = gr.Markdown(label="Weather Report")
285
+
286
+ # Example locations
287
+ examples = gr.Examples(
288
+ examples=["Tokyo", "London", "New York", "Paris", "Sydney"],
289
+ inputs=location_input,
290
+ label="Try these cities:"
291
+ )
292
+
293
+ def get_weather(location):
294
+ if not location:
295
+ return "Please enter a city name."
296
+ weather_data = weather_service.get_weather(location)
297
+ return weather_service.format_weather_report(weather_data)
298
+
299
+ get_weather_btn.click(
300
+ get_weather,
301
+ inputs=location_input,
302
+ outputs=weather_output
303
+ )
304
+
305
+ return location_input, weather_output
306
+
307
+ def create_world_clock_component():
308
+ """Create a world clock component"""
309
+ with gr.Column(variant="panel"):
310
+ gr.Markdown("## 🌍 World Clock")
311
+
312
+ with gr.Row():
313
+ refresh_btn = gr.Button("🔄 Refresh Times", variant="secondary")
314
+ all_cities_btn = gr.Button("Show All Cities", variant="primary")
315
+
316
+ time_output = gr.Markdown()
317
+
318
+ # Initial display
319
+ time_output.value = get_world_time()
320
+
321
+ def refresh_times():
322
+ return get_world_time()
323
+
324
+ refresh_btn.click(refresh_times, outputs=time_output)
325
+ all_cities_btn.click(refresh_times, outputs=time_output)
326
+
327
+ return time_output
328
+
329
+ def create_calculator_component():
330
+ """Create a simple calculator component"""
331
+ with gr.Column(variant="panel"):
332
+ gr.Markdown("## 🧮 Quick Calculator")
333
+
334
+ with gr.Row():
335
+ calc_input = gr.Textbox(
336
+ label="Math Expression",
337
+ placeholder="e.g., 2 + 2, 3 * (4 + 5), sqrt(16)...",
338
+ scale=4
339
+ )
340
+ calc_btn = gr.Button("Calculate", variant="primary", scale=1)
341
+
342
+ calc_output = gr.Markdown(label="Result")
343
+
344
+ examples = gr.Examples(
345
+ examples=["2 + 2", "3 * (4 + 5)", "sqrt(16)", "sin(30)", "2 ** 8"],
346
+ inputs=calc_input,
347
+ label="Try these:"
348
+ )
349
+
350
+ def calculate(expression):
351
+ return calculator_tool(expression)
352
+
353
+ calc_btn.click(
354
+ calculate,
355
+ inputs=calc_input,
356
+ outputs=calc_output
357
+ )
358
+
359
+ return calc_input, calc_output
360
+
361
+ with gr.Blocks(theme=gr.themes.Soft(), title="🤖 AI Agent Studio") as demo:
362
+ # Header
363
+ with gr.Row():
364
+ gr.Markdown("# 🚀 AI Agent Studio")
365
+
366
+ with gr.Row():
367
+ gr.Markdown(f"### Powered by **{MODEL_ID}** via Together AI")
368
 
369
+ # API Key Notice
370
+ if "your-openweather-api-key" in WEATHER_API_KEY:
371
+ gr.Markdown("""
372
+ ⚠️ **Note:** Using mock weather data. For real weather, get a free API key from
373
+ [OpenWeatherMap](https://openweathermap.org/api) and set it as `WEATHER_API_KEY` environment variable.
374
+ """)
375
+
376
+ # Sidebar with utility tools
377
+ with gr.Row():
378
+ # Left sidebar - Utility tools
379
+ with gr.Column(scale=1, variant="panel"):
380
+ create_weather_component()
381
+ create_world_clock_component()
382
+ create_calculator_component()
383
+
384
+ # Agent Capabilities Info
385
+ with gr.Column(variant="panel"):
386
+ gr.Markdown("## 🤖 Agent Capabilities")
387
+ gr.Markdown("""
388
+ **Both Agents Can:**
389
+ • 📅 Get current time worldwide
390
+ • 🌤️ Check weather forecasts
391
+ • 🧮 Perform calculations
392
+ • 🔍 Search the web (smolagents)
393
+ • 💬 Natural conversation
394
+
395
+ **Try asking:**
396
+ - "What's the weather in London?"
397
+ - "What time is it in Tokyo?"
398
+ - "Calculate 15% of 200"
399
+ - "Tell me about AI news"
400
+ """)
401
 
402
+ # Main content area - Chat interfaces
403
+ with gr.Column(scale=3):
404
+ with gr.Tab("🦙 LlamaIndex Agent", id="llama"):
405
+ llama_chat = gr.ChatInterface(
406
+ fn=chat_llama,
407
+ chatbot=gr.Chatbot(height=500, label="LlamaIndex Agent"),
408
+ textbox=gr.Textbox(
409
+ placeholder="Ask about weather, time, calculations...",
410
+ container=False,
411
+ scale=7
412
+ ),
413
+ title="LlamaIndex Workflow Agent",
414
+ description="Uses structured workflows with function tools",
415
+ theme="soft",
416
+ examples=[
417
+ "What's the weather in Tokyo?",
418
+ "What time is it in New York and Paris?",
419
+ "Calculate 25 * 4 + 18",
420
+ "Tell me about today's weather worldwide"
421
+ ]
422
+ )
423
+
424
+ with gr.Tab("🔬 Smolagents CodeAgent", id="smol"):
425
+ smol_chat = gr.ChatInterface(
426
+ fn=chat_smol,
427
+ chatbot=gr.Chatbot(height=500, label="Smolagents CodeAgent"),
428
+ textbox=gr.Textbox(
429
+ placeholder="Ask anything or request web search...",
430
+ container=False,
431
+ scale=7
432
+ ),
433
+ title="Smolagents Code Agent",
434
+ description="Uses code execution with search capabilities",
435
+ theme="soft",
436
+ examples=[
437
+ "Search for latest AI developments",
438
+ "What's the weather forecast for this week?",
439
+ "Explain quantum computing",
440
+ "Calculate the area of a circle with radius 5"
441
+ ]
442
+ )
443
+
444
+ # Footer
445
+ with gr.Row():
446
+ gr.Markdown("""
447
+ ---
448
+ **Tips:**
449
+ 1. LlamaIndex is better for structured workflows
450
+ 2. Smolagents can search the web in real-time
451
+ 3. Use the sidebar for quick weather/time checks
452
+ 4. Both agents support natural language queries
453
+ """)
454
 
455
  if __name__ == "__main__":
456
+ demo.launch(
457
+ server_name="0.0.0.0",
458
+ server_port=7860,
459
+ share=False,
460
+ debug=True
461
+ )