Skip to content

Commit eadfc0c

Browse files
Merge pull request #270 from MervinPraison/develop
adding tools
2 parents 3f78852 + f33c44d commit eadfc0c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+10127
-63
lines changed

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
FROM python:3.11-slim
22
WORKDIR /app
33
COPY . .
4-
RUN pip install flask praisonai==2.0.32 gunicorn markdown
4+
RUN pip install flask praisonai==2.0.33 gunicorn markdown
55
EXPOSE 8080
66
CMD ["gunicorn", "-b", "0.0.0.0:8080", "api:app"]
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
# PraisonAI Tools Guide
2+
3+
Welcome to the PraisonAI Tools directory! This guide will help you understand how our tools work and how to create new ones, whether you're a beginner or an experienced programmer.
4+
5+
## What is a Tool?
6+
7+
A tool is a piece of code that helps our AI agents perform specific tasks. Think of tools as special abilities that we give to our agents. For example:
8+
- An internet search tool lets agents search the web
9+
- A stock market tool lets agents check stock prices
10+
- A weather tool lets agents check the weather
11+
12+
## Creating New Tools: The Two Approaches
13+
14+
### 1. Function-Based Approach (Simple Tools)
15+
16+
Best for simple tools that do one specific thing. Like a calculator that just adds numbers.
17+
18+
**When to use:**
19+
- Tool does one simple task
20+
- Doesn't need to remember information between uses
21+
- Doesn't need to share information with other tools
22+
- Quick, one-time operations
23+
24+
**Example:**
25+
```python
26+
def internet_search(query: str):
27+
# Search the internet and return results
28+
return search_results
29+
```
30+
31+
**Usage:**
32+
```python
33+
from praisonaiagents.tools import internet_search
34+
35+
results = internet_search("AI news")
36+
```
37+
38+
### 2. Class-Based Approach (Complex Tools)
39+
40+
Best for tools that do multiple related things or need to remember information. Like a smart calculator that remembers your previous calculations and can do many different math operations.
41+
42+
**When to use:**
43+
- Tool has multiple related functions
44+
- Needs to remember or share information
45+
- Needs to manage resources efficiently
46+
- Has complex setup requirements
47+
48+
**Example:**
49+
```python
50+
class StockTools:
51+
def get_stock_price(self, symbol):
52+
# Get current stock price
53+
return price
54+
55+
def get_stock_info(self, symbol):
56+
# Get detailed stock information
57+
return info
58+
```
59+
60+
**Usage:**
61+
```python
62+
from praisonaiagents.tools import get_stock_price, get_stock_info
63+
64+
price = get_stock_price("AAPL")
65+
info = get_stock_info("AAPL")
66+
```
67+
68+
## How to Choose Your Approach
69+
70+
Ask yourself these questions:
71+
72+
1. **Is your tool doing one simple thing?**
73+
- Yes → Use Function-Based Approach
74+
- No → Consider Class-Based Approach
75+
76+
2. **Does your tool need to remember information?**
77+
- Yes → Use Class-Based Approach
78+
- No → Use Function-Based Approach
79+
80+
3. **Are your tool's operations related to each other?**
81+
- Yes → Use Class-Based Approach
82+
- No → Use Function-Based Approach
83+
84+
4. **Does your tool need to manage resources efficiently?**
85+
- Yes → Use Class-Based Approach
86+
- No → Use Function-Based Approach
87+
88+
## Real-World Examples
89+
90+
### Internet Search Tool (Function-Based)
91+
- Does one thing: searches the internet
92+
- Doesn't need to remember previous searches
93+
- Each search is independent
94+
- Simple input/output operation
95+
96+
### Stock Market Tool (Class-Based)
97+
- Does multiple things: check prices, get company info, get historical data
98+
- Remembers stock information to avoid repeated downloads
99+
- Operations are related (all about stocks)
100+
- Manages connections efficiently
101+
102+
## Getting Started
103+
104+
1. **Choose Your Approach** based on the guidelines above
105+
106+
2. **Create Your Tool File**:
107+
- Name it descriptively (e.g., `weather_tools.py`)
108+
- Place it in the `praisonaiagents/tools` directory
109+
110+
3. **Write Your Tool**:
111+
- Add clear documentation
112+
- Include type hints for better understanding
113+
- Handle errors gracefully
114+
115+
4. **Test Your Tool**:
116+
- Make sure it works as expected
117+
- Test error cases
118+
- Check performance
119+
120+
## Best Practices
121+
122+
1. **Documentation**:
123+
- Explain what your tool does
124+
- Provide examples
125+
- List any requirements
126+
127+
2. **Error Handling**:
128+
- Always handle possible errors
129+
- Return helpful error messages
130+
- Don't let your tool crash
131+
132+
3. **Performance**:
133+
- Keep it efficient
134+
- Don't waste resources
135+
- Cache when helpful
136+
137+
4. **User-Friendly**:
138+
- Make it easy to use
139+
- Use clear function/method names
140+
- Keep it simple
141+
142+
## Need Help?
143+
144+
- Check existing tools for examples
145+
- Ask in our community
146+
- Read the documentation
147+
- Don't hesitate to ask questions!
148+
149+
Remember: The goal is to make tools that are easy to use and maintain. Choose the approach that makes the most sense for your specific tool's needs.
Lines changed: 165 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,167 @@
11
"""Tools package for PraisonAI Agents"""
2-
from .tools import Tools
2+
from importlib import import_module
3+
from typing import Any
34

4-
__all__ = ['Tools']
5+
# Map of function names to their module and class (if any)
6+
TOOL_MAPPINGS = {
7+
# Direct functions
8+
'internet_search': ('.duckduckgo_tools', None),
9+
'duckduckgo': ('.duckduckgo_tools', None),
10+
11+
# Class methods from YFinance
12+
'get_stock_price': ('.yfinance_tools', 'YFinanceTools'),
13+
'get_stock_info': ('.yfinance_tools', 'YFinanceTools'),
14+
'get_historical_data': ('.yfinance_tools', 'YFinanceTools'),
15+
'yfinance': ('.yfinance_tools', 'YFinanceTools'),
16+
17+
# File Tools
18+
'read_file': ('.file_tools', 'FileTools'),
19+
'write_file': ('.file_tools', 'FileTools'),
20+
'list_files': ('.file_tools', 'FileTools'),
21+
'get_file_info': ('.file_tools', 'FileTools'),
22+
'copy_file': ('.file_tools', 'FileTools'),
23+
'move_file': ('.file_tools', 'FileTools'),
24+
'delete_file': ('.file_tools', 'FileTools'),
25+
'file_tools': ('.file_tools', 'FileTools'),
26+
27+
# CSV Tools
28+
'read_csv': ('.csv_tools', 'CSVTools'),
29+
'write_csv': ('.csv_tools', 'CSVTools'),
30+
'merge_csv': ('.csv_tools', 'CSVTools'),
31+
'analyze_csv': ('.csv_tools', 'CSVTools'),
32+
'split_csv': ('.csv_tools', 'CSVTools'),
33+
'csv_tools': ('.csv_tools', 'CSVTools'),
34+
35+
# JSON Tools
36+
'read_json': ('.json_tools', 'JSONTools'),
37+
'write_json': ('.json_tools', 'JSONTools'),
38+
'merge_json': ('.json_tools', 'JSONTools'),
39+
'validate_json': ('.json_tools', 'JSONTools'),
40+
'analyze_json': ('.json_tools', 'JSONTools'),
41+
'transform_json': ('.json_tools', 'JSONTools'),
42+
'json_tools': ('.json_tools', 'JSONTools'),
43+
44+
# Excel Tools
45+
'read_excel': ('.excel_tools', 'ExcelTools'),
46+
'write_excel': ('.excel_tools', 'ExcelTools'),
47+
'merge_excel': ('.excel_tools', 'ExcelTools'),
48+
'create_chart': ('.excel_tools', 'ExcelTools'),
49+
'add_chart_to_sheet': ('.excel_tools', 'ExcelTools'),
50+
'excel_tools': ('.excel_tools', 'ExcelTools'),
51+
52+
# XML Tools
53+
'read_xml': ('.xml_tools', 'XMLTools'),
54+
'write_xml': ('.xml_tools', 'XMLTools'),
55+
'transform_xml': ('.xml_tools', 'XMLTools'),
56+
'validate_xml': ('.xml_tools', 'XMLTools'),
57+
'xml_to_dict': ('.xml_tools', 'XMLTools'),
58+
'dict_to_xml': ('.xml_tools', 'XMLTools'),
59+
'xpath_query': ('.xml_tools', 'XMLTools'),
60+
'xml_tools': ('.xml_tools', 'XMLTools'),
61+
62+
# YAML Tools
63+
'read_yaml': ('.yaml_tools', 'YAMLTools'),
64+
'write_yaml': ('.yaml_tools', 'YAMLTools'),
65+
'merge_yaml': ('.yaml_tools', 'YAMLTools'),
66+
'validate_yaml': ('.yaml_tools', 'YAMLTools'),
67+
'analyze_yaml': ('.yaml_tools', 'YAMLTools'),
68+
'transform_yaml': ('.yaml_tools', 'YAMLTools'),
69+
'yaml_tools': ('.yaml_tools', 'YAMLTools'),
70+
71+
# Calculator Tools
72+
'evaluate': ('.calculator_tools', 'CalculatorTools'),
73+
'solve_equation': ('.calculator_tools', 'CalculatorTools'),
74+
'convert_units': ('.calculator_tools', 'CalculatorTools'),
75+
'calculate_statistics': ('.calculator_tools', 'CalculatorTools'),
76+
'calculate_financial': ('.calculator_tools', 'CalculatorTools'),
77+
'calculator_tools': ('.calculator_tools', 'CalculatorTools'),
78+
79+
# Python Tools
80+
'execute_code': ('.python_tools', 'PythonTools'),
81+
'analyze_code': ('.python_tools', 'PythonTools'),
82+
'format_code': ('.python_tools', 'PythonTools'),
83+
'lint_code': ('.python_tools', 'PythonTools'),
84+
'disassemble_code': ('.python_tools', 'PythonTools'),
85+
'python_tools': ('.python_tools', 'PythonTools'),
86+
87+
# Pandas Tools
88+
'filter_data': ('.pandas_tools', 'PandasTools'),
89+
'get_summary': ('.pandas_tools', 'PandasTools'),
90+
'group_by': ('.pandas_tools', 'PandasTools'),
91+
'pivot_table': ('.pandas_tools', 'PandasTools'),
92+
'pandas_tools': ('.pandas_tools', 'PandasTools'),
93+
94+
# Wikipedia Tools
95+
'search': ('.wikipedia_tools', 'WikipediaTools'),
96+
'get_wikipedia_summary': ('.wikipedia_tools', 'WikipediaTools'),
97+
'get_wikipedia_page': ('.wikipedia_tools', 'WikipediaTools'),
98+
'get_random_wikipedia': ('.wikipedia_tools', 'WikipediaTools'),
99+
'set_wikipedia_language': ('.wikipedia_tools', 'WikipediaTools'),
100+
'wikipedia_tools': ('.wikipedia_tools', 'WikipediaTools'),
101+
102+
# Newspaper Tools
103+
'get_article': ('.newspaper_tools', 'NewspaperTools'),
104+
'get_news_sources': ('.newspaper_tools', 'NewspaperTools'),
105+
'get_articles_from_source': ('.newspaper_tools', 'NewspaperTools'),
106+
'get_trending_topics': ('.newspaper_tools', 'NewspaperTools'),
107+
'newspaper_tools': ('.newspaper_tools', 'NewspaperTools'),
108+
109+
# arXiv Tools
110+
'search_arxiv': ('.arxiv_tools', 'ArxivTools'),
111+
'get_arxiv_paper': ('.arxiv_tools', 'ArxivTools'),
112+
'get_papers_by_author': ('.arxiv_tools', 'ArxivTools'),
113+
'get_papers_by_category': ('.arxiv_tools', 'ArxivTools'),
114+
'arxiv_tools': ('.arxiv_tools', 'ArxivTools'),
115+
116+
# Spider Tools
117+
'scrape_page': ('.spider_tools', 'SpiderTools'),
118+
'extract_links': ('.spider_tools', 'SpiderTools'),
119+
'crawl': ('.spider_tools', 'SpiderTools'),
120+
'extract_text': ('.spider_tools', 'SpiderTools'),
121+
'spider_tools': ('.spider_tools', 'SpiderTools'),
122+
123+
# DuckDB Tools
124+
'query': ('.duckdb_tools', 'DuckDBTools'),
125+
'create_table': ('.duckdb_tools', 'DuckDBTools'),
126+
'load_data': ('.duckdb_tools', 'DuckDBTools'),
127+
'export_data': ('.duckdb_tools', 'DuckDBTools'),
128+
'get_table_info': ('.duckdb_tools', 'DuckDBTools'),
129+
'analyze_data': ('.duckdb_tools', 'DuckDBTools'),
130+
'duckdb_tools': ('.duckdb_tools', 'DuckDBTools'),
131+
132+
# Shell Tools
133+
'execute_command': ('.shell_tools', 'ShellTools'),
134+
'list_processes': ('.shell_tools', 'ShellTools'),
135+
'kill_process': ('.shell_tools', 'ShellTools'),
136+
'get_system_info': ('.shell_tools', 'ShellTools'),
137+
'shell_tools': ('.shell_tools', 'ShellTools'),
138+
}
139+
140+
_instances = {} # Cache for class instances
141+
142+
def __getattr__(name: str) -> Any:
143+
"""Smart lazy loading of tools with class method support."""
144+
if name not in TOOL_MAPPINGS:
145+
raise AttributeError(f"module '{__package__}' has no attribute '{name}'")
146+
147+
module_path, class_name = TOOL_MAPPINGS[name]
148+
149+
if class_name is None:
150+
# Direct function import
151+
module = import_module(module_path, __package__)
152+
if name in ['duckduckgo', 'file_tools', 'pandas_tools', 'wikipedia_tools',
153+
'newspaper_tools', 'arxiv_tools', 'spider_tools', 'duckdb_tools', 'csv_tools', 'json_tools', 'excel_tools', 'xml_tools', 'yaml_tools', 'calculator_tools', 'python_tools', 'shell_tools']:
154+
return module # Returns the callable module
155+
return getattr(module, name)
156+
else:
157+
# Class method import
158+
if class_name not in _instances:
159+
module = import_module(module_path, __package__)
160+
class_ = getattr(module, class_name)
161+
_instances[class_name] = class_()
162+
163+
# Get the method and bind it to the instance
164+
method = getattr(_instances[class_name], name)
165+
return method
166+
167+
__all__ = list(TOOL_MAPPINGS.keys())

0 commit comments

Comments
 (0)