File size: 9,893 Bytes
72ef6a4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import os
from dotenv import load_dotenv

# Load environment variables
load_dotenv()

# Try to import real smolagents, fallback to mock
try:
    from smolagents import ToolCallingAgent, tool
    from smolagents.models import LiteLLMModel
    SMOLAGENTS_AVAILABLE = True
    print("✅ smolagents framework loaded successfully!")
except ImportError:
    print("⚠️ smolagents not found. Using mock implementation for demonstration.")
    print("   To install: pip install git+https://github.com/huggingface/smolagents.git")
    from mock_smolagents import ToolCallingAgent, tool, LiteLLMModel
    SMOLAGENTS_AVAILABLE = False

# Define tools using the decorator (works with both real and mock)
@tool
def calculator(expression: str) -> str:
    """Evaluate a mathematical expression.
    
    Args:
        expression: A mathematical expression (e.g., '2 + 2 * 3')
    
    Returns:
        The result of the evaluation
    """
    try:
        # Safe evaluation
        allowed_chars = set('0123456789+-*/(). ')
        if not all(c in allowed_chars for c in expression):
            return "Error: Only basic math operations allowed: numbers, +, -, *, /, (, ), ."
        
        # Use eval with limited scope
        result = eval(expression, {"__builtins__": {}}, {})
        return f"Calculator: {expression} = {result}"
    except Exception as e:
        return f"Calculation error: {str(e)}"

@tool
def search_web(query: str) -> str:
    """Search the web for information.
    
    Args:
        query: Search query
    
    Returns:
        Search results summary
    """
    try:
        # Try to use duckduckgo if available
        from duckduckgo_search import DDGS
        
        results = []
        with DDGS() as ddgs:
            for r in ddgs.text(query, max_results=3):
                results.append(f"• {r['title']}: {r['body'][:100]}...")
        
        if results:
            return f"Web search for '{query}':\n" + "\n".join(results)
        return f"No web results found for '{query}'"
    except ImportError:
        return f"[Mock] Web search for '{query}':\n• Result 1: Information about {query}\n• Result 2: More details..."
    except Exception as e:
        return f"Search error: {str(e)}"

@tool
def get_hf_dataset_info(dataset_name: str = "mnist") -> str:
    """Get information about a Hugging Face dataset.
    
    Args:
        dataset_name: Name of the dataset (e.g., 'mnist', 'glue')
    
    Returns:
        Dataset information
    """
    try:
        from huggingface_hub import get_dataset_info
        
        info = get_dataset_info(dataset_name)
        response = f"📊 **Hugging Face Dataset: {info.id}**\n"
        response += f"📥 Downloads: {info.downloads:,}\n"
        response += f"📝 Description: {info.description[:250]}..."
        
        return response
    except ImportError:
        datasets = {
            "mnist": "MNIST: 70,000 handwritten digits (28x28 grayscale images), standard computer vision dataset",
            "glue": "GLUE: General Language Understanding Evaluation benchmark for natural language understanding"
        }
        info = datasets.get(dataset_name.lower(), f"Dataset '{dataset_name}' not found in mock database")
        return f"📊 **Dataset Info (Mock):**\n{info}"
    except Exception as e:
        return f"Error getting dataset info: {str(e)}"

@tool
def translate_text(text: str, target_language: str = "Spanish") -> str:
    """Translate text to another language.
    
    Args:
        text: Text to translate
        target_language: Target language (default: Spanish)
    
    Returns:
        Translated text
    """
    translations = {
        "hello": {
            "spanish": "hola",
            "french": "bonjour",
            "german": "hallo",
            "italian": "ciao"
        },
        "world": {
            "spanish": "mundo",
            "french": "monde",
            "german": "welt",
            "italian": "mondo"
        },
        "goodbye": {
            "spanish": "adiós",
            "french": "au revoir",
            "german": "auf wiedersehen",
            "italian": "addio"
        }
    }
    
    text_lower = text.lower()
    lang_lower = target_language.lower()
    
    if text_lower in translations and lang_lower in translations[text_lower]:
        return f"Translation: '{text}' → {target_language}: '{translations[text_lower][lang_lower]}'"
    else:
        return f"No translation found for '{text}' to {target_language}. Try: 'hello', 'world', or 'goodbye'"

class MyHuggingFaceAgent:
    def __init__(self, use_mock_model=False):
        """Initialize the agent.
        
        Args:
            use_mock_model: Use mock model instead of real API (for testing)
        """
        self.use_mock_model = use_mock_model or not SMOLAGENTS_AVAILABLE
        
        # Get all tools
        self.tools = [calculator, search_web, get_hf_dataset_info, translate_text]
        
        # Initialize the agent
        self.agent = self._create_agent()
        
        print(f"Agent initialized with {len(self.tools)} tools")
        print(f"smolagents available: {SMOLAGENTS_AVAILABLE}")
    
    def _create_agent(self):
        """Create the smolagents agent."""
        try:
            if self.use_mock_model or not SMOLAGENTS_AVAILABLE:
                # Use mock model
                model = LiteLLMModel(
                    model_id="mock-model",
                    api_key="mock-key"
                )
            else:
                # Use real model (requires API key)
                api_key = os.getenv("OPENAI_API_KEY") or os.getenv("HF_TOKEN")
                if api_key and api_key != "not-provided":
                    model = LiteLLMModel(
                        model_id="gpt-3.5-turbo",
                        api_key=api_key
                    )
                else:
                    print("⚠️ No API key found. Using mock model.")
                    model = LiteLLMModel(
                        model_id="mock-model",
                        api_key="mock-key"
                    )
            
            # Create agent
            agent = ToolCallingAgent(
                model=model,
                tools=self.tools,
                max_steps=5,
                verbose=True,
                add_base_tools=False
            )
            
            return agent
            
        except Exception as e:
            print(f"Error creating agent: {e}")
            # Return a basic agent as fallback
            return None
    
    def run(self, task: str) -> str:
        """Run the agent on a task."""
        try:
            if self.agent:
                # Use smolagents agent
                result = self.agent.run(task)
                
                # Format the response
                response = "🤖 **AI Agent Response (smolagents Framework)**\n\n"
                response += f"{result}\n\n"
                response += "---\n"
                response += "🛠️ **Framework:** smolagents (Hugging Face)\n"
                response += f"📊 **Status:** {'Using real framework' if SMOLAGENTS_AVAILABLE else 'Using mock for demonstration'}"
                
                return response
            else:
                # Fallback to simple processing
                return self._simple_agent(task)
                
        except Exception as e:
            return f"⚠️ **Agent Error:** {str(e)}\n\n{self._simple_agent(task)}"
    
    def _simple_agent(self, task: str) -> str:
        """Simple fallback agent."""
        response = "🔧 **Simple Agent Response**\n\n"
        
        # Try each tool
        for tool_func in self.tools:
            tool_name = tool_func.name
            if tool_name in task.lower():
                try:
                    # Simple argument extraction
                    if tool_name == "calculator":
                        import re
                        expr = re.sub(r'[^\d\+\-\*\/\(\)\.\s]', '', task).strip()
                        if expr:
                            result = tool_func(expr)
                        else:
                            result = "Please provide a math expression"
                    elif tool_name == "search_web":
                        query = task.replace("search", "").replace("find", "").strip()
                        result = tool_func(query if query else task)
                    elif tool_name == "get_hf_dataset_info":
                        result = tool_func()
                    elif tool_name == "translate_text":
                        if " to " in task.lower():
                            parts = task.lower().split(" to ")
                            text = parts[0].replace("translate", "").strip()
                            lang = parts[1].strip().title()
                            result = tool_func(text, lang)
                        else:
                            result = tool_func("hello")
                    else:
                        result = tool_func(task)
                    
                    response += f"**{tool_name.replace('_', ' ').title()}:**\n{result}\n\n"
                    break
                except Exception as e:
                    response += f"Error using {tool_name}: {str(e)}\n\n"
        else:
            # No tool matched
            response += """**I can help with:**
1. **Calculator** - Perform math calculations
   Example: 'calculate 15 * 3' or 'what is 45 + 23?'
2. **Web Search** - Search for information
   Example: 'search for AI news' or 'find machine learning tutorials'
3. **Dataset Info** - Get Hugging Face dataset information
   Example: 'tell me about mnist dataset' or 'glue dataset info'
4. **Translation** - Translate words
   Example: 'translate hello to Spanish' or 'translate goodbye to French'
Try one of these commands!"""
        
        return response