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

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +222 -384
app.py CHANGED
@@ -4,458 +4,296 @@ 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
11
  from llama_index.core.tools import FunctionTool
12
- from llama_index.llms.huggingface_api import HuggingFaceInferenceAPI
13
 
14
  # Framework 2: smolagents
15
- from smolagents import CodeAgent, DuckDuckGoSearchTool, tool, InferenceClientModel
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,
218
- llm=li_llm,
219
- )
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,
252
- token=HF_TOKEN,
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):
262
- try:
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
  )
 
4
  import pytz
5
  import asyncio
6
  import requests
 
7
 
8
  # Framework 1: LlamaIndex
9
+ from llama_index.core.agent import ReActAgent
10
  from llama_index.core.tools import FunctionTool
11
+ from llama_index.llms.huggingface import HuggingFaceInferenceAPI
12
 
13
  # Framework 2: smolagents
14
+ from smolagents import CodeAgent, DuckDuckGoSearchTool, tool
15
 
16
  # 0. SHARED CONFIG
17
  HF_TOKEN = os.getenv("HF_TOKEN")
 
18
  MODEL_ID = "Qwen/Qwen2.5-7B-Instruct"
19
 
20
  # ==========================================
21
+ # WEATHER FUNCTION WITH REAL API
22
  # ==========================================
23
+ def get_weather(location: str) -> str:
24
+ """Get weather for a location using OpenWeatherMap API"""
25
+ try:
26
+ # You can get a free API key from https://openweathermap.org/api
27
+ api_key = os.getenv("WEATHER_API_KEY", "")
28
+
29
+ if api_key:
30
+ url = f"http://api.openweathermap.org/data/2.5/weather?q={location}&appid={api_key}&units=metric"
31
+ response = requests.get(url, timeout=5)
 
 
 
 
 
 
 
 
32
  data = response.json()
33
 
34
+ if response.status_code == 200:
35
+ temp = data['main']['temp']
36
+ desc = data['weather'][0]['description']
37
+ humidity = data['main']['humidity']
38
+ return f"🌤️ Weather in {location}: {desc}, {temp}°C, Humidity: {humidity}%"
39
+ else:
40
+ # Fallback to mock data if API fails
41
+ return f"🌤️ Weather in {location}: Sunny, 22°C (mock data - add real API key for live weather)"
42
+ else:
43
+ # Mock weather if no API key
44
+ weather_data = {
45
+ "tokyo": "Cloudy, 18°C",
46
+ "london": "Rainy, 12°C",
47
+ "new york": "Sunny, 15°C",
48
+ "paris": "Partly Cloudy, 14°C",
49
+ "sydney": "Clear, 22°C"
50
  }
51
+ for city, weather in weather_data.items():
52
+ if city in location.lower():
53
+ return f"🌤️ Weather in {location}: {weather} (mock data)"
54
+ return f"🌤️ Weather in {location}: Sunny, 22°C (mock data - set WEATHER_API_KEY for real data)"
55
+ except Exception as e:
56
+ return f"🌤️ Weather in {location}: Sunny, 22°C (error: {str(e)[:50]})"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
 
58
  # ==========================================
59
+ # TIME FUNCTIONS
60
  # ==========================================
61
  def get_tokyo_time() -> str:
62
  """Returns the current time in Tokyo, Japan."""
63
  tz = pytz.timezone('Asia/Tokyo')
64
+ now = datetime.datetime.now(tz)
65
+ return f"🕐 Tokyo Time: {now.strftime('%A, %B %d, %Y %H:%M:%S')}"
66
 
67
+ def get_world_time(city: str = "all") -> str:
68
+ """Get current time for various cities."""
69
  timezones = {
70
+ "Tokyo": "Asia/Tokyo",
71
+ "New York": "America/New_York",
72
+ "London": "Europe/London",
73
+ "Paris": "Europe/Paris",
74
+ "Sydney": "Australia/Sydney",
75
+ "Dubai": "Asia/Dubai",
76
+ "Singapore": "Asia/Singapore"
 
77
  }
78
 
79
+ if city.lower() != "all" and city.title() in timezones:
80
+ tz = pytz.timezone(timezones[city.title()])
81
+ now = datetime.datetime.now(tz)
82
+ return f"🕐 {city} Time: {now.strftime('%H:%M:%S')}"
 
 
 
 
83
 
84
+ result = "🌍 World Clock:\n"
85
+ for city_name, tz_str in timezones.items():
86
+ tz = pytz.timezone(tz_str)
87
+ now = datetime.datetime.now(tz)
88
+ result += f"{city_name}: {now.strftime('%H:%M:%S')}\n"
89
+ return result
 
90
 
91
  # ==========================================
92
+ # CALCULATOR FUNCTION
93
  # ==========================================
94
+ def calculate(expression: str) -> str:
95
+ """Calculate mathematical expressions."""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
  try:
97
+ # Safe evaluation with basic math functions
98
  import math
 
 
 
 
 
 
 
 
 
 
99
 
100
+ # Create a safe environment
101
+ safe_dict = {
102
+ 'abs': abs, 'round': round, 'min': min, 'max': max,
103
+ 'sum': sum, 'len': len, 'int': int, 'float': float,
104
+ 'math': math, 'sqrt': math.sqrt, 'pow': math.pow,
105
+ 'sin': math.sin, 'cos': math.cos, 'tan': math.tan,
106
+ 'pi': math.pi, 'e': math.e
107
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
 
109
+ # Remove any dangerous characters
110
+ expression = ''.join(c for c in expression if c.isalnum() or c in ' +-*/().,')
 
 
 
 
 
 
 
 
 
 
 
111
 
112
+ result = eval(expression, {"__builtins__": {}}, safe_dict)
113
+ return f"🧮 {expression} = {result}"
114
  except Exception as e:
115
+ return f"❌ Calculation error: {str(e)[:100]}"
116
 
117
  # ==========================================
118
+ # PART 1: LLAMAINDEX AGENT (FIXED)
119
  # ==========================================
120
+ try:
121
+ li_llm = HuggingFaceInferenceAPI(
122
+ model_name=MODEL_ID,
123
+ token=HF_TOKEN,
124
+ )
125
+
126
+ # Create tools for LlamaIndex
127
+ li_tools = [
128
+ FunctionTool.from_defaults(fn=get_tokyo_time, name="get_tokyo_time"),
129
+ FunctionTool.from_defaults(fn=get_weather, name="get_weather"),
130
+ FunctionTool.from_defaults(fn=get_world_time, name="get_world_time"),
131
+ FunctionTool.from_defaults(fn=calculate, name="calculate")
132
+ ]
133
+
134
+ li_agent = ReActAgent.from_tools(
135
+ li_tools,
136
+ llm=li_llm,
137
+ verbose=False
138
+ )
139
+
140
+ async def chat_llama(message, history):
141
+ try:
142
+ response = await li_agent.achat(message)
143
+ return str(response)
144
+ except Exception as e:
145
+ return f"❌ LlamaIndex Error: {str(e)[:200]}"
146
+
147
+ except Exception as e:
148
+ print(f"LlamaIndex setup error: {e}")
149
+ async def chat_llama(message, history):
150
+ return f"❌ LlamaIndex not available: {str(e)[:200]}"
151
 
152
  # ==========================================
153
+ # PART 2: SMOLAGENTS
154
  # ==========================================
155
+ try:
156
+ from smolagents import CodeAgent, DuckDuckGoSearchTool, tool
157
+
158
+ @tool
159
+ def weather_tool(location: str) -> str:
160
+ """Get the current weather for a location."""
161
+ return get_weather(location)
162
+
163
+ @tool
164
+ def time_tool(city: str = "all") -> str:
165
+ """Get current time for a city or all major cities."""
166
+ return get_world_time(city)
167
+
168
+ @tool
169
+ def calculator_tool(expression: str) -> str:
170
+ """Calculate mathematical expressions."""
171
+ return calculate(expression)
172
+
173
+ smol_agent = CodeAgent(
174
+ tools=[weather_tool, time_tool, calculator_tool, DuckDuckGoSearchTool()],
175
+ model=MODEL_ID,
176
+ max_steps=5
177
+ )
178
+
179
+ def chat_smol(message, history):
180
+ try:
181
+ response = smol_agent.run(message)
182
+ return str(response)
183
+ except Exception as e:
184
+ return f"❌ Smolagents Error: {str(e)[:200]}"
185
+
186
+ except Exception as e:
187
+ print(f"Smolagents setup error: {e}")
188
+ def chat_smol(message, history):
189
+ return f"❌ Smolagents not available: {str(e)[:200]}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
190
 
191
+ # ==========================================
192
+ # PART 3: UNIFIED GRADIO UI
193
+ # ==========================================
194
  with gr.Blocks(theme=gr.themes.Soft(), title="🤖 AI Agent Studio") as demo:
195
  # Header
196
+ gr.Markdown("# 🤖 AI Agent Studio")
197
+ gr.Markdown(f"**Model:** {MODEL_ID} | **Provider:** Together AI")
 
 
 
 
 
 
 
 
 
 
198
 
199
+ # Quick Tools Section
200
  with gr.Row():
201
+ with gr.Column(scale=1):
202
+ gr.Markdown("### 🛠️ Quick Tools")
 
 
 
203
 
204
+ # Weather Tool
205
+ with gr.Group():
206
+ weather_city = gr.Textbox(
207
+ label="Check Weather",
208
+ placeholder="Enter city name...",
209
+ scale=4
210
+ )
211
+ weather_btn = gr.Button("🌤️ Get Weather", scale=1)
212
+ weather_output = gr.Textbox(label="Result", interactive=False)
 
213
 
214
+ def get_weather_quick(city):
215
+ return get_weather(city) if city else "Please enter a city name."
216
+
217
+ weather_btn.click(
218
+ get_weather_quick,
219
+ inputs=weather_city,
220
+ outputs=weather_output
221
+ )
222
+
223
+ # Calculator Tool
224
+ with gr.Group():
225
+ calc_expr = gr.Textbox(
226
+ label="Calculator",
227
+ placeholder="Enter math expression...",
228
+ scale=4
229
+ )
230
+ calc_btn = gr.Button("🧮 Calculate", scale=1)
231
+ calc_output = gr.Textbox(label="Result", interactive=False)
232
+
233
+ calc_btn.click(
234
+ calculate,
235
+ inputs=calc_expr,
236
+ outputs=calc_output
237
+ )
238
+
239
+ # Time Tool
240
+ with gr.Group():
241
+ time_btn = gr.Button("🌍 Show World Clock")
242
+ time_output = gr.Textbox(label="World Times", interactive=False)
243
+
244
+ time_btn.click(
245
+ lambda: get_world_time("all"),
246
+ outputs=time_output
247
+ )
248
+
249
+ # Chat Agents Section
250
+ with gr.Row():
251
+ with gr.Tabs():
252
+ with gr.TabItem("🦙 LlamaIndex Agent"):
253
  llama_chat = gr.ChatInterface(
254
  fn=chat_llama,
255
+ title="LlamaIndex ReAct Agent",
256
+ description="Structured agent with reasoning capabilities",
 
 
 
 
 
 
 
257
  examples=[
258
  "What's the weather in Tokyo?",
259
+ "What time is it in New York?",
260
  "Calculate 25 * 4 + 18",
261
+ "Tell me the time in London and Sydney"
262
  ]
263
  )
264
 
265
+ with gr.TabItem("🔬 Smolagents"):
266
  smol_chat = gr.ChatInterface(
267
  fn=chat_smol,
268
+ title="Smolagents CodeAgent",
269
+ description="Code-based agent with web search",
 
 
 
 
 
 
 
270
  examples=[
271
+ "Search for AI news",
272
+ "What's the weather like today?",
273
+ "Calculate 15% of 200",
274
+ "Tell me about machine learning"
275
  ]
276
  )
277
 
278
  # Footer
279
+ gr.Markdown("---")
280
+ gr.Markdown("""
281
+ ### 💡 Try asking:
282
+ - "What's the weather in London and what time is it there?"
283
+ - "Calculate the area of a circle with radius 5"
284
+ - "Search for latest technology news"
285
+ - "Compare time between Tokyo and New York"
286
+ """)
287
+
288
+ # API Key Notice
289
+ if not os.getenv("WEATHER_API_KEY"):
290
  gr.Markdown("""
291
+ ⚠️ **Note:** Using mock weather data. For real weather, add `WEATHER_API_KEY` to your Hugging Face Space secrets.
 
 
 
 
 
292
  """)
293
 
294
  if __name__ == "__main__":
295
  demo.launch(
296
  server_name="0.0.0.0",
297
  server_port=7860,
298
+ share=True
 
299
  )