superone001 commited on
Commit
1862d27
·
verified ·
1 Parent(s): c7e11bd

Update ai_tools.py

Browse files
Files changed (1) hide show
  1. ai_tools.py +344 -61
ai_tools.py CHANGED
@@ -1,62 +1,345 @@
 
 
 
1
  import re
2
- from duckduckgo_search import DDGS
3
- from typing import List, Dict, Any
4
-
5
- class BaseTool:
6
- def __init__(self, name: str, description: str):
7
- self.name = name
8
- self.description = description
9
-
10
- def run(self, *args, **kwargs) -> str:
11
- raise NotImplementedError
12
-
13
- class Calculator(BaseTool):
14
- def __init__(self):
15
- super().__init__(
16
- name="Calculator",
17
- description="Performs basic arithmetic. Input: math expression as string"
18
- )
19
-
20
- def run(self, expression: str) -> str:
21
- try:
22
- expression = expression.replace(' ', '')
23
- if not re.match(r'^[\d+\-*/.()]+$', expression):
24
- return "Error: Invalid characters in expression"
25
- result = eval(expression)
26
- return str(result)
27
- except Exception as e:
28
- return f"Calculation error: {str(e)}"
29
-
30
- class DocRetriever(BaseTool):
31
- def __init__(self):
32
- super().__init__(
33
- name="DocRetriever",
34
- description="Searches provided text. Input: 'query: <search_term>'"
35
- )
36
- self.document = ""
37
-
38
- def load_document(self, text: str):
39
- self.document = text
40
-
41
- def run(self, query: str) -> str:
42
- if not self.document:
43
- return "No document loaded"
44
-
45
- sentences = [s.strip() for s in self.document.split('.') if s]
46
- results = [s for s in sentences if query.lower() in s.lower()]
47
- return '. '.join(results[:3]) + '...' if results else "No matches found"
48
-
49
- class WebSearcher(BaseTool):
50
- def __init__(self):
51
- super().__init__(
52
- name="WebSearcher",
53
- description="Searches the web. Input: search query"
54
- )
55
-
56
- def run(self, query: str) -> str:
57
- try:
58
- with DDGS() as ddgs:
59
- results = [r for r in ddgs.text(query, max_results=3)]
60
- return '\n'.join([f"[{r['title']}]({r['href']}): {r['body']}" for r in results])
61
- except Exception as e:
62
- return f"Search error: {str(e)}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langchain.tools import tool
2
+ import requests
3
+ import math
4
  import re
5
+ from datetime import datetime, timedelta
6
+
7
+ # === 基础计算工具 ===
8
+ @tool
9
+ def calculator(expression: str) -> str:
10
+ """
11
+ 执行数学计算,支持加减乘除、指数、对数、三角函数等。
12
+ 示例:
13
+ - "2 + 3 * 4" -> 14
14
+ - "sqrt(16)" -> 4.0
15
+ - "log10(100)" -> 2.0
16
+ """
17
+ try:
18
+ # 安全检查 - 只允许数学表达式
19
+ if re.search(r"[a-zA-Z_`'\"]", expression):
20
+ return "Error: Expression contains invalid characters"
21
+
22
+ # 替换常用数学函数
23
+ expression = expression.replace("^", "**")
24
+ expression = expression.replace("sqrt", "math.sqrt")
25
+ expression = expression.replace("log", "math.log10")
26
+ expression = expression.replace("ln", "math.log")
27
+ expression = expression.replace("sin", "math.sin")
28
+ expression = expression.replace("cos", "math.cos")
29
+ expression = expression.replace("tan", "math.tan")
30
+
31
+ # 添加math模块的常量
32
+ if "pi" in expression:
33
+ expression = expression.replace("pi", str(math.pi))
34
+ if "e" in expression:
35
+ expression = expression.replace("e", str(math.e))
36
+
37
+ # 执行计算
38
+ result = eval(expression, {"__builtins__": None}, {"math": math})
39
+ return str(round(result, 6)) if isinstance(result, float) else str(result)
40
+ except Exception as e:
41
+ return f"Calculation error: {str(e)}"
42
+
43
+ # === 科学计算工具 ===
44
+ @tool
45
+ def scientific_calculator(operation: str, values: list) -> str:
46
+ """
47
+ 执行高级科学计算:
48
+ - 统计: 'mean', 'median', 'mode', 'std'
49
+ - 金融: 'compound_interest'
50
+ - 几何: 'area_circle', 'volume_sphere'
51
+ - 三角: 'hypotenuse'
52
+ """
53
+ try:
54
+ operation = operation.lower()
55
+
56
+ if operation == "mean":
57
+ return str(sum(values) / len(values))
58
+
59
+ elif operation == "median":
60
+ sorted_vals = sorted(values)
61
+ n = len(sorted_vals)
62
+ mid = n // 2
63
+ return str(sorted_vals[mid] if n % 2 else (sorted_vals[mid-1] + sorted_vals[mid]) / 2)
64
+
65
+ elif operation == "mode":
66
+ from collections import Counter
67
+ count = Counter(values)
68
+ max_count = max(count.values())
69
+ modes = [k for k, v in count.items() if v == max_count]
70
+ return str(modes[0] if len(modes) == 1 else modes)
71
+
72
+ elif operation == "std":
73
+ mean = sum(values) / len(values)
74
+ variance = sum((x - mean) ** 2 for x in values) / len(values)
75
+ return str(math.sqrt(variance))
76
+
77
+ elif operation == "compound_interest":
78
+ principal, rate, time, periods = values
79
+ amount = principal * (1 + rate/(periods*100)) ** (periods*time)
80
+ return str(round(amount, 2))
81
+
82
+ elif operation == "area_circle":
83
+ return str(math.pi * values[0] ** 2)
84
+
85
+ elif operation == "volume_sphere":
86
+ return str((4/3) * math.pi * values[0] ** 3)
87
+
88
+ elif operation == "hypotenuse":
89
+ return str(math.sqrt(values[0]**2 + values[1]**2))
90
+
91
+ else:
92
+ return f"Unknown operation: {operation}"
93
+
94
+ except Exception as e:
95
+ return f"Scientific calculation error: {str(e)}"
96
+
97
+ # === 单位转换工具 ===
98
+ @tool
99
+ def unit_converter(value: float, from_unit: str, to_unit: str) -> str:
100
+ """
101
+ 执行单位转换,支持:
102
+ - 长度: m, km, cm, mm, inch, foot, mile
103
+ - 重量: g, kg, mg, lb, oz
104
+ - 温度: C, F, K
105
+ - 体积: L, mL, gallon, pint
106
+ """
107
+ try:
108
+ # 长度转换
109
+ length_factors = {
110
+ 'm': 1, 'km': 1000, 'cm': 0.01, 'mm': 0.001,
111
+ 'inch': 0.0254, 'foot': 0.3048, 'mile': 1609.34
112
+ }
113
+
114
+ # 重量转换
115
+ weight_factors = {
116
+ 'kg': 1, 'g': 0.001, 'mg': 0.000001,
117
+ 'lb': 0.453592, 'oz': 0.0283495
118
+ }
119
+
120
+ # 体积转换
121
+ volume_factors = {
122
+ 'L': 1, 'mL': 0.001, 'gallon': 3.78541, 'pint': 0.473176
123
+ }
124
+
125
+ # 温度转换
126
+ if from_unit.upper() in ['C', 'F', 'K'] and to_unit.upper() in ['C', 'F', 'K']:
127
+ temp = value
128
+ if from_unit.upper() == 'C':
129
+ if to_unit.upper() == 'F':
130
+ return str(temp * 9/5 + 32)
131
+ elif to_unit.upper() == 'K':
132
+ return str(temp + 273.15)
133
+ elif from_unit.upper() == 'F':
134
+ if to_unit.upper() == 'C':
135
+ return str((temp - 32) * 5/9)
136
+ elif to_unit.upper() == 'K':
137
+ return str((temp - 32) * 5/9 + 273.15)
138
+ elif from_unit.upper() == 'K':
139
+ if to_unit.upper() == 'C':
140
+ return str(temp - 273.15)
141
+ elif to_unit.upper() == 'F':
142
+ return str((temp - 273.15) * 9/5 + 32)
143
+ return str(value)
144
+
145
+ # 长度转换
146
+ if from_unit in length_factors and to_unit in length_factors:
147
+ return str(value * length_factors[from_unit] / length_factors[to_unit])
148
+
149
+ # 重量转换
150
+ if from_unit in weight_factors and to_unit in weight_factors:
151
+ return str(value * weight_factors[from_unit] / weight_factors[to_unit])
152
+
153
+ # 体积转换
154
+ if from_unit in volume_factors and to_unit in volume_factors:
155
+ return str(value * volume_factors[from_unit] / volume_factors[to_unit])
156
+
157
+ return f"Unsupported conversion: {from_unit} to {to_unit}"
158
+
159
+ except Exception as e:
160
+ return f"Unit conversion error: {str(e)}"
161
+
162
+ # === 时间计算工具 ===
163
+ @tool
164
+ def time_calculator(operation: str, base_time: str = None, duration: str = None, timezone: str = None) -> str:
165
+ """
166
+ 执行时间计算:
167
+ - 'current_time': 获取当前时间
168
+ - 'add_duration': 添加时间间隔
169
+ - 'subtract_duration': 减去时间间隔
170
+ - 'time_diff': 计算两个时间的差值
171
+
172
+ 时间格式: YYYY-MM-DD HH:MM:SS
173
+ 持续时间格式: Xd Yh Zm (例如: 2d 3h 30m)
174
+ """
175
+ try:
176
+ now = datetime.utcnow()
177
+
178
+ if operation == "current_time":
179
+ return now.strftime("%Y-%m-%d %H:%M:%S UTC")
180
+
181
+ elif operation == "add_duration" and base_time and duration:
182
+ base = datetime.strptime(base_time, "%Y-%m-%d %H:%M:%S")
183
+ return add_duration(base, duration)
184
+
185
+ elif operation == "subtract_duration" and base_time and duration:
186
+ base = datetime.strptime(base_time, "%Y-%m-%d %H:%M:%S")
187
+ return subtract_duration(base, duration)
188
+
189
+ elif operation == "time_diff" and duration:
190
+ parts = duration.split()
191
+ time1 = datetime.strptime(parts[0], "%Y-%m-%d")
192
+ time2 = datetime.strptime(parts[1], "%Y-%m-%d")
193
+ diff = abs((time2 - time1).days)
194
+ return f"{diff} days"
195
+
196
+ return "Invalid operation or missing parameters"
197
+
198
+ except Exception as e:
199
+ return f"Time calculation error: {str(e)}"
200
+
201
+ def add_duration(base: datetime, duration: str) -> str:
202
+ """添加持续时间到基础时间"""
203
+ parts = duration.split()
204
+ delta = timedelta()
205
+ for part in parts:
206
+ if part.endswith('d'):
207
+ delta += timedelta(days=int(part[:-1]))
208
+ elif part.endswith('h'):
209
+ delta += timedelta(hours=int(part[:-1]))
210
+ elif part.endswith('m'):
211
+ delta += timedelta(minutes=int(part[:-1]))
212
+ return (base + delta).strftime("%Y-%m-%d %H:%M:%S")
213
+
214
+ def subtract_duration(base: datetime, duration: str) -> str:
215
+ """从基础时间减去持续时间"""
216
+ parts = duration.split()
217
+ delta = timedelta()
218
+ for part in parts:
219
+ if part.endswith('d'):
220
+ delta += timedelta(days=int(part[:-1]))
221
+ elif part.endswith('h'):
222
+ delta += timedelta(hours=int(part[:-1]))
223
+ elif part.endswith('m'):
224
+ delta += timedelta(minutes=int(part[:-1]))
225
+ return (base - delta).strftime("%Y-%m-%d %H:%M:%S")
226
+
227
+ # === 网络搜索工具 ===
228
+ @tool
229
+ def web_search(query: str, max_results: int = 3) -> str:
230
+ """
231
+ 执行网络搜索并返回相关结果。使用DuckDuckGo作为搜索引擎。
232
+
233
+ 参数:
234
+ query: 搜索查询
235
+ max_results: 返回的最大结果数 (默认3)
236
+
237
+ 返回: 格式化的搜索结果
238
+ """
239
+ try:
240
+ url = "https://api.duckduckgo.com/"
241
+ params = {
242
+ "q": query,
243
+ "format": "json",
244
+ "no_redirect": 1,
245
+ "no_html": 1,
246
+ "skip_disambig": 1
247
+ }
248
+
249
+ response = requests.get(url, params=params, timeout=10)
250
+ data = response.json()
251
+
252
+ # 处理搜索结果
253
+ results = []
254
+
255
+ # 主要摘要
256
+ if data.get("AbstractText"):
257
+ results.append(f"摘要: {data['AbstractText']}")
258
+
259
+ # 相关主题
260
+ if data.get("RelatedTopics"):
261
+ for i, topic in enumerate(data["RelatedTopics"]):
262
+ if i >= max_results:
263
+ break
264
+ if "Text" in topic:
265
+ results.append(f"{i+1}. {topic['Text']} [来源: {topic.get('FirstURL', '未知')}]")
266
+
267
+ # 如果没有结果
268
+ if not results:
269
+ return "未找到相关信息"
270
+
271
+ return "\n\n".join(results)
272
+
273
+ except Exception as e:
274
+ return f"搜索错误: {str(e)}"
275
+
276
+ # === 货币转换工具 ===
277
+ @tool
278
+ def currency_converter(amount: float, from_currency: str, to_currency: str) -> str:
279
+ """
280
+ 使用实时汇率转换货币
281
+
282
+ 支持的货币: USD, EUR, GBP, JPY, CNY, CAD, AUD, CHF, INR, RUB
283
+ """
284
+ try:
285
+ # 使用免费API获取汇率
286
+ url = f"https://api.exchangerate-api.com/v4/latest/{from_currency.upper()}"
287
+ response = requests.get(url, timeout=5)
288
+ data = response.json()
289
+
290
+ if "error" in data:
291
+ return f"货币错误: {data['error']}"
292
+
293
+ rates = data.get("rates", {})
294
+ rate = rates.get(to_currency.upper())
295
+
296
+ if not rate:
297
+ return f"不支持的目标货币: {to_currency}"
298
+
299
+ converted = amount * rate
300
+ return f"{amount} {from_currency.upper()} = {converted:.2f} {to_currency.upper()}"
301
+
302
+ except Exception as e:
303
+ return f"货币转换错误: {str(e)}"
304
+
305
+ # === 获取所有工具 ===
306
+ def get_tools():
307
+ return [
308
+ calculator,
309
+ scientific_calculator,
310
+ unit_converter,
311
+ time_calculator,
312
+ web_search,
313
+ currency_converter
314
+ ]
315
+
316
+ # === 测试代码 ===
317
+ if __name__ == "__main__":
318
+ # 测试计算器
319
+ print("计算器测试:")
320
+ print(calculator("2 + 3 * 4")) # 14
321
+ print(calculator("sqrt(16)")) # 4.0
322
+ print(calculator("sin(pi/2)")) # 1.0
323
+
324
+ # 测试科学计算器
325
+ print("\n科学计算器测试:")
326
+ print(scientific_calculator("mean", [1, 2, 3, 4, 5])) # 3.0
327
+ print(scientific_calculator("compound_interest", [1000, 5, 10, 1])) # 1628.89
328
+
329
+ # 测试单位转换
330
+ print("\n单位转换测试:")
331
+ print(unit_converter(10, "km", "m")) # 10000.0
332
+ print(unit_converter(32, "F", "C")) # 0.0
333
+
334
+ # 测试时间计算
335
+ print("\n时间计算测试:")
336
+ print(time_calculator("current_time"))
337
+ print(time_calculator("add_duration", "2023-01-01 00:00:00", "2d 3h"))
338
+
339
+ # 测试网络搜索
340
+ print("\n网络搜索测试:")
341
+ print(web_search("Python programming", max_results=2))
342
+
343
+ # 测试货币转换
344
+ print("\n货币转换测试:")
345
+ print(currency_converter(100, "USD", "EUR"))