agercas commited on
Commit
24665ea
·
1 Parent(s): e4223d1
Files changed (1) hide show
  1. src/tools.py +133 -104
src/tools.py CHANGED
@@ -14,6 +14,8 @@ import requests
14
  import whisper
15
  import wikipedia
16
  from bs4 import BeautifulSoup
 
 
17
  from openpyxl import load_workbook
18
  from smolagents import tool
19
 
@@ -138,141 +140,61 @@ def fetch_webpage_content(url: str, max_length: int = 3000) -> str:
138
  return f"Error fetching webpage {url}: {str(e)}"
139
 
140
 
141
- # === MATHEMATICAL OPERATIONS ===
142
-
143
-
144
  @tool
145
- def add_numbers(*numbers: int | float) -> str:
146
  """
147
- Add multiple numbers together.
148
 
149
  Args:
150
- numbers: Variable number of integers or floats to add
151
 
152
  Returns:
153
- Sum of all numbers as string
154
  """
155
  try:
156
- if not numbers:
157
- return "Error: No numbers provided to add"
158
-
159
- # Convert strings to numbers if needed
160
- converted_numbers = []
161
- for num in numbers:
162
- if isinstance(num, str):
163
- try:
164
- converted_numbers.append(float(num) if "." in num else int(num))
165
- except ValueError:
166
- return f"Error: '{num}' is not a valid number"
167
- else:
168
- converted_numbers.append(num)
169
-
170
- result = sum(converted_numbers)
171
- return f"Sum of {converted_numbers} = {result}"
172
-
173
  except Exception as e:
174
- return f"Error adding numbers: {str(e)}"
175
 
176
 
177
  @tool
178
- def multiply_numbers(*numbers: int | float) -> str:
179
  """
180
- Multiply multiple numbers together.
181
 
182
  Args:
183
- numbers: Variable number of integers or floats to multiply
184
 
185
  Returns:
186
- Product of all numbers as string
187
  """
188
  try:
189
- if not numbers:
190
- return "Error: No numbers provided to multiply"
191
-
192
- # Convert strings to numbers if needed
193
- converted_numbers = []
194
- for num in numbers:
195
- if isinstance(num, str):
196
- try:
197
- converted_numbers.append(float(num) if "." in num else int(num))
198
- except ValueError:
199
- return f"Error: '{num}' is not a valid number"
200
- else:
201
- converted_numbers.append(num)
202
-
203
- result = 1
204
- for num in converted_numbers:
205
- result *= num
206
-
207
- return f"Product of {converted_numbers} = {result}"
208
-
209
- except Exception as e:
210
- return f"Error multiplying numbers: {str(e)}"
211
-
212
-
213
- @tool
214
- def divide_numbers(dividend: int | float, divisor: int | float) -> str:
215
- """
216
- Divide two numbers.
217
-
218
- Args:
219
- dividend: The number to be divided
220
- divisor: The number to divide by
221
-
222
- Returns:
223
- Result of division as string
224
- """
225
- try:
226
- # Convert strings to numbers if needed
227
- if isinstance(dividend, str):
228
- dividend = float(dividend) if "." in dividend else int(dividend)
229
- if isinstance(divisor, str):
230
- divisor = float(divisor) if "." in divisor else int(divisor)
231
-
232
- if divisor == 0:
233
- return "Error: Cannot divide by zero"
234
-
235
- result = dividend / divisor
236
- return f"{dividend} ÷ {divisor} = {result}"
237
-
238
- except ValueError as e:
239
- return f"Error: Invalid number format - {str(e)}"
240
  except Exception as e:
241
- return f"Error dividing numbers: {str(e)}"
242
 
243
 
244
  @tool
245
- def calculate_percentage(part: int | float, whole: int | float) -> str:
246
  """
247
- Calculate what percentage one number is of another.
248
 
249
  Args:
250
- part: The part value
251
- whole: The whole value
252
 
253
  Returns:
254
- Percentage calculation as string
255
  """
256
  try:
257
- # Convert strings to numbers if needed
258
- if isinstance(part, str):
259
- part = float(part) if "." in part else int(part)
260
- if isinstance(whole, str):
261
- whole = float(whole) if "." in whole else int(whole)
262
-
263
- if whole == 0:
264
- return "Error: Cannot calculate percentage with zero as whole"
265
-
266
- percentage = (part / whole) * 100
267
- return f"{part} is {percentage:.2f}% of {whole}"
268
-
269
- except ValueError as e:
270
- return f"Error: Invalid number format - {str(e)}"
271
  except Exception as e:
272
- return f"Error calculating percentage: {str(e)}"
273
-
274
-
275
- # === FILE PROCESSING TOOLS ===
276
 
277
 
278
  @tool
@@ -661,3 +583,110 @@ def count_items_in_list(items_text: str, separator: str = ",") -> str:
661
 
662
  except Exception as e:
663
  return f"Error counting items: {str(e)}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  import whisper
15
  import wikipedia
16
  from bs4 import BeautifulSoup
17
+ from langchain_community.tools import DuckDuckGoSearchRun, WikipediaQueryRun
18
+ from langchain_community.utilities import ArxivAPIWrapper, WikipediaAPIWrapper
19
  from openpyxl import load_workbook
20
  from smolagents import tool
21
 
 
140
  return f"Error fetching webpage {url}: {str(e)}"
141
 
142
 
 
 
 
143
  @tool
144
+ def arxiv_search(query: str) -> str:
145
  """
146
+ Search arXiv papers.
147
 
148
  Args:
149
+ query: Search query or paper ID (e.g., "1605.08386")
150
 
151
  Returns:
152
+ str: arXiv paper information
153
  """
154
  try:
155
+ arxiv = ArxivAPIWrapper()
156
+ docs = arxiv.run(query)
157
+ return str(docs)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
158
  except Exception as e:
159
+ return f"arXiv search error: {str(e)}"
160
 
161
 
162
  @tool
163
+ def wikipedia_search_tool(query: str) -> str:
164
  """
165
+ Search Wikipedia using LangChain's WikipediaQueryRun.
166
 
167
  Args:
168
+ query: Search query
169
 
170
  Returns:
171
+ str: Wikipedia search results
172
  """
173
  try:
174
+ wikipedia = WikipediaQueryRun(api_wrapper=WikipediaAPIWrapper())
175
+ result = wikipedia.run(query)
176
+ return result
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
177
  except Exception as e:
178
+ return f"Wikipedia search error: {str(e)}"
179
 
180
 
181
  @tool
182
+ def duckduckgo_search(query: str) -> str:
183
  """
184
+ Search using DuckDuckGo.
185
 
186
  Args:
187
+ query: Search query
 
188
 
189
  Returns:
190
+ str: DuckDuckGo search results
191
  """
192
  try:
193
+ search = DuckDuckGoSearchRun()
194
+ result = search.invoke(query)
195
+ return result
 
 
 
 
 
 
 
 
 
 
 
196
  except Exception as e:
197
+ return f"DuckDuckGo search error: {str(e)}"
 
 
 
198
 
199
 
200
  @tool
 
583
 
584
  except Exception as e:
585
  return f"Error counting items: {str(e)}"
586
+
587
+
588
+ @tool
589
+ def ocr_tool(image_path: str) -> str:
590
+ """
591
+ Extract text from images using OCR.
592
+
593
+ Args:
594
+ image_path: Path to image file
595
+
596
+ Returns:
597
+ str: Extracted text
598
+ """
599
+ try:
600
+ import pytesseract
601
+ from PIL import Image
602
+
603
+ image = Image.open(image_path)
604
+ text = pytesseract.image_to_string(image)
605
+ return f"OCR text from {image_path}:\n{text.strip()}"
606
+
607
+ except ImportError:
608
+ return "Error: pytesseract not installed. Install with: pip install pytesseract"
609
+ except Exception as e:
610
+ return f"OCR error: {str(e)}"
611
+
612
+
613
+ @tool
614
+ def image_captioning_tool(image_path: str) -> str:
615
+ """
616
+ Generate basic image information (placeholder for actual captioning).
617
+
618
+ Args:
619
+ image_path: Path to image file
620
+
621
+ Returns:
622
+ str: Basic image information
623
+ """
624
+ try:
625
+ from PIL import Image
626
+
627
+ image = Image.open(image_path)
628
+ width, height = image.size
629
+ mode = image.mode
630
+ format_type = image.format
631
+
632
+ caption = f"Image: {image_path}\n"
633
+ caption += f"Dimensions: {width}x{height} pixels\n"
634
+ caption += f"Mode: {mode}\n"
635
+ caption += f"Format: {format_type}\n"
636
+ caption += "Note: For detailed content description, integrate with a vision model."
637
+
638
+ return caption
639
+
640
+ except Exception as e:
641
+ return f"Image info error: {str(e)}"
642
+
643
+
644
+ @tool
645
+ def visual_qa_tool(image_path: str, question: str) -> str:
646
+ """
647
+ Answer questions about images (placeholder for actual VQA).
648
+
649
+ Args:
650
+ image_path: Path to image file
651
+ question: Question about the image
652
+
653
+ Returns:
654
+ str: Basic response about the image
655
+ """
656
+ try:
657
+ from PIL import Image
658
+
659
+ image = Image.open(image_path)
660
+ width, height = image.size
661
+ mode = image.mode
662
+
663
+ response = f"Question: {question}\n"
664
+ response += f"Image: {image_path} ({width}x{height}, {mode})\n"
665
+ response += "Note: For actual visual QA, integrate with a vision-language model."
666
+
667
+ return response
668
+
669
+ except Exception as e:
670
+ return f"Visual QA error: {str(e)}"
671
+
672
+
673
+ all_tools = [
674
+ wikipedia_search,
675
+ web_search_duckduckgo,
676
+ fetch_webpage_content,
677
+ arxiv_search,
678
+ wikipedia_search_tool,
679
+ duckduckgo_search,
680
+ load_csv_file,
681
+ load_excel_file,
682
+ read_text_file,
683
+ transcribe_audio_file,
684
+ analyze_chess_position,
685
+ reverse_string,
686
+ reverse_words_in_string,
687
+ analyze_table_commutativity,
688
+ count_items_in_list,
689
+ ocr_tool,
690
+ image_captioning_tool,
691
+ visual_qa_tool,
692
+ ]