mjschock commited on
Commit
55ef143
·
unverified ·
1 Parent(s): 3a4521b

Add new agent functionalities by creating agents for web browsing, data analysis, and media handling in agents.py. Introduce various tools in tools.py for web searching, webpage browsing, image analysis, PDF reading, CSV parsing, and date extraction, enhancing the overall capabilities of the agent system.

Browse files
Files changed (2) hide show
  1. agents.py +78 -0
  2. tools.py +254 -0
agents.py ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from smolagents import CodeAgent
2
+
3
+ from tools import (
4
+ analyze_image,
5
+ browse_webpage,
6
+ extract_dates,
7
+ find_in_page,
8
+ parse_csv,
9
+ perform_calculation,
10
+ read_pdf,
11
+ web_search,
12
+ )
13
+
14
+
15
+ def create_web_agent(model):
16
+ """
17
+ Create a specialized agent for web browsing tasks.
18
+
19
+ Args:
20
+ model: The model to use for the agent
21
+
22
+ Returns:
23
+ Configured CodeAgent for web browsing
24
+ """
25
+ web_agent = CodeAgent(
26
+ tools=[web_search, browse_webpage, find_in_page, extract_dates],
27
+ model=model,
28
+ name="web_agent",
29
+ description="Specialized agent for web browsing and searching. Use this agent to find information online, browse websites, and extract information from web pages.",
30
+ add_base_tools=True,
31
+ additional_authorized_imports=["requests", "bs4", "re", "json"],
32
+ )
33
+
34
+ return web_agent
35
+
36
+
37
+ def create_data_analysis_agent(model):
38
+ """
39
+ Create a specialized agent for data analysis tasks.
40
+
41
+ Args:
42
+ model: The model to use for the agent
43
+
44
+ Returns:
45
+ Configured CodeAgent for data analysis
46
+ """
47
+ data_agent = CodeAgent(
48
+ tools=[parse_csv, perform_calculation],
49
+ model=model,
50
+ name="data_agent",
51
+ description="Specialized agent for data analysis. Use this agent to analyze data, perform calculations, and extract insights from structured data.",
52
+ add_base_tools=True,
53
+ additional_authorized_imports=["pandas", "numpy", "math", "csv", "io"],
54
+ )
55
+
56
+ return data_agent
57
+
58
+
59
+ def create_media_agent(model):
60
+ """
61
+ Create a specialized agent for handling media (images, PDFs).
62
+
63
+ Args:
64
+ model: The model to use for the agent
65
+
66
+ Returns:
67
+ Configured CodeAgent for media handling
68
+ """
69
+ media_agent = CodeAgent(
70
+ tools=[analyze_image, read_pdf],
71
+ model=model,
72
+ name="media_agent",
73
+ description="Specialized agent for handling media files like images and PDFs. Use this agent to analyze images and extract text from PDF documents.",
74
+ add_base_tools=True,
75
+ additional_authorized_imports=["PIL", "io", "requests"],
76
+ )
77
+
78
+ return media_agent
tools.py ADDED
@@ -0,0 +1,254 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import io
2
+ import re
3
+ from typing import Any, Dict, List
4
+
5
+ import pandas as pd
6
+ import requests
7
+ from bs4 import BeautifulSoup
8
+ from PIL import Image
9
+ from smolagents import tool
10
+ from smolagents.default_tools import DuckDuckGoSearchTool, VisitWebpageTool
11
+
12
+
13
+ @tool
14
+ def web_search(query: str) -> str:
15
+ """
16
+ Search the web for information.
17
+
18
+ Args:
19
+ query: Search query to find information
20
+
21
+ Returns:
22
+ Search results as text
23
+ """
24
+ # Using the built-in DuckDuckGo search tool from smolagents
25
+ # search_tool = DuckDuckGoSearchTool()
26
+ search_tool = DuckDuckGoSearchTool(max_results=3)
27
+ results = search_tool.execute(query)
28
+ return results
29
+
30
+
31
+ @tool
32
+ def browse_webpage(url: str) -> Dict[str, Any]:
33
+ """
34
+ Browse a webpage and extract its content.
35
+
36
+ Args:
37
+ url: URL of the webpage to browse
38
+
39
+ Returns:
40
+ Dictionary containing title, text content, and links from the webpage
41
+ """
42
+ try:
43
+ headers = {
44
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
45
+ }
46
+ response = requests.get(url, headers=headers)
47
+ response.raise_for_status()
48
+
49
+ soup = BeautifulSoup(response.text, "html.parser")
50
+
51
+ # Extract title
52
+ title = soup.title.string if soup.title else "No title found"
53
+
54
+ # Extract main text content
55
+ paragraphs = soup.find_all("p")
56
+ text_content = "\n".join([p.get_text().strip() for p in paragraphs])
57
+
58
+ # Extract links
59
+ links = []
60
+ for link in soup.find_all("a", href=True):
61
+ href = link["href"]
62
+ text = link.get_text().strip()
63
+ if href.startswith("http"):
64
+ links.append({"text": text, "href": href})
65
+
66
+ return {"title": title, "content": text_content, "links": links}
67
+ except Exception as e:
68
+ return {"error": str(e)}
69
+
70
+
71
+ @tool
72
+ def analyze_image(image_url: str) -> Dict[str, Any]:
73
+ """
74
+ Analyze an image and extract information from it.
75
+
76
+ Args:
77
+ image_url: URL of the image to analyze
78
+
79
+ Returns:
80
+ Dictionary containing information about the image
81
+ """
82
+ try:
83
+ # Download the image
84
+ response = requests.get(image_url)
85
+ response.raise_for_status()
86
+
87
+ # Open the image
88
+ img = Image.open(io.BytesIO(response.content))
89
+
90
+ # Extract basic image information
91
+ width, height = img.size
92
+ format_type = img.format
93
+ mode = img.mode
94
+
95
+ return {
96
+ "width": width,
97
+ "height": height,
98
+ "format": format_type,
99
+ "mode": mode,
100
+ "aspect_ratio": width / height,
101
+ }
102
+ except Exception as e:
103
+ return {"error": str(e)}
104
+
105
+
106
+ @tool
107
+ def read_pdf(pdf_url: str) -> str:
108
+ """
109
+ Extract text content from a PDF document.
110
+
111
+ Args:
112
+ pdf_url: URL of the PDF to read
113
+
114
+ Returns:
115
+ Text content extracted from the PDF
116
+ """
117
+ try:
118
+ # Download the PDF
119
+ response = requests.get(pdf_url)
120
+ response.raise_for_status()
121
+
122
+ # This is a placeholder - in a real implementation, you would use a PDF parsing library
123
+ # such as PyPDF2, pdfplumber, or pdf2text
124
+ return "PDF content extraction would happen here in a real implementation"
125
+ except Exception as e:
126
+ return f"Error: {str(e)}"
127
+
128
+
129
+ @tool
130
+ def parse_csv(csv_url: str) -> Dict[str, Any]:
131
+ """
132
+ Parse a CSV file and return its content as structured data.
133
+
134
+ Args:
135
+ csv_url: URL of the CSV file to parse
136
+
137
+ Returns:
138
+ Dictionary containing parsed CSV data
139
+ """
140
+ try:
141
+ # Download the CSV
142
+ response = requests.get(csv_url)
143
+ response.raise_for_status()
144
+
145
+ # Parse the CSV
146
+ df = pd.read_csv(io.StringIO(response.text))
147
+
148
+ # Convert to dictionary format
149
+ columns = df.columns.tolist()
150
+ data = df.to_dict(orient="records")
151
+
152
+ # Return basic statistics and preview
153
+ return {
154
+ "columns": columns,
155
+ "row_count": len(data),
156
+ "preview": data[:5] if len(data) > 5 else data,
157
+ "column_dtypes": {col: str(df[col].dtype) for col in columns},
158
+ }
159
+ except Exception as e:
160
+ return {"error": str(e)}
161
+
162
+
163
+ @tool
164
+ def find_in_page(page_content: Dict[str, Any], query: str) -> List[str]:
165
+ """
166
+ Find occurrences of a query string in page content.
167
+
168
+ Args:
169
+ page_content: Page content returned by browse_webpage
170
+ query: String to search for in the page
171
+
172
+ Returns:
173
+ List of sentences or sections containing the query
174
+ """
175
+ results = []
176
+ if "content" in page_content:
177
+ content = page_content["content"]
178
+ # Split content into sentences
179
+ sentences = re.split(r"(?<=[.!?])\s+", content)
180
+
181
+ # Find sentences containing the query
182
+ for sentence in sentences:
183
+ if query.lower() in sentence.lower():
184
+ results.append(sentence)
185
+
186
+ return results
187
+
188
+
189
+ @tool
190
+ def extract_dates(text: str) -> List[str]:
191
+ """
192
+ Extract dates from text content.
193
+
194
+ Args:
195
+ text: Text content to extract dates from
196
+
197
+ Returns:
198
+ List of date strings found in the text
199
+ """
200
+ # Simple regex patterns for date extraction
201
+ # These patterns can be expanded for better coverage
202
+ date_patterns = [
203
+ r"\d{1,2}/\d{1,2}/\d{2,4}", # MM/DD/YYYY or DD/MM/YYYY
204
+ r"\d{1,2}-\d{1,2}-\d{2,4}", # MM-DD-YYYY or DD-MM-YYYY
205
+ r"\b(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[a-z]* \d{1,2},? \d{4}\b", # Month DD, YYYY
206
+ r"\b\d{1,2} (?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[a-z]* \d{4}\b", # DD Month YYYY
207
+ ]
208
+
209
+ results = []
210
+ for pattern in date_patterns:
211
+ matches = re.findall(pattern, text, re.IGNORECASE)
212
+ results.extend(matches)
213
+
214
+ return results
215
+
216
+
217
+ @tool
218
+ def perform_calculation(expression: str) -> Dict[str, Any]:
219
+ """
220
+ Safely evaluate a mathematical expression.
221
+
222
+ Args:
223
+ expression: Mathematical expression to evaluate
224
+
225
+ Returns:
226
+ Dictionary containing the result or error message
227
+ """
228
+ try:
229
+ # Using a safer approach than eval()
230
+ # This is very limited but safer
231
+ import math
232
+
233
+ # Define allowed names
234
+ allowed_names = {
235
+ "abs": abs,
236
+ "round": round,
237
+ "min": min,
238
+ "max": max,
239
+ "sum": sum,
240
+ "len": len,
241
+ "pow": pow,
242
+ "math": math,
243
+ }
244
+
245
+ # Clean the expression
246
+ cleaned_expr = expression.strip()
247
+
248
+ # Evaluate using safer methods (this is still a simplified example)
249
+ # In a real implementation, use a proper math expression parser
250
+ result = eval(cleaned_expr, {"__builtins__": {}}, allowed_names)
251
+
252
+ return {"result": result}
253
+ except Exception as e:
254
+ return {"error": str(e)}