praisonaiagents 0.0.23__py3-none-any.whl → 0.0.24__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,278 @@
1
+ """Tools for performing calculations.
2
+
3
+ Usage:
4
+ from praisonaiagents.tools import calculator_tools
5
+ result = calculator_tools.evaluate("2 + 2 * 3")
6
+
7
+ or
8
+ from praisonaiagents.tools import evaluate, solve_equation, convert_units
9
+ result = evaluate("2 + 2 * 3")
10
+ """
11
+
12
+ import logging
13
+ from typing import List, Dict, Optional, Any
14
+ from importlib import util
15
+ import math
16
+
17
+ class CalculatorTools:
18
+ """Tools for performing calculations."""
19
+
20
+ def __init__(self):
21
+ """Initialize CalculatorTools."""
22
+ self._check_dependencies()
23
+
24
+ def _check_dependencies(self):
25
+ """Check if required packages are installed."""
26
+ missing = []
27
+ for package in ['sympy', 'pint']:
28
+ if util.find_spec(package) is None:
29
+ missing.append(package)
30
+
31
+ if missing:
32
+ raise ImportError(
33
+ f"Required packages not available. Please install: {', '.join(missing)}\n"
34
+ f"Run: pip install {' '.join(missing)}"
35
+ )
36
+
37
+ def evaluate(
38
+ self,
39
+ expression: str,
40
+ variables: Optional[Dict[str, float]] = None,
41
+ precision: int = 10
42
+ ) -> Dict[str, Any]:
43
+ """Evaluate a mathematical expression."""
44
+ try:
45
+ if util.find_spec('sympy') is None:
46
+ error_msg = "sympy package is not available. Please install it using: pip install sympy"
47
+ logging.error(error_msg)
48
+ return {"error": error_msg}
49
+
50
+ # Import sympy only when needed
51
+ import sympy
52
+
53
+ # Replace common mathematical functions
54
+ expression = expression.lower()
55
+ replacements = {
56
+ 'sin(': 'math.sin(',
57
+ 'cos(': 'math.cos(',
58
+ 'tan(': 'math.tan(',
59
+ 'sqrt(': 'math.sqrt(',
60
+ 'log(': 'math.log(',
61
+ 'exp(': 'math.exp(',
62
+ 'pi': str(math.pi),
63
+ 'e': str(math.e)
64
+ }
65
+ for old, new in replacements.items():
66
+ expression = expression.replace(old, new)
67
+
68
+ # Create safe namespace
69
+ safe_dict = {
70
+ 'math': math,
71
+ '__builtins__': None
72
+ }
73
+ if variables:
74
+ safe_dict.update(variables)
75
+
76
+ # Evaluate expression
77
+ result = eval(expression, safe_dict)
78
+
79
+ # Round to specified precision
80
+ if isinstance(result, (int, float)):
81
+ return {"result": round(float(result), precision)}
82
+ return {"error": "Invalid expression"}
83
+ except Exception as e:
84
+ error_msg = f"Error evaluating expression: {str(e)}"
85
+ logging.error(error_msg)
86
+ return {"error": error_msg}
87
+
88
+ def solve_equation(
89
+ self,
90
+ equation: str,
91
+ variable: str = 'x'
92
+ ) -> Dict[str, Any]:
93
+ """Solve a mathematical equation."""
94
+ try:
95
+ if util.find_spec('sympy') is None:
96
+ error_msg = "sympy package is not available. Please install it using: pip install sympy"
97
+ logging.error(error_msg)
98
+ return {"error": error_msg}
99
+
100
+ # Import sympy only when needed
101
+ import sympy
102
+
103
+ # Parse equation
104
+ if '=' in equation:
105
+ left, right = equation.split('=')
106
+ equation = f"({left}) - ({right})"
107
+
108
+ # Convert to SymPy expression
109
+ x = sympy.Symbol(variable)
110
+ expr = sympy.sympify(equation)
111
+
112
+ # Solve equation
113
+ solutions = sympy.solve(expr, x)
114
+
115
+ # Convert complex solutions to real if possible
116
+ real_solutions = []
117
+ for sol in solutions:
118
+ if sol.is_real:
119
+ real_solutions.append(float(sol))
120
+
121
+ return {"solutions": real_solutions} if real_solutions else {"error": "No real solutions found"}
122
+ except Exception as e:
123
+ error_msg = f"Error solving equation: {str(e)}"
124
+ logging.error(error_msg)
125
+ return {"error": error_msg}
126
+
127
+ def convert_units(
128
+ self,
129
+ value: float,
130
+ from_unit: str,
131
+ to_unit: str
132
+ ) -> Dict[str, Any]:
133
+ """Convert between different units."""
134
+ try:
135
+ if util.find_spec('pint') is None:
136
+ error_msg = "pint package is not available. Please install it using: pip install pint"
137
+ logging.error(error_msg)
138
+ return {"error": error_msg}
139
+
140
+ # Import pint only when needed
141
+ import pint
142
+
143
+ # Create quantity with source unit
144
+ ureg = pint.UnitRegistry()
145
+ quantity = value * ureg(from_unit)
146
+
147
+ # Convert to target unit
148
+ result = quantity.to(to_unit)
149
+
150
+ return {"result": float(result.magnitude)}
151
+ except Exception as e:
152
+ error_msg = f"Error converting units: {str(e)}"
153
+ logging.error(error_msg)
154
+ return {"error": error_msg}
155
+
156
+ def calculate_statistics(
157
+ self,
158
+ numbers: List[float]
159
+ ) -> Dict[str, Any]:
160
+ """Calculate basic statistics for a list of numbers."""
161
+ try:
162
+ if not numbers:
163
+ return {"error": "No numbers provided"}
164
+
165
+ n = len(numbers)
166
+ mean = sum(numbers) / n
167
+
168
+ # Calculate variance and std dev
169
+ squared_diff_sum = sum((x - mean) ** 2 for x in numbers)
170
+ variance = squared_diff_sum / (n - 1) if n > 1 else 0
171
+ std_dev = math.sqrt(variance)
172
+
173
+ # Calculate median
174
+ sorted_nums = sorted(numbers)
175
+ if n % 2 == 0:
176
+ median = (sorted_nums[n//2 - 1] + sorted_nums[n//2]) / 2
177
+ else:
178
+ median = sorted_nums[n//2]
179
+
180
+ return {
181
+ "mean": mean,
182
+ "median": median,
183
+ "std_dev": std_dev,
184
+ "variance": variance,
185
+ "min": min(numbers),
186
+ "max": max(numbers),
187
+ "range": max(numbers) - min(numbers),
188
+ "count": n
189
+ }
190
+ except Exception as e:
191
+ error_msg = f"Error calculating statistics: {str(e)}"
192
+ logging.error(error_msg)
193
+ return {"error": error_msg}
194
+
195
+ def calculate_financial(
196
+ self,
197
+ principal: float,
198
+ rate: float,
199
+ time: float,
200
+ frequency: str = 'yearly'
201
+ ) -> Dict[str, Any]:
202
+ """Calculate financial metrics like compound interest."""
203
+ try:
204
+ # Convert rate to decimal
205
+ rate = rate / 100
206
+
207
+ # Get compounding frequency
208
+ freq_map = {
209
+ 'yearly': 1,
210
+ 'semi-annual': 2,
211
+ 'quarterly': 4,
212
+ 'monthly': 12,
213
+ 'daily': 365
214
+ }
215
+ n = freq_map.get(frequency.lower(), 1)
216
+
217
+ # Calculate compound interest
218
+ amount = principal * (1 + rate/n)**(n*time)
219
+ interest = amount - principal
220
+
221
+ # Calculate simple interest
222
+ simple_interest = principal * rate * time
223
+
224
+ return {
225
+ "final_amount": amount,
226
+ "compound_interest": interest,
227
+ "simple_interest": simple_interest,
228
+ "difference": interest - simple_interest
229
+ }
230
+ except Exception as e:
231
+ error_msg = f"Error calculating financial metrics: {str(e)}"
232
+ logging.error(error_msg)
233
+ return {"error": error_msg}
234
+
235
+ # Create instance for direct function access
236
+ _calculator_tools = CalculatorTools()
237
+ evaluate = _calculator_tools.evaluate
238
+ solve_equation = _calculator_tools.solve_equation
239
+ convert_units = _calculator_tools.convert_units
240
+ calculate_statistics = _calculator_tools.calculate_statistics
241
+ calculate_financial = _calculator_tools.calculate_financial
242
+
243
+ if __name__ == "__main__":
244
+ print("\n==================================================")
245
+ print("CalculatorTools Demonstration")
246
+ print("==================================================\n")
247
+
248
+ print("1. Basic Arithmetic")
249
+ print("------------------------------")
250
+ print("2 + 2 =", evaluate("2 + 2")["result"])
251
+ print("5 * 6 =", evaluate("5 * 6")["result"])
252
+ print("10 / 3 =", evaluate("10 / 3")["result"])
253
+ print()
254
+
255
+ print("2. Complex Expressions")
256
+ print("------------------------------")
257
+ print("(2 + 3) * 4 =", evaluate("(2 + 3) * 4")["result"])
258
+ print("2^3 + 4 =", evaluate("2^3 + 4")["result"])
259
+ print("sqrt(16) + 2 =", evaluate("sqrt(16) + 2")["result"])
260
+ print()
261
+
262
+ print("3. Solving Equations")
263
+ print("------------------------------")
264
+ result = solve_equation("x^2 - 5*x + 6 = 0")
265
+ print("x^2 - 5*x + 6 = 0")
266
+ print("Solutions:", result["solutions"])
267
+ print()
268
+
269
+ print("4. Unit Conversions")
270
+ print("------------------------------")
271
+ print("100 meters to kilometers:", convert_units(100, "meters", "kilometers")["result"])
272
+ print("1 hour to minutes:", convert_units(1, "hours", "minutes")["result"])
273
+ print("32 fahrenheit to celsius:", convert_units(32, "fahrenheit", "celsius")["result"])
274
+ print()
275
+
276
+ print("==================================================")
277
+ print("Demonstration Complete")
278
+ print("==================================================")
@@ -0,0 +1,266 @@
1
+ """Tools for working with CSV files.
2
+
3
+ Usage:
4
+ from praisonaiagents.tools import csv_tools
5
+ df = csv_tools.read_csv("data.csv")
6
+
7
+ or
8
+ from praisonaiagents.tools import read_csv, write_csv, merge_csv
9
+ df = read_csv("data.csv")
10
+ """
11
+
12
+ import logging
13
+ from typing import List, Dict, Union, Optional, Any, TYPE_CHECKING
14
+ from importlib import util
15
+ import json
16
+ import csv
17
+ from pathlib import Path
18
+
19
+ if TYPE_CHECKING:
20
+ import pandas as pd
21
+
22
+ class CSVTools:
23
+ """Tools for working with CSV files."""
24
+
25
+ def __init__(self):
26
+ """Initialize CSVTools."""
27
+ pass
28
+
29
+ def _get_pandas(self) -> Optional['pd']:
30
+ """Get pandas module, installing if needed"""
31
+ if util.find_spec('pandas') is None:
32
+ error_msg = "pandas package is not available. Please install it using: pip install pandas"
33
+ logging.error(error_msg)
34
+ return None
35
+ import pandas as pd
36
+ return pd
37
+
38
+ def read_csv(
39
+ self,
40
+ filepath: str,
41
+ encoding: str = 'utf-8',
42
+ delimiter: str = ',',
43
+ header: Union[int, List[int], None] = 0,
44
+ usecols: Optional[List[str]] = None,
45
+ dtype: Optional[Dict[str, str]] = None,
46
+ parse_dates: Optional[List[str]] = None,
47
+ na_values: Optional[List[str]] = None,
48
+ nrows: Optional[int] = None
49
+ ) -> List[Dict[str, Any]]:
50
+ """Read a CSV file with advanced options.
51
+
52
+ Args:
53
+ filepath: Path to CSV file
54
+ encoding: File encoding
55
+ delimiter: Column delimiter
56
+ header: Row number(s) to use as column names
57
+ usecols: Columns to read
58
+ dtype: Dict of column dtypes
59
+ parse_dates: List of columns to parse as dates
60
+ na_values: Additional strings to recognize as NA/NaN
61
+ nrows: Number of rows to read
62
+
63
+ Returns:
64
+ List of row dicts
65
+ """
66
+ try:
67
+ pd = self._get_pandas()
68
+ if pd is None:
69
+ return {"error": "pandas package not available"}
70
+
71
+ df = pd.read_csv(
72
+ filepath,
73
+ encoding=encoding,
74
+ delimiter=delimiter,
75
+ header=header,
76
+ usecols=usecols,
77
+ dtype=dtype,
78
+ parse_dates=parse_dates,
79
+ na_values=na_values,
80
+ nrows=nrows
81
+ )
82
+ return df.to_dict('records')
83
+
84
+ except Exception as e:
85
+ error_msg = f"Error reading CSV file {filepath}: {str(e)}"
86
+ logging.error(error_msg)
87
+ return {"error": error_msg}
88
+
89
+ def write_csv(
90
+ self,
91
+ filepath: str,
92
+ data: List[Dict[str, Any]],
93
+ encoding: str = 'utf-8',
94
+ delimiter: str = ',',
95
+ index: bool = False,
96
+ header: bool = True,
97
+ float_format: Optional[str] = None,
98
+ date_format: Optional[str] = None,
99
+ mode: str = 'w'
100
+ ) -> bool:
101
+ """Write data to a CSV file.
102
+
103
+ Args:
104
+ filepath: Path to CSV file
105
+ data: List of row dicts to write
106
+ encoding: File encoding
107
+ delimiter: Column delimiter
108
+ index: Whether to write row indices
109
+ header: Whether to write column headers
110
+ float_format: Format string for float values
111
+ date_format: Format string for date values
112
+ mode: Write mode ('w' for write, 'a' for append)
113
+
114
+ Returns:
115
+ bool: Success status
116
+ """
117
+ try:
118
+ pd = self._get_pandas()
119
+ if pd is None:
120
+ return False
121
+
122
+ df = pd.DataFrame(data)
123
+ df.to_csv(
124
+ filepath,
125
+ encoding=encoding,
126
+ sep=delimiter,
127
+ index=index,
128
+ header=header,
129
+ float_format=float_format,
130
+ date_format=date_format,
131
+ mode=mode
132
+ )
133
+ return True
134
+
135
+ except Exception as e:
136
+ error_msg = f"Error writing CSV file {filepath}: {str(e)}"
137
+ logging.error(error_msg)
138
+ return False
139
+
140
+ def merge_csv(
141
+ self,
142
+ files: List[str],
143
+ output_file: str,
144
+ how: str = 'inner',
145
+ on: Optional[Union[str, List[str]]] = None,
146
+ suffixes: Optional[tuple] = None
147
+ ) -> bool:
148
+ """Merge multiple CSV files.
149
+
150
+ Args:
151
+ files: List of CSV files to merge
152
+ output_file: Output file path
153
+ how: Merge method ('inner', 'outer', 'left', 'right')
154
+ on: Column(s) to merge on
155
+ suffixes: Suffixes for overlapping columns
156
+
157
+ Returns:
158
+ bool: Success status
159
+ """
160
+ try:
161
+ if len(files) < 2:
162
+ error_msg = "At least two files are required for merging"
163
+ logging.error(error_msg)
164
+ return False
165
+
166
+ pd = self._get_pandas()
167
+ if pd is None:
168
+ return False
169
+
170
+ # Read first file
171
+ result = pd.read_csv(files[0])
172
+
173
+ # Merge with remaining files
174
+ for file in files[1:]:
175
+ df = pd.read_csv(file)
176
+ result = pd.merge(
177
+ result,
178
+ df,
179
+ how=how,
180
+ on=on,
181
+ suffixes=suffixes or ('_1', '_2')
182
+ )
183
+
184
+ # Write merged result
185
+ result.to_csv(output_file, index=False)
186
+ return True
187
+
188
+ except Exception as e:
189
+ error_msg = f"Error merging CSV files: {str(e)}"
190
+ logging.error(error_msg)
191
+ return False
192
+
193
+ # Create instance for direct function access
194
+ _csv_tools = CSVTools()
195
+ read_csv = _csv_tools.read_csv
196
+ write_csv = _csv_tools.write_csv
197
+ merge_csv = _csv_tools.merge_csv
198
+
199
+ if __name__ == "__main__":
200
+ print("\n==================================================")
201
+ print("CSVTools Demonstration")
202
+ print("==================================================\n")
203
+
204
+ # Create a temporary file for testing
205
+ import tempfile
206
+ import os
207
+
208
+ with tempfile.NamedTemporaryFile(suffix='.csv', delete=False) as temp:
209
+ temp_file = temp.name
210
+
211
+ print("1. Writing CSV File")
212
+ print("------------------------------")
213
+ data = [
214
+ {"name": "Alice", "age": 25, "city": "New York"},
215
+ {"name": "Bob", "age": 30, "city": "San Francisco"},
216
+ {"name": "Charlie", "age": 35, "city": "Chicago"}
217
+ ]
218
+ result = write_csv(temp_file, data)
219
+ print(f"Data written successfully: {result}")
220
+ print()
221
+
222
+ print("2. Reading CSV File")
223
+ print("------------------------------")
224
+ read_data = read_csv(temp_file)
225
+ print("Contents of CSV file:")
226
+ for row in read_data:
227
+ print(row)
228
+ print()
229
+
230
+ print("3. Merging CSV Files")
231
+ print("------------------------------")
232
+ # Create a second file for merging
233
+ with tempfile.NamedTemporaryFile(suffix='.csv', delete=False) as temp2:
234
+ temp_file2 = temp2.name
235
+ data2 = [
236
+ {"name": "Alice", "salary": 75000},
237
+ {"name": "Bob", "salary": 85000},
238
+ {"name": "Charlie", "salary": 95000}
239
+ ]
240
+ write_csv(temp_file2, data2)
241
+
242
+ # Merge files
243
+ with tempfile.NamedTemporaryFile(suffix='.csv', delete=False) as temp3:
244
+ temp_file3 = temp3.name
245
+ result = merge_csv(
246
+ [temp_file, temp_file2],
247
+ temp_file3,
248
+ how='inner',
249
+ on='name'
250
+ )
251
+ print(f"Files merged successfully: {result}")
252
+ if result:
253
+ merged_data = read_csv(temp_file3)
254
+ print("\nMerged contents:")
255
+ for row in merged_data:
256
+ print(row)
257
+ print()
258
+
259
+ # Clean up temporary files
260
+ os.unlink(temp_file)
261
+ os.unlink(temp_file2)
262
+ os.unlink(temp_file3)
263
+
264
+ print("==================================================")
265
+ print("Demonstration Complete")
266
+ print("==================================================\n")