File size: 11,827 Bytes
1862d27
 
 
82c5973
1862d27
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
from langchain.tools import tool
import requests
import math
import re
from datetime import datetime, timedelta

# === 基础计算工具 ===
@tool
def calculator(expression: str) -> str:
    """
    执行数学计算,支持加减乘除、指数、对数、三角函数等。
    示例: 
    - "2 + 3 * 4" -> 14
    - "sqrt(16)" -> 4.0
    - "log10(100)" -> 2.0
    """
    try:
        # 安全检查 - 只允许数学表达式
        if re.search(r"[a-zA-Z_`'\"]", expression):
            return "Error: Expression contains invalid characters"
        
        # 替换常用数学函数
        expression = expression.replace("^", "**")
        expression = expression.replace("sqrt", "math.sqrt")
        expression = expression.replace("log", "math.log10")
        expression = expression.replace("ln", "math.log")
        expression = expression.replace("sin", "math.sin")
        expression = expression.replace("cos", "math.cos")
        expression = expression.replace("tan", "math.tan")
        
        # 添加math模块的常量
        if "pi" in expression:
            expression = expression.replace("pi", str(math.pi))
        if "e" in expression:
            expression = expression.replace("e", str(math.e))
        
        # 执行计算
        result = eval(expression, {"__builtins__": None}, {"math": math})
        return str(round(result, 6)) if isinstance(result, float) else str(result)
    except Exception as e:
        return f"Calculation error: {str(e)}"

# === 科学计算工具 ===
@tool
def scientific_calculator(operation: str, values: list) -> str:
    """
    执行高级科学计算:
    - 统计: 'mean', 'median', 'mode', 'std'
    - 金融: 'compound_interest'
    - 几何: 'area_circle', 'volume_sphere'
    - 三角: 'hypotenuse'
    """
    try:
        operation = operation.lower()
        
        if operation == "mean":
            return str(sum(values) / len(values))
            
        elif operation == "median":
            sorted_vals = sorted(values)
            n = len(sorted_vals)
            mid = n // 2
            return str(sorted_vals[mid] if n % 2 else (sorted_vals[mid-1] + sorted_vals[mid]) / 2)
            
        elif operation == "mode":
            from collections import Counter
            count = Counter(values)
            max_count = max(count.values())
            modes = [k for k, v in count.items() if v == max_count]
            return str(modes[0] if len(modes) == 1 else modes)
            
        elif operation == "std":
            mean = sum(values) / len(values)
            variance = sum((x - mean) ** 2 for x in values) / len(values)
            return str(math.sqrt(variance))
            
        elif operation == "compound_interest":
            principal, rate, time, periods = values
            amount = principal * (1 + rate/(periods*100)) ** (periods*time)
            return str(round(amount, 2))
            
        elif operation == "area_circle":
            return str(math.pi * values[0] ** 2)
            
        elif operation == "volume_sphere":
            return str((4/3) * math.pi * values[0] ** 3)
            
        elif operation == "hypotenuse":
            return str(math.sqrt(values[0]**2 + values[1]**2))
            
        else:
            return f"Unknown operation: {operation}"
            
    except Exception as e:
        return f"Scientific calculation error: {str(e)}"

# === 单位转换工具 ===
@tool
def unit_converter(value: float, from_unit: str, to_unit: str) -> str:
    """
    执行单位转换,支持:
    - 长度: m, km, cm, mm, inch, foot, mile
    - 重量: g, kg, mg, lb, oz
    - 温度: C, F, K
    - 体积: L, mL, gallon, pint
    """
    try:
        # 长度转换
        length_factors = {
            'm': 1, 'km': 1000, 'cm': 0.01, 'mm': 0.001,
            'inch': 0.0254, 'foot': 0.3048, 'mile': 1609.34
        }
        
        # 重量转换
        weight_factors = {
            'kg': 1, 'g': 0.001, 'mg': 0.000001,
            'lb': 0.453592, 'oz': 0.0283495
        }
        
        # 体积转换
        volume_factors = {
            'L': 1, 'mL': 0.001, 'gallon': 3.78541, 'pint': 0.473176
        }
        
        # 温度转换
        if from_unit.upper() in ['C', 'F', 'K'] and to_unit.upper() in ['C', 'F', 'K']:
            temp = value
            if from_unit.upper() == 'C':
                if to_unit.upper() == 'F':
                    return str(temp * 9/5 + 32)
                elif to_unit.upper() == 'K':
                    return str(temp + 273.15)
            elif from_unit.upper() == 'F':
                if to_unit.upper() == 'C':
                    return str((temp - 32) * 5/9)
                elif to_unit.upper() == 'K':
                    return str((temp - 32) * 5/9 + 273.15)
            elif from_unit.upper() == 'K':
                if to_unit.upper() == 'C':
                    return str(temp - 273.15)
                elif to_unit.upper() == 'F':
                    return str((temp - 273.15) * 9/5 + 32)
            return str(value)
        
        # 长度转换
        if from_unit in length_factors and to_unit in length_factors:
            return str(value * length_factors[from_unit] / length_factors[to_unit])
        
        # 重量转换
        if from_unit in weight_factors and to_unit in weight_factors:
            return str(value * weight_factors[from_unit] / weight_factors[to_unit])
        
        # 体积转换
        if from_unit in volume_factors and to_unit in volume_factors:
            return str(value * volume_factors[from_unit] / volume_factors[to_unit])
        
        return f"Unsupported conversion: {from_unit} to {to_unit}"
    
    except Exception as e:
        return f"Unit conversion error: {str(e)}"

# === 时间计算工具 ===
@tool
def time_calculator(operation: str, base_time: str = None, duration: str = None, timezone: str = None) -> str:
    """
    执行时间计算:
    - 'current_time': 获取当前时间
    - 'add_duration': 添加时间间隔
    - 'subtract_duration': 减去时间间隔
    - 'time_diff': 计算两个时间的差值
    
    时间格式: YYYY-MM-DD HH:MM:SS
    持续时间格式: Xd Yh Zm (例如: 2d 3h 30m)
    """
    try:
        now = datetime.utcnow()
        
        if operation == "current_time":
            return now.strftime("%Y-%m-%d %H:%M:%S UTC")
        
        elif operation == "add_duration" and base_time and duration:
            base = datetime.strptime(base_time, "%Y-%m-%d %H:%M:%S")
            return add_duration(base, duration)
        
        elif operation == "subtract_duration" and base_time and duration:
            base = datetime.strptime(base_time, "%Y-%m-%d %H:%M:%S")
            return subtract_duration(base, duration)
        
        elif operation == "time_diff" and duration:
            parts = duration.split()
            time1 = datetime.strptime(parts[0], "%Y-%m-%d")
            time2 = datetime.strptime(parts[1], "%Y-%m-%d")
            diff = abs((time2 - time1).days)
            return f"{diff} days"
        
        return "Invalid operation or missing parameters"
    
    except Exception as e:
        return f"Time calculation error: {str(e)}"

def add_duration(base: datetime, duration: str) -> str:
    """添加持续时间到基础时间"""
    parts = duration.split()
    delta = timedelta()
    for part in parts:
        if part.endswith('d'):
            delta += timedelta(days=int(part[:-1]))
        elif part.endswith('h'):
            delta += timedelta(hours=int(part[:-1]))
        elif part.endswith('m'):
            delta += timedelta(minutes=int(part[:-1]))
    return (base + delta).strftime("%Y-%m-%d %H:%M:%S")

def subtract_duration(base: datetime, duration: str) -> str:
    """从基础时间减去持续时间"""
    parts = duration.split()
    delta = timedelta()
    for part in parts:
        if part.endswith('d'):
            delta += timedelta(days=int(part[:-1]))
        elif part.endswith('h'):
            delta += timedelta(hours=int(part[:-1]))
        elif part.endswith('m'):
            delta += timedelta(minutes=int(part[:-1]))
    return (base - delta).strftime("%Y-%m-%d %H:%M:%S")

# === 网络搜索工具 ===
@tool
def web_search(query: str, max_results: int = 3) -> str:
    """
    执行网络搜索并返回相关结果。使用DuckDuckGo作为搜索引擎。
    
    参数:
    query: 搜索查询
    max_results: 返回的最大结果数 (默认3)
    
    返回: 格式化的搜索结果
    """
    try:
        url = "https://api.duckduckgo.com/"
        params = {
            "q": query,
            "format": "json",
            "no_redirect": 1,
            "no_html": 1,
            "skip_disambig": 1
        }
        
        response = requests.get(url, params=params, timeout=10)
        data = response.json()
        
        # 处理搜索结果
        results = []
        
        # 主要摘要
        if data.get("AbstractText"):
            results.append(f"摘要: {data['AbstractText']}")
        
        # 相关主题
        if data.get("RelatedTopics"):
            for i, topic in enumerate(data["RelatedTopics"]):
                if i >= max_results:
                    break
                if "Text" in topic:
                    results.append(f"{i+1}. {topic['Text']} [来源: {topic.get('FirstURL', '未知')}]")
        
        # 如果没有结果
        if not results:
            return "未找到相关信息"
        
        return "\n\n".join(results)
    
    except Exception as e:
        return f"搜索错误: {str(e)}"

# === 货币转换工具 ===
@tool
def currency_converter(amount: float, from_currency: str, to_currency: str) -> str:
    """
    使用实时汇率转换货币
    
    支持的货币: USD, EUR, GBP, JPY, CNY, CAD, AUD, CHF, INR, RUB
    """
    try:
        # 使用免费API获取汇率
        url = f"https://api.exchangerate-api.com/v4/latest/{from_currency.upper()}"
        response = requests.get(url, timeout=5)
        data = response.json()
        
        if "error" in data:
            return f"货币错误: {data['error']}"
        
        rates = data.get("rates", {})
        rate = rates.get(to_currency.upper())
        
        if not rate:
            return f"不支持的目标货币: {to_currency}"
        
        converted = amount * rate
        return f"{amount} {from_currency.upper()} = {converted:.2f} {to_currency.upper()}"
    
    except Exception as e:
        return f"货币转换错误: {str(e)}"

# === 获取所有工具 ===
def get_tools():
    return [
        calculator,
        scientific_calculator,
        unit_converter,
        time_calculator,
        web_search,
        currency_converter
    ]

# === 测试代码 ===
if __name__ == "__main__":
    # 测试计算器
    print("计算器测试:")
    print(calculator("2 + 3 * 4"))  # 14
    print(calculator("sqrt(16)"))   # 4.0
    print(calculator("sin(pi/2)"))  # 1.0
    
    # 测试科学计算器
    print("\n科学计算器测试:")
    print(scientific_calculator("mean", [1, 2, 3, 4, 5]))  # 3.0
    print(scientific_calculator("compound_interest", [1000, 5, 10, 1]))  # 1628.89
    
    # 测试单位转换
    print("\n单位转换测试:")
    print(unit_converter(10, "km", "m"))  # 10000.0
    print(unit_converter(32, "F", "C"))   # 0.0
    
    # 测试时间计算
    print("\n时间计算测试:")
    print(time_calculator("current_time"))
    print(time_calculator("add_duration", "2023-01-01 00:00:00", "2d 3h"))
    
    # 测试网络搜索
    print("\n网络搜索测试:")
    print(web_search("Python programming", max_results=2))
    
    # 测试货币转换
    print("\n货币转换测试:")
    print(currency_converter(100, "USD", "EUR"))