mirror of
https://github.com/MervinPraison/PraisonAI.git
synced 2026-11-07 17:33:33 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
43c03f4813 | ||
|
|
03856b74bf | ||
|
|
eadfc0cff0 | ||
|
|
f33c44d4c5 | ||
|
|
3f7885289d | ||
|
|
833c795e9a | ||
|
|
c460c9da60 | ||
|
|
656887c700 |
No files matched your search
+1
-1
@@ -1,6 +1,6 @@
|
||||
FROM python:3.11-slim
|
||||
WORKDIR /app
|
||||
COPY . .
|
||||
RUN pip install flask praisonai==2.0.31 gunicorn markdown
|
||||
RUN pip install flask praisonai==2.0.34 gunicorn markdown
|
||||
EXPOSE 8080
|
||||
CMD ["gunicorn", "-b", "0.0.0.0:8080", "api:app"]
|
||||
@@ -0,0 +1,50 @@
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
import json
|
||||
from e2b_code_interpreter import Sandbox
|
||||
|
||||
def code_interpreter(code: str):
|
||||
"""
|
||||
A function to demonstrate running Python code dynamically using e2b_code_interpreter.
|
||||
"""
|
||||
print(f"\n{'='*50}\n> Running following AI-generated code:\n{code}\n{'='*50}")
|
||||
exec_result = Sandbox().run_code(code)
|
||||
if exec_result.error:
|
||||
print("[Code Interpreter error]", exec_result.error)
|
||||
return {"error": str(exec_result.error)}
|
||||
else:
|
||||
results = []
|
||||
for result in exec_result.results:
|
||||
if hasattr(result, '__iter__'):
|
||||
results.extend(list(result))
|
||||
else:
|
||||
results.append(str(result))
|
||||
logs = {"stdout": list(exec_result.logs.stdout), "stderr": list(exec_result.logs.stderr)}
|
||||
return json.dumps({"results": results, "logs": logs})
|
||||
|
||||
code_agent = Agent(
|
||||
name="code_agent",
|
||||
llm="gpt-4o-mini",
|
||||
backstory="Expert in writing Python scripts",
|
||||
self_reflect=False
|
||||
)
|
||||
execution_agent = Agent(
|
||||
name="execution_agent",
|
||||
llm="gpt-4o-mini",
|
||||
backstory="Expert in executing Python scripts",
|
||||
self_reflect=False,
|
||||
tools=[code_interpreter]
|
||||
)
|
||||
|
||||
code_agent_task = Task(
|
||||
description="Write a simple Python script to print 'Hello, World!'",
|
||||
expected_output="A Python script that prints 'Hello, World!'",
|
||||
agent=code_agent
|
||||
)
|
||||
execution_agent_task = Task(
|
||||
description="Execute the Python script",
|
||||
expected_output="The output of the Python script",
|
||||
agent=execution_agent
|
||||
)
|
||||
|
||||
agents = PraisonAIAgents(agents=[code_agent, execution_agent], tasks=[code_agent_task, execution_agent_task])
|
||||
agents.start()
|
||||
@@ -394,7 +394,7 @@ Your Goal: {self.goal}
|
||||
display_error(f"Error in chat completion: {e}")
|
||||
return None
|
||||
|
||||
def chat(self, prompt, temperature=0.2, tools=None, output_json=None):
|
||||
def chat(self, prompt, temperature=0.2, tools=None, output_json=None, output_pydantic=None):
|
||||
if self.use_system_prompt:
|
||||
system_prompt = f"""{self.backstory}\n
|
||||
Your Role: {self.role}\n
|
||||
@@ -402,6 +402,8 @@ Your Goal: {self.goal}
|
||||
"""
|
||||
if output_json:
|
||||
system_prompt += f"\nReturn ONLY a JSON object that matches this Pydantic model: {output_json.schema_json()}"
|
||||
elif output_pydantic:
|
||||
system_prompt += f"\nReturn ONLY a JSON object that matches this Pydantic model: {output_pydantic.schema_json()}"
|
||||
else:
|
||||
system_prompt = None
|
||||
|
||||
@@ -410,9 +412,9 @@ Your Goal: {self.goal}
|
||||
messages.append({"role": "system", "content": system_prompt})
|
||||
messages.extend(self.chat_history)
|
||||
|
||||
# Modify prompt if output_json is specified
|
||||
# Modify prompt if output_json or output_pydantic is specified
|
||||
original_prompt = prompt
|
||||
if output_json:
|
||||
if output_json or output_pydantic:
|
||||
if isinstance(prompt, str):
|
||||
prompt += "\nReturn ONLY a valid JSON object. No other text or explanation."
|
||||
elif isinstance(prompt, list):
|
||||
@@ -487,23 +489,15 @@ Your Goal: {self.goal}
|
||||
return None
|
||||
response_text = response.choices[0].message.content.strip()
|
||||
|
||||
# Handle output_json if specified
|
||||
if output_json:
|
||||
try:
|
||||
# Clean the response text to get only JSON
|
||||
cleaned_json = self.clean_json_output(response_text)
|
||||
# Parse into Pydantic model
|
||||
parsed_model = output_json.model_validate_json(cleaned_json)
|
||||
# Add to chat history and return
|
||||
self.chat_history.append({"role": "user", "content": original_prompt})
|
||||
self.chat_history.append({"role": "assistant", "content": response_text})
|
||||
if self.verbose:
|
||||
display_interaction(original_prompt, response_text, markdown=self.markdown,
|
||||
generation_time=time.time() - start_time, console=self.console)
|
||||
return parsed_model
|
||||
except Exception as e:
|
||||
display_error(f"Failed to parse response as {output_json.__name__}: {e}")
|
||||
return None
|
||||
# Handle output_json or output_pydantic if specified
|
||||
if output_json or output_pydantic:
|
||||
# Add to chat history and return raw response
|
||||
self.chat_history.append({"role": "user", "content": original_prompt})
|
||||
self.chat_history.append({"role": "assistant", "content": response_text})
|
||||
if self.verbose:
|
||||
display_interaction(original_prompt, response_text, markdown=self.markdown,
|
||||
generation_time=time.time() - start_time, console=self.console)
|
||||
return response_text
|
||||
|
||||
if not self.self_reflect:
|
||||
self.chat_history.append({"role": "user", "content": original_prompt})
|
||||
@@ -585,19 +579,21 @@ Output MUST be JSON with 'reflection' and 'satisfactory'.
|
||||
cleaned = cleaned[:-3].strip()
|
||||
return cleaned
|
||||
|
||||
async def achat(self, prompt, temperature=0.2, tools=None, output_json=None):
|
||||
async def achat(self, prompt, temperature=0.2, tools=None, output_json=None, output_pydantic=None):
|
||||
"""Async version of chat method"""
|
||||
try:
|
||||
# Build system prompt
|
||||
system_prompt = self.system_prompt
|
||||
if output_json:
|
||||
system_prompt += f"\nReturn ONLY a JSON object that matches this Pydantic model: {output_json.schema_json()}"
|
||||
elif output_pydantic:
|
||||
system_prompt += f"\nReturn ONLY a JSON object that matches this Pydantic model: {output_pydantic.schema_json()}"
|
||||
|
||||
# Build messages
|
||||
if isinstance(prompt, str):
|
||||
messages = [
|
||||
{"role": "system", "content": system_prompt},
|
||||
{"role": "user", "content": prompt + ("\nReturn ONLY a valid JSON object. No other text or explanation." if output_json else "")}
|
||||
{"role": "user", "content": prompt + ("\nReturn ONLY a valid JSON object. No other text or explanation." if (output_json or output_pydantic) else "")}
|
||||
]
|
||||
else:
|
||||
# For multimodal prompts
|
||||
@@ -605,7 +601,7 @@ Output MUST be JSON with 'reflection' and 'satisfactory'.
|
||||
{"role": "system", "content": system_prompt},
|
||||
{"role": "user", "content": prompt}
|
||||
]
|
||||
if output_json:
|
||||
if output_json or output_pydantic:
|
||||
# Add JSON instruction to text content
|
||||
for item in messages[-1]["content"]:
|
||||
if item["type"] == "text":
|
||||
@@ -639,22 +635,15 @@ Output MUST be JSON with 'reflection' and 'satisfactory'.
|
||||
tools=formatted_tools
|
||||
)
|
||||
return await self._achat_completion(response, tools)
|
||||
elif output_json:
|
||||
elif output_json or output_pydantic:
|
||||
response = await async_client.chat.completions.create(
|
||||
model=self.llm,
|
||||
messages=messages,
|
||||
temperature=temperature,
|
||||
response_format={"type": "json_object"}
|
||||
)
|
||||
result = response.choices[0].message.content
|
||||
# Clean and parse the JSON response
|
||||
cleaned_json = self.clean_json_output(result)
|
||||
try:
|
||||
parsed = json.loads(cleaned_json)
|
||||
return output_json(**parsed)
|
||||
except Exception as e:
|
||||
display_error(f"Error parsing JSON response: {e}")
|
||||
return None
|
||||
# Return the raw response
|
||||
return response.choices[0].message.content
|
||||
else:
|
||||
response = await async_client.chat.completions.create(
|
||||
model=self.llm,
|
||||
|
||||
@@ -195,10 +195,17 @@ Here are the results of previous tasks that might be useful:\n
|
||||
|
||||
agent_output = await executor_agent.achat(
|
||||
_get_multimodal_message(task_prompt, task.images),
|
||||
tools=task.tools
|
||||
tools=task.tools,
|
||||
output_json=task.output_json,
|
||||
output_pydantic=task.output_pydantic
|
||||
)
|
||||
else:
|
||||
agent_output = await executor_agent.achat(task_prompt, tools=task.tools)
|
||||
agent_output = await executor_agent.achat(
|
||||
task_prompt,
|
||||
tools=task.tools,
|
||||
output_json=task.output_json,
|
||||
output_pydantic=task.output_pydantic
|
||||
)
|
||||
|
||||
if agent_output:
|
||||
task_output = TaskOutput(
|
||||
@@ -405,10 +412,17 @@ Here are the results of previous tasks that might be useful:\n
|
||||
|
||||
agent_output = executor_agent.chat(
|
||||
_get_multimodal_message(task_prompt, task.images),
|
||||
tools=task.tools
|
||||
tools=task.tools,
|
||||
output_json=task.output_json,
|
||||
output_pydantic=task.output_pydantic
|
||||
)
|
||||
else:
|
||||
agent_output = executor_agent.chat(task_prompt, tools=task.tools)
|
||||
agent_output = executor_agent.chat(
|
||||
task_prompt,
|
||||
tools=task.tools,
|
||||
output_json=task.output_json,
|
||||
output_pydantic=task.output_pydantic
|
||||
)
|
||||
|
||||
if agent_output:
|
||||
task_output = TaskOutput(
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
# PraisonAI Tools Guide
|
||||
|
||||
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.
|
||||
|
||||
## What is a Tool?
|
||||
|
||||
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:
|
||||
- An internet search tool lets agents search the web
|
||||
- A stock market tool lets agents check stock prices
|
||||
- A weather tool lets agents check the weather
|
||||
|
||||
## Creating New Tools: The Two Approaches
|
||||
|
||||
### 1. Function-Based Approach (Simple Tools)
|
||||
|
||||
Best for simple tools that do one specific thing. Like a calculator that just adds numbers.
|
||||
|
||||
**When to use:**
|
||||
- Tool does one simple task
|
||||
- Doesn't need to remember information between uses
|
||||
- Doesn't need to share information with other tools
|
||||
- Quick, one-time operations
|
||||
|
||||
**Example:**
|
||||
```python
|
||||
def internet_search(query: str):
|
||||
# Search the internet and return results
|
||||
return search_results
|
||||
```
|
||||
|
||||
**Usage:**
|
||||
```python
|
||||
from praisonaiagents.tools import internet_search
|
||||
|
||||
results = internet_search("AI news")
|
||||
```
|
||||
|
||||
### 2. Class-Based Approach (Complex Tools)
|
||||
|
||||
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.
|
||||
|
||||
**When to use:**
|
||||
- Tool has multiple related functions
|
||||
- Needs to remember or share information
|
||||
- Needs to manage resources efficiently
|
||||
- Has complex setup requirements
|
||||
|
||||
**Example:**
|
||||
```python
|
||||
class StockTools:
|
||||
def get_stock_price(self, symbol):
|
||||
# Get current stock price
|
||||
return price
|
||||
|
||||
def get_stock_info(self, symbol):
|
||||
# Get detailed stock information
|
||||
return info
|
||||
```
|
||||
|
||||
**Usage:**
|
||||
```python
|
||||
from praisonaiagents.tools import get_stock_price, get_stock_info
|
||||
|
||||
price = get_stock_price("AAPL")
|
||||
info = get_stock_info("AAPL")
|
||||
```
|
||||
|
||||
## How to Choose Your Approach
|
||||
|
||||
Ask yourself these questions:
|
||||
|
||||
1. **Is your tool doing one simple thing?**
|
||||
- Yes → Use Function-Based Approach
|
||||
- No → Consider Class-Based Approach
|
||||
|
||||
2. **Does your tool need to remember information?**
|
||||
- Yes → Use Class-Based Approach
|
||||
- No → Use Function-Based Approach
|
||||
|
||||
3. **Are your tool's operations related to each other?**
|
||||
- Yes → Use Class-Based Approach
|
||||
- No → Use Function-Based Approach
|
||||
|
||||
4. **Does your tool need to manage resources efficiently?**
|
||||
- Yes → Use Class-Based Approach
|
||||
- No → Use Function-Based Approach
|
||||
|
||||
## Real-World Examples
|
||||
|
||||
### Internet Search Tool (Function-Based)
|
||||
- Does one thing: searches the internet
|
||||
- Doesn't need to remember previous searches
|
||||
- Each search is independent
|
||||
- Simple input/output operation
|
||||
|
||||
### Stock Market Tool (Class-Based)
|
||||
- Does multiple things: check prices, get company info, get historical data
|
||||
- Remembers stock information to avoid repeated downloads
|
||||
- Operations are related (all about stocks)
|
||||
- Manages connections efficiently
|
||||
|
||||
## Getting Started
|
||||
|
||||
1. **Choose Your Approach** based on the guidelines above
|
||||
|
||||
2. **Create Your Tool File**:
|
||||
- Name it descriptively (e.g., `weather_tools.py`)
|
||||
- Place it in the `praisonaiagents/tools` directory
|
||||
|
||||
3. **Write Your Tool**:
|
||||
- Add clear documentation
|
||||
- Include type hints for better understanding
|
||||
- Handle errors gracefully
|
||||
|
||||
4. **Test Your Tool**:
|
||||
- Make sure it works as expected
|
||||
- Test error cases
|
||||
- Check performance
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Documentation**:
|
||||
- Explain what your tool does
|
||||
- Provide examples
|
||||
- List any requirements
|
||||
|
||||
2. **Error Handling**:
|
||||
- Always handle possible errors
|
||||
- Return helpful error messages
|
||||
- Don't let your tool crash
|
||||
|
||||
3. **Performance**:
|
||||
- Keep it efficient
|
||||
- Don't waste resources
|
||||
- Cache when helpful
|
||||
|
||||
4. **User-Friendly**:
|
||||
- Make it easy to use
|
||||
- Use clear function/method names
|
||||
- Keep it simple
|
||||
|
||||
## Need Help?
|
||||
|
||||
- Check existing tools for examples
|
||||
- Ask in our community
|
||||
- Read the documentation
|
||||
- Don't hesitate to ask questions!
|
||||
|
||||
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.
|
||||
@@ -1,4 +1,167 @@
|
||||
"""Tools package for PraisonAI Agents"""
|
||||
from .tools import Tools
|
||||
from importlib import import_module
|
||||
from typing import Any
|
||||
|
||||
__all__ = ['Tools']
|
||||
# Map of function names to their module and class (if any)
|
||||
TOOL_MAPPINGS = {
|
||||
# Direct functions
|
||||
'internet_search': ('.duckduckgo_tools', None),
|
||||
'duckduckgo': ('.duckduckgo_tools', None),
|
||||
|
||||
# Class methods from YFinance
|
||||
'get_stock_price': ('.yfinance_tools', 'YFinanceTools'),
|
||||
'get_stock_info': ('.yfinance_tools', 'YFinanceTools'),
|
||||
'get_historical_data': ('.yfinance_tools', 'YFinanceTools'),
|
||||
'yfinance': ('.yfinance_tools', 'YFinanceTools'),
|
||||
|
||||
# File Tools
|
||||
'read_file': ('.file_tools', 'FileTools'),
|
||||
'write_file': ('.file_tools', 'FileTools'),
|
||||
'list_files': ('.file_tools', 'FileTools'),
|
||||
'get_file_info': ('.file_tools', 'FileTools'),
|
||||
'copy_file': ('.file_tools', 'FileTools'),
|
||||
'move_file': ('.file_tools', 'FileTools'),
|
||||
'delete_file': ('.file_tools', 'FileTools'),
|
||||
'file_tools': ('.file_tools', 'FileTools'),
|
||||
|
||||
# CSV Tools
|
||||
'read_csv': ('.csv_tools', 'CSVTools'),
|
||||
'write_csv': ('.csv_tools', 'CSVTools'),
|
||||
'merge_csv': ('.csv_tools', 'CSVTools'),
|
||||
'analyze_csv': ('.csv_tools', 'CSVTools'),
|
||||
'split_csv': ('.csv_tools', 'CSVTools'),
|
||||
'csv_tools': ('.csv_tools', 'CSVTools'),
|
||||
|
||||
# JSON Tools
|
||||
'read_json': ('.json_tools', 'JSONTools'),
|
||||
'write_json': ('.json_tools', 'JSONTools'),
|
||||
'merge_json': ('.json_tools', 'JSONTools'),
|
||||
'validate_json': ('.json_tools', 'JSONTools'),
|
||||
'analyze_json': ('.json_tools', 'JSONTools'),
|
||||
'transform_json': ('.json_tools', 'JSONTools'),
|
||||
'json_tools': ('.json_tools', 'JSONTools'),
|
||||
|
||||
# Excel Tools
|
||||
'read_excel': ('.excel_tools', 'ExcelTools'),
|
||||
'write_excel': ('.excel_tools', 'ExcelTools'),
|
||||
'merge_excel': ('.excel_tools', 'ExcelTools'),
|
||||
'create_chart': ('.excel_tools', 'ExcelTools'),
|
||||
'add_chart_to_sheet': ('.excel_tools', 'ExcelTools'),
|
||||
'excel_tools': ('.excel_tools', 'ExcelTools'),
|
||||
|
||||
# XML Tools
|
||||
'read_xml': ('.xml_tools', 'XMLTools'),
|
||||
'write_xml': ('.xml_tools', 'XMLTools'),
|
||||
'transform_xml': ('.xml_tools', 'XMLTools'),
|
||||
'validate_xml': ('.xml_tools', 'XMLTools'),
|
||||
'xml_to_dict': ('.xml_tools', 'XMLTools'),
|
||||
'dict_to_xml': ('.xml_tools', 'XMLTools'),
|
||||
'xpath_query': ('.xml_tools', 'XMLTools'),
|
||||
'xml_tools': ('.xml_tools', 'XMLTools'),
|
||||
|
||||
# YAML Tools
|
||||
'read_yaml': ('.yaml_tools', 'YAMLTools'),
|
||||
'write_yaml': ('.yaml_tools', 'YAMLTools'),
|
||||
'merge_yaml': ('.yaml_tools', 'YAMLTools'),
|
||||
'validate_yaml': ('.yaml_tools', 'YAMLTools'),
|
||||
'analyze_yaml': ('.yaml_tools', 'YAMLTools'),
|
||||
'transform_yaml': ('.yaml_tools', 'YAMLTools'),
|
||||
'yaml_tools': ('.yaml_tools', 'YAMLTools'),
|
||||
|
||||
# Calculator Tools
|
||||
'evaluate': ('.calculator_tools', 'CalculatorTools'),
|
||||
'solve_equation': ('.calculator_tools', 'CalculatorTools'),
|
||||
'convert_units': ('.calculator_tools', 'CalculatorTools'),
|
||||
'calculate_statistics': ('.calculator_tools', 'CalculatorTools'),
|
||||
'calculate_financial': ('.calculator_tools', 'CalculatorTools'),
|
||||
'calculator_tools': ('.calculator_tools', 'CalculatorTools'),
|
||||
|
||||
# Python Tools
|
||||
'execute_code': ('.python_tools', 'PythonTools'),
|
||||
'analyze_code': ('.python_tools', 'PythonTools'),
|
||||
'format_code': ('.python_tools', 'PythonTools'),
|
||||
'lint_code': ('.python_tools', 'PythonTools'),
|
||||
'disassemble_code': ('.python_tools', 'PythonTools'),
|
||||
'python_tools': ('.python_tools', 'PythonTools'),
|
||||
|
||||
# Pandas Tools
|
||||
'filter_data': ('.pandas_tools', 'PandasTools'),
|
||||
'get_summary': ('.pandas_tools', 'PandasTools'),
|
||||
'group_by': ('.pandas_tools', 'PandasTools'),
|
||||
'pivot_table': ('.pandas_tools', 'PandasTools'),
|
||||
'pandas_tools': ('.pandas_tools', 'PandasTools'),
|
||||
|
||||
# Wikipedia Tools
|
||||
'search': ('.wikipedia_tools', 'WikipediaTools'),
|
||||
'get_wikipedia_summary': ('.wikipedia_tools', 'WikipediaTools'),
|
||||
'get_wikipedia_page': ('.wikipedia_tools', 'WikipediaTools'),
|
||||
'get_random_wikipedia': ('.wikipedia_tools', 'WikipediaTools'),
|
||||
'set_wikipedia_language': ('.wikipedia_tools', 'WikipediaTools'),
|
||||
'wikipedia_tools': ('.wikipedia_tools', 'WikipediaTools'),
|
||||
|
||||
# Newspaper Tools
|
||||
'get_article': ('.newspaper_tools', 'NewspaperTools'),
|
||||
'get_news_sources': ('.newspaper_tools', 'NewspaperTools'),
|
||||
'get_articles_from_source': ('.newspaper_tools', 'NewspaperTools'),
|
||||
'get_trending_topics': ('.newspaper_tools', 'NewspaperTools'),
|
||||
'newspaper_tools': ('.newspaper_tools', 'NewspaperTools'),
|
||||
|
||||
# arXiv Tools
|
||||
'search_arxiv': ('.arxiv_tools', 'ArxivTools'),
|
||||
'get_arxiv_paper': ('.arxiv_tools', 'ArxivTools'),
|
||||
'get_papers_by_author': ('.arxiv_tools', 'ArxivTools'),
|
||||
'get_papers_by_category': ('.arxiv_tools', 'ArxivTools'),
|
||||
'arxiv_tools': ('.arxiv_tools', 'ArxivTools'),
|
||||
|
||||
# Spider Tools
|
||||
'scrape_page': ('.spider_tools', 'SpiderTools'),
|
||||
'extract_links': ('.spider_tools', 'SpiderTools'),
|
||||
'crawl': ('.spider_tools', 'SpiderTools'),
|
||||
'extract_text': ('.spider_tools', 'SpiderTools'),
|
||||
'spider_tools': ('.spider_tools', 'SpiderTools'),
|
||||
|
||||
# DuckDB Tools
|
||||
'query': ('.duckdb_tools', 'DuckDBTools'),
|
||||
'create_table': ('.duckdb_tools', 'DuckDBTools'),
|
||||
'load_data': ('.duckdb_tools', 'DuckDBTools'),
|
||||
'export_data': ('.duckdb_tools', 'DuckDBTools'),
|
||||
'get_table_info': ('.duckdb_tools', 'DuckDBTools'),
|
||||
'analyze_data': ('.duckdb_tools', 'DuckDBTools'),
|
||||
'duckdb_tools': ('.duckdb_tools', 'DuckDBTools'),
|
||||
|
||||
# Shell Tools
|
||||
'execute_command': ('.shell_tools', 'ShellTools'),
|
||||
'list_processes': ('.shell_tools', 'ShellTools'),
|
||||
'kill_process': ('.shell_tools', 'ShellTools'),
|
||||
'get_system_info': ('.shell_tools', 'ShellTools'),
|
||||
'shell_tools': ('.shell_tools', 'ShellTools'),
|
||||
}
|
||||
|
||||
_instances = {} # Cache for class instances
|
||||
|
||||
def __getattr__(name: str) -> Any:
|
||||
"""Smart lazy loading of tools with class method support."""
|
||||
if name not in TOOL_MAPPINGS:
|
||||
raise AttributeError(f"module '{__package__}' has no attribute '{name}'")
|
||||
|
||||
module_path, class_name = TOOL_MAPPINGS[name]
|
||||
|
||||
if class_name is None:
|
||||
# Direct function import
|
||||
module = import_module(module_path, __package__)
|
||||
if name in ['duckduckgo', 'file_tools', 'pandas_tools', 'wikipedia_tools',
|
||||
'newspaper_tools', 'arxiv_tools', 'spider_tools', 'duckdb_tools', 'csv_tools', 'json_tools', 'excel_tools', 'xml_tools', 'yaml_tools', 'calculator_tools', 'python_tools', 'shell_tools']:
|
||||
return module # Returns the callable module
|
||||
return getattr(module, name)
|
||||
else:
|
||||
# Class method import
|
||||
if class_name not in _instances:
|
||||
module = import_module(module_path, __package__)
|
||||
class_ = getattr(module, class_name)
|
||||
_instances[class_name] = class_()
|
||||
|
||||
# Get the method and bind it to the instance
|
||||
method = getattr(_instances[class_name], name)
|
||||
return method
|
||||
|
||||
__all__ = list(TOOL_MAPPINGS.keys())
|
||||
@@ -0,0 +1,292 @@
|
||||
"""Tools for searching and retrieving papers from arXiv.
|
||||
|
||||
Usage:
|
||||
from praisonaiagents.tools import arxiv_tools
|
||||
papers = arxiv_tools.search("quantum computing")
|
||||
paper = arxiv_tools.get_paper("2401.00123")
|
||||
|
||||
or
|
||||
from praisonaiagents.tools import search_arxiv, get_arxiv_paper
|
||||
papers = search_arxiv("quantum computing")
|
||||
"""
|
||||
|
||||
import logging
|
||||
from typing import List, Dict, Union, Optional, Any
|
||||
from importlib import util
|
||||
import json
|
||||
|
||||
# Map sort criteria to arxiv.SortCriterion
|
||||
SORT_CRITERIA = {
|
||||
"relevance": "Relevance",
|
||||
"lastupdateddate": "LastUpdatedDate",
|
||||
"submitteddate": "SubmittedDate"
|
||||
}
|
||||
|
||||
# Map sort order to arxiv.SortOrder
|
||||
SORT_ORDER = {
|
||||
"ascending": "Ascending",
|
||||
"descending": "Descending"
|
||||
}
|
||||
|
||||
class ArxivTools:
|
||||
"""Tools for searching and retrieving papers from arXiv."""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize ArxivTools and check for arxiv package."""
|
||||
self._check_arxiv()
|
||||
|
||||
def _check_arxiv(self):
|
||||
"""Check if arxiv package is installed."""
|
||||
if util.find_spec("arxiv") is None:
|
||||
raise ImportError("arxiv package is not available. Please install it using: pip install arxiv")
|
||||
global arxiv
|
||||
import arxiv
|
||||
|
||||
def search(
|
||||
self,
|
||||
query: str,
|
||||
max_results: int = 10,
|
||||
sort_by: str = "relevance",
|
||||
sort_order: str = "descending",
|
||||
include_fields: Optional[List[str]] = None
|
||||
) -> Union[List[Dict[str, Any]], Dict[str, str]]:
|
||||
"""
|
||||
Search arXiv for papers matching the query.
|
||||
|
||||
Args:
|
||||
query: Search query (e.g., "quantum computing", "author:Einstein")
|
||||
max_results: Maximum number of results to return
|
||||
sort_by: Sort results by ("relevance", "lastUpdatedDate", "submittedDate")
|
||||
sort_order: Sort order ("ascending" or "descending")
|
||||
include_fields: List of fields to include in results. If None, includes all.
|
||||
Available fields: ["title", "authors", "summary", "comment", "journal_ref",
|
||||
"doi", "primary_category", "categories", "links"]
|
||||
|
||||
Returns:
|
||||
List[Dict] or Dict: List of papers or error dict
|
||||
"""
|
||||
try:
|
||||
import arxiv
|
||||
|
||||
# Configure search client
|
||||
client = arxiv.Client()
|
||||
|
||||
# Map sort criteria
|
||||
sort_by_enum = getattr(arxiv.SortCriterion, SORT_CRITERIA[sort_by.lower()])
|
||||
sort_order_enum = getattr(arxiv.SortOrder, SORT_ORDER[sort_order.lower()])
|
||||
|
||||
# Build search query
|
||||
search = arxiv.Search(
|
||||
query=query,
|
||||
max_results=max_results,
|
||||
sort_by=sort_by_enum,
|
||||
sort_order=sort_order_enum
|
||||
)
|
||||
|
||||
# Execute search
|
||||
results = []
|
||||
for result in client.results(search):
|
||||
# Convert to dict with selected fields
|
||||
paper = self._result_to_dict(result, include_fields)
|
||||
results.append(paper)
|
||||
|
||||
return results
|
||||
except Exception as e:
|
||||
error_msg = f"Error searching arXiv: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return {"error": error_msg}
|
||||
|
||||
def get_paper(
|
||||
self,
|
||||
paper_id: str,
|
||||
include_fields: Optional[List[str]] = None
|
||||
) -> Union[Dict[str, Any], Dict[str, str]]:
|
||||
"""
|
||||
Get details of a specific paper by its arXiv ID.
|
||||
|
||||
Args:
|
||||
paper_id: arXiv paper ID (e.g., "2401.00123")
|
||||
include_fields: List of fields to include in results. If None, includes all.
|
||||
Available fields: ["title", "authors", "summary", "comment", "journal_ref",
|
||||
"doi", "primary_category", "categories", "links"]
|
||||
|
||||
Returns:
|
||||
Dict: Paper details or error dict
|
||||
"""
|
||||
try:
|
||||
import arxiv
|
||||
|
||||
# Configure client
|
||||
client = arxiv.Client()
|
||||
|
||||
# Get paper by ID
|
||||
search = arxiv.Search(id_list=[paper_id])
|
||||
results = list(client.results(search))
|
||||
|
||||
if not results:
|
||||
return {"error": f"Paper with ID {paper_id} not found"}
|
||||
|
||||
# Convert to dict with selected fields
|
||||
paper = self._result_to_dict(results[0], include_fields)
|
||||
return paper
|
||||
except Exception as e:
|
||||
error_msg = f"Error getting paper {paper_id}: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return {"error": error_msg}
|
||||
|
||||
def get_papers_by_author(
|
||||
self,
|
||||
author: str,
|
||||
max_results: int = 10,
|
||||
sort_by: str = "submittedDate",
|
||||
sort_order: str = "descending",
|
||||
include_fields: Optional[List[str]] = None
|
||||
) -> Union[List[Dict[str, Any]], Dict[str, str]]:
|
||||
"""
|
||||
Get papers by a specific author.
|
||||
|
||||
Args:
|
||||
author: Author name (e.g., "Einstein")
|
||||
max_results: Maximum number of results to return
|
||||
sort_by: Sort results by ("relevance", "lastUpdatedDate", "submittedDate")
|
||||
sort_order: Sort order ("ascending" or "descending")
|
||||
include_fields: List of fields to include in results
|
||||
|
||||
Returns:
|
||||
List[Dict] or Dict: List of papers or error dict
|
||||
"""
|
||||
query = f'au:"{author}"'
|
||||
return self.search(query, max_results, sort_by, sort_order, include_fields)
|
||||
|
||||
def get_papers_by_category(
|
||||
self,
|
||||
category: str,
|
||||
max_results: int = 10,
|
||||
sort_by: str = "submittedDate",
|
||||
sort_order: str = "descending",
|
||||
include_fields: Optional[List[str]] = None
|
||||
) -> Union[List[Dict[str, Any]], Dict[str, str]]:
|
||||
"""
|
||||
Get papers from a specific category.
|
||||
|
||||
Args:
|
||||
category: arXiv category (e.g., "cs.AI", "physics.gen-ph")
|
||||
max_results: Maximum number of results to return
|
||||
sort_by: Sort results by ("relevance", "lastUpdatedDate", "submittedDate")
|
||||
sort_order: Sort order ("ascending" or "descending")
|
||||
include_fields: List of fields to include in results
|
||||
|
||||
Returns:
|
||||
List[Dict] or Dict: List of papers or error dict
|
||||
"""
|
||||
query = f'cat:{category}'
|
||||
return self.search(query, max_results, sort_by, sort_order, include_fields)
|
||||
|
||||
def _result_to_dict(
|
||||
self,
|
||||
result: Any,
|
||||
include_fields: Optional[List[str]] = None
|
||||
) -> Dict[str, Any]:
|
||||
"""Convert arxiv.Result to dictionary with selected fields."""
|
||||
# Default fields to include
|
||||
if include_fields is None:
|
||||
include_fields = [
|
||||
"title", "authors", "summary", "comment", "journal_ref",
|
||||
"doi", "primary_category", "categories", "links"
|
||||
]
|
||||
|
||||
# Build paper dict with selected fields
|
||||
paper = {}
|
||||
|
||||
# Always include these basic fields
|
||||
paper["arxiv_id"] = result.entry_id.split("/")[-1]
|
||||
paper["updated"] = result.updated.isoformat() if result.updated else None
|
||||
paper["published"] = result.published.isoformat() if result.published else None
|
||||
|
||||
# Add requested fields
|
||||
if "title" in include_fields:
|
||||
paper["title"] = result.title
|
||||
if "authors" in include_fields:
|
||||
paper["authors"] = [str(author) for author in result.authors]
|
||||
if "summary" in include_fields:
|
||||
paper["summary"] = result.summary
|
||||
if "comment" in include_fields:
|
||||
paper["comment"] = result.comment
|
||||
if "journal_ref" in include_fields:
|
||||
paper["journal_ref"] = result.journal_ref
|
||||
if "doi" in include_fields:
|
||||
paper["doi"] = result.doi
|
||||
if "primary_category" in include_fields:
|
||||
paper["primary_category"] = result.primary_category
|
||||
if "categories" in include_fields:
|
||||
paper["categories"] = result.categories
|
||||
if "links" in include_fields:
|
||||
paper["pdf_url"] = result.pdf_url
|
||||
paper["abstract_url"] = f"https://arxiv.org/abs/{paper['arxiv_id']}"
|
||||
|
||||
return paper
|
||||
|
||||
# Create instance for direct function access
|
||||
_arxiv_tools = ArxivTools()
|
||||
search_arxiv = _arxiv_tools.search
|
||||
get_arxiv_paper = _arxiv_tools.get_paper
|
||||
get_papers_by_author = _arxiv_tools.get_papers_by_author
|
||||
get_papers_by_category = _arxiv_tools.get_papers_by_category
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Example usage
|
||||
print("\n==================================================")
|
||||
print("ArxivTools Demonstration")
|
||||
print("==================================================\n")
|
||||
|
||||
# 1. Search for papers
|
||||
print("1. Searching for Papers")
|
||||
print("------------------------------")
|
||||
query = "quantum computing"
|
||||
papers = search_arxiv(query, max_results=3)
|
||||
print(f"Papers about {query}:")
|
||||
if isinstance(papers, list):
|
||||
print(json.dumps(papers, indent=2))
|
||||
else:
|
||||
print(papers) # Show error
|
||||
print()
|
||||
|
||||
# 2. Get specific paper
|
||||
print("2. Getting Specific Paper")
|
||||
print("------------------------------")
|
||||
if isinstance(papers, list) and papers:
|
||||
paper_id = papers[0]["arxiv_id"]
|
||||
paper = get_arxiv_paper(paper_id)
|
||||
print(f"Paper {paper_id}:")
|
||||
if "error" not in paper:
|
||||
print(json.dumps(paper, indent=2))
|
||||
else:
|
||||
print(paper) # Show error
|
||||
print()
|
||||
|
||||
# 3. Get papers by author
|
||||
print("3. Getting Papers by Author")
|
||||
print("------------------------------")
|
||||
author = "Yoshua Bengio"
|
||||
author_papers = get_papers_by_author(author, max_results=3)
|
||||
print(f"Papers by {author}:")
|
||||
if isinstance(author_papers, list):
|
||||
print(json.dumps(author_papers, indent=2))
|
||||
else:
|
||||
print(author_papers) # Show error
|
||||
print()
|
||||
|
||||
# 4. Get papers by category
|
||||
print("4. Getting Papers by Category")
|
||||
print("------------------------------")
|
||||
category = "cs.AI"
|
||||
category_papers = get_papers_by_category(category, max_results=3)
|
||||
print(f"Papers in category {category}:")
|
||||
if isinstance(category_papers, list):
|
||||
print(json.dumps(category_papers, indent=2))
|
||||
else:
|
||||
print(category_papers) # Show error
|
||||
|
||||
print("\n==================================================")
|
||||
print("Demonstration Complete")
|
||||
print("==================================================")
|
||||
@@ -0,0 +1,278 @@
|
||||
"""Tools for performing calculations.
|
||||
|
||||
Usage:
|
||||
from praisonaiagents.tools import calculator_tools
|
||||
result = calculator_tools.evaluate("2 + 2 * 3")
|
||||
|
||||
or
|
||||
from praisonaiagents.tools import evaluate, solve_equation, convert_units
|
||||
result = evaluate("2 + 2 * 3")
|
||||
"""
|
||||
|
||||
import logging
|
||||
from typing import List, Dict, Optional, Any
|
||||
from importlib import util
|
||||
import math
|
||||
|
||||
class CalculatorTools:
|
||||
"""Tools for performing calculations."""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize CalculatorTools."""
|
||||
self._check_dependencies()
|
||||
|
||||
def _check_dependencies(self):
|
||||
"""Check if required packages are installed."""
|
||||
missing = []
|
||||
for package in ['sympy', 'pint']:
|
||||
if util.find_spec(package) is None:
|
||||
missing.append(package)
|
||||
|
||||
if missing:
|
||||
raise ImportError(
|
||||
f"Required packages not available. Please install: {', '.join(missing)}\n"
|
||||
f"Run: pip install {' '.join(missing)}"
|
||||
)
|
||||
|
||||
def evaluate(
|
||||
self,
|
||||
expression: str,
|
||||
variables: Optional[Dict[str, float]] = None,
|
||||
precision: int = 10
|
||||
) -> Dict[str, Any]:
|
||||
"""Evaluate a mathematical expression."""
|
||||
try:
|
||||
if util.find_spec('sympy') is None:
|
||||
error_msg = "sympy package is not available. Please install it using: pip install sympy"
|
||||
logging.error(error_msg)
|
||||
return {"error": error_msg}
|
||||
|
||||
# Import sympy only when needed
|
||||
import sympy
|
||||
|
||||
# Replace common mathematical functions
|
||||
expression = expression.lower()
|
||||
replacements = {
|
||||
'sin(': 'math.sin(',
|
||||
'cos(': 'math.cos(',
|
||||
'tan(': 'math.tan(',
|
||||
'sqrt(': 'math.sqrt(',
|
||||
'log(': 'math.log(',
|
||||
'exp(': 'math.exp(',
|
||||
'pi': str(math.pi),
|
||||
'e': str(math.e)
|
||||
}
|
||||
for old, new in replacements.items():
|
||||
expression = expression.replace(old, new)
|
||||
|
||||
# Create safe namespace
|
||||
safe_dict = {
|
||||
'math': math,
|
||||
'__builtins__': None
|
||||
}
|
||||
if variables:
|
||||
safe_dict.update(variables)
|
||||
|
||||
# Evaluate expression
|
||||
result = eval(expression, safe_dict)
|
||||
|
||||
# Round to specified precision
|
||||
if isinstance(result, (int, float)):
|
||||
return {"result": round(float(result), precision)}
|
||||
return {"error": "Invalid expression"}
|
||||
except Exception as e:
|
||||
error_msg = f"Error evaluating expression: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return {"error": error_msg}
|
||||
|
||||
def solve_equation(
|
||||
self,
|
||||
equation: str,
|
||||
variable: str = 'x'
|
||||
) -> Dict[str, Any]:
|
||||
"""Solve a mathematical equation."""
|
||||
try:
|
||||
if util.find_spec('sympy') is None:
|
||||
error_msg = "sympy package is not available. Please install it using: pip install sympy"
|
||||
logging.error(error_msg)
|
||||
return {"error": error_msg}
|
||||
|
||||
# Import sympy only when needed
|
||||
import sympy
|
||||
|
||||
# Parse equation
|
||||
if '=' in equation:
|
||||
left, right = equation.split('=')
|
||||
equation = f"({left}) - ({right})"
|
||||
|
||||
# Convert to SymPy expression
|
||||
x = sympy.Symbol(variable)
|
||||
expr = sympy.sympify(equation)
|
||||
|
||||
# Solve equation
|
||||
solutions = sympy.solve(expr, x)
|
||||
|
||||
# Convert complex solutions to real if possible
|
||||
real_solutions = []
|
||||
for sol in solutions:
|
||||
if sol.is_real:
|
||||
real_solutions.append(float(sol))
|
||||
|
||||
return {"solutions": real_solutions} if real_solutions else {"error": "No real solutions found"}
|
||||
except Exception as e:
|
||||
error_msg = f"Error solving equation: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return {"error": error_msg}
|
||||
|
||||
def convert_units(
|
||||
self,
|
||||
value: float,
|
||||
from_unit: str,
|
||||
to_unit: str
|
||||
) -> Dict[str, Any]:
|
||||
"""Convert between different units."""
|
||||
try:
|
||||
if util.find_spec('pint') is None:
|
||||
error_msg = "pint package is not available. Please install it using: pip install pint"
|
||||
logging.error(error_msg)
|
||||
return {"error": error_msg}
|
||||
|
||||
# Import pint only when needed
|
||||
import pint
|
||||
|
||||
# Create quantity with source unit
|
||||
ureg = pint.UnitRegistry()
|
||||
quantity = value * ureg(from_unit)
|
||||
|
||||
# Convert to target unit
|
||||
result = quantity.to(to_unit)
|
||||
|
||||
return {"result": float(result.magnitude)}
|
||||
except Exception as e:
|
||||
error_msg = f"Error converting units: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return {"error": error_msg}
|
||||
|
||||
def calculate_statistics(
|
||||
self,
|
||||
numbers: List[float]
|
||||
) -> Dict[str, Any]:
|
||||
"""Calculate basic statistics for a list of numbers."""
|
||||
try:
|
||||
if not numbers:
|
||||
return {"error": "No numbers provided"}
|
||||
|
||||
n = len(numbers)
|
||||
mean = sum(numbers) / n
|
||||
|
||||
# Calculate variance and std dev
|
||||
squared_diff_sum = sum((x - mean) ** 2 for x in numbers)
|
||||
variance = squared_diff_sum / (n - 1) if n > 1 else 0
|
||||
std_dev = math.sqrt(variance)
|
||||
|
||||
# Calculate median
|
||||
sorted_nums = sorted(numbers)
|
||||
if n % 2 == 0:
|
||||
median = (sorted_nums[n//2 - 1] + sorted_nums[n//2]) / 2
|
||||
else:
|
||||
median = sorted_nums[n//2]
|
||||
|
||||
return {
|
||||
"mean": mean,
|
||||
"median": median,
|
||||
"std_dev": std_dev,
|
||||
"variance": variance,
|
||||
"min": min(numbers),
|
||||
"max": max(numbers),
|
||||
"range": max(numbers) - min(numbers),
|
||||
"count": n
|
||||
}
|
||||
except Exception as e:
|
||||
error_msg = f"Error calculating statistics: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return {"error": error_msg}
|
||||
|
||||
def calculate_financial(
|
||||
self,
|
||||
principal: float,
|
||||
rate: float,
|
||||
time: float,
|
||||
frequency: str = 'yearly'
|
||||
) -> Dict[str, Any]:
|
||||
"""Calculate financial metrics like compound interest."""
|
||||
try:
|
||||
# Convert rate to decimal
|
||||
rate = rate / 100
|
||||
|
||||
# Get compounding frequency
|
||||
freq_map = {
|
||||
'yearly': 1,
|
||||
'semi-annual': 2,
|
||||
'quarterly': 4,
|
||||
'monthly': 12,
|
||||
'daily': 365
|
||||
}
|
||||
n = freq_map.get(frequency.lower(), 1)
|
||||
|
||||
# Calculate compound interest
|
||||
amount = principal * (1 + rate/n)**(n*time)
|
||||
interest = amount - principal
|
||||
|
||||
# Calculate simple interest
|
||||
simple_interest = principal * rate * time
|
||||
|
||||
return {
|
||||
"final_amount": amount,
|
||||
"compound_interest": interest,
|
||||
"simple_interest": simple_interest,
|
||||
"difference": interest - simple_interest
|
||||
}
|
||||
except Exception as e:
|
||||
error_msg = f"Error calculating financial metrics: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return {"error": error_msg}
|
||||
|
||||
# Create instance for direct function access
|
||||
_calculator_tools = CalculatorTools()
|
||||
evaluate = _calculator_tools.evaluate
|
||||
solve_equation = _calculator_tools.solve_equation
|
||||
convert_units = _calculator_tools.convert_units
|
||||
calculate_statistics = _calculator_tools.calculate_statistics
|
||||
calculate_financial = _calculator_tools.calculate_financial
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("\n==================================================")
|
||||
print("CalculatorTools Demonstration")
|
||||
print("==================================================\n")
|
||||
|
||||
print("1. Basic Arithmetic")
|
||||
print("------------------------------")
|
||||
print("2 + 2 =", evaluate("2 + 2")["result"])
|
||||
print("5 * 6 =", evaluate("5 * 6")["result"])
|
||||
print("10 / 3 =", evaluate("10 / 3")["result"])
|
||||
print()
|
||||
|
||||
print("2. Complex Expressions")
|
||||
print("------------------------------")
|
||||
print("(2 + 3) * 4 =", evaluate("(2 + 3) * 4")["result"])
|
||||
print("2^3 + 4 =", evaluate("2^3 + 4")["result"])
|
||||
print("sqrt(16) + 2 =", evaluate("sqrt(16) + 2")["result"])
|
||||
print()
|
||||
|
||||
print("3. Solving Equations")
|
||||
print("------------------------------")
|
||||
result = solve_equation("x^2 - 5*x + 6 = 0")
|
||||
print("x^2 - 5*x + 6 = 0")
|
||||
print("Solutions:", result["solutions"])
|
||||
print()
|
||||
|
||||
print("4. Unit Conversions")
|
||||
print("------------------------------")
|
||||
print("100 meters to kilometers:", convert_units(100, "meters", "kilometers")["result"])
|
||||
print("1 hour to minutes:", convert_units(1, "hours", "minutes")["result"])
|
||||
print("32 fahrenheit to celsius:", convert_units(32, "fahrenheit", "celsius")["result"])
|
||||
print()
|
||||
|
||||
print("==================================================")
|
||||
print("Demonstration Complete")
|
||||
print("==================================================")
|
||||
@@ -0,0 +1,266 @@
|
||||
"""Tools for working with CSV files.
|
||||
|
||||
Usage:
|
||||
from praisonaiagents.tools import csv_tools
|
||||
df = csv_tools.read_csv("data.csv")
|
||||
|
||||
or
|
||||
from praisonaiagents.tools import read_csv, write_csv, merge_csv
|
||||
df = read_csv("data.csv")
|
||||
"""
|
||||
|
||||
import logging
|
||||
from typing import List, Dict, Union, Optional, Any, TYPE_CHECKING
|
||||
from importlib import util
|
||||
import json
|
||||
import csv
|
||||
from pathlib import Path
|
||||
|
||||
if TYPE_CHECKING:
|
||||
import pandas as pd
|
||||
|
||||
class CSVTools:
|
||||
"""Tools for working with CSV files."""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize CSVTools."""
|
||||
pass
|
||||
|
||||
def _get_pandas(self) -> Optional['pd']:
|
||||
"""Get pandas module, installing if needed"""
|
||||
if util.find_spec('pandas') is None:
|
||||
error_msg = "pandas package is not available. Please install it using: pip install pandas"
|
||||
logging.error(error_msg)
|
||||
return None
|
||||
import pandas as pd
|
||||
return pd
|
||||
|
||||
def read_csv(
|
||||
self,
|
||||
filepath: str,
|
||||
encoding: str = 'utf-8',
|
||||
delimiter: str = ',',
|
||||
header: Union[int, List[int], None] = 0,
|
||||
usecols: Optional[List[str]] = None,
|
||||
dtype: Optional[Dict[str, str]] = None,
|
||||
parse_dates: Optional[List[str]] = None,
|
||||
na_values: Optional[List[str]] = None,
|
||||
nrows: Optional[int] = None
|
||||
) -> List[Dict[str, Any]]:
|
||||
"""Read a CSV file with advanced options.
|
||||
|
||||
Args:
|
||||
filepath: Path to CSV file
|
||||
encoding: File encoding
|
||||
delimiter: Column delimiter
|
||||
header: Row number(s) to use as column names
|
||||
usecols: Columns to read
|
||||
dtype: Dict of column dtypes
|
||||
parse_dates: List of columns to parse as dates
|
||||
na_values: Additional strings to recognize as NA/NaN
|
||||
nrows: Number of rows to read
|
||||
|
||||
Returns:
|
||||
List of row dicts
|
||||
"""
|
||||
try:
|
||||
pd = self._get_pandas()
|
||||
if pd is None:
|
||||
return {"error": "pandas package not available"}
|
||||
|
||||
df = pd.read_csv(
|
||||
filepath,
|
||||
encoding=encoding,
|
||||
delimiter=delimiter,
|
||||
header=header,
|
||||
usecols=usecols,
|
||||
dtype=dtype,
|
||||
parse_dates=parse_dates,
|
||||
na_values=na_values,
|
||||
nrows=nrows
|
||||
)
|
||||
return df.to_dict('records')
|
||||
|
||||
except Exception as e:
|
||||
error_msg = f"Error reading CSV file {filepath}: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return {"error": error_msg}
|
||||
|
||||
def write_csv(
|
||||
self,
|
||||
filepath: str,
|
||||
data: List[Dict[str, Any]],
|
||||
encoding: str = 'utf-8',
|
||||
delimiter: str = ',',
|
||||
index: bool = False,
|
||||
header: bool = True,
|
||||
float_format: Optional[str] = None,
|
||||
date_format: Optional[str] = None,
|
||||
mode: str = 'w'
|
||||
) -> bool:
|
||||
"""Write data to a CSV file.
|
||||
|
||||
Args:
|
||||
filepath: Path to CSV file
|
||||
data: List of row dicts to write
|
||||
encoding: File encoding
|
||||
delimiter: Column delimiter
|
||||
index: Whether to write row indices
|
||||
header: Whether to write column headers
|
||||
float_format: Format string for float values
|
||||
date_format: Format string for date values
|
||||
mode: Write mode ('w' for write, 'a' for append)
|
||||
|
||||
Returns:
|
||||
bool: Success status
|
||||
"""
|
||||
try:
|
||||
pd = self._get_pandas()
|
||||
if pd is None:
|
||||
return False
|
||||
|
||||
df = pd.DataFrame(data)
|
||||
df.to_csv(
|
||||
filepath,
|
||||
encoding=encoding,
|
||||
sep=delimiter,
|
||||
index=index,
|
||||
header=header,
|
||||
float_format=float_format,
|
||||
date_format=date_format,
|
||||
mode=mode
|
||||
)
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
error_msg = f"Error writing CSV file {filepath}: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return False
|
||||
|
||||
def merge_csv(
|
||||
self,
|
||||
files: List[str],
|
||||
output_file: str,
|
||||
how: str = 'inner',
|
||||
on: Optional[Union[str, List[str]]] = None,
|
||||
suffixes: Optional[tuple] = None
|
||||
) -> bool:
|
||||
"""Merge multiple CSV files.
|
||||
|
||||
Args:
|
||||
files: List of CSV files to merge
|
||||
output_file: Output file path
|
||||
how: Merge method ('inner', 'outer', 'left', 'right')
|
||||
on: Column(s) to merge on
|
||||
suffixes: Suffixes for overlapping columns
|
||||
|
||||
Returns:
|
||||
bool: Success status
|
||||
"""
|
||||
try:
|
||||
if len(files) < 2:
|
||||
error_msg = "At least two files are required for merging"
|
||||
logging.error(error_msg)
|
||||
return False
|
||||
|
||||
pd = self._get_pandas()
|
||||
if pd is None:
|
||||
return False
|
||||
|
||||
# Read first file
|
||||
result = pd.read_csv(files[0])
|
||||
|
||||
# Merge with remaining files
|
||||
for file in files[1:]:
|
||||
df = pd.read_csv(file)
|
||||
result = pd.merge(
|
||||
result,
|
||||
df,
|
||||
how=how,
|
||||
on=on,
|
||||
suffixes=suffixes or ('_1', '_2')
|
||||
)
|
||||
|
||||
# Write merged result
|
||||
result.to_csv(output_file, index=False)
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
error_msg = f"Error merging CSV files: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return False
|
||||
|
||||
# Create instance for direct function access
|
||||
_csv_tools = CSVTools()
|
||||
read_csv = _csv_tools.read_csv
|
||||
write_csv = _csv_tools.write_csv
|
||||
merge_csv = _csv_tools.merge_csv
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("\n==================================================")
|
||||
print("CSVTools Demonstration")
|
||||
print("==================================================\n")
|
||||
|
||||
# Create a temporary file for testing
|
||||
import tempfile
|
||||
import os
|
||||
|
||||
with tempfile.NamedTemporaryFile(suffix='.csv', delete=False) as temp:
|
||||
temp_file = temp.name
|
||||
|
||||
print("1. Writing CSV File")
|
||||
print("------------------------------")
|
||||
data = [
|
||||
{"name": "Alice", "age": 25, "city": "New York"},
|
||||
{"name": "Bob", "age": 30, "city": "San Francisco"},
|
||||
{"name": "Charlie", "age": 35, "city": "Chicago"}
|
||||
]
|
||||
result = write_csv(temp_file, data)
|
||||
print(f"Data written successfully: {result}")
|
||||
print()
|
||||
|
||||
print("2. Reading CSV File")
|
||||
print("------------------------------")
|
||||
read_data = read_csv(temp_file)
|
||||
print("Contents of CSV file:")
|
||||
for row in read_data:
|
||||
print(row)
|
||||
print()
|
||||
|
||||
print("3. Merging CSV Files")
|
||||
print("------------------------------")
|
||||
# Create a second file for merging
|
||||
with tempfile.NamedTemporaryFile(suffix='.csv', delete=False) as temp2:
|
||||
temp_file2 = temp2.name
|
||||
data2 = [
|
||||
{"name": "Alice", "salary": 75000},
|
||||
{"name": "Bob", "salary": 85000},
|
||||
{"name": "Charlie", "salary": 95000}
|
||||
]
|
||||
write_csv(temp_file2, data2)
|
||||
|
||||
# Merge files
|
||||
with tempfile.NamedTemporaryFile(suffix='.csv', delete=False) as temp3:
|
||||
temp_file3 = temp3.name
|
||||
result = merge_csv(
|
||||
[temp_file, temp_file2],
|
||||
temp_file3,
|
||||
how='inner',
|
||||
on='name'
|
||||
)
|
||||
print(f"Files merged successfully: {result}")
|
||||
if result:
|
||||
merged_data = read_csv(temp_file3)
|
||||
print("\nMerged contents:")
|
||||
for row in merged_data:
|
||||
print(row)
|
||||
print()
|
||||
|
||||
# Clean up temporary files
|
||||
os.unlink(temp_file)
|
||||
os.unlink(temp_file2)
|
||||
os.unlink(temp_file3)
|
||||
|
||||
print("==================================================")
|
||||
print("Demonstration Complete")
|
||||
print("==================================================\n")
|
||||
@@ -0,0 +1,268 @@
|
||||
"""Tools for working with DuckDB databases.
|
||||
|
||||
Usage:
|
||||
from praisonaiagents.tools import duckdb_tools
|
||||
df = duckdb_tools.query("SELECT * FROM my_table")
|
||||
|
||||
or
|
||||
from praisonaiagents.tools import query_db, create_table, load_data
|
||||
df = query_db("SELECT * FROM my_table")
|
||||
"""
|
||||
|
||||
import logging
|
||||
from typing import List, Dict, Any, Optional, Union, TYPE_CHECKING
|
||||
from importlib import util
|
||||
import json
|
||||
|
||||
if TYPE_CHECKING:
|
||||
import duckdb
|
||||
import pandas as pd
|
||||
|
||||
class DuckDBTools:
|
||||
"""Tools for working with DuckDB databases."""
|
||||
|
||||
def __init__(self, database: str = ':memory:'):
|
||||
"""Initialize DuckDBTools.
|
||||
|
||||
Args:
|
||||
database: Path to database file or ':memory:' for in-memory database
|
||||
"""
|
||||
self.database = database
|
||||
self._conn = None
|
||||
|
||||
def _get_duckdb(self) -> Optional['duckdb']:
|
||||
"""Get duckdb module, installing if needed"""
|
||||
if util.find_spec('duckdb') is None:
|
||||
error_msg = "duckdb package is not available. Please install it using: pip install duckdb"
|
||||
logging.error(error_msg)
|
||||
return None
|
||||
import duckdb
|
||||
return duckdb
|
||||
|
||||
def _get_pandas(self) -> Optional['pd']:
|
||||
"""Get pandas module, installing if needed"""
|
||||
if util.find_spec('pandas') is None:
|
||||
error_msg = "pandas package is not available. Please install it using: pip install pandas"
|
||||
logging.error(error_msg)
|
||||
return None
|
||||
import pandas as pd
|
||||
return pd
|
||||
|
||||
def _get_connection(self) -> Optional['duckdb.DuckDBPyConnection']:
|
||||
"""Get or create database connection"""
|
||||
if self._conn is None:
|
||||
duckdb = self._get_duckdb()
|
||||
if duckdb is None:
|
||||
return None
|
||||
try:
|
||||
self._conn = duckdb.connect(self.database)
|
||||
except Exception as e:
|
||||
error_msg = f"Error connecting to database {self.database}: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return None
|
||||
return self._conn
|
||||
|
||||
def execute_query(
|
||||
self,
|
||||
query: str,
|
||||
params: Optional[Union[tuple, dict]] = None,
|
||||
return_df: bool = True
|
||||
) -> Union[List[Dict[str, Any]], Dict[str, str]]:
|
||||
"""Execute a SQL query.
|
||||
|
||||
Args:
|
||||
query: SQL query to execute
|
||||
params: Query parameters
|
||||
return_df: If True, return results as DataFrame records
|
||||
|
||||
Returns:
|
||||
Query results as list of dicts, or error dict
|
||||
"""
|
||||
try:
|
||||
conn = self._get_connection()
|
||||
if conn is None:
|
||||
return {"error": "Could not connect to database"}
|
||||
|
||||
if params:
|
||||
result = conn.execute(query, params)
|
||||
else:
|
||||
result = conn.execute(query)
|
||||
|
||||
if return_df:
|
||||
pd = self._get_pandas()
|
||||
if pd is None:
|
||||
return {"error": "pandas package not available"}
|
||||
df = result.df()
|
||||
return df.to_dict('records')
|
||||
else:
|
||||
return [dict(row) for row in result.fetchall()]
|
||||
|
||||
except Exception as e:
|
||||
error_msg = f"Error executing query: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return {"error": error_msg}
|
||||
|
||||
def load_csv(
|
||||
self,
|
||||
table_name: str,
|
||||
filepath: str,
|
||||
schema: Optional[Dict[str, str]] = None,
|
||||
if_exists: str = 'replace'
|
||||
) -> bool:
|
||||
"""Load a CSV file into a table.
|
||||
|
||||
Args:
|
||||
table_name: Name of table to create
|
||||
filepath: Path to CSV file
|
||||
schema: Optional column definitions
|
||||
if_exists: What to do if table exists ('fail', 'replace', 'append')
|
||||
|
||||
Returns:
|
||||
bool: Success status
|
||||
"""
|
||||
try:
|
||||
conn = self._get_connection()
|
||||
if conn is None:
|
||||
return False
|
||||
|
||||
# Check if table exists
|
||||
exists = conn.execute(f"""
|
||||
SELECT name FROM sqlite_master
|
||||
WHERE type='table' AND name='{table_name}'
|
||||
""").fetchone() is not None
|
||||
|
||||
if exists:
|
||||
if if_exists == 'fail':
|
||||
raise ValueError(f"Table {table_name} already exists")
|
||||
elif if_exists == 'replace':
|
||||
conn.execute(f"DROP TABLE IF EXISTS {table_name}")
|
||||
elif if_exists != 'append':
|
||||
raise ValueError("if_exists must be 'fail', 'replace', or 'append'")
|
||||
|
||||
# Create table if needed
|
||||
if not exists or if_exists == 'replace':
|
||||
if schema:
|
||||
# Create table with schema
|
||||
columns = ', '.join(f"{k} {v}" for k, v in schema.items())
|
||||
conn.execute(f"CREATE TABLE {table_name} ({columns})")
|
||||
else:
|
||||
# Infer schema from CSV
|
||||
conn.execute(f"""
|
||||
CREATE TABLE {table_name} AS
|
||||
SELECT * FROM read_csv_auto('{filepath}')
|
||||
WHERE 1=0
|
||||
""")
|
||||
|
||||
# Load data
|
||||
conn.execute(f"""
|
||||
INSERT INTO {table_name}
|
||||
SELECT * FROM read_csv_auto('{filepath}')
|
||||
""")
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
error_msg = f"Error loading CSV file {filepath}: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return False
|
||||
|
||||
def export_csv(
|
||||
self,
|
||||
query: str,
|
||||
filepath: str,
|
||||
params: Optional[Union[tuple, dict]] = None
|
||||
) -> bool:
|
||||
"""Export query results to CSV.
|
||||
|
||||
Args:
|
||||
query: SQL query to execute
|
||||
filepath: Output file path
|
||||
params: Optional query parameters
|
||||
|
||||
Returns:
|
||||
bool: Success status
|
||||
"""
|
||||
try:
|
||||
# Execute query and get results as DataFrame
|
||||
results = self.execute_query(query, params)
|
||||
if isinstance(results, dict) and 'error' in results:
|
||||
return False
|
||||
|
||||
pd = self._get_pandas()
|
||||
if pd is None:
|
||||
return False
|
||||
|
||||
# Convert to DataFrame and save
|
||||
df = pd.DataFrame(results)
|
||||
df.to_csv(filepath, index=False)
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
error_msg = f"Error exporting to CSV file {filepath}: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return False
|
||||
|
||||
def close(self):
|
||||
"""Close database connection."""
|
||||
if self._conn:
|
||||
self._conn.close()
|
||||
self._conn = None
|
||||
|
||||
# Create instance for direct function access
|
||||
_duckdb_tools = DuckDBTools()
|
||||
execute_query = _duckdb_tools.execute_query
|
||||
load_csv = _duckdb_tools.load_csv
|
||||
export_csv = _duckdb_tools.export_csv
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("\n==================================================")
|
||||
print("DuckDBTools Demonstration")
|
||||
print("==================================================\n")
|
||||
|
||||
# Create a temporary file for testing
|
||||
import tempfile
|
||||
import os
|
||||
|
||||
with tempfile.NamedTemporaryFile(suffix='.csv', delete=False) as temp:
|
||||
temp_file = temp.name
|
||||
|
||||
# Create sample data
|
||||
with open(temp_file, 'w') as f:
|
||||
f.write("name,age,city\n")
|
||||
f.write("Alice,25,New York\n")
|
||||
f.write("Bob,30,San Francisco\n")
|
||||
f.write("Charlie,35,Chicago\n")
|
||||
|
||||
print("1. Loading CSV File")
|
||||
print("------------------------------")
|
||||
result = load_csv('users', temp_file)
|
||||
print(f"CSV loaded successfully: {result}")
|
||||
print()
|
||||
|
||||
print("2. Executing Query")
|
||||
print("------------------------------")
|
||||
query = "SELECT * FROM users WHERE age > 25"
|
||||
results = execute_query(query)
|
||||
print("Query results:")
|
||||
for row in results:
|
||||
print(row)
|
||||
print()
|
||||
|
||||
print("3. Exporting Query Results")
|
||||
print("------------------------------")
|
||||
with tempfile.NamedTemporaryFile(suffix='.csv', delete=False) as temp2:
|
||||
temp_file2 = temp2.name
|
||||
result = export_csv(query, temp_file2)
|
||||
print(f"Results exported successfully: {result}")
|
||||
if result:
|
||||
print("\nExported file contents:")
|
||||
with open(temp_file2) as f:
|
||||
print(f.read())
|
||||
|
||||
# Clean up temporary files
|
||||
os.unlink(temp_file)
|
||||
os.unlink(temp_file2)
|
||||
|
||||
print("==================================================")
|
||||
print("Demonstration Complete")
|
||||
print("==================================================\n")
|
||||
@@ -0,0 +1,52 @@
|
||||
"""DuckDuckGo search functionality.
|
||||
|
||||
Usage:
|
||||
from praisonaiagents.tools import internet_search
|
||||
results = internet_search("AI news")
|
||||
|
||||
or
|
||||
from praisonaiagents.tools import duckduckgo
|
||||
results = duckduckgo("AI news")
|
||||
"""
|
||||
|
||||
from typing import List, Dict
|
||||
import logging
|
||||
from importlib import util
|
||||
import sys
|
||||
|
||||
def internet_search(query: str) -> List[Dict]:
|
||||
"""Perform an internet search using DuckDuckGo."""
|
||||
# Check if duckduckgo_search is installed
|
||||
if util.find_spec("duckduckgo_search") is None:
|
||||
error_msg = "DuckDuckGo search is not available. Please install duckduckgo_search package using: pip install duckduckgo_search"
|
||||
logging.error(error_msg)
|
||||
return [{"error": error_msg}]
|
||||
|
||||
try:
|
||||
# Import only when needed
|
||||
from duckduckgo_search import DDGS
|
||||
results = []
|
||||
ddgs = DDGS()
|
||||
for result in ddgs.text(keywords=query, max_results=5):
|
||||
results.append({
|
||||
"title": result.get("title", ""),
|
||||
"url": result.get("href", ""),
|
||||
"snippet": result.get("body", "")
|
||||
})
|
||||
return results
|
||||
|
||||
except Exception as e:
|
||||
error_msg = f"Error during DuckDuckGo search: {e}"
|
||||
logging.error(error_msg)
|
||||
return [{"error": error_msg}]
|
||||
|
||||
# Make the module callable
|
||||
sys.modules[__name__].__call__ = internet_search
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Example usage
|
||||
results = internet_search("Python programming")
|
||||
for result in results:
|
||||
print(f"\nTitle: {result.get('title')}")
|
||||
print(f"URL: {result.get('url')}")
|
||||
print(f"Snippet: {result.get('snippet')}")
|
||||
@@ -0,0 +1,310 @@
|
||||
"""Tools for working with Excel files.
|
||||
|
||||
Usage:
|
||||
from praisonaiagents.tools import excel_tools
|
||||
df = excel_tools.read_excel("data.xlsx")
|
||||
|
||||
or
|
||||
from praisonaiagents.tools import read_excel, write_excel, merge_excel
|
||||
df = read_excel("data.xlsx")
|
||||
"""
|
||||
|
||||
import logging
|
||||
from typing import List, Dict, Union, Optional, Any, TYPE_CHECKING, Tuple
|
||||
from importlib import util
|
||||
import json
|
||||
from pathlib import Path
|
||||
import tempfile
|
||||
import os
|
||||
|
||||
if TYPE_CHECKING:
|
||||
import pandas as pd
|
||||
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
|
||||
from openpyxl.chart import BarChart, LineChart, PieChart, Reference
|
||||
from openpyxl.chart.label import DataLabelList
|
||||
|
||||
class ExcelTools:
|
||||
"""Tools for working with Excel files."""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize ExcelTools."""
|
||||
pass
|
||||
|
||||
def _get_pandas(self) -> Optional['pd']:
|
||||
"""Get pandas module, installing if needed"""
|
||||
if util.find_spec('pandas') is None:
|
||||
error_msg = "pandas package is not available. Please install it using: pip install pandas"
|
||||
logging.error(error_msg)
|
||||
return None
|
||||
if util.find_spec('openpyxl') is None:
|
||||
error_msg = "openpyxl package is not available. Please install it using: pip install openpyxl"
|
||||
logging.error(error_msg)
|
||||
return None
|
||||
import pandas as pd
|
||||
return pd
|
||||
|
||||
def read_excel(
|
||||
self,
|
||||
filepath: str,
|
||||
sheet_name: Optional[Union[str, int, List[Union[str, int]]]] = 0,
|
||||
header: Optional[int] = 0,
|
||||
usecols: Optional[List[str]] = None,
|
||||
skiprows: Optional[Union[int, List[int]]] = None,
|
||||
na_values: Optional[List[str]] = None,
|
||||
dtype: Optional[Dict[str, str]] = None
|
||||
) -> Union[Dict[str, List[Dict[str, Any]]], List[Dict[str, Any]]]:
|
||||
"""Read an Excel file with advanced options.
|
||||
|
||||
Args:
|
||||
filepath: Path to Excel file
|
||||
sheet_name: Sheet name(s) or index(es)
|
||||
header: Row number(s) to use as column names
|
||||
usecols: Columns to read
|
||||
skiprows: Line numbers to skip
|
||||
na_values: Additional strings to recognize as NA/NaN
|
||||
dtype: Dict of column dtypes
|
||||
|
||||
Returns:
|
||||
Dict of sheet names to data if multiple sheets, else list of row dicts
|
||||
"""
|
||||
try:
|
||||
pd = self._get_pandas()
|
||||
if pd is None:
|
||||
return {"error": "Required packages not available"}
|
||||
|
||||
# Read Excel file
|
||||
df = pd.read_excel(
|
||||
filepath,
|
||||
sheet_name=sheet_name,
|
||||
header=header,
|
||||
usecols=usecols,
|
||||
skiprows=skiprows,
|
||||
na_values=na_values,
|
||||
dtype=dtype,
|
||||
engine='openpyxl'
|
||||
)
|
||||
|
||||
# Convert to dict format
|
||||
if isinstance(df, dict):
|
||||
return {
|
||||
name: df[name].to_dict('records')
|
||||
for name in df.keys()
|
||||
}
|
||||
else:
|
||||
return df.to_dict('records')
|
||||
|
||||
except Exception as e:
|
||||
error_msg = f"Error reading Excel file {filepath}: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return {"error": error_msg}
|
||||
|
||||
def write_excel(
|
||||
self,
|
||||
filepath: str,
|
||||
data: Union[Dict[str, List[Dict[str, Any]]], List[Dict[str, Any]]],
|
||||
sheet_name: Optional[str] = None,
|
||||
index: bool = False,
|
||||
header: bool = True,
|
||||
mode: str = 'w'
|
||||
) -> bool:
|
||||
"""Write data to an Excel file.
|
||||
|
||||
Args:
|
||||
filepath: Path to Excel file
|
||||
data: Data to write (dict of sheet names to data or list of row dicts)
|
||||
sheet_name: Sheet name if data is a list
|
||||
index: Whether to write row indices
|
||||
header: Whether to write column headers
|
||||
mode: Write mode ('w' for write, 'a' for append)
|
||||
|
||||
Returns:
|
||||
bool: Success status
|
||||
"""
|
||||
try:
|
||||
pd = self._get_pandas()
|
||||
if pd is None:
|
||||
return False
|
||||
|
||||
# Convert data to DataFrame(s)
|
||||
if isinstance(data, dict):
|
||||
if mode == 'a' and os.path.exists(filepath):
|
||||
book = pd.ExcelFile(filepath)
|
||||
with pd.ExcelWriter(filepath, engine='openpyxl') as writer:
|
||||
# Copy existing sheets
|
||||
for sheet in book.sheet_names:
|
||||
pd.read_excel(filepath, sheet_name=sheet).to_excel(
|
||||
writer, sheet_name=sheet, index=index, header=header
|
||||
)
|
||||
# Add new sheets
|
||||
for name, sheet_data in data.items():
|
||||
df = pd.DataFrame(sheet_data)
|
||||
df.to_excel(
|
||||
writer, sheet_name=name, index=index, header=header
|
||||
)
|
||||
else:
|
||||
with pd.ExcelWriter(filepath, engine='openpyxl') as writer:
|
||||
for name, sheet_data in data.items():
|
||||
df = pd.DataFrame(sheet_data)
|
||||
df.to_excel(
|
||||
writer, sheet_name=name, index=index, header=header
|
||||
)
|
||||
else:
|
||||
if mode == 'a' and os.path.exists(filepath):
|
||||
book = pd.ExcelFile(filepath)
|
||||
with pd.ExcelWriter(filepath, engine='openpyxl') as writer:
|
||||
# Copy existing sheets
|
||||
for sheet in book.sheet_names:
|
||||
pd.read_excel(filepath, sheet_name=sheet).to_excel(
|
||||
writer, sheet_name=sheet, index=index, header=header
|
||||
)
|
||||
# Add new sheet
|
||||
df = pd.DataFrame(data)
|
||||
df.to_excel(
|
||||
writer,
|
||||
sheet_name=sheet_name or 'Sheet1',
|
||||
index=index,
|
||||
header=header
|
||||
)
|
||||
else:
|
||||
df = pd.DataFrame(data)
|
||||
df.to_excel(
|
||||
filepath,
|
||||
sheet_name=sheet_name or 'Sheet1',
|
||||
index=index,
|
||||
header=header,
|
||||
engine='openpyxl'
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
error_msg = f"Error writing Excel file {filepath}: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return False
|
||||
|
||||
def merge_excel(
|
||||
self,
|
||||
files: List[str],
|
||||
output_file: str,
|
||||
how: str = 'inner',
|
||||
on: Optional[Union[str, List[str]]] = None,
|
||||
suffixes: Optional[Tuple[str, str]] = None
|
||||
) -> bool:
|
||||
"""Merge multiple Excel files.
|
||||
|
||||
Args:
|
||||
files: List of Excel files to merge
|
||||
output_file: Output file path
|
||||
how: Merge method ('inner', 'outer', 'left', 'right')
|
||||
on: Column(s) to merge on
|
||||
suffixes: Suffixes for overlapping columns
|
||||
|
||||
Returns:
|
||||
bool: Success status
|
||||
"""
|
||||
try:
|
||||
if len(files) < 2:
|
||||
error_msg = "At least two files are required for merging"
|
||||
logging.error(error_msg)
|
||||
return False
|
||||
|
||||
# Read first file
|
||||
result = self.read_excel(files[0])
|
||||
|
||||
# Merge with remaining files
|
||||
for file in files[1:]:
|
||||
df = self.read_excel(file)
|
||||
if isinstance(df, dict):
|
||||
df = next(iter(df.values()))
|
||||
|
||||
pd = self._get_pandas()
|
||||
if pd is None:
|
||||
return False
|
||||
|
||||
result = pd.merge(
|
||||
pd.DataFrame(result),
|
||||
pd.DataFrame(df),
|
||||
how=how,
|
||||
on=on,
|
||||
suffixes=suffixes or ('_1', '_2')
|
||||
).to_dict('records')
|
||||
|
||||
# Write merged result
|
||||
return self.write_excel(output_file, result)
|
||||
|
||||
except Exception as e:
|
||||
error_msg = f"Error merging Excel files: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return False
|
||||
|
||||
# Create instance for direct function access
|
||||
_excel_tools = ExcelTools()
|
||||
read_excel = _excel_tools.read_excel
|
||||
write_excel = _excel_tools.write_excel
|
||||
merge_excel = _excel_tools.merge_excel
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("\n==================================================")
|
||||
print("ExcelTools Demonstration")
|
||||
print("==================================================\n")
|
||||
|
||||
# Create a temporary file for testing
|
||||
with tempfile.NamedTemporaryFile(suffix='.xlsx', delete=False) as temp:
|
||||
temp_file = temp.name
|
||||
|
||||
print("1. Writing Excel File")
|
||||
print("------------------------------")
|
||||
data = [
|
||||
{"name": "Alice", "age": 25, "city": "New York"},
|
||||
{"name": "Bob", "age": 30, "city": "San Francisco"},
|
||||
{"name": "Charlie", "age": 35, "city": "Chicago"}
|
||||
]
|
||||
result = write_excel(temp_file, data, "People")
|
||||
print(f"Data written successfully: {result}")
|
||||
print()
|
||||
|
||||
print("2. Reading Excel File")
|
||||
print("------------------------------")
|
||||
read_data = read_excel(temp_file)
|
||||
print("Contents of Excel file:")
|
||||
for row in read_data:
|
||||
print(row)
|
||||
print()
|
||||
|
||||
print("3. Merging Excel Files")
|
||||
print("------------------------------")
|
||||
# Create a second file for merging
|
||||
with tempfile.NamedTemporaryFile(suffix='.xlsx', delete=False) as temp2:
|
||||
temp_file2 = temp2.name
|
||||
data2 = [
|
||||
{"name": "Alice", "salary": 75000},
|
||||
{"name": "Bob", "salary": 85000},
|
||||
{"name": "Charlie", "salary": 95000}
|
||||
]
|
||||
write_excel(temp_file2, data2, "Salaries")
|
||||
|
||||
# Merge files
|
||||
with tempfile.NamedTemporaryFile(suffix='.xlsx', delete=False) as temp3:
|
||||
temp_file3 = temp3.name
|
||||
result = merge_excel(
|
||||
[temp_file, temp_file2],
|
||||
temp_file3,
|
||||
how='inner',
|
||||
on='name'
|
||||
)
|
||||
print(f"Files merged successfully: {result}")
|
||||
if result:
|
||||
merged_data = read_excel(temp_file3)
|
||||
print("\nMerged contents:")
|
||||
for row in merged_data:
|
||||
print(row)
|
||||
print()
|
||||
|
||||
# Clean up temporary files
|
||||
os.unlink(temp_file)
|
||||
os.unlink(temp_file2)
|
||||
os.unlink(temp_file3)
|
||||
|
||||
print("==================================================")
|
||||
print("Demonstration Complete")
|
||||
print("==================================================\n")
|
||||
@@ -0,0 +1,274 @@
|
||||
"""File handling tools for basic file operations.
|
||||
|
||||
Usage:
|
||||
from praisonaiagents.tools import file_tools
|
||||
content = file_tools.read_file("example.txt")
|
||||
file_tools.write_file("output.txt", "Hello World")
|
||||
|
||||
or
|
||||
from praisonaiagents.tools import read_file, write_file, list_files
|
||||
content = read_file("example.txt")
|
||||
"""
|
||||
|
||||
import os
|
||||
import json
|
||||
from typing import List, Dict, Union, Optional
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
import logging
|
||||
|
||||
class FileTools:
|
||||
"""Tools for file operations including read, write, list, and information."""
|
||||
|
||||
@staticmethod
|
||||
def read_file(filepath: str, encoding: str = 'utf-8') -> str:
|
||||
"""
|
||||
Read content from a file.
|
||||
|
||||
Args:
|
||||
filepath: Path to the file
|
||||
encoding: File encoding (default: utf-8)
|
||||
|
||||
Returns:
|
||||
str: Content of the file
|
||||
"""
|
||||
try:
|
||||
with open(filepath, 'r', encoding=encoding) as f:
|
||||
return f.read()
|
||||
except Exception as e:
|
||||
error_msg = f"Error reading file {filepath}: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return error_msg
|
||||
|
||||
@staticmethod
|
||||
def write_file(filepath: str, content: str, encoding: str = 'utf-8') -> bool:
|
||||
"""
|
||||
Write content to a file.
|
||||
|
||||
Args:
|
||||
filepath: Path to the file
|
||||
content: Content to write
|
||||
encoding: File encoding (default: utf-8)
|
||||
|
||||
Returns:
|
||||
bool: True if successful, False otherwise
|
||||
"""
|
||||
try:
|
||||
# Create directory if it doesn't exist
|
||||
os.makedirs(os.path.dirname(filepath), exist_ok=True)
|
||||
with open(filepath, 'w', encoding=encoding) as f:
|
||||
f.write(content)
|
||||
return True
|
||||
except Exception as e:
|
||||
error_msg = f"Error writing to file {filepath}: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def list_files(directory: str, pattern: Optional[str] = None) -> List[Dict[str, Union[str, int]]]:
|
||||
"""
|
||||
List files in a directory with optional pattern matching.
|
||||
|
||||
Args:
|
||||
directory: Directory path
|
||||
pattern: Optional glob pattern (e.g., "*.txt")
|
||||
|
||||
Returns:
|
||||
List[Dict]: List of file information dictionaries
|
||||
"""
|
||||
try:
|
||||
path = Path(directory)
|
||||
if pattern:
|
||||
files = path.glob(pattern)
|
||||
else:
|
||||
files = path.iterdir()
|
||||
|
||||
result = []
|
||||
for file in files:
|
||||
if file.is_file():
|
||||
stat = file.stat()
|
||||
result.append({
|
||||
'name': file.name,
|
||||
'path': str(file),
|
||||
'size': stat.st_size,
|
||||
'modified': stat.st_mtime,
|
||||
'created': stat.st_ctime
|
||||
})
|
||||
return result
|
||||
except Exception as e:
|
||||
error_msg = f"Error listing files in {directory}: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return [{'error': error_msg}]
|
||||
|
||||
@staticmethod
|
||||
def get_file_info(filepath: str) -> Dict[str, Union[str, int]]:
|
||||
"""
|
||||
Get detailed information about a file.
|
||||
|
||||
Args:
|
||||
filepath: Path to the file
|
||||
|
||||
Returns:
|
||||
Dict: File information including size, dates, etc.
|
||||
"""
|
||||
try:
|
||||
path = Path(filepath)
|
||||
if not path.exists():
|
||||
return {'error': f'File not found: {filepath}'}
|
||||
|
||||
stat = path.stat()
|
||||
return {
|
||||
'name': path.name,
|
||||
'path': str(path),
|
||||
'size': stat.st_size,
|
||||
'modified': stat.st_mtime,
|
||||
'created': stat.st_ctime,
|
||||
'is_file': path.is_file(),
|
||||
'is_dir': path.is_dir(),
|
||||
'extension': path.suffix,
|
||||
'parent': str(path.parent)
|
||||
}
|
||||
except Exception as e:
|
||||
error_msg = f"Error getting file info for {filepath}: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return {'error': error_msg}
|
||||
|
||||
@staticmethod
|
||||
def copy_file(src: str, dst: str) -> bool:
|
||||
"""
|
||||
Copy a file from source to destination.
|
||||
|
||||
Args:
|
||||
src: Source file path
|
||||
dst: Destination file path
|
||||
|
||||
Returns:
|
||||
bool: True if successful, False otherwise
|
||||
"""
|
||||
try:
|
||||
# Create destination directory if it doesn't exist
|
||||
os.makedirs(os.path.dirname(dst), exist_ok=True)
|
||||
shutil.copy2(src, dst)
|
||||
return True
|
||||
except Exception as e:
|
||||
error_msg = f"Error copying file from {src} to {dst}: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def move_file(src: str, dst: str) -> bool:
|
||||
"""
|
||||
Move a file from source to destination.
|
||||
|
||||
Args:
|
||||
src: Source file path
|
||||
dst: Destination file path
|
||||
|
||||
Returns:
|
||||
bool: True if successful, False otherwise
|
||||
"""
|
||||
try:
|
||||
# Create destination directory if it doesn't exist
|
||||
os.makedirs(os.path.dirname(dst), exist_ok=True)
|
||||
shutil.move(src, dst)
|
||||
return True
|
||||
except Exception as e:
|
||||
error_msg = f"Error moving file from {src} to {dst}: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def delete_file(filepath: str) -> bool:
|
||||
"""
|
||||
Delete a file.
|
||||
|
||||
Args:
|
||||
filepath: Path to the file
|
||||
|
||||
Returns:
|
||||
bool: True if successful, False otherwise
|
||||
"""
|
||||
try:
|
||||
os.remove(filepath)
|
||||
return True
|
||||
except Exception as e:
|
||||
error_msg = f"Error deleting file {filepath}: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return False
|
||||
|
||||
# Create instance for direct function access
|
||||
_file_tools = FileTools()
|
||||
read_file = _file_tools.read_file
|
||||
write_file = _file_tools.write_file
|
||||
list_files = _file_tools.list_files
|
||||
get_file_info = _file_tools.get_file_info
|
||||
copy_file = _file_tools.copy_file
|
||||
move_file = _file_tools.move_file
|
||||
delete_file = _file_tools.delete_file
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Example usage
|
||||
print("\n==================================================")
|
||||
print("FileTools Demonstration")
|
||||
print("==================================================\n")
|
||||
|
||||
# Create a test directory
|
||||
test_dir = os.path.join(os.getcwd(), "test_files")
|
||||
os.makedirs(test_dir, exist_ok=True)
|
||||
|
||||
# Create test files
|
||||
test_file = os.path.join(test_dir, "test_file.txt")
|
||||
test_content = "Hello, this is a test file!"
|
||||
|
||||
print("1. Writing to file")
|
||||
print("------------------------------")
|
||||
success = write_file(test_file, test_content)
|
||||
print(f"Write successful: {success}\n")
|
||||
|
||||
print("2. Reading from file")
|
||||
print("------------------------------")
|
||||
content = read_file(test_file)
|
||||
print(f"Content: {content}\n")
|
||||
|
||||
print("3. File Information")
|
||||
print("------------------------------")
|
||||
info = get_file_info(test_file)
|
||||
print(json.dumps(info, indent=2))
|
||||
print()
|
||||
|
||||
print("4. Listing Files")
|
||||
print("------------------------------")
|
||||
files = list_files(test_dir, "*.txt")
|
||||
for file in files:
|
||||
print(f"Found: {file['name']} ({file['size']} bytes)")
|
||||
print()
|
||||
|
||||
print("5. Copying File")
|
||||
print("------------------------------")
|
||||
copy_file_path = os.path.join(test_dir, "test_file_copy.txt")
|
||||
copy_success = copy_file(test_file, copy_file_path)
|
||||
print(f"Copy successful: {copy_success}\n")
|
||||
|
||||
print("6. Moving File")
|
||||
print("------------------------------")
|
||||
move_file_path = os.path.join(test_dir, "test_file_moved.txt")
|
||||
move_success = move_file(copy_file_path, move_file_path)
|
||||
print(f"Move successful: {move_success}\n")
|
||||
|
||||
print("7. Deleting Files")
|
||||
print("------------------------------")
|
||||
delete_success = delete_file(test_file)
|
||||
print(f"Delete original successful: {delete_success}")
|
||||
delete_success = delete_file(move_file_path)
|
||||
print(f"Delete moved file successful: {delete_success}\n")
|
||||
|
||||
# Clean up test directory
|
||||
try:
|
||||
shutil.rmtree(test_dir)
|
||||
print("Test directory cleaned up successfully")
|
||||
except Exception as e:
|
||||
print(f"Error cleaning up test directory: {str(e)}")
|
||||
|
||||
print("\n==================================================")
|
||||
print("Demonstration Complete")
|
||||
print("==================================================")
|
||||
@@ -0,0 +1,515 @@
|
||||
"""Tools for working with JSON files.
|
||||
|
||||
Usage:
|
||||
from praisonaiagents.tools import json_tools
|
||||
data = json_tools.read_json("data.json")
|
||||
|
||||
or
|
||||
from praisonaiagents.tools import read_json, write_json, merge_json
|
||||
data = read_json("data.json")
|
||||
"""
|
||||
|
||||
import logging
|
||||
from typing import List, Dict, Union, Optional, Any, Tuple
|
||||
from importlib import util
|
||||
import json
|
||||
from datetime import datetime
|
||||
|
||||
class JSONTools:
|
||||
"""Tools for working with JSON files."""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize JSONTools."""
|
||||
pass
|
||||
|
||||
def read_json(
|
||||
self,
|
||||
filepath: str,
|
||||
encoding: str = 'utf-8',
|
||||
validate_schema: Optional[Dict[str, Any]] = None
|
||||
) -> Dict[str, Any]:
|
||||
"""Read a JSON file with optional schema validation.
|
||||
|
||||
Args:
|
||||
filepath: Path to JSON file
|
||||
encoding: File encoding
|
||||
validate_schema: Optional JSON schema for validation
|
||||
|
||||
Returns:
|
||||
Dict with JSON data
|
||||
"""
|
||||
try:
|
||||
# Read JSON file
|
||||
with open(filepath, 'r', encoding=encoding) as f:
|
||||
data = json.load(f)
|
||||
|
||||
# Validate against schema if provided
|
||||
if validate_schema:
|
||||
if util.find_spec('jsonschema') is None:
|
||||
error_msg = "jsonschema package is not available. Please install it using: pip install jsonschema"
|
||||
logging.error(error_msg)
|
||||
return {"error": error_msg}
|
||||
import jsonschema
|
||||
try:
|
||||
jsonschema.validate(instance=data, schema=validate_schema)
|
||||
except jsonschema.exceptions.ValidationError as e:
|
||||
error_msg = f"JSON validation failed: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return {"error": error_msg}
|
||||
|
||||
return data
|
||||
|
||||
except Exception as e:
|
||||
error_msg = f"Error reading JSON file {filepath}: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return {"error": error_msg}
|
||||
|
||||
def write_json(
|
||||
self,
|
||||
data: Union[Dict[str, Any], List[Any]],
|
||||
filepath: str,
|
||||
encoding: str = 'utf-8',
|
||||
indent: int = 2,
|
||||
sort_keys: bool = False,
|
||||
ensure_ascii: bool = False
|
||||
) -> bool:
|
||||
"""Write data to a JSON file.
|
||||
|
||||
Args:
|
||||
data: Data to write
|
||||
filepath: Output file path
|
||||
encoding: File encoding
|
||||
indent: Number of spaces for indentation
|
||||
sort_keys: Sort dictionary keys
|
||||
ensure_ascii: Escape non-ASCII characters
|
||||
|
||||
Returns:
|
||||
True if successful, False otherwise
|
||||
"""
|
||||
try:
|
||||
with open(filepath, 'w', encoding=encoding) as f:
|
||||
json.dump(
|
||||
data,
|
||||
f,
|
||||
indent=indent,
|
||||
sort_keys=sort_keys,
|
||||
ensure_ascii=ensure_ascii
|
||||
)
|
||||
return True
|
||||
except Exception as e:
|
||||
error_msg = f"Error writing JSON file {filepath}: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return False
|
||||
|
||||
def merge_json(
|
||||
self,
|
||||
files: List[str],
|
||||
output_file: str,
|
||||
merge_arrays: bool = True,
|
||||
overwrite_duplicates: bool = True
|
||||
) -> bool:
|
||||
"""Merge multiple JSON files.
|
||||
|
||||
Args:
|
||||
files: List of JSON files to merge
|
||||
output_file: Output file path
|
||||
merge_arrays: Merge arrays instead of overwriting
|
||||
overwrite_duplicates: Overwrite duplicate keys
|
||||
|
||||
Returns:
|
||||
True if successful, False otherwise
|
||||
"""
|
||||
try:
|
||||
if len(files) < 2:
|
||||
raise ValueError("At least two files are required for merging")
|
||||
|
||||
# Read first file
|
||||
result = self.read_json(files[0])
|
||||
|
||||
# Merge with remaining files
|
||||
for file in files[1:]:
|
||||
data = self.read_json(file)
|
||||
result = self._deep_merge(
|
||||
result,
|
||||
data,
|
||||
merge_arrays=merge_arrays,
|
||||
overwrite_duplicates=overwrite_duplicates
|
||||
)
|
||||
|
||||
# Write merged result
|
||||
return self.write_json(result, output_file)
|
||||
except Exception as e:
|
||||
error_msg = f"Error merging JSON files: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return False
|
||||
|
||||
def _deep_merge(
|
||||
self,
|
||||
dict1: Dict[str, Any],
|
||||
dict2: Dict[str, Any],
|
||||
merge_arrays: bool = True,
|
||||
overwrite_duplicates: bool = True
|
||||
) -> Dict[str, Any]:
|
||||
"""Deep merge two dictionaries.
|
||||
|
||||
Args:
|
||||
dict1: First dictionary
|
||||
dict2: Second dictionary
|
||||
merge_arrays: Merge arrays instead of overwriting
|
||||
overwrite_duplicates: Overwrite duplicate keys
|
||||
|
||||
Returns:
|
||||
Merged dictionary
|
||||
"""
|
||||
result = dict1.copy()
|
||||
|
||||
for key, value in dict2.items():
|
||||
if key in result:
|
||||
if isinstance(result[key], dict) and isinstance(value, dict):
|
||||
result[key] = self._deep_merge(
|
||||
result[key],
|
||||
value,
|
||||
merge_arrays=merge_arrays,
|
||||
overwrite_duplicates=overwrite_duplicates
|
||||
)
|
||||
elif isinstance(result[key], list) and isinstance(value, list):
|
||||
if merge_arrays:
|
||||
result[key].extend(value)
|
||||
elif overwrite_duplicates:
|
||||
result[key] = value
|
||||
elif overwrite_duplicates:
|
||||
result[key] = value
|
||||
else:
|
||||
result[key] = value
|
||||
|
||||
return result
|
||||
|
||||
def validate_json(
|
||||
self,
|
||||
data: Union[Dict[str, Any], str],
|
||||
schema: Dict[str, Any]
|
||||
) -> Tuple[bool, Optional[str]]:
|
||||
"""Validate JSON data against a schema.
|
||||
|
||||
Args:
|
||||
data: JSON data or filepath
|
||||
schema: JSON schema for validation
|
||||
|
||||
Returns:
|
||||
Tuple of (is_valid, error_message)
|
||||
"""
|
||||
try:
|
||||
if util.find_spec('jsonschema') is None:
|
||||
error_msg = "jsonschema package is not available. Please install it using: pip install jsonschema"
|
||||
logging.error(error_msg)
|
||||
return False, error_msg
|
||||
import jsonschema
|
||||
|
||||
# Load data if filepath provided
|
||||
if isinstance(data, str):
|
||||
with open(data, 'r') as f:
|
||||
data = json.load(f)
|
||||
|
||||
jsonschema.validate(instance=data, schema=schema)
|
||||
return True, None
|
||||
|
||||
except jsonschema.exceptions.ValidationError as e:
|
||||
error_msg = f"JSON validation failed: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return False, error_msg
|
||||
|
||||
except Exception as e:
|
||||
error_msg = f"Error validating JSON: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return False, error_msg
|
||||
|
||||
def analyze_json(
|
||||
self,
|
||||
data: Union[Dict[str, Any], str],
|
||||
max_depth: int = 10
|
||||
) -> Dict[str, Any]:
|
||||
"""Analyze JSON data structure.
|
||||
|
||||
Args:
|
||||
data: JSON data or filepath
|
||||
max_depth: Maximum depth to analyze
|
||||
|
||||
Returns:
|
||||
Dict with analysis results
|
||||
"""
|
||||
try:
|
||||
# Load data if filepath provided
|
||||
if isinstance(data, str):
|
||||
data = self.read_json(data)
|
||||
|
||||
def analyze_value(value: Any, depth: int = 0) -> Dict[str, Any]:
|
||||
if depth >= max_depth:
|
||||
return {'type': 'max_depth_reached'}
|
||||
|
||||
result = {'type': type(value).__name__}
|
||||
|
||||
if isinstance(value, dict):
|
||||
result['size'] = len(value)
|
||||
result['keys'] = list(value.keys())
|
||||
if depth < max_depth - 1:
|
||||
result['children'] = {
|
||||
k: analyze_value(v, depth + 1)
|
||||
for k, v in value.items()
|
||||
}
|
||||
|
||||
elif isinstance(value, list):
|
||||
result['length'] = len(value)
|
||||
if value:
|
||||
result['element_types'] = list(set(
|
||||
type(x).__name__ for x in value
|
||||
))
|
||||
if depth < max_depth - 1:
|
||||
result['sample_elements'] = [
|
||||
analyze_value(x, depth + 1)
|
||||
for x in value[:5]
|
||||
]
|
||||
|
||||
elif isinstance(value, (int, float)):
|
||||
result.update({
|
||||
'value': value,
|
||||
'is_integer': isinstance(value, int)
|
||||
})
|
||||
|
||||
elif isinstance(value, str):
|
||||
result.update({
|
||||
'length': len(value),
|
||||
'sample': value[:100] if len(value) > 100 else value
|
||||
})
|
||||
|
||||
return result
|
||||
|
||||
return {
|
||||
'analysis_time': datetime.now().isoformat(),
|
||||
'structure': analyze_value(data)
|
||||
}
|
||||
except Exception as e:
|
||||
error_msg = f"Error analyzing JSON: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return {}
|
||||
|
||||
def transform_json(
|
||||
self,
|
||||
data: Union[Dict[str, Any], str],
|
||||
transformations: List[Dict[str, Any]]
|
||||
) -> Dict[str, Any]:
|
||||
"""Transform JSON data using a list of operations.
|
||||
|
||||
Args:
|
||||
data: JSON data or filepath
|
||||
transformations: List of transformation operations
|
||||
|
||||
Returns:
|
||||
Transformed JSON data
|
||||
"""
|
||||
try:
|
||||
# Load data if filepath provided
|
||||
if isinstance(data, str):
|
||||
data = self.read_json(data)
|
||||
|
||||
result = data.copy()
|
||||
|
||||
for transform in transformations:
|
||||
op = transform.get('operation')
|
||||
path = transform.get('path', '').split('.')
|
||||
value = transform.get('value')
|
||||
|
||||
if op == 'set':
|
||||
self._set_value(result, path, value)
|
||||
elif op == 'delete':
|
||||
self._delete_value(result, path)
|
||||
elif op == 'rename':
|
||||
old_path = path
|
||||
new_path = value.split('.')
|
||||
self._rename_key(result, old_path, new_path)
|
||||
elif op == 'move':
|
||||
old_path = path
|
||||
new_path = value.split('.')
|
||||
self._move_value(result, old_path, new_path)
|
||||
|
||||
return result
|
||||
except Exception as e:
|
||||
error_msg = f"Error transforming JSON: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return data
|
||||
|
||||
def _set_value(self, data: Dict[str, Any], path: List[str], value: Any):
|
||||
"""Set a value at the specified path."""
|
||||
current = data
|
||||
for key in path[:-1]:
|
||||
if key not in current:
|
||||
current[key] = {}
|
||||
current = current[key]
|
||||
current[path[-1]] = value
|
||||
|
||||
def _delete_value(self, data: Dict[str, Any], path: List[str]):
|
||||
"""Delete a value at the specified path."""
|
||||
current = data
|
||||
for key in path[:-1]:
|
||||
if key not in current:
|
||||
return
|
||||
current = current[key]
|
||||
if path[-1] in current:
|
||||
del current[path[-1]]
|
||||
|
||||
def _rename_key(
|
||||
self,
|
||||
data: Dict[str, Any],
|
||||
old_path: List[str],
|
||||
new_path: List[str]
|
||||
):
|
||||
"""Rename a key at the specified path."""
|
||||
value = self._get_value(data, old_path)
|
||||
if value is not None:
|
||||
self._delete_value(data, old_path)
|
||||
self._set_value(data, new_path, value)
|
||||
|
||||
def _move_value(
|
||||
self,
|
||||
data: Dict[str, Any],
|
||||
old_path: List[str],
|
||||
new_path: List[str]
|
||||
):
|
||||
"""Move a value from one path to another."""
|
||||
self._rename_key(data, old_path, new_path)
|
||||
|
||||
def _get_value(
|
||||
self,
|
||||
data: Dict[str, Any],
|
||||
path: List[str]
|
||||
) -> Optional[Any]:
|
||||
"""Get a value at the specified path."""
|
||||
current = data
|
||||
for key in path:
|
||||
if key not in current:
|
||||
return None
|
||||
current = current[key]
|
||||
return current
|
||||
|
||||
# Create instance for direct function access
|
||||
_json_tools = JSONTools()
|
||||
read_json = _json_tools.read_json
|
||||
write_json = _json_tools.write_json
|
||||
merge_json = _json_tools.merge_json
|
||||
validate_json = _json_tools.validate_json
|
||||
analyze_json = _json_tools.analyze_json
|
||||
transform_json = _json_tools.transform_json
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Example usage
|
||||
print("\n==================================================")
|
||||
print("JSONTools Demonstration")
|
||||
print("==================================================\n")
|
||||
|
||||
# Sample data
|
||||
data1 = {
|
||||
'id': 1,
|
||||
'name': 'Alice',
|
||||
'scores': [95, 87, 92],
|
||||
'details': {
|
||||
'age': 25,
|
||||
'city': 'New York'
|
||||
}
|
||||
}
|
||||
|
||||
data2 = {
|
||||
'id': 2,
|
||||
'name': 'Bob',
|
||||
'scores': [88, 90, 85],
|
||||
'details': {
|
||||
'age': 30,
|
||||
'country': 'USA'
|
||||
}
|
||||
}
|
||||
|
||||
# 1. Write JSON files
|
||||
print("1. Writing JSON Files")
|
||||
print("------------------------------")
|
||||
success = write_json(data1, 'test1.json')
|
||||
print(f"First file written: {success}")
|
||||
success = write_json(data2, 'test2.json')
|
||||
print(f"Second file written: {success}")
|
||||
print()
|
||||
|
||||
# 2. Read JSON file
|
||||
print("2. Reading JSON File")
|
||||
print("------------------------------")
|
||||
data = read_json('test1.json')
|
||||
print("Contents of test1.json:")
|
||||
print(json.dumps(data, indent=2))
|
||||
print()
|
||||
|
||||
# 3. Merge JSON files
|
||||
print("3. Merging JSON Files")
|
||||
print("------------------------------")
|
||||
success = merge_json(['test1.json', 'test2.json'], 'merged.json')
|
||||
print(f"Files merged: {success}")
|
||||
if success:
|
||||
print("Merged contents:")
|
||||
print(json.dumps(read_json('merged.json'), indent=2))
|
||||
print()
|
||||
|
||||
# 4. Validate JSON
|
||||
print("4. Validating JSON")
|
||||
print("------------------------------")
|
||||
schema = {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'id': {'type': 'integer'},
|
||||
'name': {'type': 'string'},
|
||||
'scores': {
|
||||
'type': 'array',
|
||||
'items': {'type': 'number'}
|
||||
},
|
||||
'details': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'age': {'type': 'integer'},
|
||||
'city': {'type': 'string'}
|
||||
}
|
||||
}
|
||||
},
|
||||
'required': ['id', 'name']
|
||||
}
|
||||
|
||||
is_valid, error = validate_json(data1, schema)
|
||||
print(f"Validation result: {is_valid}")
|
||||
if error:
|
||||
print(f"Validation error: {error}")
|
||||
print()
|
||||
|
||||
# 5. Analyze JSON
|
||||
print("5. Analyzing JSON")
|
||||
print("------------------------------")
|
||||
analysis = analyze_json(data1)
|
||||
print("Analysis results:")
|
||||
print(json.dumps(analysis, indent=2))
|
||||
print()
|
||||
|
||||
# 6. Transform JSON
|
||||
print("6. Transforming JSON")
|
||||
print("------------------------------")
|
||||
transformations = [
|
||||
{
|
||||
'operation': 'set',
|
||||
'path': 'details.status',
|
||||
'value': 'active'
|
||||
},
|
||||
{
|
||||
'operation': 'rename',
|
||||
'path': 'details.city',
|
||||
'value': 'details.location'
|
||||
}
|
||||
]
|
||||
|
||||
transformed = transform_json(data1, transformations)
|
||||
print("Transformed data:")
|
||||
print(json.dumps(transformed, indent=2))
|
||||
|
||||
print("\n==================================================")
|
||||
print("Demonstration Complete")
|
||||
print("==================================================")
|
||||
@@ -0,0 +1,354 @@
|
||||
"""Newspaper tools for scraping and parsing news articles.
|
||||
|
||||
Usage:
|
||||
from praisonaiagents.tools import newspaper_tools
|
||||
article = newspaper_tools.get_article("https://example.com/article")
|
||||
sources = newspaper_tools.get_news_sources("technology")
|
||||
articles = newspaper_tools.get_articles_from_source("https://techcrunch.com")
|
||||
|
||||
or
|
||||
from praisonaiagents.tools import get_article, get_news_sources
|
||||
article = get_article("https://example.com/article")
|
||||
"""
|
||||
|
||||
import logging
|
||||
from typing import List, Dict, Union, Optional, Any
|
||||
from importlib import util
|
||||
import json
|
||||
from urllib.parse import urlparse
|
||||
|
||||
# Predefined list of popular news sources
|
||||
POPULAR_NEWS_SOURCES = {
|
||||
'technology': [
|
||||
'https://techcrunch.com',
|
||||
'https://www.theverge.com',
|
||||
'https://www.wired.com',
|
||||
'https://www.engadget.com',
|
||||
'https://arstechnica.com'
|
||||
],
|
||||
'business': [
|
||||
'https://www.bloomberg.com',
|
||||
'https://www.reuters.com',
|
||||
'https://www.wsj.com',
|
||||
'https://www.ft.com',
|
||||
'https://www.cnbc.com'
|
||||
],
|
||||
'general': [
|
||||
'https://www.nytimes.com',
|
||||
'https://www.theguardian.com',
|
||||
'https://www.washingtonpost.com',
|
||||
'https://www.bbc.com',
|
||||
'https://www.cnn.com'
|
||||
],
|
||||
'sports': [
|
||||
'https://www.espn.com',
|
||||
'https://sports.yahoo.com',
|
||||
'https://www.cbssports.com',
|
||||
'https://www.skysports.com',
|
||||
'https://www.bleacherreport.com'
|
||||
],
|
||||
'entertainment': [
|
||||
'https://variety.com',
|
||||
'https://www.hollywoodreporter.com',
|
||||
'https://www.ew.com',
|
||||
'https://www.deadline.com',
|
||||
'https://www.imdb.com/news'
|
||||
],
|
||||
'science': [
|
||||
'https://www.scientificamerican.com',
|
||||
'https://www.sciencedaily.com',
|
||||
'https://www.newscientist.com',
|
||||
'https://www.sciencemag.org',
|
||||
'https://www.nature.com/news'
|
||||
]
|
||||
}
|
||||
|
||||
class NewspaperTools:
|
||||
"""Tools for scraping and parsing news articles."""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize NewspaperTools and check for newspaper package."""
|
||||
self._check_newspaper()
|
||||
|
||||
def _check_newspaper(self):
|
||||
"""Check if newspaper package is installed."""
|
||||
if util.find_spec("newspaper") is None:
|
||||
raise ImportError("newspaper3k package is not available. Please install it using: pip install newspaper3k")
|
||||
global newspaper
|
||||
import newspaper
|
||||
|
||||
def get_article(
|
||||
self,
|
||||
url: str,
|
||||
language: str = 'en'
|
||||
) -> Dict[str, Any]:
|
||||
"""
|
||||
Extract and parse a news article from a URL.
|
||||
|
||||
Args:
|
||||
url: URL of the article
|
||||
language: Language code (e.g., 'en' for English)
|
||||
|
||||
Returns:
|
||||
Dict: Article information including title, text, authors, etc.
|
||||
"""
|
||||
try:
|
||||
from newspaper import Article, Config
|
||||
|
||||
# Configure article download
|
||||
config = Config()
|
||||
config.browser_user_agent = 'Mozilla/5.0'
|
||||
config.language = language
|
||||
|
||||
# Download and parse article
|
||||
article = Article(url, config=config)
|
||||
article.download()
|
||||
article.parse()
|
||||
|
||||
# Try to extract additional information
|
||||
try:
|
||||
article.nlp()
|
||||
except Exception as e:
|
||||
logging.warning(f"NLP processing failed: {str(e)}")
|
||||
|
||||
# Build response
|
||||
response = {
|
||||
"url": url,
|
||||
"title": article.title,
|
||||
"text": article.text,
|
||||
"authors": article.authors,
|
||||
"publish_date": article.publish_date.isoformat() if article.publish_date else None,
|
||||
"top_image": article.top_image,
|
||||
"images": list(article.images),
|
||||
"movies": list(article.movies),
|
||||
"source_domain": urlparse(url).netloc,
|
||||
}
|
||||
|
||||
# Add NLP results if available
|
||||
if hasattr(article, 'keywords') and article.keywords:
|
||||
response["keywords"] = article.keywords
|
||||
if hasattr(article, 'summary') and article.summary:
|
||||
response["summary"] = article.summary
|
||||
|
||||
return response
|
||||
except Exception as e:
|
||||
error_msg = f"Error extracting article from {url}: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return {"error": error_msg}
|
||||
|
||||
def get_news_sources(
|
||||
self,
|
||||
category: Optional[str] = None,
|
||||
language: str = 'en',
|
||||
country: Optional[str] = None
|
||||
) -> Union[List[Dict[str, str]], Dict[str, str]]:
|
||||
"""
|
||||
Get a list of news sources, optionally filtered by category.
|
||||
|
||||
Args:
|
||||
category: Category to filter by (e.g., 'technology', 'sports')
|
||||
language: Language code
|
||||
country: Country code
|
||||
|
||||
Returns:
|
||||
List[Dict] or Dict: List of news sources or error dict
|
||||
"""
|
||||
try:
|
||||
sources = []
|
||||
|
||||
# Get sources for the specified category or all categories
|
||||
if category:
|
||||
category = category.lower()
|
||||
if category in POPULAR_NEWS_SOURCES:
|
||||
urls = POPULAR_NEWS_SOURCES[category]
|
||||
else:
|
||||
urls = []
|
||||
for cat_urls in POPULAR_NEWS_SOURCES.values():
|
||||
urls.extend(cat_urls)
|
||||
else:
|
||||
urls = []
|
||||
for cat_urls in POPULAR_NEWS_SOURCES.values():
|
||||
urls.extend(cat_urls)
|
||||
|
||||
# Create source objects
|
||||
for url in urls:
|
||||
domain = urlparse(url).netloc
|
||||
source = {
|
||||
"url": url,
|
||||
"domain": domain,
|
||||
"name": domain.replace("www.", "").split(".")[0].title(),
|
||||
"category": category if category else "general"
|
||||
}
|
||||
sources.append(source)
|
||||
|
||||
return sources
|
||||
except Exception as e:
|
||||
error_msg = f"Error getting news sources: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return {"error": error_msg}
|
||||
|
||||
def get_articles_from_source(
|
||||
self,
|
||||
source_url: str,
|
||||
limit: int = 10,
|
||||
language: str = 'en'
|
||||
) -> Union[List[Dict[str, Any]], Dict[str, str]]:
|
||||
"""
|
||||
Get recent articles from a news source.
|
||||
|
||||
Args:
|
||||
source_url: URL of the news source
|
||||
limit: Maximum number of articles to return
|
||||
language: Language code
|
||||
|
||||
Returns:
|
||||
List[Dict] or Dict: List of articles or error dict
|
||||
"""
|
||||
try:
|
||||
from newspaper import Source, Config
|
||||
|
||||
# Configure source scraping
|
||||
config = Config()
|
||||
config.browser_user_agent = 'Mozilla/5.0'
|
||||
config.language = language
|
||||
config.fetch_images = False # Speed up processing
|
||||
|
||||
# Build news source
|
||||
source = Source(source_url, config=config)
|
||||
source.build()
|
||||
|
||||
# Get articles
|
||||
articles = []
|
||||
for article_url in source.article_urls()[:limit]:
|
||||
try:
|
||||
article = self.get_article(article_url, language)
|
||||
if "error" not in article:
|
||||
articles.append(article)
|
||||
except Exception as e:
|
||||
logging.warning(f"Error processing article {article_url}: {str(e)}")
|
||||
continue
|
||||
|
||||
if len(articles) >= limit:
|
||||
break
|
||||
|
||||
return articles
|
||||
except Exception as e:
|
||||
error_msg = f"Error getting articles from {source_url}: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return {"error": error_msg}
|
||||
|
||||
def get_trending_topics(
|
||||
self,
|
||||
sources: Optional[List[str]] = None,
|
||||
limit: int = 10,
|
||||
language: str = 'en'
|
||||
) -> Union[List[str], Dict[str, str]]:
|
||||
"""
|
||||
Get trending topics across news sources.
|
||||
|
||||
Args:
|
||||
sources: List of source URLs to analyze
|
||||
limit: Maximum number of trending topics to return
|
||||
language: Language code
|
||||
|
||||
Returns:
|
||||
List[str] or Dict: List of trending topics or error dict
|
||||
"""
|
||||
try:
|
||||
from collections import Counter
|
||||
|
||||
# Use default sources if none provided
|
||||
if not sources:
|
||||
sources_data = self.get_news_sources(language=language)
|
||||
if isinstance(sources_data, dict) and "error" in sources_data:
|
||||
return sources_data
|
||||
sources = [s["url"] for s in sources_data[:5]] # Use top 5 sources
|
||||
|
||||
# Collect keywords from articles
|
||||
all_keywords = []
|
||||
for source_url in sources:
|
||||
try:
|
||||
articles = self.get_articles_from_source(source_url, limit=5, language=language)
|
||||
if isinstance(articles, list):
|
||||
for article in articles:
|
||||
if "keywords" in article:
|
||||
all_keywords.extend(article["keywords"])
|
||||
except Exception as e:
|
||||
logging.warning(f"Error processing source {source_url}: {str(e)}")
|
||||
continue
|
||||
|
||||
# Get most common keywords
|
||||
trending = Counter(all_keywords).most_common(limit)
|
||||
return [topic for topic, count in trending]
|
||||
except Exception as e:
|
||||
error_msg = f"Error getting trending topics: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return {"error": error_msg}
|
||||
|
||||
# Create instance for direct function access
|
||||
_newspaper_tools = NewspaperTools()
|
||||
get_article = _newspaper_tools.get_article
|
||||
get_news_sources = _newspaper_tools.get_news_sources
|
||||
get_articles_from_source = _newspaper_tools.get_articles_from_source
|
||||
get_trending_topics = _newspaper_tools.get_trending_topics
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Example usage
|
||||
print("\n==================================================")
|
||||
print("NewspaperTools Demonstration")
|
||||
print("==================================================\n")
|
||||
|
||||
# 1. Get news sources
|
||||
print("1. Getting News Sources")
|
||||
print("------------------------------")
|
||||
tech_sources = get_news_sources("technology")
|
||||
print("Technology news sources:")
|
||||
if isinstance(tech_sources, list):
|
||||
print(json.dumps(tech_sources[:3], indent=2)) # Show first 3 sources
|
||||
else:
|
||||
print(tech_sources) # Show error
|
||||
print()
|
||||
|
||||
if isinstance(tech_sources, list) and tech_sources:
|
||||
source_url = tech_sources[0]["url"]
|
||||
|
||||
# 2. Get articles from a source
|
||||
print("2. Getting Articles from Source")
|
||||
print("------------------------------")
|
||||
articles = get_articles_from_source(source_url, limit=2)
|
||||
print(f"Articles from {source_url}:")
|
||||
if isinstance(articles, list):
|
||||
for article in articles:
|
||||
print(f"- {article['title']}")
|
||||
if "summary" in article:
|
||||
print(f" Summary: {article['summary'][:200]}...")
|
||||
else:
|
||||
print(articles) # Show error
|
||||
print()
|
||||
|
||||
# 3. Get a single article
|
||||
print("3. Getting Single Article")
|
||||
print("------------------------------")
|
||||
if isinstance(articles, list) and articles:
|
||||
article_url = articles[0]["url"]
|
||||
article = get_article(article_url)
|
||||
if "error" not in article:
|
||||
print(f"Article: {article['title']}")
|
||||
if "summary" in article:
|
||||
print(f"Summary: {article['summary'][:200]}...")
|
||||
print(f"Authors: {', '.join(article['authors'])}")
|
||||
print(f"Date: {article['publish_date']}")
|
||||
else:
|
||||
print(article) # Show error
|
||||
print()
|
||||
|
||||
# 4. Get trending topics
|
||||
print("4. Getting Trending Topics")
|
||||
print("------------------------------")
|
||||
topics = get_trending_topics([source_url], limit=5)
|
||||
print("Trending topics:")
|
||||
print(json.dumps(topics, indent=2))
|
||||
|
||||
print("\n==================================================")
|
||||
print("Demonstration Complete")
|
||||
print("==================================================")
|
||||
@@ -0,0 +1,326 @@
|
||||
"""Pandas tools for data manipulation and analysis.
|
||||
|
||||
Usage:
|
||||
from praisonaiagents.tools import pandas_tools
|
||||
df = pandas_tools.read_csv("data.csv")
|
||||
df = pandas_tools.filter_data(df, "column > 5")
|
||||
summary = pandas_tools.get_summary(df)
|
||||
|
||||
or
|
||||
from praisonaiagents.tools import read_csv, filter_data, get_summary
|
||||
df = read_csv("data.csv")
|
||||
"""
|
||||
|
||||
import logging
|
||||
from typing import List, Dict, Union, Optional, Any
|
||||
from importlib import util
|
||||
import json
|
||||
import os
|
||||
|
||||
# Import pandas for type hints, but don't use it until we check it's installed
|
||||
if util.find_spec("pandas") is not None:
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
else:
|
||||
# Create a placeholder for type hints
|
||||
class pd:
|
||||
DataFrame = None
|
||||
|
||||
def _convert_to_serializable(obj: Any) -> Any:
|
||||
"""Convert numpy/pandas types to JSON serializable Python types."""
|
||||
if isinstance(obj, (np.integer, np.floating)):
|
||||
return obj.item()
|
||||
elif isinstance(obj, np.ndarray):
|
||||
return obj.tolist()
|
||||
elif isinstance(obj, pd.Series):
|
||||
return obj.to_list()
|
||||
elif isinstance(obj, pd.DataFrame):
|
||||
return obj.to_dict(orient='records')
|
||||
return obj
|
||||
|
||||
class PandasTools:
|
||||
"""Tools for data manipulation and analysis using pandas."""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize PandasTools and check for pandas installation."""
|
||||
self._check_pandas()
|
||||
|
||||
def _check_pandas(self):
|
||||
"""Check if pandas is installed."""
|
||||
if util.find_spec("pandas") is None:
|
||||
raise ImportError("pandas is not available. Please install it using: pip install pandas")
|
||||
global pd, np
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
|
||||
def read_csv(self, filepath: str, **kwargs) -> Union[pd.DataFrame, Dict[str, str]]:
|
||||
"""
|
||||
Read a CSV file into a pandas DataFrame.
|
||||
|
||||
Args:
|
||||
filepath: Path to the CSV file
|
||||
**kwargs: Additional arguments to pass to pd.read_csv()
|
||||
|
||||
Returns:
|
||||
pd.DataFrame or Dict: DataFrame if successful, error dict if failed
|
||||
"""
|
||||
try:
|
||||
return pd.read_csv(filepath, **kwargs)
|
||||
except Exception as e:
|
||||
error_msg = f"Error reading CSV file {filepath}: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return {"error": error_msg}
|
||||
|
||||
def read_excel(self, filepath: str, **kwargs) -> Union[pd.DataFrame, Dict[str, str]]:
|
||||
"""
|
||||
Read an Excel file into a pandas DataFrame.
|
||||
|
||||
Args:
|
||||
filepath: Path to the Excel file
|
||||
**kwargs: Additional arguments to pass to pd.read_excel()
|
||||
|
||||
Returns:
|
||||
pd.DataFrame or Dict: DataFrame if successful, error dict if failed
|
||||
"""
|
||||
try:
|
||||
return pd.read_excel(filepath, **kwargs)
|
||||
except Exception as e:
|
||||
error_msg = f"Error reading Excel file {filepath}: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return {"error": error_msg}
|
||||
|
||||
def write_csv(self, df: pd.DataFrame, filepath: str, **kwargs) -> bool:
|
||||
"""
|
||||
Write DataFrame to a CSV file.
|
||||
|
||||
Args:
|
||||
df: DataFrame to write
|
||||
filepath: Output file path
|
||||
**kwargs: Additional arguments to pass to df.to_csv()
|
||||
|
||||
Returns:
|
||||
bool: True if successful, False otherwise
|
||||
"""
|
||||
try:
|
||||
os.makedirs(os.path.dirname(filepath), exist_ok=True)
|
||||
df.to_csv(filepath, **kwargs)
|
||||
return True
|
||||
except Exception as e:
|
||||
error_msg = f"Error writing CSV file {filepath}: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return False
|
||||
|
||||
def write_excel(self, df: pd.DataFrame, filepath: str, **kwargs) -> bool:
|
||||
"""
|
||||
Write DataFrame to an Excel file.
|
||||
|
||||
Args:
|
||||
df: DataFrame to write
|
||||
filepath: Output file path
|
||||
**kwargs: Additional arguments to pass to df.to_excel()
|
||||
|
||||
Returns:
|
||||
bool: True if successful, False otherwise
|
||||
"""
|
||||
try:
|
||||
os.makedirs(os.path.dirname(filepath), exist_ok=True)
|
||||
df.to_excel(filepath, **kwargs)
|
||||
return True
|
||||
except Exception as e:
|
||||
error_msg = f"Error writing Excel file {filepath}: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return False
|
||||
|
||||
def filter_data(self, df: pd.DataFrame, query: str) -> Union[pd.DataFrame, Dict[str, str]]:
|
||||
"""
|
||||
Filter DataFrame using a query string.
|
||||
|
||||
Args:
|
||||
df: Input DataFrame
|
||||
query: Query string (e.g., "column > 5 and other_column == 'value'")
|
||||
|
||||
Returns:
|
||||
pd.DataFrame or Dict: Filtered DataFrame if successful, error dict if failed
|
||||
"""
|
||||
try:
|
||||
return df.query(query)
|
||||
except Exception as e:
|
||||
error_msg = f"Error filtering data with query '{query}': {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return {"error": error_msg}
|
||||
|
||||
def get_summary(self, df: pd.DataFrame) -> Dict[str, Any]:
|
||||
"""
|
||||
Get a summary of the DataFrame including basic statistics and info.
|
||||
|
||||
Args:
|
||||
df: Input DataFrame
|
||||
|
||||
Returns:
|
||||
Dict: Summary statistics and information
|
||||
"""
|
||||
try:
|
||||
numeric_summary = df.describe().to_dict()
|
||||
# Convert numpy types to native Python types
|
||||
for col in numeric_summary:
|
||||
numeric_summary[col] = {k: _convert_to_serializable(v)
|
||||
for k, v in numeric_summary[col].items()}
|
||||
|
||||
summary = {
|
||||
"shape": list(df.shape),
|
||||
"columns": list(df.columns),
|
||||
"dtypes": df.dtypes.astype(str).to_dict(),
|
||||
"null_counts": df.isnull().sum().to_dict(),
|
||||
"numeric_summary": numeric_summary,
|
||||
"memory_usage": int(df.memory_usage(deep=True).sum()),
|
||||
}
|
||||
return summary
|
||||
except Exception as e:
|
||||
error_msg = f"Error getting data summary: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return {"error": error_msg}
|
||||
|
||||
def group_by(
|
||||
self,
|
||||
df: pd.DataFrame,
|
||||
columns: Union[str, List[str]],
|
||||
agg_dict: Dict[str, Union[str, List[str]]]
|
||||
) -> Union[pd.DataFrame, Dict[str, str]]:
|
||||
"""
|
||||
Group DataFrame by columns and apply aggregation functions.
|
||||
|
||||
Args:
|
||||
df: Input DataFrame
|
||||
columns: Column(s) to group by
|
||||
agg_dict: Dictionary of column:function pairs for aggregation
|
||||
|
||||
Returns:
|
||||
pd.DataFrame or Dict: Grouped DataFrame if successful, error dict if failed
|
||||
"""
|
||||
try:
|
||||
return df.groupby(columns).agg(agg_dict).reset_index()
|
||||
except Exception as e:
|
||||
error_msg = f"Error grouping data: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return {"error": error_msg}
|
||||
|
||||
def pivot_table(
|
||||
self,
|
||||
df: pd.DataFrame,
|
||||
index: Union[str, List[str]],
|
||||
columns: Optional[Union[str, List[str]]] = None,
|
||||
values: Optional[Union[str, List[str]]] = None,
|
||||
aggfunc: str = "mean"
|
||||
) -> Union[pd.DataFrame, Dict[str, str]]:
|
||||
"""
|
||||
Create a pivot table from DataFrame.
|
||||
|
||||
Args:
|
||||
df: Input DataFrame
|
||||
index: Column(s) to use as index
|
||||
columns: Column(s) to use as columns
|
||||
values: Column(s) to aggregate
|
||||
aggfunc: Aggregation function to use
|
||||
|
||||
Returns:
|
||||
pd.DataFrame or Dict: Pivot table if successful, error dict if failed
|
||||
"""
|
||||
try:
|
||||
return pd.pivot_table(
|
||||
df,
|
||||
index=index,
|
||||
columns=columns,
|
||||
values=values,
|
||||
aggfunc=aggfunc
|
||||
).reset_index()
|
||||
except Exception as e:
|
||||
error_msg = f"Error creating pivot table: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return {"error": error_msg}
|
||||
|
||||
# Create instance for direct function access
|
||||
_pandas_tools = PandasTools()
|
||||
read_csv = _pandas_tools.read_csv
|
||||
read_excel = _pandas_tools.read_excel
|
||||
write_csv = _pandas_tools.write_csv
|
||||
write_excel = _pandas_tools.write_excel
|
||||
filter_data = _pandas_tools.filter_data
|
||||
get_summary = _pandas_tools.get_summary
|
||||
group_by = _pandas_tools.group_by
|
||||
pivot_table = _pandas_tools.pivot_table
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Example usage
|
||||
print("\n==================================================")
|
||||
print("PandasTools Demonstration")
|
||||
print("==================================================\n")
|
||||
|
||||
# Create a test directory
|
||||
test_dir = os.path.join(os.getcwd(), "test_files")
|
||||
os.makedirs(test_dir, exist_ok=True)
|
||||
|
||||
# Create a sample DataFrame
|
||||
df = pd.DataFrame({
|
||||
'name': ['John', 'Jane', 'Bob', 'Alice', 'Charlie'],
|
||||
'age': [25, 30, 35, 28, 32],
|
||||
'city': ['New York', 'London', 'Paris', 'Tokyo', 'London'],
|
||||
'salary': [50000, 60000, 75000, 65000, 55000]
|
||||
})
|
||||
|
||||
# 1. Write to CSV
|
||||
print("1. Writing to CSV")
|
||||
print("------------------------------")
|
||||
csv_file = os.path.join(test_dir, "sample.csv")
|
||||
success = write_csv(df, csv_file, index=False)
|
||||
print(f"Write successful: {success}\n")
|
||||
|
||||
# 2. Read from CSV
|
||||
print("2. Reading from CSV")
|
||||
print("------------------------------")
|
||||
df_read = read_csv(csv_file)
|
||||
print("First few rows:")
|
||||
print(df_read.head())
|
||||
print()
|
||||
|
||||
# 3. Filter Data
|
||||
print("3. Filtering Data")
|
||||
print("------------------------------")
|
||||
filtered_df = filter_data(df, "age > 30 and salary > 60000")
|
||||
print("People over 30 with salary > 60000:")
|
||||
print(filtered_df)
|
||||
print()
|
||||
|
||||
# 4. Get Summary
|
||||
print("4. Data Summary")
|
||||
print("------------------------------")
|
||||
summary = get_summary(df)
|
||||
print(json.dumps(summary, indent=2))
|
||||
print()
|
||||
|
||||
# 5. Group By
|
||||
print("5. Group By")
|
||||
print("------------------------------")
|
||||
grouped = group_by(df, "city", {"salary": ["mean", "count"], "age": "mean"})
|
||||
print("Statistics by city:")
|
||||
print(grouped)
|
||||
print()
|
||||
|
||||
# 6. Pivot Table
|
||||
print("6. Pivot Table")
|
||||
print("------------------------------")
|
||||
pivoted = pivot_table(df, index="city", values=["salary", "age"])
|
||||
print("Pivot table by city:")
|
||||
print(pivoted)
|
||||
print()
|
||||
|
||||
# Clean up test directory
|
||||
try:
|
||||
import shutil
|
||||
shutil.rmtree(test_dir)
|
||||
print("Test directory cleaned up successfully")
|
||||
except Exception as e:
|
||||
print(f"Error cleaning up test directory: {str(e)}")
|
||||
|
||||
print("\n==================================================")
|
||||
print("Demonstration Complete")
|
||||
print("==================================================")
|
||||
@@ -0,0 +1,423 @@
|
||||
"""Tools for Python code execution and analysis.
|
||||
|
||||
Usage:
|
||||
from praisonaiagents.tools import python_tools
|
||||
result = python_tools.execute_code("print('Hello, World!')")
|
||||
|
||||
or
|
||||
from praisonaiagents.tools import execute_code, analyze_code, format_code
|
||||
result = execute_code("print('Hello, World!')")
|
||||
"""
|
||||
|
||||
import logging
|
||||
from typing import Dict, List, Optional, Any
|
||||
from importlib import util
|
||||
import io
|
||||
from contextlib import redirect_stdout, redirect_stderr
|
||||
import traceback
|
||||
|
||||
class PythonTools:
|
||||
"""Tools for Python code execution and analysis."""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize PythonTools."""
|
||||
self._check_dependencies()
|
||||
|
||||
def _check_dependencies(self):
|
||||
"""Check if required packages are installed."""
|
||||
missing = []
|
||||
for package in ['black', 'pylint', 'autopep8']:
|
||||
if util.find_spec(package) is None:
|
||||
missing.append(package)
|
||||
|
||||
if missing:
|
||||
raise ImportError(
|
||||
f"Required packages not available. Please install: {', '.join(missing)}\n"
|
||||
f"Run: pip install {' '.join(missing)}"
|
||||
)
|
||||
|
||||
def execute_code(
|
||||
self,
|
||||
code: str,
|
||||
globals_dict: Optional[Dict[str, Any]] = None,
|
||||
locals_dict: Optional[Dict[str, Any]] = None,
|
||||
timeout: int = 30,
|
||||
max_output_size: int = 10000
|
||||
) -> Dict[str, Any]:
|
||||
"""Execute Python code safely."""
|
||||
try:
|
||||
# Set up execution environment
|
||||
if globals_dict is None:
|
||||
globals_dict = {'__builtins__': __builtins__}
|
||||
if locals_dict is None:
|
||||
locals_dict = {}
|
||||
|
||||
# Capture output
|
||||
stdout_buffer = io.StringIO()
|
||||
stderr_buffer = io.StringIO()
|
||||
|
||||
try:
|
||||
# Compile code
|
||||
compiled_code = compile(code, '<string>', 'exec')
|
||||
|
||||
# Execute with output capture
|
||||
with redirect_stdout(stdout_buffer), redirect_stderr(stderr_buffer):
|
||||
exec(compiled_code, globals_dict, locals_dict)
|
||||
|
||||
# Get last expression value if any
|
||||
import ast
|
||||
tree = ast.parse(code)
|
||||
if tree.body and isinstance(tree.body[-1], ast.Expr):
|
||||
result = eval(
|
||||
compile(ast.Expression(tree.body[-1].value), '<string>', 'eval'),
|
||||
globals_dict,
|
||||
locals_dict
|
||||
)
|
||||
else:
|
||||
result = None
|
||||
|
||||
# Get output
|
||||
stdout = stdout_buffer.getvalue()
|
||||
stderr = stderr_buffer.getvalue()
|
||||
|
||||
# Truncate output if too large
|
||||
if len(stdout) > max_output_size:
|
||||
stdout = stdout[:max_output_size] + "...[truncated]"
|
||||
if len(stderr) > max_output_size:
|
||||
stderr = stderr[:max_output_size] + "...[truncated]"
|
||||
|
||||
return {
|
||||
'result': result,
|
||||
'stdout': stdout,
|
||||
'stderr': stderr,
|
||||
'success': True
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
error_msg = f"Error executing code: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return {
|
||||
'result': None,
|
||||
'stdout': stdout_buffer.getvalue(),
|
||||
'stderr': error_msg,
|
||||
'success': False
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
error_msg = f"Error executing code: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return {
|
||||
'result': None,
|
||||
'stdout': '',
|
||||
'stderr': error_msg,
|
||||
'success': False
|
||||
}
|
||||
|
||||
def analyze_code(
|
||||
self,
|
||||
code: str
|
||||
) -> Optional[Dict[str, Any]]:
|
||||
"""Analyze Python code structure and quality.
|
||||
|
||||
Args:
|
||||
code: Python code to analyze
|
||||
|
||||
Returns:
|
||||
Dictionary with analysis results
|
||||
"""
|
||||
try:
|
||||
# Import ast only when needed
|
||||
import ast
|
||||
|
||||
# Parse code
|
||||
tree = ast.parse(code)
|
||||
|
||||
# Analyze structure
|
||||
analysis = {
|
||||
'imports': [],
|
||||
'functions': [],
|
||||
'classes': [],
|
||||
'variables': [],
|
||||
'complexity': {
|
||||
'lines': len(code.splitlines()),
|
||||
'functions': 0,
|
||||
'classes': 0,
|
||||
'branches': 0
|
||||
}
|
||||
}
|
||||
|
||||
# Analyze nodes
|
||||
for node in ast.walk(tree):
|
||||
if isinstance(node, ast.Import):
|
||||
for name in node.names:
|
||||
analysis['imports'].append(name.name)
|
||||
elif isinstance(node, ast.ImportFrom):
|
||||
module = node.module or ''
|
||||
for name in node.names:
|
||||
analysis['imports'].append(f"{module}.{name.name}")
|
||||
elif isinstance(node, ast.FunctionDef):
|
||||
analysis['functions'].append({
|
||||
'name': node.name,
|
||||
'args': [
|
||||
arg.arg for arg in node.args.args
|
||||
],
|
||||
'decorators': [
|
||||
ast.unparse(d) for d in node.decorator_list
|
||||
]
|
||||
})
|
||||
analysis['complexity']['functions'] += 1
|
||||
elif isinstance(node, ast.ClassDef):
|
||||
analysis['classes'].append({
|
||||
'name': node.name,
|
||||
'bases': [
|
||||
ast.unparse(base) for base in node.bases
|
||||
],
|
||||
'decorators': [
|
||||
ast.unparse(d) for d in node.decorator_list
|
||||
]
|
||||
})
|
||||
analysis['complexity']['classes'] += 1
|
||||
elif isinstance(node, ast.Assign):
|
||||
for target in node.targets:
|
||||
if isinstance(target, ast.Name):
|
||||
analysis['variables'].append(target.id)
|
||||
elif isinstance(node, (ast.If, ast.While, ast.For)):
|
||||
analysis['complexity']['branches'] += 1
|
||||
|
||||
return analysis
|
||||
except Exception as e:
|
||||
error_msg = f"Error analyzing code: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return None
|
||||
|
||||
def format_code(
|
||||
self,
|
||||
code: str,
|
||||
style: str = 'black',
|
||||
line_length: int = 88
|
||||
) -> Optional[str]:
|
||||
"""Format Python code according to style guide.
|
||||
|
||||
Args:
|
||||
code: Python code to format
|
||||
style: Formatting style ('black' or 'pep8')
|
||||
line_length: Maximum line length
|
||||
|
||||
Returns:
|
||||
Formatted code
|
||||
"""
|
||||
try:
|
||||
if util.find_spec(style) is None:
|
||||
error_msg = f"{style} package is not available. Please install it using: pip install {style}"
|
||||
logging.error(error_msg)
|
||||
return None
|
||||
|
||||
if style == 'black':
|
||||
import black
|
||||
return black.format_str(
|
||||
code,
|
||||
mode=black.FileMode(
|
||||
line_length=line_length
|
||||
)
|
||||
)
|
||||
else: # pep8
|
||||
import autopep8
|
||||
return autopep8.fix_code(
|
||||
code,
|
||||
options={
|
||||
'max_line_length': line_length
|
||||
}
|
||||
)
|
||||
except Exception as e:
|
||||
error_msg = f"Error formatting code: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return None
|
||||
|
||||
def lint_code(
|
||||
self,
|
||||
code: str
|
||||
) -> Optional[Dict[str, List[Dict[str, Any]]]]:
|
||||
"""Lint Python code for potential issues.
|
||||
|
||||
Args:
|
||||
code: Python code to lint
|
||||
|
||||
Returns:
|
||||
Dictionary with linting results
|
||||
"""
|
||||
try:
|
||||
if util.find_spec('pylint') is None:
|
||||
error_msg = "pylint package is not available. Please install it using: pip install pylint"
|
||||
logging.error(error_msg)
|
||||
return None
|
||||
|
||||
# Import pylint only when needed
|
||||
from pylint.reporters import JSONReporter
|
||||
from pylint.lint.run import Run
|
||||
|
||||
# Create temporary file for pylint
|
||||
import tempfile
|
||||
with tempfile.NamedTemporaryFile(
|
||||
mode='w',
|
||||
suffix='.py',
|
||||
delete=False
|
||||
) as f:
|
||||
f.write(code)
|
||||
temp_path = f.name
|
||||
|
||||
# Run pylint
|
||||
reporter = JSONReporter()
|
||||
Run(
|
||||
[temp_path],
|
||||
reporter=reporter,
|
||||
exit=False
|
||||
)
|
||||
|
||||
# Process results
|
||||
results = {
|
||||
'errors': [],
|
||||
'warnings': [],
|
||||
'conventions': []
|
||||
}
|
||||
|
||||
for msg in reporter.messages:
|
||||
item = {
|
||||
'type': msg.category,
|
||||
'module': msg.module,
|
||||
'obj': msg.obj,
|
||||
'line': msg.line,
|
||||
'column': msg.column,
|
||||
'path': msg.path,
|
||||
'symbol': msg.symbol,
|
||||
'message': msg.msg,
|
||||
'message-id': msg.msg_id
|
||||
}
|
||||
|
||||
if msg.category in ['error', 'fatal']:
|
||||
results['errors'].append(item)
|
||||
elif msg.category == 'warning':
|
||||
results['warnings'].append(item)
|
||||
else:
|
||||
results['conventions'].append(item)
|
||||
|
||||
# Clean up
|
||||
import os
|
||||
os.unlink(temp_path)
|
||||
|
||||
return results
|
||||
except Exception as e:
|
||||
error_msg = f"Error linting code: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return {
|
||||
'errors': [],
|
||||
'warnings': [],
|
||||
'conventions': []
|
||||
}
|
||||
|
||||
def disassemble_code(
|
||||
self,
|
||||
code: str
|
||||
) -> Optional[str]:
|
||||
"""Disassemble Python code to bytecode.
|
||||
|
||||
Args:
|
||||
code: Python code to disassemble
|
||||
|
||||
Returns:
|
||||
Disassembled bytecode as string
|
||||
"""
|
||||
try:
|
||||
# Import dis only when needed
|
||||
import dis
|
||||
|
||||
# Compile code
|
||||
compiled_code = compile(code, '<string>', 'exec')
|
||||
|
||||
# Capture disassembly
|
||||
output = io.StringIO()
|
||||
with redirect_stdout(output):
|
||||
dis.dis(compiled_code)
|
||||
|
||||
return output.getvalue()
|
||||
except Exception as e:
|
||||
error_msg = f"Error disassembling code: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return None
|
||||
|
||||
# Create instance for direct function access
|
||||
_python_tools = PythonTools()
|
||||
execute_code = _python_tools.execute_code
|
||||
analyze_code = _python_tools.analyze_code
|
||||
format_code = _python_tools.format_code
|
||||
lint_code = _python_tools.lint_code
|
||||
disassemble_code = _python_tools.disassemble_code
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("\n==================================================")
|
||||
print("PythonTools Demonstration")
|
||||
print("==================================================\n")
|
||||
|
||||
print("1. Execute Python Code")
|
||||
print("------------------------------")
|
||||
code = """
|
||||
def greet(name):
|
||||
return f"Hello, {name}!"
|
||||
|
||||
result = greet("World")
|
||||
print(result)
|
||||
"""
|
||||
print("Code to execute:")
|
||||
print(code)
|
||||
print("\nOutput:")
|
||||
result = execute_code(code)
|
||||
print(result["stdout"])
|
||||
print()
|
||||
|
||||
print("2. Format Python Code")
|
||||
print("------------------------------")
|
||||
code = """
|
||||
def messy_function(x,y, z):
|
||||
if x>0:
|
||||
return y+z
|
||||
else:
|
||||
return y-z
|
||||
"""
|
||||
print("Before formatting:")
|
||||
print(code)
|
||||
print("\nAfter formatting:")
|
||||
result = format_code(code)
|
||||
print(result)
|
||||
print()
|
||||
|
||||
print("3. Lint Python Code")
|
||||
print("------------------------------")
|
||||
code = """
|
||||
def bad_function():
|
||||
unused_var = 42
|
||||
return 'result'
|
||||
"""
|
||||
print("Code to lint:")
|
||||
print(code)
|
||||
print("\nLinting results:")
|
||||
result = lint_code(code)
|
||||
print(result)
|
||||
print()
|
||||
|
||||
print("4. Execute Code with Variables")
|
||||
print("------------------------------")
|
||||
code = """
|
||||
x = 10
|
||||
y = 20
|
||||
result = x + y
|
||||
print(f"The sum of {x} and {y} is {result}")
|
||||
"""
|
||||
print("Code to execute:")
|
||||
print(code)
|
||||
print("\nOutput:")
|
||||
result = execute_code(code)
|
||||
print(result["stdout"])
|
||||
print()
|
||||
|
||||
print("==================================================")
|
||||
print("Demonstration Complete")
|
||||
print("==================================================")
|
||||
@@ -0,0 +1,278 @@
|
||||
"""Tools for executing shell commands safely.
|
||||
|
||||
This module provides a safe interface for executing shell commands with:
|
||||
- Timeout control
|
||||
- Output capture
|
||||
- Error handling
|
||||
- Resource limits
|
||||
"""
|
||||
|
||||
import subprocess
|
||||
import shlex
|
||||
import logging
|
||||
import os
|
||||
import time
|
||||
from typing import Dict, List, Optional, Union
|
||||
|
||||
class ShellTools:
|
||||
"""Tools for executing shell commands safely."""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize ShellTools."""
|
||||
self._check_dependencies()
|
||||
|
||||
def _check_dependencies(self):
|
||||
"""Check if required packages are installed."""
|
||||
try:
|
||||
import psutil
|
||||
except ImportError:
|
||||
raise ImportError(
|
||||
"Required package not available. Please install: psutil\n"
|
||||
"Run: pip install psutil"
|
||||
)
|
||||
|
||||
def execute_command(
|
||||
self,
|
||||
command: str,
|
||||
cwd: Optional[str] = None,
|
||||
timeout: int = 30,
|
||||
shell: bool = False,
|
||||
env: Optional[Dict[str, str]] = None,
|
||||
max_output_size: int = 10000
|
||||
) -> Dict[str, Union[str, int, bool]]:
|
||||
"""Execute a shell command safely.
|
||||
|
||||
Args:
|
||||
command: Command to execute
|
||||
cwd: Working directory
|
||||
timeout: Maximum execution time in seconds
|
||||
shell: Whether to run command in shell
|
||||
env: Environment variables
|
||||
max_output_size: Maximum output size in bytes
|
||||
|
||||
Returns:
|
||||
Dictionary with execution results
|
||||
"""
|
||||
try:
|
||||
# Split command if not using shell
|
||||
if not shell:
|
||||
command = shlex.split(command)
|
||||
|
||||
# Set up process environment
|
||||
process_env = os.environ.copy()
|
||||
if env:
|
||||
process_env.update(env)
|
||||
|
||||
# Start process
|
||||
start_time = time.time()
|
||||
process = subprocess.Popen(
|
||||
command,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
cwd=cwd,
|
||||
shell=shell,
|
||||
env=process_env,
|
||||
text=True
|
||||
)
|
||||
|
||||
try:
|
||||
# Wait for process with timeout
|
||||
stdout, stderr = process.communicate(timeout=timeout)
|
||||
|
||||
# Truncate output if too large
|
||||
if len(stdout) > max_output_size:
|
||||
stdout = stdout[:max_output_size] + "...[truncated]"
|
||||
if len(stderr) > max_output_size:
|
||||
stderr = stderr[:max_output_size] + "...[truncated]"
|
||||
|
||||
return {
|
||||
'stdout': stdout,
|
||||
'stderr': stderr,
|
||||
'exit_code': process.returncode,
|
||||
'success': process.returncode == 0,
|
||||
'execution_time': time.time() - start_time
|
||||
}
|
||||
|
||||
except subprocess.TimeoutExpired:
|
||||
# Kill process on timeout
|
||||
parent = psutil.Process(process.pid)
|
||||
children = parent.children(recursive=True)
|
||||
for child in children:
|
||||
child.kill()
|
||||
parent.kill()
|
||||
|
||||
return {
|
||||
'stdout': '',
|
||||
'stderr': f'Command timed out after {timeout} seconds',
|
||||
'exit_code': -1,
|
||||
'success': False,
|
||||
'execution_time': timeout
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
error_msg = f"Error executing command: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return {
|
||||
'stdout': '',
|
||||
'stderr': error_msg,
|
||||
'exit_code': -1,
|
||||
'success': False,
|
||||
'execution_time': 0
|
||||
}
|
||||
|
||||
def list_processes(self) -> List[Dict[str, Union[int, str, float]]]:
|
||||
"""List running processes with their details.
|
||||
|
||||
Returns:
|
||||
List of process information dictionaries
|
||||
"""
|
||||
try:
|
||||
processes = []
|
||||
for proc in psutil.process_iter(['pid', 'name', 'username', 'memory_percent', 'cpu_percent']):
|
||||
try:
|
||||
pinfo = proc.info
|
||||
processes.append({
|
||||
'pid': pinfo['pid'],
|
||||
'name': pinfo['name'],
|
||||
'username': pinfo['username'],
|
||||
'memory_percent': round(pinfo['memory_percent'], 2),
|
||||
'cpu_percent': round(pinfo['cpu_percent'], 2)
|
||||
})
|
||||
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
|
||||
pass
|
||||
return processes
|
||||
except Exception as e:
|
||||
error_msg = f"Error listing processes: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return []
|
||||
|
||||
def kill_process(
|
||||
self,
|
||||
pid: int,
|
||||
force: bool = False
|
||||
) -> Dict[str, Union[bool, str]]:
|
||||
"""Kill a process by its PID.
|
||||
|
||||
Args:
|
||||
pid: Process ID to kill
|
||||
force: Whether to force kill (-9)
|
||||
|
||||
Returns:
|
||||
Dictionary with operation results
|
||||
"""
|
||||
try:
|
||||
process = psutil.Process(pid)
|
||||
if force:
|
||||
process.kill() # SIGKILL
|
||||
else:
|
||||
process.terminate() # SIGTERM
|
||||
|
||||
return {
|
||||
'success': True,
|
||||
'message': f'Process {pid} killed successfully'
|
||||
}
|
||||
except psutil.NoSuchProcess:
|
||||
return {
|
||||
'success': False,
|
||||
'message': f'No process found with PID {pid}'
|
||||
}
|
||||
except psutil.AccessDenied:
|
||||
return {
|
||||
'success': False,
|
||||
'message': f'Access denied to kill process {pid}'
|
||||
}
|
||||
except Exception as e:
|
||||
error_msg = f"Error killing process: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return {
|
||||
'success': False,
|
||||
'message': error_msg
|
||||
}
|
||||
|
||||
def get_system_info(self) -> Dict[str, Union[float, int, str, Dict]]:
|
||||
"""Get system information.
|
||||
|
||||
Returns:
|
||||
Dictionary with system information
|
||||
"""
|
||||
try:
|
||||
cpu_percent = psutil.cpu_percent(interval=1)
|
||||
memory = psutil.virtual_memory()
|
||||
disk = psutil.disk_usage('/')
|
||||
|
||||
return {
|
||||
'cpu': {
|
||||
'percent': cpu_percent,
|
||||
'cores': psutil.cpu_count(),
|
||||
'physical_cores': psutil.cpu_count(logical=False)
|
||||
},
|
||||
'memory': {
|
||||
'total': memory.total,
|
||||
'available': memory.available,
|
||||
'percent': memory.percent,
|
||||
'used': memory.used,
|
||||
'free': memory.free
|
||||
},
|
||||
'disk': {
|
||||
'total': disk.total,
|
||||
'used': disk.used,
|
||||
'free': disk.free,
|
||||
'percent': disk.percent
|
||||
},
|
||||
'boot_time': psutil.boot_time(),
|
||||
'platform': os.uname().sysname
|
||||
}
|
||||
except Exception as e:
|
||||
error_msg = f"Error getting system info: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return {}
|
||||
|
||||
# Create instance for direct function access
|
||||
_shell_tools = ShellTools()
|
||||
execute_command = _shell_tools.execute_command
|
||||
list_processes = _shell_tools.list_processes
|
||||
kill_process = _shell_tools.kill_process
|
||||
get_system_info = _shell_tools.get_system_info
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Example usage
|
||||
print("\n==================================================")
|
||||
print("ShellTools Demonstration")
|
||||
print("==================================================\n")
|
||||
|
||||
# 1. Execute command
|
||||
print("1. Command Execution")
|
||||
print("------------------------------")
|
||||
result = execute_command("ls -la")
|
||||
print(f"Success: {result['success']}")
|
||||
print(f"Output:\n{result['stdout']}")
|
||||
if result['stderr']:
|
||||
print(f"Errors:\n{result['stderr']}")
|
||||
print(f"Execution time: {result['execution_time']:.2f}s")
|
||||
print()
|
||||
|
||||
# 2. System Information
|
||||
print("2. System Information")
|
||||
print("------------------------------")
|
||||
info = get_system_info()
|
||||
print(f"CPU Usage: {info['cpu']['percent']}%")
|
||||
print(f"Memory Usage: {info['memory']['percent']}%")
|
||||
print(f"Disk Usage: {info['disk']['percent']}%")
|
||||
print(f"Platform: {info['platform']}")
|
||||
print()
|
||||
|
||||
# 3. Process List
|
||||
print("3. Process List (top 5 by CPU)")
|
||||
print("------------------------------")
|
||||
processes = sorted(
|
||||
list_processes(),
|
||||
key=lambda x: x['cpu_percent'],
|
||||
reverse=True
|
||||
)[:5]
|
||||
for proc in processes:
|
||||
print(f"PID: {proc['pid']}, Name: {proc['name']}, CPU: {proc['cpu_percent']}%")
|
||||
print()
|
||||
|
||||
print("\n==================================================")
|
||||
print("Demonstration Complete")
|
||||
print("==================================================")
|
||||
@@ -0,0 +1,431 @@
|
||||
"""Tools for web scraping and crawling.
|
||||
|
||||
Usage:
|
||||
from praisonaiagents.tools import spider_tools
|
||||
content = spider_tools.scrape_page("https://example.com")
|
||||
links = spider_tools.extract_links("https://example.com")
|
||||
|
||||
or
|
||||
from praisonaiagents.tools import scrape_page, extract_links
|
||||
content = scrape_page("https://example.com")
|
||||
"""
|
||||
|
||||
import logging
|
||||
from typing import List, Dict, Union, Optional, Any
|
||||
from importlib import util
|
||||
import json
|
||||
from urllib.parse import urljoin, urlparse
|
||||
import re
|
||||
import os
|
||||
import hashlib
|
||||
import time
|
||||
|
||||
class SpiderTools:
|
||||
"""Tools for web scraping and crawling."""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize SpiderTools and check for required packages."""
|
||||
self._session = None
|
||||
|
||||
def _get_session(self):
|
||||
"""Get or create requests session with common headers."""
|
||||
if util.find_spec('requests') is None:
|
||||
error_msg = "requests package is not available. Please install it using: pip install requests"
|
||||
logging.error(error_msg)
|
||||
return None
|
||||
|
||||
if self._session is None:
|
||||
import requests
|
||||
self._session = requests.Session()
|
||||
self._session.headers.update({
|
||||
'User-Agent': 'Mozilla/5.0 (compatible; PraisonAI/1.0; +http://praisonai.com/bot)',
|
||||
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
|
||||
'Accept-Language': 'en-US,en;q=0.5',
|
||||
'Accept-Encoding': 'gzip, deflate, br',
|
||||
'Connection': 'keep-alive',
|
||||
})
|
||||
return self._session
|
||||
|
||||
def scrape_page(
|
||||
self,
|
||||
url: str,
|
||||
selector: Optional[str] = None,
|
||||
extract_images: bool = False,
|
||||
extract_links: bool = False,
|
||||
timeout: int = 30,
|
||||
verify_ssl: bool = True
|
||||
) -> Union[Dict[str, Any], Dict[str, str]]:
|
||||
"""
|
||||
Scrape content from a webpage.
|
||||
|
||||
Args:
|
||||
url: URL to scrape
|
||||
selector: Optional CSS selector to extract specific content
|
||||
extract_images: Whether to extract image URLs
|
||||
extract_links: Whether to extract links
|
||||
timeout: Request timeout in seconds
|
||||
verify_ssl: Whether to verify SSL certificates
|
||||
|
||||
Returns:
|
||||
Dict: Scraped content or error dict
|
||||
"""
|
||||
try:
|
||||
session = self._get_session()
|
||||
if session is None:
|
||||
return {"error": "requests package not available"}
|
||||
|
||||
# Import BeautifulSoup only when needed
|
||||
if util.find_spec('bs4') is None:
|
||||
error_msg = "bs4 package is not available. Please install it using: pip install beautifulsoup4"
|
||||
logging.error(error_msg)
|
||||
return {"error": error_msg}
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
# Make request
|
||||
response = session.get(
|
||||
url,
|
||||
timeout=timeout,
|
||||
verify=verify_ssl
|
||||
)
|
||||
response.raise_for_status()
|
||||
|
||||
# Parse HTML
|
||||
soup = BeautifulSoup(response.text, 'lxml')
|
||||
|
||||
# Remove unwanted elements
|
||||
for element in soup(['script', 'style']):
|
||||
element.decompose()
|
||||
|
||||
# Initialize result
|
||||
result = {
|
||||
'url': url,
|
||||
'status_code': response.status_code,
|
||||
'encoding': response.encoding,
|
||||
'headers': dict(response.headers),
|
||||
}
|
||||
|
||||
# Extract content based on selector
|
||||
if selector:
|
||||
elements = soup.select(selector)
|
||||
result['content'] = [elem.get_text(strip=True) for elem in elements]
|
||||
result['html'] = [str(elem) for elem in elements]
|
||||
else:
|
||||
result['title'] = soup.title.string if soup.title else None
|
||||
result['content'] = soup.get_text(separator=' ', strip=True)
|
||||
result['html'] = str(soup)
|
||||
|
||||
# Extract metadata
|
||||
meta_tags = {}
|
||||
for meta in soup.find_all('meta'):
|
||||
name = meta.get('name') or meta.get('property')
|
||||
if name:
|
||||
meta_tags[name] = meta.get('content')
|
||||
result['meta_tags'] = meta_tags
|
||||
|
||||
# Extract images if requested
|
||||
if extract_images:
|
||||
images = []
|
||||
for img in soup.find_all('img'):
|
||||
src = img.get('src')
|
||||
if src:
|
||||
images.append({
|
||||
'src': urljoin(url, src),
|
||||
'alt': img.get('alt', ''),
|
||||
'title': img.get('title', '')
|
||||
})
|
||||
result['images'] = images
|
||||
|
||||
# Extract links if requested
|
||||
if extract_links:
|
||||
links = []
|
||||
for link in soup.find_all('a'):
|
||||
href = link.get('href')
|
||||
if href:
|
||||
links.append({
|
||||
'url': urljoin(url, href),
|
||||
'text': link.get_text(strip=True),
|
||||
'title': link.get('title', '')
|
||||
})
|
||||
result['links'] = links
|
||||
|
||||
return result
|
||||
except Exception as e:
|
||||
error_msg = f"Error scraping {url}: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return {"error": error_msg}
|
||||
|
||||
def extract_links(
|
||||
self,
|
||||
url: str,
|
||||
same_domain: bool = True,
|
||||
exclude_patterns: Optional[List[str]] = None,
|
||||
timeout: int = 30,
|
||||
verify_ssl: bool = True
|
||||
) -> Union[List[Dict[str, str]], Dict[str, str]]:
|
||||
"""
|
||||
Extract all links from a webpage.
|
||||
|
||||
Args:
|
||||
url: URL to extract links from
|
||||
same_domain: Only return links from the same domain
|
||||
exclude_patterns: List of regex patterns to exclude
|
||||
timeout: Request timeout in seconds
|
||||
verify_ssl: Whether to verify SSL certificates
|
||||
|
||||
Returns:
|
||||
List[Dict] or Dict: List of links or error dict
|
||||
"""
|
||||
try:
|
||||
# Compile exclude patterns
|
||||
if exclude_patterns:
|
||||
exclude_patterns = [re.compile(p) for p in exclude_patterns]
|
||||
|
||||
# Get base domain
|
||||
base_domain = urlparse(url).netloc
|
||||
|
||||
# Scrape page
|
||||
result = self.scrape_page(
|
||||
url,
|
||||
extract_links=True,
|
||||
timeout=timeout,
|
||||
verify_ssl=verify_ssl
|
||||
)
|
||||
|
||||
if "error" in result:
|
||||
return result
|
||||
|
||||
# Filter and clean links
|
||||
links = []
|
||||
seen_urls = set()
|
||||
|
||||
for link in result.get('links', []):
|
||||
link_url = link['url']
|
||||
|
||||
# Skip if already seen
|
||||
if link_url in seen_urls:
|
||||
continue
|
||||
|
||||
# Parse URL
|
||||
parsed = urlparse(link_url)
|
||||
|
||||
# Skip if not same domain and same_domain is True
|
||||
if same_domain and parsed.netloc != base_domain:
|
||||
continue
|
||||
|
||||
# Skip if matches exclude patterns
|
||||
if exclude_patterns and any(p.search(link_url) for p in exclude_patterns):
|
||||
continue
|
||||
|
||||
# Add to results
|
||||
links.append(link)
|
||||
seen_urls.add(link_url)
|
||||
|
||||
return links
|
||||
except Exception as e:
|
||||
error_msg = f"Error extracting links from {url}: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return {"error": error_msg}
|
||||
|
||||
def crawl(
|
||||
self,
|
||||
start_url: str,
|
||||
max_pages: int = 10,
|
||||
same_domain: bool = True,
|
||||
exclude_patterns: Optional[List[str]] = None,
|
||||
delay: float = 1.0,
|
||||
timeout: int = 30,
|
||||
verify_ssl: bool = True,
|
||||
output_dir: Optional[str] = None
|
||||
) -> Union[List[Dict[str, Any]], Dict[str, str]]:
|
||||
"""
|
||||
Crawl multiple pages starting from a URL.
|
||||
|
||||
Args:
|
||||
start_url: Starting URL
|
||||
max_pages: Maximum number of pages to crawl
|
||||
same_domain: Only crawl pages from the same domain
|
||||
exclude_patterns: List of regex patterns to exclude
|
||||
delay: Delay between requests in seconds
|
||||
timeout: Request timeout in seconds
|
||||
verify_ssl: Whether to verify SSL certificates
|
||||
output_dir: Directory to save crawled pages
|
||||
|
||||
Returns:
|
||||
List[Dict] or Dict: Crawled pages or error dict
|
||||
"""
|
||||
try:
|
||||
# Create output directory if needed
|
||||
if output_dir:
|
||||
os.makedirs(output_dir, exist_ok=True)
|
||||
|
||||
# Initialize crawl state
|
||||
to_visit = {start_url}
|
||||
visited = set()
|
||||
results = []
|
||||
|
||||
while to_visit and len(visited) < max_pages:
|
||||
# Get next URL
|
||||
url = to_visit.pop()
|
||||
|
||||
# Skip if already visited
|
||||
if url in visited:
|
||||
continue
|
||||
|
||||
# Add to visited
|
||||
visited.add(url)
|
||||
|
||||
# Delay if not first request
|
||||
if len(visited) > 1:
|
||||
time.sleep(delay)
|
||||
|
||||
# Scrape page
|
||||
result = self.scrape_page(
|
||||
url,
|
||||
extract_links=True,
|
||||
timeout=timeout,
|
||||
verify_ssl=verify_ssl
|
||||
)
|
||||
|
||||
if "error" in result:
|
||||
logging.warning(f"Error crawling {url}: {result['error']}")
|
||||
continue
|
||||
|
||||
# Save result
|
||||
results.append(result)
|
||||
|
||||
# Save to file if requested
|
||||
if output_dir:
|
||||
filename = hashlib.md5(url.encode()).hexdigest() + '.json'
|
||||
filepath = os.path.join(output_dir, filename)
|
||||
with open(filepath, 'w', encoding='utf-8') as f:
|
||||
json.dump(result, f, indent=2, ensure_ascii=False)
|
||||
|
||||
# Add new links to visit
|
||||
for link in result.get('links', []):
|
||||
link_url = link['url']
|
||||
parsed = urlparse(link_url)
|
||||
|
||||
# Skip if not same domain and same_domain is True
|
||||
if same_domain and parsed.netloc != urlparse(start_url).netloc:
|
||||
continue
|
||||
|
||||
# Skip if matches exclude patterns
|
||||
if exclude_patterns and any(
|
||||
re.compile(p).search(link_url) for p in exclude_patterns
|
||||
):
|
||||
continue
|
||||
|
||||
# Add to visit if not visited
|
||||
if link_url not in visited:
|
||||
to_visit.add(link_url)
|
||||
|
||||
return results
|
||||
except Exception as e:
|
||||
error_msg = f"Error crawling from {start_url}: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return {"error": error_msg}
|
||||
|
||||
def extract_text(
|
||||
self,
|
||||
url: str,
|
||||
selector: Optional[str] = None,
|
||||
timeout: int = 30,
|
||||
verify_ssl: bool = True
|
||||
) -> Union[str, Dict[str, str]]:
|
||||
"""
|
||||
Extract clean text content from a webpage.
|
||||
|
||||
Args:
|
||||
url: URL to extract text from
|
||||
selector: Optional CSS selector to extract specific content
|
||||
timeout: Request timeout in seconds
|
||||
verify_ssl: Whether to verify SSL certificates
|
||||
|
||||
Returns:
|
||||
str or Dict: Extracted text or error dict
|
||||
"""
|
||||
try:
|
||||
result = self.scrape_page(
|
||||
url,
|
||||
selector=selector,
|
||||
timeout=timeout,
|
||||
verify_ssl=verify_ssl
|
||||
)
|
||||
|
||||
if "error" in result:
|
||||
return result
|
||||
|
||||
if selector:
|
||||
return '\n'.join(result['content'])
|
||||
return result['content']
|
||||
except Exception as e:
|
||||
error_msg = f"Error extracting text from {url}: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return {"error": error_msg}
|
||||
|
||||
# Create instance for direct function access
|
||||
_spider_tools = SpiderTools()
|
||||
scrape_page = _spider_tools.scrape_page
|
||||
extract_links = _spider_tools.extract_links
|
||||
crawl = _spider_tools.crawl
|
||||
extract_text = _spider_tools.extract_text
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Example usage
|
||||
print("\n==================================================")
|
||||
print("SpiderTools Demonstration")
|
||||
print("==================================================\n")
|
||||
|
||||
# 1. Scrape a webpage
|
||||
print("1. Scraping Webpage")
|
||||
print("------------------------------")
|
||||
url = "https://example.com"
|
||||
result = scrape_page(url, extract_images=True, extract_links=True)
|
||||
print(f"Content from {url}:")
|
||||
if "error" not in result:
|
||||
print(f"Title: {result['title']}")
|
||||
print(f"Content length: {len(result['content'])} characters")
|
||||
print(f"Number of images: {len(result.get('images', []))}")
|
||||
print(f"Number of links: {len(result.get('links', []))}")
|
||||
else:
|
||||
print(result) # Show error
|
||||
print()
|
||||
|
||||
# 2. Extract links
|
||||
print("2. Extracting Links")
|
||||
print("------------------------------")
|
||||
links = extract_links(url)
|
||||
print(f"Links from {url}:")
|
||||
if isinstance(links, list):
|
||||
for link in links:
|
||||
print(f"- {link['url']} ({link['text']})")
|
||||
else:
|
||||
print(links) # Show error
|
||||
print()
|
||||
|
||||
# 3. Extract text
|
||||
print("3. Extracting Text")
|
||||
print("------------------------------")
|
||||
text = extract_text(url)
|
||||
print(f"Text from {url}:")
|
||||
if isinstance(text, str):
|
||||
print(text[:500] + "..." if len(text) > 500 else text)
|
||||
else:
|
||||
print(text) # Show error
|
||||
print()
|
||||
|
||||
# 4. Crawl multiple pages
|
||||
print("4. Crawling Multiple Pages")
|
||||
print("------------------------------")
|
||||
results = crawl(url, max_pages=2, delay=1.0)
|
||||
print(f"Crawl results from {url}:")
|
||||
if isinstance(results, list):
|
||||
print(f"Crawled {len(results)} pages")
|
||||
for result in results:
|
||||
print(f"- {result['url']}: {result['title']}")
|
||||
else:
|
||||
print(results) # Show error
|
||||
|
||||
print("\n==================================================")
|
||||
print("Demonstration Complete")
|
||||
print("==================================================")
|
||||
@@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Test runner for all tools."""
|
||||
|
||||
import os
|
||||
import glob
|
||||
import logging
|
||||
import subprocess
|
||||
|
||||
# Set up logging
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
||||
)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def main():
|
||||
"""Run all tool files."""
|
||||
logger.info("Starting tests...")
|
||||
|
||||
# Get all *_tools.py files
|
||||
tools_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
tool_files = glob.glob(os.path.join(tools_dir, "*_tools.py"))
|
||||
|
||||
# Run each tool file
|
||||
for tool_file in sorted(tool_files):
|
||||
module_name = os.path.basename(tool_file)
|
||||
logger.info(f"\nRunning {module_name}...")
|
||||
|
||||
try:
|
||||
# Run the tool file directly
|
||||
result = subprocess.run(
|
||||
["python3", tool_file],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
cwd=tools_dir
|
||||
)
|
||||
|
||||
# Log output
|
||||
if result.stdout:
|
||||
logger.info(f"Output:\n{result.stdout}")
|
||||
if result.stderr:
|
||||
logger.error(f"Errors:\n{result.stderr}")
|
||||
|
||||
if result.returncode == 0:
|
||||
logger.info(f" {module_name} completed successfully")
|
||||
else:
|
||||
logger.error(f" {module_name} failed with return code {result.returncode}")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error running {module_name}: {str(e)}")
|
||||
continue
|
||||
|
||||
logger.info("\nAll tests completed!")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,40 +1,9 @@
|
||||
"""Tools module for PraisonAI Agents"""
|
||||
from typing import List, Dict
|
||||
import logging
|
||||
import importlib
|
||||
from .duckduckgo_tools import internet_search
|
||||
|
||||
class Tools:
|
||||
@staticmethod
|
||||
def internet_search(query: str) -> List[Dict]:
|
||||
"""
|
||||
Perform a search using DuckDuckGo.
|
||||
"""Tools class for backward compatibility"""
|
||||
internet_search = staticmethod(internet_search)
|
||||
|
||||
Args:
|
||||
query (str): The search query.
|
||||
|
||||
Returns:
|
||||
list: A list of search result titles, URLs, and snippets.
|
||||
"""
|
||||
# Check if duckduckgo_search is installed
|
||||
if importlib.util.find_spec("duckduckgo_search") is None:
|
||||
error_msg = "DuckDuckGo search is not available. Please install duckduckgo_search package using: pip install duckduckgo_search"
|
||||
logging.error(error_msg)
|
||||
return [{"error": error_msg}]
|
||||
|
||||
try:
|
||||
# Import only when needed
|
||||
from duckduckgo_search import DDGS
|
||||
results = []
|
||||
ddgs = DDGS()
|
||||
for result in ddgs.text(keywords=query, max_results=5):
|
||||
results.append({
|
||||
"title": result.get("title", ""),
|
||||
"url": result.get("href", ""),
|
||||
"snippet": result.get("body", "")
|
||||
})
|
||||
return results
|
||||
|
||||
except Exception as e:
|
||||
error_msg = f"Error during DuckDuckGo search: {e}"
|
||||
logging.error(error_msg)
|
||||
return [{"error": error_msg}]
|
||||
# Re-export the function
|
||||
__all__ = ['Tools', 'internet_search']
|
||||
@@ -0,0 +1,272 @@
|
||||
"""Wikipedia tools for accessing and searching Wikipedia content.
|
||||
|
||||
Usage:
|
||||
from praisonaiagents.tools import wikipedia_tools
|
||||
summary = wikipedia_tools.get_summary("Python programming language")
|
||||
page = wikipedia_tools.get_page("Python programming language")
|
||||
results = wikipedia_tools.search("Python programming")
|
||||
|
||||
or
|
||||
from praisonaiagents.tools import get_wikipedia_summary, get_wikipedia_page
|
||||
summary = get_wikipedia_summary("Python programming language")
|
||||
"""
|
||||
|
||||
import logging
|
||||
from typing import List, Dict, Union, Any
|
||||
from importlib import util
|
||||
import json
|
||||
|
||||
class WikipediaTools:
|
||||
"""Tools for accessing and searching Wikipedia content."""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize WikipediaTools and check for wikipedia package."""
|
||||
self._check_wikipedia()
|
||||
|
||||
def _check_wikipedia(self):
|
||||
"""Check if wikipedia package is installed."""
|
||||
if util.find_spec("wikipedia") is None:
|
||||
raise ImportError("wikipedia package is not available. Please install it using: pip install wikipedia")
|
||||
global wikipedia
|
||||
import wikipedia
|
||||
# Set default language to English
|
||||
wikipedia.set_lang("en")
|
||||
|
||||
def search(
|
||||
self,
|
||||
query: str,
|
||||
results: int = 10,
|
||||
suggestion: bool = True
|
||||
) -> Union[List[str], Dict[str, str]]:
|
||||
"""
|
||||
Search Wikipedia for a query.
|
||||
|
||||
Args:
|
||||
query: Search query
|
||||
results: Maximum number of results to return
|
||||
suggestion: Whether to suggest similar queries
|
||||
|
||||
Returns:
|
||||
List[str] or Dict: List of search results or error dict
|
||||
"""
|
||||
try:
|
||||
search_results = wikipedia.search(query, results=results, suggestion=suggestion)
|
||||
if isinstance(search_results, tuple):
|
||||
# If suggestion is True, returns (results, suggestion)
|
||||
return {
|
||||
"results": search_results[0],
|
||||
"suggestion": search_results[1] if search_results[1] else None
|
||||
}
|
||||
return {"results": search_results, "suggestion": None}
|
||||
except Exception as e:
|
||||
error_msg = f"Error searching Wikipedia for '{query}': {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return {"error": error_msg}
|
||||
|
||||
def get_summary(
|
||||
self,
|
||||
title: str,
|
||||
sentences: int = 5,
|
||||
auto_suggest: bool = True
|
||||
) -> Union[str, Dict[str, str]]:
|
||||
"""
|
||||
Get a summary of a Wikipedia page.
|
||||
|
||||
Args:
|
||||
title: Title of the Wikipedia page
|
||||
sentences: Number of sentences to return
|
||||
auto_suggest: Whether to auto-suggest similar titles
|
||||
|
||||
Returns:
|
||||
str or Dict: Page summary if successful, error dict if failed
|
||||
"""
|
||||
try:
|
||||
return wikipedia.summary(title, sentences=sentences, auto_suggest=auto_suggest)
|
||||
except wikipedia.exceptions.DisambiguationError as e:
|
||||
return {
|
||||
"error": "Disambiguation page",
|
||||
"options": e.options[:10] # Limit to first 10 options
|
||||
}
|
||||
except Exception as e:
|
||||
error_msg = f"Error getting summary for '{title}': {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return {"error": error_msg}
|
||||
|
||||
def get_page(
|
||||
self,
|
||||
title: str,
|
||||
auto_suggest: bool = True
|
||||
) -> Union[Dict[str, Any], Dict[str, str]]:
|
||||
"""
|
||||
Get detailed information about a Wikipedia page.
|
||||
|
||||
Args:
|
||||
title: Title of the Wikipedia page
|
||||
auto_suggest: Whether to auto-suggest similar titles
|
||||
|
||||
Returns:
|
||||
Dict: Page information if successful, error dict if failed
|
||||
"""
|
||||
try:
|
||||
page = wikipedia.page(title, auto_suggest=auto_suggest)
|
||||
return {
|
||||
"title": page.title,
|
||||
"url": page.url,
|
||||
"content": page.content,
|
||||
"summary": page.summary,
|
||||
"references": page.references,
|
||||
"categories": page.categories,
|
||||
"links": page.links,
|
||||
"images": page.images,
|
||||
"sections": self.get_sections(page)
|
||||
}
|
||||
except wikipedia.exceptions.DisambiguationError as e:
|
||||
return {
|
||||
"error": "Disambiguation page",
|
||||
"options": e.options[:10] # Limit to first 10 options
|
||||
}
|
||||
except Exception as e:
|
||||
error_msg = f"Error getting page for '{title}': {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return {"error": error_msg}
|
||||
|
||||
def get_sections(self, page: Any) -> List[Dict[str, Any]]:
|
||||
"""
|
||||
Extract sections and their content from a Wikipedia page.
|
||||
|
||||
Args:
|
||||
page: Wikipedia page object
|
||||
|
||||
Returns:
|
||||
List[Dict]: List of sections with their titles and content
|
||||
"""
|
||||
sections = []
|
||||
content = page.content
|
||||
section_titles = [s.strip() for s in content.split("==")[1::2]]
|
||||
section_contents = [s.strip() for s in content.split("==")[2::2]]
|
||||
|
||||
# Add introduction section
|
||||
intro = content.split("==")[0].strip()
|
||||
if intro:
|
||||
sections.append({
|
||||
"title": "Introduction",
|
||||
"level": 0,
|
||||
"content": intro
|
||||
})
|
||||
|
||||
# Process remaining sections
|
||||
for title, content in zip(section_titles, section_contents):
|
||||
# Count leading '=' to determine section level
|
||||
level = title.count("=") // 2
|
||||
clean_title = title.strip("= ")
|
||||
|
||||
sections.append({
|
||||
"title": clean_title,
|
||||
"level": level,
|
||||
"content": content.strip()
|
||||
})
|
||||
|
||||
return sections
|
||||
|
||||
def get_random(self, pages: int = 1) -> Union[List[str], Dict[str, str]]:
|
||||
"""
|
||||
Get random Wikipedia page titles.
|
||||
|
||||
Args:
|
||||
pages: Number of random pages to return
|
||||
|
||||
Returns:
|
||||
List[str] or Dict: List of random page titles or error dict
|
||||
"""
|
||||
try:
|
||||
return wikipedia.random(pages)
|
||||
except Exception as e:
|
||||
error_msg = f"Error getting random pages: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return {"error": error_msg}
|
||||
|
||||
def set_language(self, language: str) -> bool:
|
||||
"""
|
||||
Set the language for Wikipedia searches.
|
||||
|
||||
Args:
|
||||
language: Language code (e.g., 'en' for English, 'es' for Spanish)
|
||||
|
||||
Returns:
|
||||
bool: True if successful, False if failed
|
||||
"""
|
||||
try:
|
||||
wikipedia.set_lang(language)
|
||||
return True
|
||||
except Exception as e:
|
||||
error_msg = f"Error setting language to '{language}': {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return False
|
||||
|
||||
# Create instance for direct function access
|
||||
_wikipedia_tools = WikipediaTools()
|
||||
search = _wikipedia_tools.search
|
||||
get_summary = _wikipedia_tools.get_summary
|
||||
get_page = _wikipedia_tools.get_page
|
||||
get_random = _wikipedia_tools.get_random
|
||||
set_language = _wikipedia_tools.set_language
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Example usage
|
||||
print("\n==================================================")
|
||||
print("WikipediaTools Demonstration")
|
||||
print("==================================================\n")
|
||||
|
||||
# 1. Search for a topic
|
||||
print("1. Searching Wikipedia")
|
||||
print("------------------------------")
|
||||
search_results = search("Python programming language")
|
||||
print("Search results:")
|
||||
print(json.dumps(search_results, indent=2))
|
||||
print()
|
||||
|
||||
# 2. Get a page summary
|
||||
print("2. Getting Page Summary")
|
||||
print("------------------------------")
|
||||
summary = get_summary("Python programming language", sentences=3)
|
||||
print("Summary:")
|
||||
print(summary)
|
||||
print()
|
||||
|
||||
# 3. Get detailed page information
|
||||
print("3. Getting Full Page Information")
|
||||
print("------------------------------")
|
||||
page = get_page("Python programming language")
|
||||
if isinstance(page, dict) and "error" not in page:
|
||||
print("Page sections:")
|
||||
for section in page["sections"]:
|
||||
print(f"- {section['title']} (Level {section['level']})")
|
||||
print(f"\nNumber of references: {len(page['references'])}")
|
||||
print(f"Number of categories: {len(page['categories'])}")
|
||||
print(f"Number of links: {len(page['links'])}")
|
||||
print(f"Number of images: {len(page['images'])}")
|
||||
else:
|
||||
print("Error getting page:", page.get("error"))
|
||||
print()
|
||||
|
||||
# 4. Get random pages
|
||||
print("4. Getting Random Pages")
|
||||
print("------------------------------")
|
||||
random_pages = get_random(3)
|
||||
print("Random page titles:")
|
||||
print(json.dumps(random_pages, indent=2))
|
||||
print()
|
||||
|
||||
# 5. Try different language
|
||||
print("5. Changing Language")
|
||||
print("------------------------------")
|
||||
success = set_language("es")
|
||||
if success:
|
||||
summary = get_summary("Python (lenguaje de programación)", sentences=1)
|
||||
print("Spanish summary:")
|
||||
print(summary)
|
||||
print()
|
||||
|
||||
print("\n==================================================")
|
||||
print("Demonstration Complete")
|
||||
print("==================================================")
|
||||
@@ -0,0 +1,498 @@
|
||||
"""Tools for working with XML files.
|
||||
|
||||
Usage:
|
||||
from praisonaiagents.tools import xml_tools
|
||||
tree = xml_tools.read_xml("data.xml")
|
||||
|
||||
or
|
||||
from praisonaiagents.tools import read_xml, write_xml, transform_xml
|
||||
tree = read_xml("data.xml")
|
||||
"""
|
||||
|
||||
import logging
|
||||
from typing import List, Dict, Union, Optional, Any, Tuple
|
||||
from importlib import util
|
||||
import xml.etree.ElementTree as ET
|
||||
import xml.dom.minidom as minidom
|
||||
from io import StringIO
|
||||
import json
|
||||
|
||||
class XMLTools:
|
||||
"""Tools for working with XML files."""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize XMLTools."""
|
||||
pass
|
||||
|
||||
def read_xml(
|
||||
self,
|
||||
filepath: str,
|
||||
encoding: str = 'utf-8',
|
||||
validate_schema: Optional[str] = None,
|
||||
parser: str = 'lxml'
|
||||
) -> ET.Element:
|
||||
"""Read an XML file with optional schema validation.
|
||||
|
||||
Args:
|
||||
filepath: Path to XML file
|
||||
encoding: File encoding
|
||||
validate_schema: Optional path to XSD schema file
|
||||
parser: XML parser to use ('lxml' or 'etree')
|
||||
|
||||
Returns:
|
||||
ElementTree root element
|
||||
"""
|
||||
try:
|
||||
if parser == 'lxml':
|
||||
if util.find_spec('lxml') is None:
|
||||
error_msg = "lxml package is not available. Please install it using: pip install lxml"
|
||||
logging.error(error_msg)
|
||||
return None
|
||||
import lxml.etree as lxml_etree
|
||||
tree = lxml_etree.parse(filepath)
|
||||
root = tree.getroot()
|
||||
else:
|
||||
tree = ET.parse(filepath)
|
||||
root = tree.getroot()
|
||||
|
||||
if validate_schema:
|
||||
if util.find_spec('xmlschema') is None:
|
||||
error_msg = "xmlschema package is not available. Please install it using: pip install xmlschema"
|
||||
logging.error(error_msg)
|
||||
return None
|
||||
import xmlschema
|
||||
schema = xmlschema.XMLSchema(validate_schema)
|
||||
if not schema.is_valid(filepath):
|
||||
error_msg = f"XML file does not validate against schema: {schema.validate(filepath)}"
|
||||
logging.error(error_msg)
|
||||
return None
|
||||
|
||||
return root
|
||||
|
||||
except Exception as e:
|
||||
error_msg = f"Error reading XML file {filepath}: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return None
|
||||
|
||||
def write_xml(
|
||||
self,
|
||||
root: ET.Element,
|
||||
filepath: str,
|
||||
encoding: str = 'utf-8',
|
||||
pretty: bool = True,
|
||||
xml_declaration: bool = True
|
||||
) -> bool:
|
||||
"""Write XML Element tree to file.
|
||||
|
||||
Args:
|
||||
root: XML Element tree root
|
||||
filepath: Output file path
|
||||
encoding: File encoding
|
||||
pretty: Format output with proper indentation
|
||||
xml_declaration: Include XML declaration
|
||||
|
||||
Returns:
|
||||
True if successful, False otherwise
|
||||
"""
|
||||
try:
|
||||
# Convert to string
|
||||
if pretty:
|
||||
xml_str = minidom.parseString(
|
||||
ET.tostring(root, encoding='unicode')
|
||||
).toprettyxml(indent=' ')
|
||||
else:
|
||||
xml_str = ET.tostring(
|
||||
root,
|
||||
encoding='unicode'
|
||||
)
|
||||
|
||||
# Add declaration if requested
|
||||
if xml_declaration:
|
||||
if not xml_str.startswith('<?xml'):
|
||||
xml_str = (
|
||||
f'<?xml version="1.0" encoding="{encoding}"?>\n'
|
||||
+ xml_str
|
||||
)
|
||||
|
||||
# Write to file
|
||||
with open(filepath, 'w', encoding=encoding) as f:
|
||||
f.write(xml_str)
|
||||
|
||||
return True
|
||||
except Exception as e:
|
||||
error_msg = f"Error writing XML file {filepath}: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return False
|
||||
|
||||
def transform_xml(
|
||||
self,
|
||||
xml_file: str,
|
||||
xslt_file: str,
|
||||
output_file: str,
|
||||
params: Optional[Dict[str, str]] = None
|
||||
) -> bool:
|
||||
"""Transform XML using XSLT stylesheet.
|
||||
|
||||
Args:
|
||||
xml_file: Input XML file
|
||||
xslt_file: XSLT stylesheet file
|
||||
output_file: Output file path
|
||||
params: Optional parameters for transformation
|
||||
|
||||
Returns:
|
||||
True if successful, False otherwise
|
||||
"""
|
||||
try:
|
||||
# Parse XML and XSLT
|
||||
if util.find_spec('lxml') is None:
|
||||
error_msg = "lxml package is not available. Please install it using: pip install lxml"
|
||||
logging.error(error_msg)
|
||||
return False
|
||||
import lxml.etree as lxml_etree
|
||||
xml_doc = lxml_etree.parse(xml_file)
|
||||
xslt_doc = lxml_etree.parse(xslt_file)
|
||||
transform = lxml_etree.XSLT(xslt_doc)
|
||||
|
||||
# Apply transformation
|
||||
if params:
|
||||
result = transform(xml_doc, **params)
|
||||
else:
|
||||
result = transform(xml_doc)
|
||||
|
||||
# Write result
|
||||
result.write(
|
||||
output_file,
|
||||
pretty_print=True,
|
||||
xml_declaration=True,
|
||||
encoding='utf-8'
|
||||
)
|
||||
|
||||
return True
|
||||
except Exception as e:
|
||||
error_msg = f"Error transforming XML: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return False
|
||||
|
||||
def validate_xml(
|
||||
self,
|
||||
xml_file: str,
|
||||
schema_file: str
|
||||
) -> Tuple[bool, Optional[str]]:
|
||||
"""Validate XML against XSD schema.
|
||||
|
||||
Args:
|
||||
xml_file: XML file to validate
|
||||
schema_file: XSD schema file
|
||||
|
||||
Returns:
|
||||
Tuple of (is_valid, error_message)
|
||||
"""
|
||||
try:
|
||||
if util.find_spec('xmlschema') is None:
|
||||
error_msg = "xmlschema package is not available. Please install it using: pip install xmlschema"
|
||||
logging.error(error_msg)
|
||||
return False, error_msg
|
||||
import xmlschema
|
||||
schema = xmlschema.XMLSchema(schema_file)
|
||||
schema.validate(xml_file)
|
||||
return True, None
|
||||
except xmlschema.validators.exceptions.XMLSchemaValidationError as e:
|
||||
return False, str(e)
|
||||
except Exception as e:
|
||||
error_msg = f"Error validating XML: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return False, error_msg
|
||||
|
||||
def xml_to_dict(
|
||||
self,
|
||||
root: Union[str, ET.Element],
|
||||
preserve_attrs: bool = True
|
||||
) -> Dict[str, Any]:
|
||||
"""Convert XML to dictionary.
|
||||
|
||||
Args:
|
||||
root: XML string or Element tree root
|
||||
preserve_attrs: Keep XML attributes in result
|
||||
|
||||
Returns:
|
||||
Dict representation of XML
|
||||
"""
|
||||
try:
|
||||
# Parse XML if string
|
||||
if isinstance(root, str):
|
||||
if root.startswith('<'):
|
||||
root = ET.fromstring(root)
|
||||
else:
|
||||
root = ET.parse(root).getroot()
|
||||
|
||||
result = {}
|
||||
|
||||
# Add attributes if present and requested
|
||||
if preserve_attrs and root.attrib:
|
||||
result['@attributes'] = dict(root.attrib)
|
||||
|
||||
# Add children
|
||||
children = list(root)
|
||||
if not children:
|
||||
text = root.text
|
||||
if text is not None and text.strip():
|
||||
result = text.strip()
|
||||
else:
|
||||
for child in children:
|
||||
child_data = self.xml_to_dict(child, preserve_attrs)
|
||||
if child.tag in result:
|
||||
if not isinstance(result[child.tag], list):
|
||||
result[child.tag] = [result[child.tag]]
|
||||
result[child.tag].append(child_data)
|
||||
else:
|
||||
result[child.tag] = child_data
|
||||
|
||||
return result
|
||||
except Exception as e:
|
||||
error_msg = f"Error converting XML to dict: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return {}
|
||||
|
||||
def dict_to_xml(
|
||||
self,
|
||||
data: Dict[str, Any],
|
||||
root_tag: str = 'root'
|
||||
) -> Optional[ET.Element]:
|
||||
"""Convert dictionary to XML.
|
||||
|
||||
Args:
|
||||
data: Dictionary to convert
|
||||
root_tag: Tag for root element
|
||||
|
||||
Returns:
|
||||
XML Element tree root
|
||||
"""
|
||||
try:
|
||||
def _create_element(
|
||||
parent: ET.Element,
|
||||
key: str,
|
||||
value: Any
|
||||
):
|
||||
"""Create XML element from key-value pair."""
|
||||
if key == '@attributes':
|
||||
for attr_key, attr_val in value.items():
|
||||
parent.set(attr_key, str(attr_val))
|
||||
elif isinstance(value, dict):
|
||||
child = ET.SubElement(parent, key)
|
||||
for k, v in value.items():
|
||||
_create_element(child, k, v)
|
||||
elif isinstance(value, list):
|
||||
for item in value:
|
||||
child = ET.SubElement(parent, key)
|
||||
if isinstance(item, dict):
|
||||
for k, v in item.items():
|
||||
_create_element(child, k, v)
|
||||
else:
|
||||
child.text = str(item)
|
||||
else:
|
||||
child = ET.SubElement(parent, key)
|
||||
child.text = str(value)
|
||||
|
||||
root = ET.Element(root_tag)
|
||||
for key, value in data.items():
|
||||
_create_element(root, key, value)
|
||||
|
||||
return root
|
||||
except Exception as e:
|
||||
error_msg = f"Error converting dict to XML: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return None
|
||||
|
||||
def xpath_query(
|
||||
self,
|
||||
root: Union[str, ET.Element],
|
||||
query: str,
|
||||
namespaces: Optional[Dict[str, str]] = None
|
||||
) -> List[ET.Element]:
|
||||
"""Execute XPath query on XML.
|
||||
|
||||
Args:
|
||||
root: XML string or Element tree root
|
||||
query: XPath query string
|
||||
namespaces: Optional namespace mappings
|
||||
|
||||
Returns:
|
||||
List of matching elements
|
||||
"""
|
||||
try:
|
||||
# Parse XML if string
|
||||
if isinstance(root, str):
|
||||
if root.startswith('<'):
|
||||
if util.find_spec('lxml') is None:
|
||||
error_msg = "lxml package is not available. Please install it using: pip install lxml"
|
||||
logging.error(error_msg)
|
||||
return []
|
||||
import lxml.etree as lxml_etree
|
||||
tree = lxml_etree.fromstring(root)
|
||||
else:
|
||||
tree = ET.parse(root)
|
||||
else:
|
||||
if util.find_spec('lxml') is None:
|
||||
error_msg = "lxml package is not available. Please install it using: pip install lxml"
|
||||
logging.error(error_msg)
|
||||
return []
|
||||
import lxml.etree as lxml_etree
|
||||
tree = lxml_etree.fromstring(
|
||||
ET.tostring(root, encoding='unicode')
|
||||
)
|
||||
|
||||
# Execute query
|
||||
results = tree.xpath(
|
||||
query,
|
||||
namespaces=namespaces or {}
|
||||
)
|
||||
|
||||
# Convert results to standard ElementTree elements
|
||||
return [
|
||||
ET.fromstring(lxml_etree.tostring(elem, encoding='unicode'))
|
||||
for elem in results
|
||||
]
|
||||
except Exception as e:
|
||||
error_msg = f"Error executing XPath query: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return []
|
||||
|
||||
# Create instance for direct function access
|
||||
_xml_tools = XMLTools()
|
||||
read_xml = _xml_tools.read_xml
|
||||
write_xml = _xml_tools.write_xml
|
||||
transform_xml = _xml_tools.transform_xml
|
||||
validate_xml = _xml_tools.validate_xml
|
||||
xml_to_dict = _xml_tools.xml_to_dict
|
||||
dict_to_xml = _xml_tools.dict_to_xml
|
||||
xpath_query = _xml_tools.xpath_query
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("\n==================================================")
|
||||
print("XMLTools Demonstration")
|
||||
print("==================================================\n")
|
||||
|
||||
# Create temporary files
|
||||
import tempfile
|
||||
import os
|
||||
|
||||
temp_file = tempfile.mktemp(suffix='.xml')
|
||||
try:
|
||||
print("1. Creating XML Document")
|
||||
print("------------------------------")
|
||||
xml_content = """<?xml version="1.0" encoding="UTF-8"?>
|
||||
<bookstore>
|
||||
<book category="fiction">
|
||||
<title>The Great Gatsby</title>
|
||||
<author>F. Scott Fitzgerald</author>
|
||||
<year>1925</year>
|
||||
<price>10.99</price>
|
||||
</book>
|
||||
<book category="non-fiction">
|
||||
<title>A Brief History of Time</title>
|
||||
<author>Stephen Hawking</author>
|
||||
<year>1988</year>
|
||||
<price>15.99</price>
|
||||
</book>
|
||||
</bookstore>"""
|
||||
|
||||
with open(temp_file, 'w') as f:
|
||||
f.write(xml_content)
|
||||
print("Sample XML file created")
|
||||
print()
|
||||
|
||||
print("2. Parsing XML")
|
||||
print("------------------------------")
|
||||
result = read_xml(temp_file)
|
||||
print("XML structure:")
|
||||
print(minidom.parseString(ET.tostring(result, encoding='unicode')).toprettyxml(indent=' '))
|
||||
print()
|
||||
|
||||
print("3. Querying XML")
|
||||
print("------------------------------")
|
||||
xpath = "//book[@category='fiction']/title/text()"
|
||||
result = xpath_query(result, xpath)
|
||||
print(f"Fiction book titles (XPath: {xpath}):")
|
||||
for title in result:
|
||||
print(title.text)
|
||||
print()
|
||||
|
||||
print("4. Validating XML")
|
||||
print("------------------------------")
|
||||
schema_file = tempfile.mktemp(suffix='.xsd')
|
||||
schema_content = """<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:element name="bookstore">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="book" maxOccurs="unbounded">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="title" type="xs:string"/>
|
||||
<xs:element name="author" type="xs:string"/>
|
||||
<xs:element name="year" type="xs:integer"/>
|
||||
<xs:element name="price" type="xs:decimal"/>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="category" type="xs:string"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:schema>"""
|
||||
with open(schema_file, 'w') as f:
|
||||
f.write(schema_content)
|
||||
result, error = validate_xml(temp_file, schema_file)
|
||||
print(f"XML validation result: {result}")
|
||||
if error:
|
||||
print(f"Error: {error}")
|
||||
print()
|
||||
|
||||
print("5. Transforming XML")
|
||||
print("------------------------------")
|
||||
xslt_content = """<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
||||
<xsl:template match="/">
|
||||
<html>
|
||||
<body>
|
||||
<h2>Bookstore Inventory</h2>
|
||||
<table>
|
||||
<tr>
|
||||
<th>Title</th>
|
||||
<th>Author</th>
|
||||
<th>Price</th>
|
||||
</tr>
|
||||
<xsl:for-each select="bookstore/book">
|
||||
<tr>
|
||||
<td><xsl:value-of select="title"/></td>
|
||||
<td><xsl:value-of select="author"/></td>
|
||||
<td><xsl:value-of select="price"/></td>
|
||||
</tr>
|
||||
</xsl:for-each>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>"""
|
||||
|
||||
xslt_file = tempfile.mktemp(suffix='.xslt')
|
||||
with open(xslt_file, 'w') as f:
|
||||
f.write(xslt_content)
|
||||
|
||||
output_file = tempfile.mktemp(suffix='.html')
|
||||
result = transform_xml(temp_file, xslt_file, output_file)
|
||||
print(f"XML transformation result: {result}")
|
||||
if result and os.path.exists(output_file):
|
||||
print("\nTransformed HTML content:")
|
||||
with open(output_file, 'r') as f:
|
||||
print(f.read())
|
||||
|
||||
finally:
|
||||
# Clean up temporary files
|
||||
for file in [temp_file, schema_file, xslt_file, output_file]:
|
||||
if os.path.exists(file):
|
||||
os.unlink(file)
|
||||
|
||||
print("\n==================================================")
|
||||
print("Demonstration Complete")
|
||||
print("==================================================")
|
||||
@@ -0,0 +1,417 @@
|
||||
"""Tools for working with YAML files.
|
||||
|
||||
Usage:
|
||||
from praisonaiagents.tools import yaml_tools
|
||||
data = yaml_tools.read_yaml("config.yaml")
|
||||
|
||||
or
|
||||
from praisonaiagents.tools import read_yaml, write_yaml, merge_yaml
|
||||
data = read_yaml("config.yaml")
|
||||
"""
|
||||
|
||||
import logging
|
||||
from typing import List, Dict, Union, Optional, Any
|
||||
from importlib import util
|
||||
import os
|
||||
from copy import deepcopy
|
||||
|
||||
class YAMLTools:
|
||||
"""Tools for working with YAML files."""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize YAMLTools."""
|
||||
self._check_dependencies()
|
||||
|
||||
def _check_dependencies(self):
|
||||
"""Check if required packages are installed."""
|
||||
missing = []
|
||||
for package, module in [('pyyaml', 'yaml'), ('jsonschema', 'jsonschema')]:
|
||||
if util.find_spec(module) is None:
|
||||
missing.append(package)
|
||||
|
||||
if missing:
|
||||
raise ImportError(
|
||||
f"Required packages not available. Please install: {', '.join(missing)}\n"
|
||||
f"Run: pip install {' '.join(missing)}"
|
||||
)
|
||||
|
||||
def read_yaml(
|
||||
self,
|
||||
filepath: str,
|
||||
safe_load: bool = True,
|
||||
encoding: str = 'utf-8'
|
||||
) -> Optional[Union[Dict[str, Any], List[Any]]]:
|
||||
"""Read a YAML file."""
|
||||
try:
|
||||
if util.find_spec('yaml') is None:
|
||||
error_msg = "pyyaml package is not available. Please install it using: pip install pyyaml"
|
||||
logging.error(error_msg)
|
||||
return None
|
||||
|
||||
# Import yaml only when needed
|
||||
import yaml
|
||||
|
||||
with open(filepath, 'r', encoding=encoding) as f:
|
||||
if safe_load:
|
||||
return yaml.safe_load(f)
|
||||
return yaml.load(f, Loader=yaml.FullLoader)
|
||||
except Exception as e:
|
||||
error_msg = f"Error reading YAML file {filepath}: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return None
|
||||
|
||||
def write_yaml(
|
||||
self,
|
||||
data: Union[Dict[str, Any], List[Any]],
|
||||
filepath: str,
|
||||
default_flow_style: bool = False,
|
||||
encoding: str = 'utf-8',
|
||||
sort_keys: bool = False,
|
||||
allow_unicode: bool = True
|
||||
) -> bool:
|
||||
"""Write data to YAML file."""
|
||||
try:
|
||||
if util.find_spec('yaml') is None:
|
||||
error_msg = "pyyaml package is not available. Please install it using: pip install pyyaml"
|
||||
logging.error(error_msg)
|
||||
return False
|
||||
|
||||
# Import yaml only when needed
|
||||
import yaml
|
||||
|
||||
with open(filepath, 'w', encoding=encoding) as f:
|
||||
yaml.dump(
|
||||
data,
|
||||
f,
|
||||
default_flow_style=default_flow_style,
|
||||
sort_keys=sort_keys,
|
||||
allow_unicode=allow_unicode
|
||||
)
|
||||
return True
|
||||
except Exception as e:
|
||||
error_msg = f"Error writing YAML file {filepath}: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return False
|
||||
|
||||
def merge_yaml(
|
||||
self,
|
||||
files: List[str],
|
||||
output_file: Optional[str] = None,
|
||||
strategy: str = 'deep'
|
||||
) -> Union[Dict[str, Any], List[Any], None]:
|
||||
"""Merge multiple YAML files."""
|
||||
try:
|
||||
if util.find_spec('yaml') is None:
|
||||
error_msg = "pyyaml package is not available. Please install it using: pip install pyyaml"
|
||||
logging.error(error_msg)
|
||||
return None
|
||||
|
||||
def deep_merge(source: dict, destination: dict) -> dict:
|
||||
"""Deep merge two dictionaries."""
|
||||
for key, value in source.items():
|
||||
if key in destination:
|
||||
if isinstance(value, dict) and isinstance(destination[key], dict):
|
||||
destination[key] = deep_merge(value, destination[key])
|
||||
elif isinstance(value, list) and isinstance(destination[key], list):
|
||||
destination[key].extend(value)
|
||||
else:
|
||||
destination[key] = value
|
||||
else:
|
||||
destination[key] = value
|
||||
return destination
|
||||
|
||||
result = {}
|
||||
for file in files:
|
||||
data = self.read_yaml(file)
|
||||
if data is None:
|
||||
continue
|
||||
|
||||
if strategy == 'deep':
|
||||
if isinstance(data, dict):
|
||||
result = deep_merge(data, result)
|
||||
elif isinstance(data, list):
|
||||
if not result:
|
||||
result = []
|
||||
result.extend(data)
|
||||
else: # shallow
|
||||
if isinstance(data, dict):
|
||||
result.update(data)
|
||||
elif isinstance(data, list):
|
||||
if not result:
|
||||
result = []
|
||||
result.extend(data)
|
||||
|
||||
if output_file:
|
||||
self.write_yaml(result, output_file)
|
||||
|
||||
return result
|
||||
except Exception as e:
|
||||
error_msg = f"Error merging YAML files: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return None
|
||||
|
||||
def validate_yaml(
|
||||
self,
|
||||
data: Union[Dict[str, Any], List[Any], str],
|
||||
schema: Dict[str, Any]
|
||||
) -> bool:
|
||||
"""Validate YAML data against a schema."""
|
||||
try:
|
||||
if util.find_spec('jsonschema') is None:
|
||||
error_msg = "jsonschema package is not available. Please install it using: pip install jsonschema"
|
||||
logging.error(error_msg)
|
||||
return False
|
||||
|
||||
# Import jsonschema only when needed
|
||||
from jsonschema import validate, ValidationError
|
||||
|
||||
# Load data if file path
|
||||
if isinstance(data, str):
|
||||
data = self.read_yaml(data)
|
||||
if data is None:
|
||||
return False
|
||||
|
||||
try:
|
||||
validate(instance=data, schema=schema)
|
||||
return True
|
||||
except ValidationError as e:
|
||||
logging.error(f"YAML validation error: {str(e)}")
|
||||
return False
|
||||
except Exception as e:
|
||||
error_msg = f"Error validating YAML: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return False
|
||||
|
||||
def analyze_yaml(
|
||||
self,
|
||||
data: Union[Dict[str, Any], List[Any], str]
|
||||
) -> Optional[Dict[str, Any]]:
|
||||
"""Analyze YAML data structure."""
|
||||
try:
|
||||
# Load data if file path
|
||||
if isinstance(data, str):
|
||||
data = self.read_yaml(data)
|
||||
if data is None:
|
||||
return None
|
||||
|
||||
def analyze_value(value: Any) -> Dict[str, Any]:
|
||||
"""Analyze a single value."""
|
||||
result = {
|
||||
'type': type(value).__name__,
|
||||
'size': len(value) if hasattr(value, '__len__') else 1
|
||||
}
|
||||
|
||||
if isinstance(value, dict):
|
||||
result['keys'] = list(value.keys())
|
||||
result['nested_types'] = {
|
||||
k: type(v).__name__
|
||||
for k, v in value.items()
|
||||
}
|
||||
elif isinstance(value, list):
|
||||
result['element_types'] = list(set(
|
||||
type(x).__name__ for x in value
|
||||
))
|
||||
|
||||
return result
|
||||
|
||||
result = {
|
||||
'structure': analyze_value(data),
|
||||
'stats': {
|
||||
'total_keys': sum(1 for _ in self._walk_dict(data))
|
||||
if isinstance(data, dict) else len(data)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
except Exception as e:
|
||||
error_msg = f"Error analyzing YAML: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return None
|
||||
|
||||
def _walk_dict(self, d: Dict[str, Any]) -> Any:
|
||||
"""Walk through nested dictionary."""
|
||||
for k, v in d.items():
|
||||
yield k
|
||||
if isinstance(v, dict):
|
||||
yield from self._walk_dict(v)
|
||||
|
||||
def transform_yaml(
|
||||
self,
|
||||
data: Union[Dict[str, Any], List[Any], str],
|
||||
operations: List[Dict[str, Any]]
|
||||
) -> Optional[Union[Dict[str, Any], List[Any]]]:
|
||||
"""Transform YAML data using specified operations."""
|
||||
try:
|
||||
# Load data if file path
|
||||
if isinstance(data, str):
|
||||
data = self.read_yaml(data)
|
||||
if data is None:
|
||||
return None
|
||||
|
||||
result = deepcopy(data)
|
||||
|
||||
for op in operations:
|
||||
op_type = op.get('type')
|
||||
path = op.get('path', '')
|
||||
value = op.get('value')
|
||||
|
||||
if not op_type:
|
||||
continue
|
||||
|
||||
# Split path into parts
|
||||
parts = [p for p in path.split('/') if p]
|
||||
|
||||
# Get reference to target location
|
||||
target = result
|
||||
parent = None
|
||||
last_key = None
|
||||
|
||||
for part in parts[:-1]:
|
||||
if isinstance(target, dict):
|
||||
if part not in target:
|
||||
target[part] = {}
|
||||
parent = target
|
||||
target = target[part]
|
||||
last_key = part
|
||||
elif isinstance(target, list):
|
||||
idx = int(part)
|
||||
while len(target) <= idx:
|
||||
target.append({})
|
||||
parent = target
|
||||
target = target[idx]
|
||||
last_key = idx
|
||||
|
||||
if parts:
|
||||
last_part = parts[-1]
|
||||
if isinstance(target, dict):
|
||||
if op_type == 'set':
|
||||
target[last_part] = value
|
||||
elif op_type == 'delete':
|
||||
target.pop(last_part, None)
|
||||
elif op_type == 'append' and isinstance(target.get(last_part), list):
|
||||
target[last_part].append(value)
|
||||
elif isinstance(target, list):
|
||||
idx = int(last_part)
|
||||
if op_type == 'set':
|
||||
while len(target) <= idx:
|
||||
target.append(None)
|
||||
target[idx] = value
|
||||
elif op_type == 'delete' and idx < len(target):
|
||||
del target[idx]
|
||||
elif op_type == 'append':
|
||||
target.append(value)
|
||||
else:
|
||||
if op_type == 'set':
|
||||
result = value
|
||||
elif op_type == 'append' and isinstance(result, list):
|
||||
result.append(value)
|
||||
|
||||
return result
|
||||
except Exception as e:
|
||||
error_msg = f"Error transforming YAML: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return None
|
||||
|
||||
# Create instance for direct function access
|
||||
_yaml_tools = YAMLTools()
|
||||
read_yaml = _yaml_tools.read_yaml
|
||||
write_yaml = _yaml_tools.write_yaml
|
||||
merge_yaml = _yaml_tools.merge_yaml
|
||||
validate_yaml = _yaml_tools.validate_yaml
|
||||
analyze_yaml = _yaml_tools.analyze_yaml
|
||||
transform_yaml = _yaml_tools.transform_yaml
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Example usage
|
||||
print("\n==================================================")
|
||||
print("YAMLTools Demonstration")
|
||||
print("==================================================\n")
|
||||
|
||||
# Sample data
|
||||
data1 = {
|
||||
'server': {
|
||||
'host': 'localhost',
|
||||
'port': 8080,
|
||||
'debug': True
|
||||
},
|
||||
'database': {
|
||||
'url': 'postgresql://localhost:5432/db',
|
||||
'pool_size': 5
|
||||
}
|
||||
}
|
||||
|
||||
data2 = {
|
||||
'server': {
|
||||
'workers': 4,
|
||||
'timeout': 30
|
||||
},
|
||||
'logging': {
|
||||
'level': 'INFO',
|
||||
'file': 'app.log'
|
||||
}
|
||||
}
|
||||
|
||||
# 1. Write YAML files
|
||||
print("1. Writing YAML Files")
|
||||
print("------------------------------")
|
||||
success1 = write_yaml(data1, 'config1.yaml')
|
||||
success2 = write_yaml(data2, 'config2.yaml')
|
||||
print(f"First file written: {success1}")
|
||||
print(f"Second file written: {success2}")
|
||||
print()
|
||||
|
||||
# 2. Read YAML file
|
||||
print("2. Reading YAML File")
|
||||
print("------------------------------")
|
||||
config = read_yaml('config1.yaml')
|
||||
print("YAML content:")
|
||||
print(config)
|
||||
print()
|
||||
|
||||
# 3. Merge YAML files
|
||||
print("3. Merging YAML Files")
|
||||
print("------------------------------")
|
||||
merged = merge_yaml(['config1.yaml', 'config2.yaml'])
|
||||
print("Merged content:")
|
||||
print(merged)
|
||||
print()
|
||||
|
||||
# 4. Analyze YAML
|
||||
print("4. Analyzing YAML")
|
||||
print("------------------------------")
|
||||
analysis = analyze_yaml(merged)
|
||||
print("Analysis results:")
|
||||
print(analysis)
|
||||
print()
|
||||
|
||||
# 5. Transform YAML
|
||||
print("5. Transforming YAML")
|
||||
print("------------------------------")
|
||||
operations = [
|
||||
{
|
||||
'type': 'set',
|
||||
'path': 'server/host',
|
||||
'value': '0.0.0.0'
|
||||
},
|
||||
{
|
||||
'type': 'delete',
|
||||
'path': 'server/debug'
|
||||
},
|
||||
{
|
||||
'type': 'set',
|
||||
'path': 'logging/handlers',
|
||||
'value': ['console', 'file']
|
||||
}
|
||||
]
|
||||
transformed = transform_yaml(merged, operations)
|
||||
print("Transformed content:")
|
||||
print(transformed)
|
||||
|
||||
print("\n==================================================")
|
||||
print("Demonstration Complete")
|
||||
print("==================================================")
|
||||
|
||||
# Cleanup
|
||||
for file in ['config1.yaml', 'config2.yaml']:
|
||||
if os.path.exists(file):
|
||||
os.remove(file)
|
||||
@@ -0,0 +1,213 @@
|
||||
"""YFinance tools for stock market data.
|
||||
|
||||
Usage:
|
||||
from praisonaiagents.tools import get_stock_price, get_stock_info
|
||||
price = get_stock_price("AAPL")
|
||||
info = get_stock_info("AAPL")
|
||||
|
||||
or
|
||||
from praisonaiagents.tools import yfinance
|
||||
price = yfinance.get_stock_price("AAPL")
|
||||
info = yfinance.get_stock_info("AAPL")
|
||||
"""
|
||||
|
||||
from typing import List, Dict, Optional, Any
|
||||
import logging
|
||||
from importlib import util
|
||||
from datetime import datetime
|
||||
|
||||
class YFinanceTools:
|
||||
"""A comprehensive tool for financial data analysis using yfinance"""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize YFinanceTools"""
|
||||
self._tickers = {}
|
||||
|
||||
def _get_yfinance(self):
|
||||
"""Get yfinance module, installing if needed"""
|
||||
if util.find_spec('yfinance') is None:
|
||||
error_msg = "yfinance package is not available. Please install it using: pip install yfinance"
|
||||
logging.error(error_msg)
|
||||
return None
|
||||
import yfinance as yf
|
||||
return yf
|
||||
|
||||
def _get_ticker(self, symbol: str):
|
||||
"""Get or create ticker instance"""
|
||||
if symbol not in self._tickers:
|
||||
yf = self._get_yfinance()
|
||||
if yf is None:
|
||||
return None
|
||||
self._tickers[symbol] = yf.Ticker(symbol)
|
||||
return self._tickers[symbol]
|
||||
|
||||
def get_stock_price(self, symbol: str) -> Dict[str, float]:
|
||||
"""
|
||||
Get current stock price and related price metrics
|
||||
|
||||
Args:
|
||||
symbol (str): Stock ticker symbol
|
||||
|
||||
Returns:
|
||||
Dict[str, float]: Current price information
|
||||
"""
|
||||
try:
|
||||
ticker = self._get_ticker(symbol)
|
||||
if ticker is None:
|
||||
return {"error": "yfinance package not available"}
|
||||
|
||||
info = ticker.info
|
||||
return {
|
||||
'symbol': symbol,
|
||||
'price': info.get('regularMarketPrice', 0.0),
|
||||
'open': info.get('regularMarketOpen', 0.0),
|
||||
'high': info.get('regularMarketDayHigh', 0.0),
|
||||
'low': info.get('regularMarketDayLow', 0.0),
|
||||
'volume': info.get('regularMarketVolume', 0),
|
||||
'previous_close': info.get('regularMarketPreviousClose', 0.0),
|
||||
'change': info.get('regularMarketChange', 0.0),
|
||||
'change_percent': info.get('regularMarketChangePercent', 0.0)
|
||||
}
|
||||
except Exception as e:
|
||||
error_msg = f"Error getting stock price for {symbol}: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return {"error": error_msg}
|
||||
|
||||
def get_stock_info(self, symbol: str) -> Dict:
|
||||
"""
|
||||
Get detailed information about a stock
|
||||
|
||||
Args:
|
||||
symbol (str): Stock ticker symbol
|
||||
|
||||
Returns:
|
||||
Dict: Stock information including company details and key metrics
|
||||
"""
|
||||
try:
|
||||
ticker = self._get_ticker(symbol)
|
||||
if ticker is None:
|
||||
return {"error": "yfinance package not available"}
|
||||
|
||||
info = ticker.info
|
||||
|
||||
relevant_info = {
|
||||
"longName": info.get("longName"),
|
||||
"symbol": info.get("symbol"),
|
||||
"sector": info.get("sector"),
|
||||
"industry": info.get("industry"),
|
||||
"country": info.get("country"),
|
||||
"marketCap": info.get("marketCap"),
|
||||
"currentPrice": info.get("currentPrice"),
|
||||
"currency": info.get("currency"),
|
||||
"exchange": info.get("exchange"),
|
||||
"fiftyTwoWeekHigh": info.get("fiftyTwoWeekHigh"),
|
||||
"fiftyTwoWeekLow": info.get("fiftyTwoWeekLow"),
|
||||
"trailingPE": info.get("trailingPE"),
|
||||
"forwardPE": info.get("forwardPE"),
|
||||
"dividendYield": info.get("dividendYield"),
|
||||
"beta": info.get("beta"),
|
||||
"volume": info.get("volume"),
|
||||
"averageVolume": info.get("averageVolume"),
|
||||
"sharesOutstanding": info.get("sharesOutstanding"),
|
||||
"website": info.get("website"),
|
||||
"longBusinessSummary": info.get("longBusinessSummary")
|
||||
}
|
||||
return {k: v for k, v in relevant_info.items() if v is not None}
|
||||
except Exception as e:
|
||||
error_msg = f"Error fetching stock info: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return {"error": error_msg}
|
||||
|
||||
def get_historical_data(
|
||||
self,
|
||||
symbol: str,
|
||||
period: str = "1y",
|
||||
interval: str = "1d",
|
||||
start: Optional[datetime] = None,
|
||||
end: Optional[datetime] = None
|
||||
) -> List[Dict[str, Any]]:
|
||||
"""
|
||||
Get historical price data for a stock
|
||||
|
||||
Args:
|
||||
symbol (str): Stock ticker symbol
|
||||
period (str): Data period e.g. 1d, 5d, 1mo, 3mo, 6mo, 1y, 2y, 5y, 10y, ytd, max
|
||||
interval (str): Data interval e.g. 1m, 2m, 5m, 15m, 30m, 60m, 90m, 1h, 1d, 5d, 1wk, 1mo, 3mo
|
||||
start (datetime, optional): Start date for data
|
||||
end (datetime, optional): End date for data
|
||||
|
||||
Returns:
|
||||
List[Dict[str, Any]]: List of historical price data points
|
||||
"""
|
||||
try:
|
||||
ticker = self._get_ticker(symbol)
|
||||
if ticker is None:
|
||||
return [{"error": "yfinance package not available"}]
|
||||
|
||||
hist = ticker.history(period=period, interval=interval, start=start, end=end)
|
||||
return hist.reset_index().to_dict('records')
|
||||
except Exception as e:
|
||||
error_msg = f"Error fetching historical data: {str(e)}"
|
||||
logging.error(error_msg)
|
||||
return [{"error": error_msg}]
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Example usage
|
||||
print("\n==================================================")
|
||||
print("YFinanceTools Demonstration")
|
||||
print("==================================================\n")
|
||||
|
||||
try:
|
||||
yf_tools = YFinanceTools()
|
||||
|
||||
# 1. Basic Stock Information
|
||||
print("1. Basic Stock Information for AAPL")
|
||||
print("------------------------------")
|
||||
info = yf_tools.get_stock_info("AAPL")
|
||||
if "error" not in info:
|
||||
print(f"Company: {info.get('longName')}")
|
||||
print(f"Sector: {info.get('sector')}")
|
||||
print(f"Industry: {info.get('industry')}")
|
||||
print(f"Country: {info.get('country')}\n")
|
||||
else:
|
||||
print(f"Error: {info['error']}\n")
|
||||
|
||||
# 2. Current Price Data
|
||||
print("2. Current Price Data")
|
||||
print("------------------------------")
|
||||
price_data = yf_tools.get_stock_price("AAPL")
|
||||
if "error" not in price_data:
|
||||
print(f"Current Price: ${price_data.get('price', 'N/A')}")
|
||||
print(f"Previous Close: ${price_data.get('previous_close', 'N/A')}")
|
||||
print(f"Day Range: ${price_data.get('low', 'N/A')} - ${price_data.get('high', 'N/A')}\n")
|
||||
else:
|
||||
print(f"Error: {price_data['error']}\n")
|
||||
|
||||
# 3. Historical Data
|
||||
print("3. Historical Data (Last 5 Days)")
|
||||
print("------------------------------")
|
||||
hist_data = yf_tools.get_historical_data("AAPL", period="5d")
|
||||
if not any("error" in d for d in hist_data):
|
||||
for day in hist_data:
|
||||
print(f"Date: {day.get('Date')}, Close: ${day.get('Close', 'N/A'):.2f}")
|
||||
print()
|
||||
else:
|
||||
print(f"{hist_data[0]['error']}\n")
|
||||
|
||||
# 4. Multi-Stock Example
|
||||
print("5. Multi-Stock Current Prices")
|
||||
print("------------------------------")
|
||||
for symbol in ["AAPL", "MSFT", "GOOGL"]:
|
||||
price_data = yf_tools.get_stock_price(symbol)
|
||||
if "error" not in price_data:
|
||||
print(f"{symbol}: ${price_data.get('price', 'N/A')}")
|
||||
else:
|
||||
print(f"{symbol}: Error fetching price")
|
||||
print()
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error: {str(e)}")
|
||||
|
||||
print("==================================================")
|
||||
print("Analysis Complete")
|
||||
print("==================================================")
|
||||
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "praisonaiagents"
|
||||
version = "0.0.22"
|
||||
version = "0.0.25"
|
||||
description = "Praison AI agents for completing complex tasks with Self Reflection Agents"
|
||||
authors = [
|
||||
{ name="Mervin Praison" }
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents, Tools
|
||||
from pydantic import BaseModel
|
||||
|
||||
class AnalysisReport(BaseModel):
|
||||
title: str
|
||||
findings: str
|
||||
summary: str
|
||||
|
||||
# Create a researcher agent
|
||||
researcher = Agent(
|
||||
name="AIResearcher",
|
||||
role="Technology Research Analyst",
|
||||
goal="Analyze and structure information about AI developments",
|
||||
backstory="Expert analyst specializing in AI technology trends",
|
||||
verbose=True,
|
||||
llm="gpt-4o-mini",
|
||||
tools=[Tools.internet_search],
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Create an analyst agent
|
||||
analyst = Agent(
|
||||
name="DataAnalyst",
|
||||
role="Data Insights Specialist",
|
||||
goal="Structure and analyze research findings",
|
||||
backstory="Senior data analyst with expertise in pattern recognition",
|
||||
verbose=True,
|
||||
llm="gpt-4o-mini",
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Define structured tasks
|
||||
research_task = Task(
|
||||
name="gather_research",
|
||||
description="Research recent AI developments in 2024",
|
||||
agent=researcher,
|
||||
expected_output="Research findings"
|
||||
)
|
||||
|
||||
analysis_task = Task(
|
||||
name="analyze_findings",
|
||||
description="Analyze research findings and create structured report. No additional text or explanation.",
|
||||
agent=analyst,
|
||||
output_json=AnalysisReport,
|
||||
expected_output="JSON object"
|
||||
)
|
||||
|
||||
# Initialize and run agents
|
||||
agents = PraisonAIAgents(
|
||||
agents=[researcher, analyst],
|
||||
tasks=[research_task, analysis_task],
|
||||
process="sequential",
|
||||
verbose=True
|
||||
)
|
||||
result = agents.start()
|
||||
print(result)
|
||||
Generated
+2
-2
@@ -186,7 +186,7 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "praisonaiagents"
|
||||
version = "0.0.22"
|
||||
version = "0.0.25"
|
||||
source = { editable = "." }
|
||||
dependencies = [
|
||||
{ name = "openai" },
|
||||
@@ -304,7 +304,7 @@ name = "tqdm"
|
||||
version = "4.67.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "colorama", marker = "platform_system == 'Windows'" },
|
||||
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/a8/4b/29b4ef32e036bb34e4ab51796dd745cdba7ed47ad142a9f4a1eb8e0c744d/tqdm-4.67.1.tar.gz", hash = "sha256:f8aef9c52c08c13a65f30ea34f4e5aac3fd1a34959879d7e59e63027286627f2", size = 169737 }
|
||||
wheels = [
|
||||
|
||||
@@ -110,7 +110,7 @@ Loads environment variables from .env file or system and sets them.</p>
|
||||
file.write("FROM python:3.11-slim\n")
|
||||
file.write("WORKDIR /app\n")
|
||||
file.write("COPY . .\n")
|
||||
file.write("RUN pip install flask praisonai==2.0.31 gunicorn markdown\n")
|
||||
file.write("RUN pip install flask praisonai==2.0.34 gunicorn markdown\n")
|
||||
file.write("EXPOSE 8080\n")
|
||||
file.write('CMD ["gunicorn", "-b", "0.0.0.0:8080", "api:app"]\n')
|
||||
|
||||
|
||||
@@ -0,0 +1,287 @@
|
||||
---
|
||||
title: "Code Execution Agent"
|
||||
sidebarTitle: "Code Agent"
|
||||
description: "Learn how to create AI agents that can write and execute Python code safely using e2b code interpreter."
|
||||
icon: "code"
|
||||
---
|
||||
|
||||
<Note>
|
||||
**Prerequisites**
|
||||
- Python 3.10 or higher
|
||||
- PraisonAI Agents package installed
|
||||
- e2b_code_interpreter package installed
|
||||
- Basic understanding of Python
|
||||
</Note>
|
||||
|
||||
## Quick Start
|
||||
|
||||
Create AI agents that can write and execute Python code in a sandboxed environment!
|
||||
|
||||
<Steps>
|
||||
<Step title="Install Packages">
|
||||
First, install the required packages:
|
||||
```bash
|
||||
pip install praisonaiagents e2b_code_interpreter
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Import Required Components">
|
||||
Import the necessary components:
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from e2b_code_interpreter import Sandbox
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Define Code Interpreter">
|
||||
Create a code interpreter function:
|
||||
```python
|
||||
def code_interpreter(code: str):
|
||||
print(f"\n{'='*50}\n> Running following AI-generated code:\n{code}\n{'='*50}")
|
||||
exec_result = Sandbox().run_code(code)
|
||||
if exec_result.error:
|
||||
print("[Code Interpreter error]", exec_result.error)
|
||||
return {"error": str(exec_result.error)}
|
||||
else:
|
||||
results = []
|
||||
for result in exec_result.results:
|
||||
if hasattr(result, '__iter__'):
|
||||
results.extend(list(result))
|
||||
else:
|
||||
results.append(str(result))
|
||||
logs = {"stdout": list(exec_result.logs.stdout), "stderr": list(exec_result.logs.stderr)}
|
||||
return json.dumps({"results": results, "logs": logs})
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Create Code Agents">
|
||||
Set up your code writing and execution agents:
|
||||
```python
|
||||
code_agent = Agent(
|
||||
name="code_agent",
|
||||
backstory="Expert in writing Python scripts",
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
execution_agent = Agent(
|
||||
name="execution_agent",
|
||||
backstory="Expert in executing Python scripts",
|
||||
self_reflect=False,
|
||||
tools=[code_interpreter]
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Understanding Code Agents
|
||||
|
||||
<Card title="What are Code Agents?" icon="question">
|
||||
Code agents are specialized AI agents that can:
|
||||
- Write Python code based on requirements
|
||||
- Execute code safely in a sandboxed environment
|
||||
- Handle code execution results and errors
|
||||
- Work together in a pipeline (writer → executor)
|
||||
</Card>
|
||||
|
||||
## Key Components
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Code Writer Agent" icon="pencil">
|
||||
Specialized in writing Python code
|
||||
```python
|
||||
Agent(
|
||||
name="code_agent",
|
||||
backstory="Expert in writing Python scripts"
|
||||
)
|
||||
```
|
||||
</Card>
|
||||
<Card title="Code Executor Agent" icon="play">
|
||||
Executes code using sandbox
|
||||
```python
|
||||
Agent(
|
||||
name="execution_agent",
|
||||
tools=[code_interpreter]
|
||||
)
|
||||
```
|
||||
</Card>
|
||||
<Card title="Sandbox Environment" icon="box">
|
||||
Safe code execution environment using e2b
|
||||
</Card>
|
||||
<Card title="Execution Results" icon="output">
|
||||
Structured output with results and logs
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Examples
|
||||
|
||||
### Simple Hello World Example
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from e2b_code_interpreter import Sandbox
|
||||
|
||||
# Create agents
|
||||
code_agent = Agent(
|
||||
name="code_agent",
|
||||
backstory="Expert in writing Python scripts",
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
execution_agent = Agent(
|
||||
name="execution_agent",
|
||||
backstory="Expert in executing Python scripts",
|
||||
self_reflect=False,
|
||||
tools=[code_interpreter]
|
||||
)
|
||||
|
||||
# Define tasks
|
||||
code_task = Task(
|
||||
description="Write a simple Python script to print 'Hello, World!'",
|
||||
expected_output="A Python script that prints 'Hello, World!'",
|
||||
agent=code_agent
|
||||
)
|
||||
|
||||
execution_task = Task(
|
||||
description="Execute the Python script",
|
||||
expected_output="The output of the Python script",
|
||||
agent=execution_agent
|
||||
)
|
||||
|
||||
# Initialize and run agents
|
||||
agents = PraisonAIAgents(
|
||||
agents=[code_agent, execution_agent],
|
||||
tasks=[code_task, execution_task]
|
||||
)
|
||||
result = agents.start()
|
||||
```
|
||||
|
||||
### Advanced Code Generation
|
||||
|
||||
<CodeGroup>
|
||||
```python Data Analysis
|
||||
# Create a data analysis script
|
||||
code_task = Task(
|
||||
description="""
|
||||
Write a Python script that:
|
||||
1. Creates a sample dataset
|
||||
2. Performs basic statistical analysis
|
||||
3. Generates a plot
|
||||
""",
|
||||
agent=code_agent
|
||||
)
|
||||
```
|
||||
|
||||
```python Web Scraping
|
||||
# Create a web scraping script
|
||||
code_task = Task(
|
||||
description="""
|
||||
Write a Python script that:
|
||||
1. Scrapes a website
|
||||
2. Extracts specific data
|
||||
3. Saves to CSV
|
||||
""",
|
||||
agent=code_agent
|
||||
)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
## Best Practices
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Code Safety">
|
||||
Ensure safe code execution:
|
||||
```python
|
||||
# Always use sandbox environment
|
||||
exec_result = Sandbox().run_code(code)
|
||||
|
||||
# Handle errors gracefully
|
||||
if exec_result.error:
|
||||
return {"error": str(exec_result.error)}
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Task Description">
|
||||
Write clear code requirements:
|
||||
```python
|
||||
# Good
|
||||
Task(description="""
|
||||
Write a Python script that:
|
||||
1. Takes user input
|
||||
2. Validates the input
|
||||
3. Processes the data
|
||||
4. Returns formatted output
|
||||
""")
|
||||
|
||||
# Too vague
|
||||
Task(description="Write some Python code")
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Code Generation and Testing
|
||||
```python
|
||||
# Generate code
|
||||
code_task = Task(
|
||||
description="Write a function to calculate fibonacci numbers",
|
||||
agent=code_agent
|
||||
)
|
||||
|
||||
# Generate test cases
|
||||
test_task = Task(
|
||||
description="Write test cases for the fibonacci function",
|
||||
agent=code_agent
|
||||
)
|
||||
|
||||
# Execute tests
|
||||
execution_task = Task(
|
||||
description="Run the test cases",
|
||||
agent=execution_agent
|
||||
)
|
||||
```
|
||||
|
||||
### Interactive Code Development
|
||||
```python
|
||||
# Write initial code
|
||||
initial_code_task = Task(
|
||||
description="Write initial version of the script",
|
||||
agent=code_agent
|
||||
)
|
||||
|
||||
# Test and improve
|
||||
improvement_task = Task(
|
||||
description="Analyze execution results and improve the code",
|
||||
agent=code_agent
|
||||
)
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Execution Errors" icon="triangle-exclamation">
|
||||
Check sandbox execution results:
|
||||
```python
|
||||
if exec_result.error:
|
||||
print("[Error]", exec_result.error)
|
||||
```
|
||||
</Card>
|
||||
<Card title="Code Generation" icon="code">
|
||||
Provide clear requirements and constraints in task description
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Next Steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Advanced Code Generation" icon="graduation-cap" href="./advanced-code">
|
||||
Learn about complex code generation patterns
|
||||
</Card>
|
||||
<Card title="Custom Tools" icon="wrench" href="./custom-tools">
|
||||
Create custom code execution tools
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
<Note>
|
||||
Code execution agents provide a powerful way to generate and run Python code safely. They're perfect for automated code generation, testing, and execution in a controlled environment.
|
||||
</Note>
|
||||
+11
-1
@@ -46,6 +46,16 @@ Create multiple AI agents that can work together in just a few lines of code!
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
<div className="relative w-full aspect-video">
|
||||
<iframe
|
||||
className="absolute top-0 left-0 w-full h-full"
|
||||
src="https://www.youtube.com/embed/OkvYp5aAGSg"
|
||||
title="YouTube video player"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
allowFullScreen
|
||||
></iframe>
|
||||
</div>
|
||||
|
||||
## Understanding Mini AI Agents
|
||||
|
||||
<Card title="What are Mini AI Agents?" icon="question">
|
||||
@@ -245,4 +255,4 @@ agents = Agents(agents=[collector, summarizer, writer])
|
||||
|
||||
<Note>
|
||||
Mini AI Agents are designed to be simple yet powerful. They're perfect for quick prototypes and straightforward automation tasks.
|
||||
</Note>
|
||||
</Note>
|
||||
@@ -0,0 +1,322 @@
|
||||
---
|
||||
title: "Structured AI Agents"
|
||||
description: "Learn how to create AI agents that return structured, type-safe outputs using Pydantic models and JSON."
|
||||
icon: "cube"
|
||||
---
|
||||
|
||||
<Note>
|
||||
**Prerequisites**
|
||||
- Python 3.10 or higher
|
||||
- PraisonAI Agents package installed
|
||||
- Basic understanding of Python and Pydantic
|
||||
</Note>
|
||||
|
||||
## Quick Start
|
||||
|
||||
Create AI agents that return structured, validated outputs in just a few lines of code!
|
||||
|
||||
<Steps>
|
||||
<Step title="Install Package">
|
||||
First, install the PraisonAI Agents package:
|
||||
```bash
|
||||
pip install praisonaiagents
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Import Required Components">
|
||||
Import the necessary components:
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents, Tools
|
||||
from pydantic import BaseModel
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Define Your Data Model">
|
||||
Create a Pydantic model to define your output structure:
|
||||
```python
|
||||
class AnalysisReport(BaseModel):
|
||||
title: str
|
||||
findings: str
|
||||
summary: str
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Create Structured Tasks">
|
||||
Create tasks with structured outputs:
|
||||
```python
|
||||
research_task = Task(
|
||||
description="Research recent AI developments",
|
||||
agent=researcher,
|
||||
expected_output="Research findings"
|
||||
)
|
||||
|
||||
analysis_task = Task(
|
||||
description="Analyze research findings",
|
||||
agent=analyst,
|
||||
output_pydantic=AnalysisReport, # For Pydantic output
|
||||
# or output_json=AnalysisReport # For JSON output
|
||||
expected_output="Structured analysis report"
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Understanding Structured Outputs
|
||||
|
||||
<Card title="What are Structured Outputs?" icon="question">
|
||||
Structured outputs allow you to:
|
||||
- Define exact shape of data using Pydantic models
|
||||
- Get type-safe, validated responses
|
||||
- Choose between Pydantic objects or JSON
|
||||
- Ensure consistent output format across agent responses
|
||||
</Card>
|
||||
|
||||
## Key Components
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Pydantic Models" icon="cube">
|
||||
Define your data structure
|
||||
```python
|
||||
class ResearchReport(BaseModel):
|
||||
title: str
|
||||
content: str
|
||||
```
|
||||
</Card>
|
||||
<Card title="Task Configuration" icon="gear">
|
||||
Configure output format
|
||||
```python
|
||||
Task(output_pydantic=Model)
|
||||
# or
|
||||
Task(output_json=Model)
|
||||
```
|
||||
</Card>
|
||||
<Card title="Output Validation" icon="check">
|
||||
Automatic validation of responses against your model
|
||||
</Card>
|
||||
<Card title="Format Options" icon="code">
|
||||
Choose between Pydantic objects or JSON output
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Output Types
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Pydantic Output" icon="cube">
|
||||
```python
|
||||
task = Task(
|
||||
output_pydantic=AnalysisReport
|
||||
)
|
||||
# Returns Pydantic object
|
||||
```
|
||||
Get type-safe Pydantic model instances
|
||||
</Card>
|
||||
<Card title="JSON Output" icon="brackets-curly">
|
||||
```python
|
||||
task = Task(
|
||||
output_json=AnalysisReport
|
||||
)
|
||||
# Returns JSON dict
|
||||
```
|
||||
Get JSON dictionary matching model schema
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Examples
|
||||
|
||||
### Research Analysis with Structured Output
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents, Tools
|
||||
from pydantic import BaseModel
|
||||
|
||||
# Define output structure
|
||||
class AnalysisReport(BaseModel):
|
||||
title: str
|
||||
findings: str
|
||||
summary: str
|
||||
|
||||
# Create agents
|
||||
researcher = Agent(
|
||||
name="AIResearcher",
|
||||
role="Technology Research Analyst",
|
||||
tools=[Tools.internet_search]
|
||||
)
|
||||
|
||||
analyst = Agent(
|
||||
name="DataAnalyst",
|
||||
role="Data Insights Specialist"
|
||||
)
|
||||
|
||||
# Define structured tasks
|
||||
research_task = Task(
|
||||
name="gather_research",
|
||||
description="Research recent AI developments in 2024",
|
||||
agent=researcher,
|
||||
expected_output="Research findings"
|
||||
)
|
||||
|
||||
analysis_task = Task(
|
||||
name="analyze_findings",
|
||||
description="Analyze research findings and create structured report",
|
||||
agent=analyst,
|
||||
output_pydantic=AnalysisReport,
|
||||
expected_output="Structured analysis report"
|
||||
)
|
||||
|
||||
# Initialize and run agents
|
||||
agents = PraisonAIAgents(
|
||||
agents=[researcher, analyst],
|
||||
tasks=[research_task, analysis_task]
|
||||
)
|
||||
result = agents.start()
|
||||
```
|
||||
|
||||
### Different Output Formats
|
||||
|
||||
<CodeGroup>
|
||||
```python Pydantic
|
||||
# Get Pydantic model instance
|
||||
analysis_task = Task(
|
||||
description="Analyze findings",
|
||||
agent=analyst,
|
||||
output_pydantic=AnalysisReport
|
||||
)
|
||||
|
||||
# Result will be AnalysisReport instance
|
||||
result.pydantic.title
|
||||
result.pydantic.findings
|
||||
result.pydantic.summary
|
||||
```
|
||||
|
||||
```python JSON
|
||||
# Get JSON dictionary
|
||||
analysis_task = Task(
|
||||
description="Analyze findings",
|
||||
agent=analyst,
|
||||
output_json=AnalysisReport
|
||||
)
|
||||
|
||||
# Result will be dictionary
|
||||
result.json_dict['title']
|
||||
result.json_dict['findings']
|
||||
result.json_dict['summary']
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
## Best Practices
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Model Design">
|
||||
Design clear, focused Pydantic models:
|
||||
```python
|
||||
# Good
|
||||
class ResearchReport(BaseModel):
|
||||
title: str
|
||||
findings: str
|
||||
summary: str
|
||||
|
||||
# Too complex
|
||||
class Report(BaseModel):
|
||||
title: str
|
||||
subtitle: Optional[str]
|
||||
findings: List[Dict[str, Any]]
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Output Format Selection">
|
||||
Choose the right output format:
|
||||
```python
|
||||
# Use Pydantic when you need:
|
||||
# - Type validation
|
||||
# - Model methods
|
||||
task = Task(output_pydantic=Model)
|
||||
|
||||
# Use JSON when you need:
|
||||
# - Simple dictionary access
|
||||
# - Serialization
|
||||
task = Task(output_json=Model)
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Research and Structured Analysis
|
||||
```python
|
||||
class ResearchReport(BaseModel):
|
||||
topic: str
|
||||
findings: str
|
||||
sources: list[str]
|
||||
|
||||
class Analysis(BaseModel):
|
||||
key_points: list[str]
|
||||
implications: str
|
||||
recommendations: str
|
||||
|
||||
research_task = Task(
|
||||
description="Research quantum computing",
|
||||
agent=researcher,
|
||||
output_pydantic=ResearchReport
|
||||
)
|
||||
|
||||
analysis_task = Task(
|
||||
description="Analyze research implications",
|
||||
agent=analyst,
|
||||
output_pydantic=Analysis
|
||||
)
|
||||
```
|
||||
|
||||
### Data Collection and Summary
|
||||
```python
|
||||
class DataPoint(BaseModel):
|
||||
timestamp: str
|
||||
value: float
|
||||
source: str
|
||||
|
||||
class Summary(BaseModel):
|
||||
average: float
|
||||
trends: str
|
||||
insights: str
|
||||
|
||||
collection_task = Task(
|
||||
description="Collect data points",
|
||||
output_pydantic=DataPoint
|
||||
)
|
||||
|
||||
summary_task = Task(
|
||||
description="Summarize data",
|
||||
output_pydantic=Summary
|
||||
)
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Validation Errors" icon="triangle-exclamation">
|
||||
Check if your model matches the expected output structure
|
||||
```python
|
||||
# Print model schema
|
||||
print(Model.schema_json())
|
||||
```
|
||||
</Card>
|
||||
<Card title="Output Format" icon="code">
|
||||
Verify you're accessing the right output field:
|
||||
- `result.pydantic` for Pydantic
|
||||
- `result.json_dict` for JSON
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Next Steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Advanced Models" icon="graduation-cap" href="./advanced-models">
|
||||
Learn about advanced Pydantic model configurations
|
||||
</Card>
|
||||
<Card title="Custom Validation" icon="check-double" href="./validation">
|
||||
Add custom validation to your models
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
<Note>
|
||||
Structured outputs make your AI agents more reliable and their responses more predictable. They're perfect for production systems where data consistency is crucial.
|
||||
</Note>
|
||||
+43
-17
@@ -76,6 +76,28 @@
|
||||
"concepts/tools"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Features",
|
||||
"pages": [
|
||||
"features/selfreflection",
|
||||
"features/reasoning",
|
||||
"framework/multimodalagents",
|
||||
"features/async",
|
||||
"features/mini",
|
||||
"features/codeagent",
|
||||
"features/structured",
|
||||
"features/callbacks"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Other Features",
|
||||
"pages": [
|
||||
"train",
|
||||
"framework/crewai",
|
||||
"framework/autogen",
|
||||
"framework/praisonaiagents"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Getting Started (No Code)",
|
||||
"pages": [
|
||||
@@ -96,21 +118,6 @@
|
||||
"ui/realtime"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Features",
|
||||
"pages": [
|
||||
"features/selfreflection",
|
||||
"features/reasoning",
|
||||
"framework/multimodalagents",
|
||||
"features/async",
|
||||
"features/mini",
|
||||
"features/callbacks",
|
||||
"train",
|
||||
"framework/praisonaiagents",
|
||||
"framework/crewai",
|
||||
"framework/autogen"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Models",
|
||||
"pages": [
|
||||
@@ -127,8 +134,25 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Tools (No Code)",
|
||||
"group": "Tools",
|
||||
"pages": [
|
||||
"tools/duckduckgo_tools",
|
||||
"tools/arxiv_tools",
|
||||
"tools/calculator_tools",
|
||||
"tools/csv_tools",
|
||||
"tools/duckdb_tools",
|
||||
"tools/excel_tools",
|
||||
"tools/file_tools",
|
||||
"tools/json_tools",
|
||||
"tools/newspaper_tools",
|
||||
"tools/pandas_tools",
|
||||
"tools/python_tools",
|
||||
"tools/shell_tools",
|
||||
"tools/spider_tools",
|
||||
"tools/wikipedia_tools",
|
||||
"tools/xml_tools",
|
||||
"tools/yaml_tools",
|
||||
"tools/yfinance_tools",
|
||||
"tools",
|
||||
"tools/custom",
|
||||
"tools/gpt",
|
||||
@@ -141,7 +165,9 @@
|
||||
"tools/reddit",
|
||||
"tools/you.com",
|
||||
"tools/crawl4ai",
|
||||
"tools/mem0"
|
||||
"tools/mem0",
|
||||
"tools/composio",
|
||||
"tools/googlecalendar"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -0,0 +1,429 @@
|
||||
---
|
||||
title: "arXiv Tools"
|
||||
description: "Scientific paper search and retrieval tools for AI agents."
|
||||
icon: "book"
|
||||
---
|
||||
|
||||
<Note>
|
||||
**Prerequisites**
|
||||
- Python 3.10 or higher
|
||||
- PraisonAI Agents package installed
|
||||
- `arxiv` package installed
|
||||
</Note>
|
||||
|
||||
## Quick Start
|
||||
|
||||
Use arXiv Tools to search and retrieve scientific papers with AI agents.
|
||||
|
||||
<Steps>
|
||||
<Step title="Install Dependencies">
|
||||
First, install the required packages:
|
||||
```bash
|
||||
pip install praisonaiagents arxiv
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Import Components">
|
||||
Import the necessary components:
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from praisonaiagents.tools import search_arxiv, get_arxiv_paper, get_papers_by_author, get_papers_by_category
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Create Agent">
|
||||
Create a research agent:
|
||||
```python
|
||||
research_agent = Agent(
|
||||
name="ResearchAgent",
|
||||
role="Scientific Literature Specialist",
|
||||
goal="Find and analyze relevant scientific papers.",
|
||||
backstory="Expert in academic research and literature review.",
|
||||
tools=[search_arxiv, get_arxiv_paper, get_papers_by_author, get_papers_by_category],
|
||||
self_reflect=False
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Define Task">
|
||||
Define the research task:
|
||||
```python
|
||||
research_task = Task(
|
||||
description="Search for recent papers on 'quantum machine learning' and summarize key findings.",
|
||||
expected_output="List of relevant papers with summaries.",
|
||||
agent=research_agent,
|
||||
name="quantum_research"
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Run Agent">
|
||||
Initialize and run the agent:
|
||||
```python
|
||||
agents = PraisonAIAgents(
|
||||
agents=[research_agent],
|
||||
tasks=[research_task],
|
||||
process="sequential"
|
||||
)
|
||||
agents.start()
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Understanding arXiv Tools
|
||||
|
||||
<Card title="What are arXiv Tools?" icon="question">
|
||||
arXiv Tools provide scientific paper search capabilities for AI agents:
|
||||
- Paper search functionality
|
||||
- Author-based search
|
||||
- Category filtering
|
||||
- Abstract retrieval
|
||||
- PDF download options
|
||||
</Card>
|
||||
|
||||
## Available Functions
|
||||
|
||||
```python
|
||||
from praisonaiagents.tools import search_arxiv
|
||||
from praisonaiagents.tools import get_arxiv_paper
|
||||
from praisonaiagents.tools import get_papers_by_author
|
||||
from praisonaiagents.tools import get_papers_by_category
|
||||
```
|
||||
|
||||
## Function Details
|
||||
|
||||
### search_arxiv(query: str, max_results: int = 10, sort_by: str = "relevance", sort_order: str = "descending", include_fields: Optional[List[str]] = None)
|
||||
|
||||
Search arXiv for papers:
|
||||
- Flexible query support
|
||||
- Customizable results
|
||||
- Multiple sorting options
|
||||
- Field selection
|
||||
- Error handling
|
||||
|
||||
```python
|
||||
# Basic search
|
||||
papers = search_arxiv("quantum computing")
|
||||
|
||||
# Advanced search
|
||||
papers = search_arxiv(
|
||||
query="quantum computing",
|
||||
max_results=5,
|
||||
sort_by="submittedDate",
|
||||
sort_order="descending",
|
||||
include_fields=["title", "authors", "summary"]
|
||||
)
|
||||
|
||||
# Returns: List[Dict[str, Any]]
|
||||
# Example output:
|
||||
# [
|
||||
# {
|
||||
# "arxiv_id": "2401.00123",
|
||||
# "title": "Quantum Computing: A Survey",
|
||||
# "authors": ["John Doe", "Jane Smith"],
|
||||
# "summary": "This paper reviews...",
|
||||
# "published": "2024-01-01T00:00:00",
|
||||
# "updated": "2024-01-02T00:00:00"
|
||||
# },
|
||||
# ...
|
||||
# ]
|
||||
```
|
||||
|
||||
### get_arxiv_paper(paper_id: str, include_fields: Optional[List[str]] = None)
|
||||
|
||||
Get specific paper details:
|
||||
- Direct ID lookup
|
||||
- Full paper metadata
|
||||
- Customizable fields
|
||||
- PDF/Abstract links
|
||||
|
||||
```python
|
||||
# Get paper by ID
|
||||
paper = get_arxiv_paper("2401.00123")
|
||||
|
||||
# Get specific fields
|
||||
paper = get_arxiv_paper(
|
||||
paper_id="2401.00123",
|
||||
include_fields=["title", "authors", "pdf_url"]
|
||||
)
|
||||
|
||||
# Returns: Dict[str, Any]
|
||||
# Example output:
|
||||
# {
|
||||
# "arxiv_id": "2401.00123",
|
||||
# "title": "Quantum Computing: A Survey",
|
||||
# "authors": ["John Doe", "Jane Smith"],
|
||||
# "pdf_url": "https://arxiv.org/pdf/2401.00123",
|
||||
# "abstract_url": "https://arxiv.org/abs/2401.00123",
|
||||
# "published": "2024-01-01T00:00:00",
|
||||
# "updated": "2024-01-02T00:00:00"
|
||||
# }
|
||||
```
|
||||
|
||||
### get_papers_by_author(author: str, max_results: int = 10, sort_by: str = "submittedDate", sort_order: str = "descending", include_fields: Optional[List[str]] = None)
|
||||
|
||||
Search papers by author:
|
||||
- Author-specific search
|
||||
- Publication timeline
|
||||
- Sort options
|
||||
- Field selection
|
||||
|
||||
```python
|
||||
# Get author's papers
|
||||
papers = get_papers_by_author("Yoshua Bengio")
|
||||
|
||||
# Recent papers first
|
||||
papers = get_papers_by_author(
|
||||
author="Yoshua Bengio",
|
||||
max_results=5,
|
||||
sort_by="submittedDate",
|
||||
sort_order="descending"
|
||||
)
|
||||
|
||||
# Returns: List[Dict[str, Any]]
|
||||
# Example output:
|
||||
# [
|
||||
# {
|
||||
# "arxiv_id": "2401.00124",
|
||||
# "title": "Deep Learning Advances",
|
||||
# "authors": ["Yoshua Bengio", "Other Author"],
|
||||
# "published": "2024-01-01T00:00:00"
|
||||
# },
|
||||
# ...
|
||||
# ]
|
||||
```
|
||||
|
||||
### get_papers_by_category(category: str, max_results: int = 10, sort_by: str = "submittedDate", sort_order: str = "descending", include_fields: Optional[List[str]] = None)
|
||||
|
||||
Search papers by category:
|
||||
- Category-specific search
|
||||
- Latest publications
|
||||
- Sort options
|
||||
- Field selection
|
||||
|
||||
```python
|
||||
# Get papers in category
|
||||
papers = get_papers_by_category("cs.AI")
|
||||
|
||||
# Recent machine learning papers
|
||||
papers = get_papers_by_category(
|
||||
category="cs.LG",
|
||||
max_results=5,
|
||||
sort_by="submittedDate",
|
||||
sort_order="descending"
|
||||
)
|
||||
|
||||
# Returns: List[Dict[str, Any]]
|
||||
# Example output:
|
||||
# [
|
||||
# {
|
||||
# "arxiv_id": "2401.00125",
|
||||
# "title": "New ML Algorithm",
|
||||
# "categories": ["cs.LG", "cs.AI"],
|
||||
# "published": "2024-01-01T00:00:00"
|
||||
# },
|
||||
# ...
|
||||
# ]
|
||||
```
|
||||
|
||||
## Dependencies
|
||||
|
||||
The arXiv tools require the following package:
|
||||
- arxiv: For accessing the arXiv API
|
||||
|
||||
This will be automatically installed when needed.
|
||||
|
||||
## Available Fields
|
||||
|
||||
When using `include_fields`, you can select from:
|
||||
- title: Paper title
|
||||
- authors: List of authors
|
||||
- summary: Abstract text
|
||||
- comment: Author comments
|
||||
- journal_ref: Journal reference
|
||||
- doi: Digital Object Identifier
|
||||
- primary_category: Main arXiv category
|
||||
- categories: All arXiv categories
|
||||
- links: PDF and abstract URLs
|
||||
|
||||
## Common Use Cases
|
||||
|
||||
1. Literature Review:
|
||||
```python
|
||||
# Search multiple related topics
|
||||
topics = ["machine learning", "neural networks", "deep learning"]
|
||||
all_papers = []
|
||||
for topic in topics:
|
||||
papers = search_arxiv(
|
||||
topic,
|
||||
max_results=5,
|
||||
sort_by="relevance"
|
||||
)
|
||||
all_papers.extend(papers)
|
||||
```
|
||||
|
||||
2. Author Research:
|
||||
```python
|
||||
# Get recent papers by multiple authors
|
||||
authors = ["Yoshua Bengio", "Geoffrey Hinton", "Yann LeCun"]
|
||||
author_papers = {}
|
||||
for author in authors:
|
||||
papers = get_papers_by_author(
|
||||
author,
|
||||
max_results=3,
|
||||
sort_by="submittedDate"
|
||||
)
|
||||
author_papers[author] = papers
|
||||
```
|
||||
|
||||
3. Category Monitoring:
|
||||
```python
|
||||
# Monitor new papers in AI categories
|
||||
categories = ["cs.AI", "cs.LG", "cs.CL"]
|
||||
new_papers = {}
|
||||
for category in categories:
|
||||
papers = get_papers_by_category(
|
||||
category,
|
||||
max_results=5,
|
||||
sort_by="submittedDate"
|
||||
)
|
||||
new_papers[category] = papers
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Basic Research Agent
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from praisonaiagents.tools import search_arxiv, get_arxiv_paper, get_papers_by_author, get_papers_by_category
|
||||
|
||||
# Create research agent
|
||||
research_agent = Agent(
|
||||
name="PaperSearcher",
|
||||
role="Scientific Literature Specialist",
|
||||
goal="Find relevant scientific papers on specified topics.",
|
||||
backstory="Expert in academic research and literature analysis.",
|
||||
tools=[search_arxiv, get_arxiv_paper, get_papers_by_author, get_papers_by_category],
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Define research task
|
||||
research_task = Task(
|
||||
description="Search for papers on 'transformer models in NLP' from the last year.",
|
||||
expected_output="List of relevant papers with abstracts and key findings.",
|
||||
agent=research_agent,
|
||||
name="nlp_research"
|
||||
)
|
||||
|
||||
# Run agent
|
||||
agents = PraisonAIAgents(
|
||||
agents=[research_agent],
|
||||
tasks=[research_task],
|
||||
process="sequential"
|
||||
)
|
||||
agents.start()
|
||||
```
|
||||
|
||||
### Advanced Research with Multiple Agents
|
||||
|
||||
```python
|
||||
# Create research agent
|
||||
research_agent = Agent(
|
||||
name="Researcher",
|
||||
role="Literature Specialist",
|
||||
goal="Gather comprehensive scientific literature.",
|
||||
tools=[search_arxiv, get_arxiv_paper, get_papers_by_author, get_papers_by_category],
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Create analysis agent
|
||||
analysis_agent = Agent(
|
||||
name="Analyzer",
|
||||
role="Research Analyst",
|
||||
goal="Analyze and synthesize research findings.",
|
||||
backstory="Expert in scientific literature analysis.",
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Define tasks
|
||||
research_task = Task(
|
||||
description="Search for papers on quantum computing applications in cryptography.",
|
||||
agent=research_agent,
|
||||
name="quantum_research"
|
||||
)
|
||||
|
||||
analysis_task = Task(
|
||||
description="Analyze the papers and identify key trends and breakthroughs.",
|
||||
agent=analysis_agent,
|
||||
name="research_analysis"
|
||||
)
|
||||
|
||||
# Run agents
|
||||
agents = PraisonAIAgents(
|
||||
agents=[research_agent, analysis_agent],
|
||||
tasks=[research_task, analysis_task],
|
||||
process="sequential"
|
||||
)
|
||||
agents.start()
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Agent Configuration">
|
||||
Configure agents with clear research focus:
|
||||
```python
|
||||
Agent(
|
||||
name="Researcher",
|
||||
role="Literature Specialist",
|
||||
goal="Find relevant scientific papers",
|
||||
tools=[search_arxiv, get_arxiv_paper, get_papers_by_author, get_papers_by_category]
|
||||
)
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Task Definition">
|
||||
Define specific research objectives:
|
||||
```python
|
||||
Task(
|
||||
description="Find papers on 'deep learning in healthcare' from top authors",
|
||||
expected_output="Curated list of papers with impact analysis"
|
||||
)
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Literature Review
|
||||
```python
|
||||
# Literature search agent
|
||||
searcher = Agent(
|
||||
name="Searcher",
|
||||
role="Literature Specialist",
|
||||
tools=[search_arxiv, get_arxiv_paper, get_papers_by_author, get_papers_by_category]
|
||||
)
|
||||
|
||||
# Review agent
|
||||
reviewer = Agent(
|
||||
name="Reviewer",
|
||||
role="Research Reviewer"
|
||||
)
|
||||
|
||||
# Define tasks
|
||||
search_task = Task(
|
||||
description="Find papers on AI ethics",
|
||||
agent=searcher
|
||||
)
|
||||
|
||||
review_task = Task(
|
||||
description="Review and summarize findings",
|
||||
agent=reviewer
|
||||
)
|
||||
|
||||
# Run workflow
|
||||
agents = PraisonAIAgents(
|
||||
agents=[searcher, reviewer],
|
||||
tasks=[search_task, review_task]
|
||||
)
|
||||
@@ -0,0 +1,260 @@
|
||||
---
|
||||
title: "Calculator Tools"
|
||||
description: "Tools for performing mathematical calculations, unit conversions, and financial computations."
|
||||
---
|
||||
|
||||
## Available Functions
|
||||
|
||||
```python
|
||||
from praisonaiagents.tools import (
|
||||
evaluate, solve_equation, convert_units,
|
||||
calculate_statistics, calculate_financial
|
||||
)
|
||||
```
|
||||
|
||||
## Function Details
|
||||
|
||||
### evaluate(expression: str, variables: Optional[Dict[str, float]] = None, precision: int = 10)
|
||||
|
||||
Evaluate mathematical expressions:
|
||||
- Basic arithmetic
|
||||
- Mathematical functions
|
||||
- Variable substitution
|
||||
- Precision control
|
||||
- Error handling
|
||||
|
||||
```python
|
||||
# Basic arithmetic
|
||||
result = evaluate("2 + 2 * 3")
|
||||
|
||||
# Complex expressions
|
||||
result = evaluate(
|
||||
"sin(pi/2) + sqrt(16)",
|
||||
precision=5
|
||||
)
|
||||
|
||||
# With variables
|
||||
result = evaluate(
|
||||
"x^2 + y",
|
||||
variables={"x": 3, "y": 4}
|
||||
)
|
||||
|
||||
# Returns: Dict[str, Any]
|
||||
# Example output:
|
||||
# {
|
||||
# "result": 8.0
|
||||
# }
|
||||
# or
|
||||
# {
|
||||
# "error": "Invalid expression"
|
||||
# }
|
||||
```
|
||||
|
||||
### solve_equation(equation: str, variable: str = 'x')
|
||||
|
||||
Solve mathematical equations:
|
||||
- Linear equations
|
||||
- Quadratic equations
|
||||
- Polynomial equations
|
||||
- Real solutions
|
||||
- Error handling
|
||||
|
||||
```python
|
||||
# Linear equation
|
||||
result = solve_equation("2*x + 3 = 7")
|
||||
|
||||
# Quadratic equation
|
||||
result = solve_equation(
|
||||
"x^2 - 5*x + 6 = 0"
|
||||
)
|
||||
|
||||
# Custom variable
|
||||
result = solve_equation(
|
||||
"y^2 = 4",
|
||||
variable='y'
|
||||
)
|
||||
|
||||
# Returns: Dict[str, Any]
|
||||
# Example output:
|
||||
# {
|
||||
# "solutions": [2.0, 3.0]
|
||||
# }
|
||||
# or
|
||||
# {
|
||||
# "error": "No real solutions found"
|
||||
# }
|
||||
```
|
||||
|
||||
### convert_units(value: float, from_unit: str, to_unit: str)
|
||||
|
||||
Convert between units:
|
||||
- Length units
|
||||
- Mass units
|
||||
- Temperature units
|
||||
- Time units
|
||||
- Error handling
|
||||
|
||||
```python
|
||||
# Length conversion
|
||||
result = convert_units(100, "meters", "kilometers")
|
||||
|
||||
# Temperature conversion
|
||||
result = convert_units(32, "fahrenheit", "celsius")
|
||||
|
||||
# Time conversion
|
||||
result = convert_units(
|
||||
2.5,
|
||||
"hours",
|
||||
"minutes"
|
||||
)
|
||||
|
||||
# Returns: Dict[str, Any]
|
||||
# Example output:
|
||||
# {
|
||||
# "result": 0.1 # 100 meters = 0.1 kilometers
|
||||
# }
|
||||
# or
|
||||
# {
|
||||
# "error": "Invalid units"
|
||||
# }
|
||||
```
|
||||
|
||||
### calculate_statistics(numbers: List[float])
|
||||
|
||||
Calculate statistical metrics:
|
||||
- Mean
|
||||
- Median
|
||||
- Standard deviation
|
||||
- Variance
|
||||
- Range
|
||||
- Min/Max values
|
||||
|
||||
```python
|
||||
# Basic statistics
|
||||
result = calculate_statistics([1, 2, 3, 4, 5])
|
||||
|
||||
# Returns: Dict[str, Any]
|
||||
# Example output:
|
||||
# {
|
||||
# "mean": 3.0,
|
||||
# "median": 3.0,
|
||||
# "std_dev": 1.58,
|
||||
# "variance": 2.5,
|
||||
# "min": 1.0,
|
||||
# "max": 5.0,
|
||||
# "range": 4.0,
|
||||
# "count": 5
|
||||
# }
|
||||
```
|
||||
|
||||
### calculate_financial(principal: float, rate: float, time: float, frequency: str = 'yearly')
|
||||
|
||||
Calculate financial metrics:
|
||||
- Compound interest
|
||||
- Simple interest
|
||||
- Interest comparison
|
||||
- Multiple frequencies
|
||||
|
||||
```python
|
||||
# Basic compound interest
|
||||
result = calculate_financial(1000, 5, 2) # $1000, 5%, 2 years
|
||||
|
||||
# Monthly compounding
|
||||
result = calculate_financial(
|
||||
principal=1000,
|
||||
rate=5,
|
||||
time=2,
|
||||
frequency='monthly'
|
||||
)
|
||||
|
||||
# Returns: Dict[str, Any]
|
||||
# Example output:
|
||||
# {
|
||||
# "final_amount": 1102.50,
|
||||
# "compound_interest": 102.50,
|
||||
# "simple_interest": 100.00,
|
||||
# "difference": 2.50
|
||||
# }
|
||||
```
|
||||
|
||||
## Example Agent Configuration
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent
|
||||
from praisonaiagents.tools import (
|
||||
evaluate, solve_equation, convert_units,
|
||||
calculate_statistics, calculate_financial
|
||||
)
|
||||
|
||||
agent = Agent(
|
||||
name="MathAssistant",
|
||||
description="An agent that helps with mathematical calculations",
|
||||
tools=[
|
||||
evaluate, solve_equation, convert_units,
|
||||
calculate_statistics, calculate_financial
|
||||
]
|
||||
)
|
||||
```
|
||||
|
||||
## Dependencies
|
||||
|
||||
The calculator tools require the following packages:
|
||||
- sympy: For equation solving and symbolic mathematics
|
||||
- pint: For unit conversions
|
||||
|
||||
These will be automatically installed when needed.
|
||||
|
||||
## Supported Features
|
||||
|
||||
### Mathematical Functions
|
||||
- Basic: +, -, *, /, ^
|
||||
- Trigonometric: sin, cos, tan
|
||||
- Roots: sqrt
|
||||
- Logarithmic: log, exp
|
||||
- Constants: pi, e
|
||||
|
||||
### Unit Categories
|
||||
- Length: meters, kilometers, miles, etc.
|
||||
- Mass: grams, kilograms, pounds, etc.
|
||||
- Temperature: celsius, fahrenheit, kelvin
|
||||
- Time: seconds, minutes, hours, days
|
||||
- Many more via the pint library
|
||||
|
||||
### Financial Frequencies
|
||||
- yearly
|
||||
- semi-annual
|
||||
- quarterly
|
||||
- monthly
|
||||
- daily
|
||||
|
||||
## Common Use Cases
|
||||
|
||||
1. Scientific Calculations:
|
||||
```python
|
||||
# Complex mathematical expressions
|
||||
gravity = evaluate("9.81 * sin(pi/4)^2")
|
||||
kinetic = evaluate(
|
||||
"0.5 * m * v^2",
|
||||
variables={"m": 10, "v": 5}
|
||||
)
|
||||
```
|
||||
|
||||
2. Unit Conversions:
|
||||
```python
|
||||
# Multiple conversions
|
||||
distances = {
|
||||
"marathon": convert_units(42.195, "kilometers", "miles"),
|
||||
"height": convert_units(180, "centimeters", "feet"),
|
||||
"weight": convert_units(75, "kilograms", "pounds")
|
||||
}
|
||||
```
|
||||
|
||||
3. Investment Analysis:
|
||||
```python
|
||||
# Compare investment strategies
|
||||
investments = {
|
||||
"conservative": calculate_financial(10000, 3, 5, "yearly"),
|
||||
"moderate": calculate_financial(10000, 5, 5, "quarterly"),
|
||||
"aggressive": calculate_financial(10000, 8, 5, "monthly")
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,384 @@
|
||||
---
|
||||
title: "CSV Tools"
|
||||
description: "Tools for working with CSV files in AI agents."
|
||||
icon: "file-csv"
|
||||
---
|
||||
|
||||
<Note>
|
||||
**Prerequisites**
|
||||
- Python 3.10 or higher
|
||||
- PraisonAI Agents package installed
|
||||
- Basic understanding of CSV files
|
||||
</Note>
|
||||
|
||||
## Quick Start
|
||||
|
||||
Use CSV Tools to process and manipulate CSV files with AI agents.
|
||||
|
||||
<Steps>
|
||||
<Step title="Install Dependencies">
|
||||
First, install the required package:
|
||||
```bash
|
||||
pip install praisonaiagents
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Import Components">
|
||||
Import the necessary components:
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from praisonaiagents.tools import csv, read_csv, write_csv, merge_csv
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Create Agent">
|
||||
Create a CSV processing agent:
|
||||
```python
|
||||
csv_agent = Agent(
|
||||
name="CSVProcessor",
|
||||
role="CSV Processing Specialist",
|
||||
goal="Process CSV files efficiently and accurately.",
|
||||
backstory="Expert in CSV file manipulation and analysis.",
|
||||
tools=[csv, read_csv, write_csv, merge_csv],
|
||||
self_reflect=False
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Define Task">
|
||||
Define the CSV processing task:
|
||||
```python
|
||||
csv_task = Task(
|
||||
description="Process and analyze CSV data files.",
|
||||
expected_output="Processed CSV data with analysis.",
|
||||
agent=csv_agent,
|
||||
name="csv_processing"
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Run Agent">
|
||||
Initialize and run the agent:
|
||||
```python
|
||||
agents = PraisonAIAgents(
|
||||
agents=[csv_agent],
|
||||
tasks=[csv_task],
|
||||
process="sequential"
|
||||
)
|
||||
agents.start()
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Understanding CSV Tools
|
||||
|
||||
<Card title="What are CSV Tools?" icon="question">
|
||||
CSV Tools provide CSV processing capabilities for AI agents:
|
||||
- File reading and writing
|
||||
- Data parsing
|
||||
- Column manipulation
|
||||
- Data filtering
|
||||
- Format conversion
|
||||
</Card>
|
||||
|
||||
## Key Components
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="CSV Agent" icon="user-robot">
|
||||
Create specialized CSV agents:
|
||||
```python
|
||||
Agent(tools=[csv, read_csv, write_csv, merge_csv])
|
||||
```
|
||||
</Card>
|
||||
<Card title="CSV Task" icon="list-check">
|
||||
Define CSV tasks:
|
||||
```python
|
||||
Task(description="csv_operation")
|
||||
```
|
||||
</Card>
|
||||
<Card title="Process Types" icon="arrows-split-up-and-left">
|
||||
Sequential or parallel processing:
|
||||
```python
|
||||
process="sequential"
|
||||
```
|
||||
</Card>
|
||||
<Card title="CSV Options" icon="sliders">
|
||||
Customize CSV parameters:
|
||||
```python
|
||||
delimiter=",", header=True
|
||||
```
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Available Functions
|
||||
|
||||
```python
|
||||
from praisonaiagents.tools import read_csv
|
||||
from praisonaiagents.tools import write_csv
|
||||
from praisonaiagents.tools import merge_csv
|
||||
```
|
||||
|
||||
## Function Details
|
||||
|
||||
### read_csv(filepath: str, encoding: str = 'utf-8', delimiter: str = ',', header: Union[int, List[int], None] = 0, usecols: Optional[List[str]] = None, dtype: Optional[Dict[str, str]] = None, parse_dates: Optional[List[str]] = None, na_values: Optional[List[str]] = None, nrows: Optional[int] = None)
|
||||
|
||||
Reads a CSV file with advanced options:
|
||||
- Supports multiple encodings (utf-8, ascii, etc.)
|
||||
- Configurable column delimiter
|
||||
- Flexible header row handling
|
||||
- Column selection and data type specification
|
||||
- Date parsing
|
||||
- Custom NA/NaN value handling
|
||||
- Row limit option
|
||||
|
||||
```python
|
||||
# Basic usage
|
||||
data = read_csv("data.csv")
|
||||
|
||||
# Advanced usage with options
|
||||
data = read_csv(
|
||||
"data.csv",
|
||||
encoding='utf-8',
|
||||
delimiter=',',
|
||||
header=0,
|
||||
usecols=['name', 'age', 'city'],
|
||||
dtype={'age': 'int32'},
|
||||
parse_dates=['birth_date'],
|
||||
na_values=['N/A', 'missing'],
|
||||
nrows=1000
|
||||
)
|
||||
# Returns: List[Dict[str, Any]]
|
||||
# Example: [{"name": "Alice", "age": 25, "city": "New York"}, ...]
|
||||
```
|
||||
|
||||
### write_csv(filepath: str, data: List[Dict[str, Any]], encoding: str = 'utf-8', delimiter: str = ',', index: bool = False, header: bool = True, float_format: Optional[str] = None, date_format: Optional[str] = None, mode: str = 'w')
|
||||
|
||||
Writes data to a CSV file with formatting options:
|
||||
- Supports different encodings
|
||||
- Configurable delimiter
|
||||
- Optional row indices
|
||||
- Optional headers
|
||||
- Custom float and date formatting
|
||||
- Append mode support
|
||||
|
||||
```python
|
||||
# Basic usage
|
||||
data = [
|
||||
{"name": "Alice", "age": 25, "city": "New York"},
|
||||
{"name": "Bob", "age": 30, "city": "San Francisco"}
|
||||
]
|
||||
success = write_csv("output.csv", data)
|
||||
|
||||
# Advanced usage with formatting
|
||||
success = write_csv(
|
||||
"output.csv",
|
||||
data,
|
||||
encoding='utf-8',
|
||||
delimiter=',',
|
||||
index=False,
|
||||
header=True,
|
||||
float_format='%.2f',
|
||||
date_format='%Y-%m-%d',
|
||||
mode='w'
|
||||
)
|
||||
# Returns: bool (True if successful)
|
||||
```
|
||||
|
||||
### merge_csv(files: List[str], output_file: str, how: str = 'inner', on: Optional[Union[str, List[str]]] = None, suffixes: Optional[tuple] = None)
|
||||
|
||||
Merges multiple CSV files with flexible join options:
|
||||
- Supports different join types (inner, outer, left, right)
|
||||
- Merge on single or multiple columns
|
||||
- Custom suffixes for overlapping columns
|
||||
- Automatic handling of column name conflicts
|
||||
|
||||
```python
|
||||
# Merge two files on a common column
|
||||
success = merge_csv(
|
||||
files=["employees.csv", "salaries.csv"],
|
||||
output_file="merged.csv",
|
||||
how='inner',
|
||||
on='employee_id'
|
||||
)
|
||||
|
||||
# Advanced merge with multiple columns and custom suffixes
|
||||
success = merge_csv(
|
||||
files=["data1.csv", "data2.csv", "data3.csv"],
|
||||
output_file="merged.csv",
|
||||
how='outer',
|
||||
on=['id', 'department'],
|
||||
suffixes=('_2022', '_2023')
|
||||
)
|
||||
# Returns: bool (True if successful)
|
||||
```
|
||||
|
||||
## Dependencies
|
||||
|
||||
The CSV tools require the following Python packages:
|
||||
- pandas: For advanced CSV operations and data manipulation
|
||||
|
||||
These will be automatically installed when needed.
|
||||
|
||||
## Example Agent Configuration
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent
|
||||
from praisonaiagents.tools import read_csv, write_csv, merge_csv
|
||||
|
||||
agent = Agent(
|
||||
name="CSVProcessor",
|
||||
description="An agent that processes CSV files",
|
||||
tools=[read_csv, write_csv, merge_csv]
|
||||
)
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
All functions include comprehensive error handling:
|
||||
- File not found errors
|
||||
- Permission errors
|
||||
- Encoding errors
|
||||
- Data format errors
|
||||
- Missing dependency errors
|
||||
|
||||
Errors are logged and returned in a consistent format:
|
||||
- Success cases return the expected data type
|
||||
- Error cases return a dict with an "error" key containing the error message
|
||||
|
||||
## Examples
|
||||
|
||||
### Basic CSV Processing Agent
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from praisonaiagents.tools import read_csv, write_csv, merge_csv
|
||||
|
||||
# Create CSV agent
|
||||
csv_agent = Agent(
|
||||
name="CSVExpert",
|
||||
role="CSV Processing Specialist",
|
||||
goal="Process CSV files efficiently and accurately.",
|
||||
backstory="Expert in data processing and analysis.",
|
||||
tools=[read_csv, write_csv, merge_csv],
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Define CSV task
|
||||
csv_task = Task(
|
||||
description="Process and analyze customer data.",
|
||||
expected_output="Customer analysis report.",
|
||||
agent=csv_agent,
|
||||
name="customer_analysis"
|
||||
)
|
||||
|
||||
# Run agent
|
||||
agents = PraisonAIAgents(
|
||||
agents=[csv_agent],
|
||||
tasks=[csv_task],
|
||||
process="sequential"
|
||||
)
|
||||
agents.start()
|
||||
```
|
||||
|
||||
### Advanced CSV Processing with Multiple Agents
|
||||
|
||||
```python
|
||||
# Create data processing agent
|
||||
processor_agent = Agent(
|
||||
name="Processor",
|
||||
role="Data Processor",
|
||||
goal="Process CSV data systematically.",
|
||||
tools=[read_csv, write_csv, merge_csv],
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Create analysis agent
|
||||
analysis_agent = Agent(
|
||||
name="Analyzer",
|
||||
role="Data Analyst",
|
||||
goal="Analyze processed CSV data.",
|
||||
backstory="Expert in data analysis and reporting.",
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Define tasks
|
||||
processing_task = Task(
|
||||
description="Process customer data files.",
|
||||
agent=processor_agent,
|
||||
name="data_processing"
|
||||
)
|
||||
|
||||
analysis_task = Task(
|
||||
description="Analyze customer trends and patterns.",
|
||||
agent=analysis_agent,
|
||||
name="data_analysis"
|
||||
)
|
||||
|
||||
# Run agents
|
||||
agents = PraisonAIAgents(
|
||||
agents=[processor_agent, analysis_agent],
|
||||
tasks=[processing_task, analysis_task],
|
||||
process="sequential"
|
||||
)
|
||||
agents.start()
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Agent Configuration">
|
||||
Configure agents with clear CSV focus:
|
||||
```python
|
||||
Agent(
|
||||
name="CSVProcessor",
|
||||
role="CSV Processing Specialist",
|
||||
goal="Process CSV files accurately and efficiently",
|
||||
tools=[read_csv, write_csv, merge_csv]
|
||||
)
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Task Definition">
|
||||
Define specific CSV operations:
|
||||
```python
|
||||
Task(
|
||||
description="Process customer data and generate reports",
|
||||
expected_output="Customer analysis report"
|
||||
)
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### CSV Processing Pipeline
|
||||
```python
|
||||
# Processing agent
|
||||
processor = Agent(
|
||||
name="Processor",
|
||||
role="CSV Processor",
|
||||
tools=[read_csv, write_csv, merge_csv]
|
||||
)
|
||||
|
||||
# Analysis agent
|
||||
analyzer = Agent(
|
||||
name="Analyzer",
|
||||
role="Data Analyst"
|
||||
)
|
||||
|
||||
# Define tasks
|
||||
process_task = Task(
|
||||
description="Process CSV files",
|
||||
agent=processor
|
||||
)
|
||||
|
||||
analyze_task = Task(
|
||||
description="Analyze processed data",
|
||||
agent=analyzer
|
||||
)
|
||||
|
||||
# Run workflow
|
||||
agents = PraisonAIAgents(
|
||||
agents=[processor, analyzer],
|
||||
tasks=[process_task, analyze_task]
|
||||
)
|
||||
@@ -0,0 +1,421 @@
|
||||
---
|
||||
title: "DuckDB Tools"
|
||||
description: "Tools for working with DuckDB databases in AI agents."
|
||||
---
|
||||
|
||||
<Note>
|
||||
**Prerequisites**
|
||||
- Python 3.10 or higher
|
||||
- PraisonAI Agents package installed
|
||||
- `duckdb` package installed
|
||||
- Basic understanding of SQL and databases
|
||||
</Note>
|
||||
|
||||
## Quick Start
|
||||
|
||||
Use DuckDB Tools to manage and query databases with AI agents.
|
||||
|
||||
<Steps>
|
||||
<Step title="Install Dependencies">
|
||||
First, install the required packages:
|
||||
```bash
|
||||
pip install praisonaiagents duckdb
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Import Components">
|
||||
Import the necessary components:
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from praisonaiagents.tools import duckdb
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Create Agent">
|
||||
Create a DuckDB database agent:
|
||||
```python
|
||||
db_agent = Agent(
|
||||
name="DBProcessor",
|
||||
role="Database Management Specialist",
|
||||
goal="Manage and query databases efficiently.",
|
||||
backstory="Expert in database operations and SQL.",
|
||||
tools=[duckdb],
|
||||
self_reflect=False
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Define Task">
|
||||
Define the database task:
|
||||
```python
|
||||
db_task = Task(
|
||||
description="Query and analyze database data.",
|
||||
expected_output="Query results and analysis.",
|
||||
agent=db_agent,
|
||||
name="db_analysis"
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Run Agent">
|
||||
Initialize and run the agent:
|
||||
```python
|
||||
agents = PraisonAIAgents(
|
||||
agents=[db_agent],
|
||||
tasks=[db_task],
|
||||
process="sequential"
|
||||
)
|
||||
agents.start()
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Available Functions
|
||||
|
||||
```python
|
||||
from praisonaiagents.tools import execute_query
|
||||
from praisonaiagents.tools import load_csv
|
||||
from praisonaiagents.tools import export_csv
|
||||
```
|
||||
|
||||
## Function Details
|
||||
|
||||
### execute_query(query: str, params: Optional[Union[tuple, dict]] = None, return_df: bool = True)
|
||||
|
||||
Executes SQL queries with advanced features:
|
||||
- Supports parameterized queries
|
||||
- Returns results as DataFrame records or raw tuples
|
||||
- Full SQL query support (SELECT, INSERT, UPDATE, DELETE, etc.)
|
||||
- Automatic connection management
|
||||
|
||||
```python
|
||||
# Basic SELECT query
|
||||
results = execute_query("SELECT * FROM employees")
|
||||
|
||||
# Parameterized query
|
||||
results = execute_query(
|
||||
"SELECT * FROM employees WHERE department = ? AND salary > ?",
|
||||
params=('Engineering', 75000)
|
||||
)
|
||||
|
||||
# Named parameters
|
||||
results = execute_query(
|
||||
"SELECT * FROM employees WHERE department = :dept",
|
||||
params={'dept': 'Engineering'}
|
||||
)
|
||||
# Returns: List[Dict[str, Any]]
|
||||
# Example: [{"id": 1, "name": "Alice", "department": "Engineering"}, ...]
|
||||
```
|
||||
|
||||
### load_csv(table_name: str, filepath: str, schema: Optional[Dict[str, str]] = None, if_exists: str = 'replace')
|
||||
|
||||
Loads CSV files into DuckDB tables:
|
||||
- Optional schema definition
|
||||
- Flexible table existence handling
|
||||
- Automatic type inference
|
||||
- Support for large files
|
||||
|
||||
```python
|
||||
# Basic usage - auto schema inference
|
||||
success = load_csv("employees", "employees.csv")
|
||||
|
||||
# With custom schema
|
||||
schema = {
|
||||
"id": "INTEGER PRIMARY KEY",
|
||||
"name": "VARCHAR",
|
||||
"salary": "DECIMAL(10,2)",
|
||||
"hire_date": "DATE"
|
||||
}
|
||||
success = load_csv(
|
||||
"employees",
|
||||
"employees.csv",
|
||||
schema=schema,
|
||||
if_exists='replace'
|
||||
)
|
||||
# Returns: bool (True if successful)
|
||||
```
|
||||
|
||||
### export_csv(query: str, filepath: str, params: Optional[Union[tuple, dict]] = None)
|
||||
|
||||
Exports query results to CSV files:
|
||||
- Supports parameterized queries
|
||||
- Automatic header generation
|
||||
- Configurable output formatting
|
||||
- Large result set handling
|
||||
|
||||
```python
|
||||
# Export simple query results
|
||||
success = export_csv(
|
||||
"SELECT * FROM employees",
|
||||
"exported_employees.csv"
|
||||
)
|
||||
|
||||
# Export filtered data with parameters
|
||||
success = export_csv(
|
||||
"SELECT * FROM employees WHERE department = ? AND year = ?",
|
||||
"eng_2023.csv",
|
||||
params=('Engineering', 2023)
|
||||
)
|
||||
# Returns: bool (True if successful)
|
||||
```
|
||||
|
||||
## Understanding DuckDB Tools
|
||||
|
||||
<Card title="What are DuckDB Tools?" icon="question">
|
||||
DuckDB Tools provide database capabilities for AI agents:
|
||||
- SQL query execution
|
||||
- Data import/export
|
||||
- Schema management
|
||||
- Data analysis
|
||||
- Performance optimization
|
||||
</Card>
|
||||
|
||||
## Key Components
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="DB Agent" icon="user-robot">
|
||||
Create specialized database agents:
|
||||
```python
|
||||
Agent(tools=[duckdb])
|
||||
```
|
||||
</Card>
|
||||
<Card title="DB Task" icon="list-check">
|
||||
Define database tasks:
|
||||
```python
|
||||
Task(description="db_operation")
|
||||
```
|
||||
</Card>
|
||||
<Card title="Process Types" icon="arrows-split-up-and-left">
|
||||
Sequential or parallel processing:
|
||||
```python
|
||||
process="sequential"
|
||||
```
|
||||
</Card>
|
||||
<Card title="DB Options" icon="sliders">
|
||||
Customize database parameters:
|
||||
```python
|
||||
read_only=True, memory=True
|
||||
```
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Examples
|
||||
|
||||
### Basic Database Agent
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from praisonaiagents.tools import duckdb
|
||||
|
||||
# Create database agent
|
||||
db_agent = Agent(
|
||||
name="DBExpert",
|
||||
role="Database Specialist",
|
||||
goal="Query and analyze data efficiently.",
|
||||
backstory="Expert in database management and SQL.",
|
||||
tools=[duckdb],
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Define database task
|
||||
db_task = Task(
|
||||
description="Analyze sales performance data.",
|
||||
expected_output="Sales analysis report.",
|
||||
agent=db_agent,
|
||||
name="sales_analysis"
|
||||
)
|
||||
|
||||
# Run agent
|
||||
agents = PraisonAIAgents(
|
||||
agents=[db_agent],
|
||||
tasks=[db_task],
|
||||
process="sequential"
|
||||
)
|
||||
agents.start()
|
||||
```
|
||||
|
||||
### Advanced Database Operations with Multiple Agents
|
||||
|
||||
```python
|
||||
# Create query agent
|
||||
query_agent = Agent(
|
||||
name="QueryProcessor",
|
||||
role="SQL Query Specialist",
|
||||
goal="Execute SQL queries efficiently.",
|
||||
tools=[duckdb],
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Create analysis agent
|
||||
analysis_agent = Agent(
|
||||
name="DataAnalyst",
|
||||
role="Data Analyst",
|
||||
goal="Analyze query results and generate insights.",
|
||||
backstory="Expert in data analysis and reporting.",
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Define tasks
|
||||
query_task = Task(
|
||||
description="Execute complex SQL queries.",
|
||||
agent=query_agent,
|
||||
name="query_execution"
|
||||
)
|
||||
|
||||
analysis_task = Task(
|
||||
description="Analyze query results and trends.",
|
||||
agent=analysis_agent,
|
||||
name="result_analysis"
|
||||
)
|
||||
|
||||
# Run agents
|
||||
agents = PraisonAIAgents(
|
||||
agents=[query_agent, analysis_agent],
|
||||
tasks=[query_task, analysis_task],
|
||||
process="sequential"
|
||||
)
|
||||
agents.start()
|
||||
```
|
||||
|
||||
## Dependencies
|
||||
|
||||
The DuckDB tools require the following Python packages:
|
||||
- duckdb: For database operations
|
||||
- pandas: For data manipulation and CSV handling
|
||||
|
||||
These will be automatically installed when needed.
|
||||
|
||||
## Example Agent Configuration
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent
|
||||
from praisonaiagents.tools import execute_query, load_csv, export_csv
|
||||
|
||||
agent = Agent(
|
||||
name="DBProcessor",
|
||||
description="An agent that works with DuckDB databases",
|
||||
tools=[execute_query, load_csv, export_csv]
|
||||
)
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
All functions include comprehensive error handling:
|
||||
- Database connection errors
|
||||
- Query syntax errors
|
||||
- File I/O errors
|
||||
- Schema validation errors
|
||||
- Missing dependency errors
|
||||
|
||||
Errors are logged and returned in a consistent format:
|
||||
- Success cases return the expected data type
|
||||
- Error cases return a dict with an "error" key containing the error message
|
||||
|
||||
## Common Use Cases
|
||||
|
||||
1. Data Analysis:
|
||||
```python
|
||||
# Load data
|
||||
load_csv("sales", "sales_data.csv")
|
||||
|
||||
# Analyze with SQL
|
||||
results = execute_query("""
|
||||
SELECT
|
||||
department,
|
||||
COUNT(*) as count,
|
||||
AVG(salary) as avg_salary
|
||||
FROM employees
|
||||
GROUP BY department
|
||||
HAVING count > 5
|
||||
ORDER BY avg_salary DESC
|
||||
""")
|
||||
```
|
||||
|
||||
2. Data Export:
|
||||
```python
|
||||
# Export filtered and aggregated data
|
||||
export_csv("""
|
||||
SELECT
|
||||
date_trunc('month', date) as month,
|
||||
SUM(amount) as total_sales
|
||||
FROM sales
|
||||
GROUP BY 1
|
||||
ORDER BY 1
|
||||
""", "monthly_sales.csv")
|
||||
```
|
||||
|
||||
3. Data Transformation:
|
||||
```python
|
||||
# Load and transform data
|
||||
load_csv("raw_data", "input.csv")
|
||||
execute_query("""
|
||||
CREATE TABLE transformed AS
|
||||
SELECT
|
||||
id,
|
||||
UPPER(name) as name,
|
||||
ROUND(amount, 2) as amount,
|
||||
DATE_TRUNC('day', timestamp) as date
|
||||
FROM raw_data
|
||||
""")
|
||||
export_csv("SELECT * FROM transformed", "transformed.csv")
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Agent Configuration">
|
||||
Configure agents with clear database focus:
|
||||
```python
|
||||
Agent(
|
||||
name="DBProcessor",
|
||||
role="Database Specialist",
|
||||
goal="Process queries accurately and efficiently",
|
||||
tools=[duckdb]
|
||||
)
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Task Definition">
|
||||
Define specific database operations:
|
||||
```python
|
||||
Task(
|
||||
description="Query sales data and generate reports",
|
||||
expected_output="Sales performance report"
|
||||
)
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Database Operation Pipeline
|
||||
```python
|
||||
# Query agent
|
||||
querier = Agent(
|
||||
name="Querier",
|
||||
role="SQL Specialist",
|
||||
tools=[duckdb]
|
||||
)
|
||||
|
||||
# Analysis agent
|
||||
analyzer = Agent(
|
||||
name="Analyzer",
|
||||
role="Data Analyst"
|
||||
)
|
||||
|
||||
# Define tasks
|
||||
query_task = Task(
|
||||
description="Execute SQL queries",
|
||||
agent=querier
|
||||
)
|
||||
|
||||
analyze_task = Task(
|
||||
description="Analyze query results",
|
||||
agent=analyzer
|
||||
)
|
||||
|
||||
# Run workflow
|
||||
agents = PraisonAIAgents(
|
||||
agents=[querier, analyzer],
|
||||
tasks=[query_task, analyze_task]
|
||||
)
|
||||
@@ -0,0 +1,248 @@
|
||||
---
|
||||
title: "DuckDuckGo Tools"
|
||||
description: "Internet search tools using DuckDuckGo for AI agents."
|
||||
icon: "magnifying-glass"
|
||||
---
|
||||
|
||||
<Note>
|
||||
**Prerequisites**
|
||||
- Python 3.10 or higher
|
||||
- PraisonAI Agents package installed
|
||||
- `duckduckgo-search` package installed
|
||||
</Note>
|
||||
|
||||
## Quick Start
|
||||
|
||||
Use DuckDuckGo Tools to perform internet searches with AI agents.
|
||||
|
||||
<Steps>
|
||||
<Step title="Install Dependencies">
|
||||
First, install the required packages:
|
||||
```bash
|
||||
pip install praisonaiagents duckduckgo-search
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Import Components">
|
||||
Import the necessary components:
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from praisonaiagents.tools import duckduckgo
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Create Agent">
|
||||
Create a search agent:
|
||||
```python
|
||||
search_agent = Agent(
|
||||
name="SearchAgent",
|
||||
role="Internet Search Specialist",
|
||||
goal="Perform accurate internet searches and extract relevant information.",
|
||||
backstory="Expert in finding and organizing internet data.",
|
||||
tools=[duckduckgo],
|
||||
self_reflect=False
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Define Task">
|
||||
Define the search task:
|
||||
```python
|
||||
search_task = Task(
|
||||
description="Search for 'AI trends 2024' and analyze the results.",
|
||||
expected_output="List of key AI trends with sources.",
|
||||
agent=search_agent,
|
||||
name="search_trends"
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Run Agent">
|
||||
Initialize and run the agent:
|
||||
```python
|
||||
agents = PraisonAIAgents(
|
||||
agents=[search_agent],
|
||||
tasks=[search_task],
|
||||
process="sequential"
|
||||
)
|
||||
agents.start()
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Understanding DuckDuckGo Tools
|
||||
|
||||
<Card title="What are DuckDuckGo Tools?" icon="question">
|
||||
DuckDuckGo Tools provide internet search capabilities for AI agents:
|
||||
- Web search functionality
|
||||
- News search
|
||||
- Privacy-focused results
|
||||
- Region-specific searches
|
||||
</Card>
|
||||
|
||||
## Key Components
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Search Agent" icon="user-robot">
|
||||
Create specialized search agents:
|
||||
```python
|
||||
Agent(tools=[duckduckgo])
|
||||
```
|
||||
</Card>
|
||||
<Card title="Search Task" icon="list-check">
|
||||
Define search tasks:
|
||||
```python
|
||||
Task(description="search_query")
|
||||
```
|
||||
</Card>
|
||||
<Card title="Process Types" icon="arrows-split-up-and-left">
|
||||
Sequential or parallel processing:
|
||||
```python
|
||||
process="sequential"
|
||||
```
|
||||
</Card>
|
||||
<Card title="Search Options" icon="sliders">
|
||||
Customize search parameters:
|
||||
```python
|
||||
region="wt-wt", time="w"
|
||||
```
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Examples
|
||||
|
||||
### Basic Search Agent
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from praisonaiagents.tools import duckduckgo
|
||||
|
||||
# Create search agent
|
||||
search_agent = Agent(
|
||||
name="WebSearcher",
|
||||
role="Search Specialist",
|
||||
goal="Find accurate information about specified topics.",
|
||||
backstory="Expert in internet research and data collection.",
|
||||
tools=[duckduckgo],
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Define search task
|
||||
search_task = Task(
|
||||
description="Search for 'Python programming best practices 2024' and summarize the key points.",
|
||||
expected_output="List of best practices with sources.",
|
||||
agent=search_agent,
|
||||
name="search_python"
|
||||
)
|
||||
|
||||
# Run agent
|
||||
agents = PraisonAIAgents(
|
||||
agents=[search_agent],
|
||||
tasks=[search_task],
|
||||
process="sequential"
|
||||
)
|
||||
agents.start()
|
||||
```
|
||||
|
||||
### Advanced Search with Multiple Agents
|
||||
|
||||
```python
|
||||
# Create search agent
|
||||
search_agent = Agent(
|
||||
name="Researcher",
|
||||
role="Search Specialist",
|
||||
goal="Gather comprehensive information about topics.",
|
||||
tools=[duckduckgo],
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Create analysis agent
|
||||
analysis_agent = Agent(
|
||||
name="Analyzer",
|
||||
role="Data Analyst",
|
||||
goal="Analyze and synthesize search results.",
|
||||
backstory="Expert in data analysis and trend identification.",
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Define tasks
|
||||
search_task = Task(
|
||||
description="Search for latest AI developments in healthcare.",
|
||||
agent=search_agent,
|
||||
name="healthcare_search"
|
||||
)
|
||||
|
||||
analysis_task = Task(
|
||||
description="Analyze the search results and identify key trends.",
|
||||
agent=analysis_agent,
|
||||
name="trend_analysis"
|
||||
)
|
||||
|
||||
# Run agents
|
||||
agents = PraisonAIAgents(
|
||||
agents=[search_agent, analysis_agent],
|
||||
tasks=[search_task, analysis_task],
|
||||
process="sequential"
|
||||
)
|
||||
agents.start()
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Agent Configuration">
|
||||
Configure agents with clear roles and goals:
|
||||
```python
|
||||
Agent(
|
||||
name="Researcher",
|
||||
role="Search Specialist",
|
||||
goal="Find accurate and relevant information",
|
||||
tools=[duckduckgo]
|
||||
)
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Task Definition">
|
||||
Define specific and clear tasks:
|
||||
```python
|
||||
Task(
|
||||
description="Search for 'AI ethics guidelines 2024' and summarize key points",
|
||||
expected_output="Structured list of guidelines with sources"
|
||||
)
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Research and Analysis
|
||||
```python
|
||||
# Research agent
|
||||
researcher = Agent(
|
||||
name="Researcher",
|
||||
role="Search Specialist",
|
||||
tools=[duckduckgo]
|
||||
)
|
||||
|
||||
# Analysis agent
|
||||
analyst = Agent(
|
||||
name="Analyst",
|
||||
role="Information Analyst"
|
||||
)
|
||||
|
||||
# Define tasks
|
||||
research_task = Task(
|
||||
description="Research quantum computing advances",
|
||||
agent=researcher
|
||||
)
|
||||
|
||||
analysis_task = Task(
|
||||
description="Analyze research findings",
|
||||
agent=analyst
|
||||
)
|
||||
|
||||
# Run workflow
|
||||
agents = PraisonAIAgents(
|
||||
agents=[researcher, analyst],
|
||||
tasks=[research_task, analysis_task]
|
||||
)
|
||||
@@ -0,0 +1,440 @@
|
||||
---
|
||||
title: "Excel Tools"
|
||||
description: "Tools for working with Excel files in AI agents."
|
||||
---
|
||||
|
||||
<Note>
|
||||
**Prerequisites**
|
||||
- Python 3.10 or higher
|
||||
- PraisonAI Agents package installed
|
||||
- `openpyxl` package installed
|
||||
- Basic understanding of Excel files
|
||||
</Note>
|
||||
|
||||
## Quick Start
|
||||
|
||||
Use Excel Tools to process and manipulate Excel files with AI agents.
|
||||
|
||||
<Steps>
|
||||
<Step title="Install Dependencies">
|
||||
First, install the required packages:
|
||||
```bash
|
||||
pip install praisonaiagents openpyxl
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Import Components">
|
||||
Import the necessary components:
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from praisonaiagents.tools import read_excel, write_excel, merge_excel
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Create Agent">
|
||||
Create an Excel processing agent:
|
||||
```python
|
||||
excel_agent = Agent(
|
||||
name="ExcelProcessor",
|
||||
role="Excel Processing Specialist",
|
||||
goal="Process Excel files efficiently and accurately.",
|
||||
backstory="Expert in Excel file manipulation and analysis.",
|
||||
tools=[read_excel, write_excel, merge_excel],
|
||||
self_reflect=False
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Define Task">
|
||||
Define the Excel processing task:
|
||||
```python
|
||||
excel_task = Task(
|
||||
description="Process and analyze Excel spreadsheets.",
|
||||
expected_output="Processed Excel data with analysis.",
|
||||
agent=excel_agent,
|
||||
name="excel_processing"
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Run Agent">
|
||||
Initialize and run the agent:
|
||||
```python
|
||||
agents = PraisonAIAgents(
|
||||
agents=[excel_agent],
|
||||
tasks=[excel_task],
|
||||
process="sequential"
|
||||
)
|
||||
agents.start()
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Available Functions
|
||||
|
||||
```python
|
||||
from praisonaiagents.tools import read_excel
|
||||
from praisonaiagents.tools import write_excel
|
||||
from praisonaiagents.tools import merge_excel
|
||||
```
|
||||
|
||||
## Function Details
|
||||
|
||||
### read_excel(filepath: str, sheet_name: Optional[Union[str, int, List[Union[str, int]]]] = 0, header: Optional[int] = 0, usecols: Optional[List[str]] = None, skiprows: Optional[Union[int, List[int]]] = None, na_values: Optional[List[str]] = None, dtype: Optional[Dict[str, str]] = None)
|
||||
|
||||
Reads Excel files with advanced options:
|
||||
- Support for multiple sheets
|
||||
- Flexible header handling
|
||||
- Column selection
|
||||
- Row skipping
|
||||
- Custom NA values
|
||||
- Data type specification
|
||||
|
||||
```python
|
||||
# Basic usage - read first sheet
|
||||
data = read_excel("data.xlsx")
|
||||
|
||||
# Read specific sheets
|
||||
data = read_excel(
|
||||
"data.xlsx",
|
||||
sheet_name=['Sheet1', 'Sheet2'],
|
||||
header=0,
|
||||
usecols=['A', 'B', 'C'],
|
||||
skiprows=[0, 1],
|
||||
na_values=['NA', 'missing'],
|
||||
dtype={'age': 'int32', 'salary': 'float64'}
|
||||
)
|
||||
# Returns: Dict[str, List[Dict[str, Any]]] for multiple sheets
|
||||
# Example: {
|
||||
# 'Sheet1': [{"name": "Alice", "age": 25}, ...],
|
||||
# 'Sheet2': [{"dept": "Engineering", "count": 10}, ...]
|
||||
# }
|
||||
```
|
||||
|
||||
### write_excel(filepath: str, data: Union[Dict[str, List[Dict[str, Any]]], List[Dict[str, Any]]], sheet_name: Optional[str] = None, index: bool = False, header: bool = True, mode: str = 'w')
|
||||
|
||||
Writes data to Excel files with formatting:
|
||||
- Multiple sheet support
|
||||
- Append mode for existing files
|
||||
- Optional row indices
|
||||
- Optional headers
|
||||
- Flexible data structure handling
|
||||
|
||||
```python
|
||||
# Write single sheet
|
||||
data = [
|
||||
{"name": "Alice", "age": 25, "city": "New York"},
|
||||
{"name": "Bob", "age": 30, "city": "San Francisco"}
|
||||
]
|
||||
success = write_excel("output.xlsx", data, sheet_name="Employees")
|
||||
|
||||
# Write multiple sheets
|
||||
data = {
|
||||
"Employees": [
|
||||
{"name": "Alice", "age": 25},
|
||||
{"name": "Bob", "age": 30}
|
||||
],
|
||||
"Departments": [
|
||||
{"name": "Engineering", "count": 50},
|
||||
{"name": "Sales", "count": 30}
|
||||
]
|
||||
}
|
||||
success = write_excel(
|
||||
"company.xlsx",
|
||||
data,
|
||||
index=False,
|
||||
header=True,
|
||||
mode='w'
|
||||
)
|
||||
# Returns: bool (True if successful)
|
||||
```
|
||||
|
||||
### merge_excel(files: List[str], output_file: str, how: str = 'inner', on: Optional[Union[str, List[str]]] = None, suffixes: Optional[Tuple[str, str]] = None)
|
||||
|
||||
Merges multiple Excel files:
|
||||
- Flexible join operations
|
||||
- Multiple key columns support
|
||||
- Custom column suffix handling
|
||||
- Preserves data types
|
||||
|
||||
```python
|
||||
# Merge two files on a common column
|
||||
success = merge_excel(
|
||||
files=["employees.xlsx", "salaries.xlsx"],
|
||||
output_file="merged.xlsx",
|
||||
how='inner',
|
||||
on='employee_id'
|
||||
)
|
||||
|
||||
# Advanced merge with multiple keys and custom suffixes
|
||||
success = merge_excel(
|
||||
files=["data2022.xlsx", "data2023.xlsx"],
|
||||
output_file="combined.xlsx",
|
||||
how='outer',
|
||||
on=['id', 'department'],
|
||||
suffixes=('_2022', '_2023')
|
||||
)
|
||||
# Returns: bool (True if successful)
|
||||
```
|
||||
|
||||
## Understanding Excel Tools
|
||||
|
||||
<Card title="What are Excel Tools?" icon="question">
|
||||
Excel Tools provide Excel processing capabilities for AI agents:
|
||||
- File reading and writing
|
||||
- Data extraction
|
||||
- Sheet manipulation
|
||||
- Formula handling
|
||||
- Data analysis
|
||||
</Card>
|
||||
|
||||
## Key Components
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Excel Agent" icon="user-robot">
|
||||
Create specialized Excel agents:
|
||||
```python
|
||||
Agent(tools=[excel, read_excel, write_excel, merge_excel])
|
||||
```
|
||||
</Card>
|
||||
<Card title="Excel Task" icon="list-check">
|
||||
Define Excel tasks:
|
||||
```python
|
||||
Task(description="excel_operation")
|
||||
```
|
||||
</Card>
|
||||
<Card title="Process Types" icon="arrows-split-up-and-left">
|
||||
Sequential or parallel processing:
|
||||
```python
|
||||
process="sequential"
|
||||
```
|
||||
</Card>
|
||||
<Card title="Excel Options" icon="sliders">
|
||||
Customize Excel parameters:
|
||||
```python
|
||||
sheet_name="Sheet1", header=0
|
||||
```
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Examples
|
||||
|
||||
### Basic Excel Processing Agent
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from praisonaiagents.tools import excel, read_excel, write_excel, merge_excel
|
||||
|
||||
# Create Excel agent
|
||||
excel_agent = Agent(
|
||||
name="ExcelExpert",
|
||||
role="Excel Processing Specialist",
|
||||
goal="Process Excel files efficiently and accurately.",
|
||||
backstory="Expert in spreadsheet manipulation and analysis.",
|
||||
tools=[excel, read_excel, write_excel, merge_excel],
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Define Excel task
|
||||
excel_task = Task(
|
||||
description="Process and analyze sales data.",
|
||||
expected_output="Sales analysis report.",
|
||||
agent=excel_agent,
|
||||
name="sales_analysis"
|
||||
)
|
||||
|
||||
# Run agent
|
||||
agents = PraisonAIAgents(
|
||||
agents=[excel_agent],
|
||||
tasks=[excel_task],
|
||||
process="sequential"
|
||||
)
|
||||
agents.start()
|
||||
```
|
||||
|
||||
### Advanced Excel Processing with Multiple Agents
|
||||
|
||||
```python
|
||||
# Create data processing agent
|
||||
processor_agent = Agent(
|
||||
name="Processor",
|
||||
role="Data Processor",
|
||||
goal="Process Excel data systematically.",
|
||||
tools=[excel, read_excel, write_excel, merge_excel],
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Create analysis agent
|
||||
analysis_agent = Agent(
|
||||
name="Analyzer",
|
||||
role="Data Analyst",
|
||||
goal="Analyze processed Excel data.",
|
||||
backstory="Expert in data analysis and reporting.",
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Define tasks
|
||||
processing_task = Task(
|
||||
description="Process sales spreadsheets.",
|
||||
agent=processor_agent,
|
||||
name="data_processing"
|
||||
)
|
||||
|
||||
analysis_task = Task(
|
||||
description="Analyze sales trends and patterns.",
|
||||
agent=analysis_agent,
|
||||
name="data_analysis"
|
||||
)
|
||||
|
||||
# Run agents
|
||||
agents = PraisonAIAgents(
|
||||
agents=[processor_agent, analysis_agent],
|
||||
tasks=[processing_task, analysis_task],
|
||||
process="sequential"
|
||||
)
|
||||
agents.start()
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Agent Configuration">
|
||||
Configure agents with clear Excel focus:
|
||||
```python
|
||||
Agent(
|
||||
name="ExcelProcessor",
|
||||
role="Excel Processing Specialist",
|
||||
goal="Process Excel files accurately and efficiently",
|
||||
tools=[excel, read_excel, write_excel, merge_excel]
|
||||
)
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Task Definition">
|
||||
Define specific Excel operations:
|
||||
```python
|
||||
Task(
|
||||
description="Process sales data and generate reports",
|
||||
expected_output="Sales analysis report"
|
||||
)
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Excel Processing Pipeline
|
||||
```python
|
||||
# Processing agent
|
||||
processor = Agent(
|
||||
name="Processor",
|
||||
role="Excel Processor",
|
||||
tools=[excel, read_excel, write_excel, merge_excel]
|
||||
)
|
||||
|
||||
# Analysis agent
|
||||
analyzer = Agent(
|
||||
name="Analyzer",
|
||||
role="Data Analyst"
|
||||
)
|
||||
|
||||
# Define tasks
|
||||
process_task = Task(
|
||||
description="Process Excel files",
|
||||
agent=processor
|
||||
)
|
||||
|
||||
analyze_task = Task(
|
||||
description="Analyze processed data",
|
||||
agent=analyzer
|
||||
)
|
||||
|
||||
# Run workflow
|
||||
agents = PraisonAIAgents(
|
||||
agents=[processor, analyzer],
|
||||
tasks=[process_task, analyze_task]
|
||||
)
|
||||
|
||||
```
|
||||
|
||||
## Dependencies
|
||||
|
||||
The Excel tools require the following Python packages:
|
||||
- pandas: For data manipulation
|
||||
- openpyxl: For Excel file operations
|
||||
|
||||
These will be automatically installed when needed.
|
||||
|
||||
## Example Agent Configuration
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent
|
||||
from praisonaiagents.tools import read_excel, write_excel, merge_excel
|
||||
|
||||
agent = Agent(
|
||||
name="ExcelProcessor",
|
||||
description="An agent that processes Excel files",
|
||||
tools=[read_excel, write_excel, merge_excel]
|
||||
)
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
All functions include comprehensive error handling:
|
||||
- File not found errors
|
||||
- Permission errors
|
||||
- Invalid sheet names
|
||||
- Data format errors
|
||||
- Missing dependency errors
|
||||
|
||||
Errors are logged and returned in a consistent format:
|
||||
- Success cases return the expected data type
|
||||
- Error cases return a dict with an "error" key containing the error message
|
||||
|
||||
## Common Use Cases
|
||||
|
||||
1. Data Analysis:
|
||||
```python
|
||||
# Read and analyze employee data
|
||||
data = read_excel(
|
||||
"employees.xlsx",
|
||||
sheet_name="Salaries",
|
||||
usecols=["department", "salary"]
|
||||
)
|
||||
|
||||
# Write summary to new sheet
|
||||
summary = [
|
||||
{"department": dept, "avg_salary": sum(d["salary"] for d in dept_data) / len(dept_data)}
|
||||
for dept, dept_data in groupby(data, key=lambda x: x["department"])
|
||||
]
|
||||
write_excel("summary.xlsx", summary, sheet_name="Salary Summary")
|
||||
```
|
||||
|
||||
2. Data Consolidation:
|
||||
```python
|
||||
# Merge monthly reports
|
||||
monthly_files = ["jan.xlsx", "feb.xlsx", "mar.xlsx"]
|
||||
merge_excel(
|
||||
files=monthly_files,
|
||||
output_file="q1_report.xlsx",
|
||||
how='outer',
|
||||
on='transaction_id'
|
||||
)
|
||||
```
|
||||
|
||||
3. Multi-sheet Processing:
|
||||
```python
|
||||
# Read multiple sheets
|
||||
data = read_excel(
|
||||
"company_data.xlsx",
|
||||
sheet_name=None # Read all sheets
|
||||
)
|
||||
|
||||
# Process each sheet
|
||||
processed = {
|
||||
sheet: [process_record(record) for record in records]
|
||||
for sheet, records in data.items()
|
||||
}
|
||||
|
||||
# Write back to new file
|
||||
write_excel("processed_data.xlsx", processed)
|
||||
@@ -0,0 +1,469 @@
|
||||
---
|
||||
title: "File Tools"
|
||||
description: "Basic file operation tools for AI agents."
|
||||
---
|
||||
|
||||
<Note>
|
||||
**Prerequisites**
|
||||
- Python 3.10 or higher
|
||||
- PraisonAI Agents package installed
|
||||
- Basic understanding of file operations
|
||||
</Note>
|
||||
|
||||
## Quick Start
|
||||
|
||||
Use File Tools to manage files and directories with AI agents.
|
||||
|
||||
<Steps>
|
||||
<Step title="Install Dependencies">
|
||||
First, install the required package:
|
||||
```bash
|
||||
pip install praisonaiagents
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Import Components">
|
||||
Import the necessary components:
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from praisonaiagents.tools import file_tools
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Create Agent">
|
||||
Create a file management agent:
|
||||
```python
|
||||
file_agent = Agent(
|
||||
name="FileManager",
|
||||
role="File System Specialist",
|
||||
goal="Manage files and directories efficiently.",
|
||||
backstory="Expert in file system operations and organization.",
|
||||
tools=[file_tools],
|
||||
self_reflect=False
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Define Task">
|
||||
Define the file management task:
|
||||
```python
|
||||
file_task = Task(
|
||||
description="Organize files in the downloads directory by file type.",
|
||||
expected_output="Organized directory structure with categorized files.",
|
||||
agent=file_agent,
|
||||
name="organize_files"
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Run Agent">
|
||||
Initialize and run the agent:
|
||||
```python
|
||||
agents = PraisonAIAgents(
|
||||
agents=[file_agent],
|
||||
tasks=[file_task],
|
||||
process="sequential"
|
||||
)
|
||||
agents.start()
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Understanding File Tools
|
||||
|
||||
<Card title="What are File Tools?" icon="question">
|
||||
File Tools provide file system management capabilities for AI agents:
|
||||
- File operations (read, write, copy, move)
|
||||
- Directory management
|
||||
- File information retrieval
|
||||
- File organization
|
||||
- Path manipulation
|
||||
</Card>
|
||||
|
||||
## Key Components
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="File Agent" icon="user-robot">
|
||||
Create specialized file agents:
|
||||
```python
|
||||
Agent(tools=[file_tools])
|
||||
```
|
||||
</Card>
|
||||
<Card title="File Task" icon="list-check">
|
||||
Define file tasks:
|
||||
```python
|
||||
Task(description="file_operation")
|
||||
```
|
||||
</Card>
|
||||
<Card title="Process Types" icon="arrows-split-up-and-left">
|
||||
Sequential or parallel processing:
|
||||
```python
|
||||
process="sequential"
|
||||
```
|
||||
</Card>
|
||||
<Card title="File Options" icon="sliders">
|
||||
Customize file operations:
|
||||
```python
|
||||
recursive=True, overwrite=False
|
||||
```
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Available Functions
|
||||
|
||||
```python
|
||||
from praisonaiagents.tools import read_file
|
||||
from praisonaiagents.tools import write_file
|
||||
from praisonaiagents.tools import list_files
|
||||
from praisonaiagents.tools import get_file_info
|
||||
from praisonaiagents.tools import copy_file
|
||||
from praisonaiagents.tools import move_file
|
||||
from praisonaiagents.tools import delete_file
|
||||
```
|
||||
|
||||
## Function Details
|
||||
|
||||
### read_file(filepath: str, encoding: str = 'utf-8')
|
||||
|
||||
Reads content from a file:
|
||||
- Supports different encodings
|
||||
- Error handling for missing files
|
||||
- Automatic encoding detection
|
||||
|
||||
```python
|
||||
# Basic usage
|
||||
content = read_file("example.txt")
|
||||
|
||||
# With specific encoding
|
||||
content = read_file("data.txt", encoding="latin-1")
|
||||
|
||||
# Returns: str (file content)
|
||||
# Error case: Returns error message as string
|
||||
```
|
||||
|
||||
### write_file(filepath: str, content: str, encoding: str = 'utf-8')
|
||||
|
||||
Writes content to a file:
|
||||
- Creates directories if they don't exist
|
||||
- Supports different encodings
|
||||
- Overwrites existing files
|
||||
|
||||
```python
|
||||
# Basic usage
|
||||
success = write_file("output.txt", "Hello World")
|
||||
|
||||
# With specific encoding and nested path
|
||||
success = write_file(
|
||||
"path/to/data/output.txt",
|
||||
"Content with special chars: áéíóú",
|
||||
encoding="utf-8"
|
||||
)
|
||||
# Returns: bool (True if successful)
|
||||
```
|
||||
|
||||
### list_files(directory: str, pattern: Optional[str] = None)
|
||||
|
||||
Lists files in a directory:
|
||||
- Optional pattern matching
|
||||
- Detailed file information
|
||||
- Recursive directory support
|
||||
|
||||
```python
|
||||
# List all files
|
||||
files = list_files("/path/to/directory")
|
||||
|
||||
# With pattern matching
|
||||
files = list_files("/path/to/directory", pattern="*.txt")
|
||||
|
||||
# Returns: List[Dict[str, Union[str, int]]]
|
||||
# Example: [
|
||||
# {
|
||||
# 'name': 'example.txt',
|
||||
# 'path': '/path/to/directory/example.txt',
|
||||
# 'size': 1024,
|
||||
# 'modified': 1609459200.0,
|
||||
# 'created': 1609459100.0
|
||||
# },
|
||||
# ...
|
||||
# ]
|
||||
```
|
||||
|
||||
### get_file_info(filepath: str)
|
||||
|
||||
Gets detailed information about a file:
|
||||
- File metadata
|
||||
- Size and timestamps
|
||||
- Type information
|
||||
- Path details
|
||||
|
||||
```python
|
||||
# Get file information
|
||||
info = get_file_info("example.txt")
|
||||
|
||||
# Returns: Dict[str, Union[str, int]]
|
||||
# Example: {
|
||||
# 'name': 'example.txt',
|
||||
# 'path': '/absolute/path/to/example.txt',
|
||||
# 'size': 1024,
|
||||
# 'modified': 1609459200.0,
|
||||
# 'created': 1609459100.0,
|
||||
# 'is_file': True,
|
||||
# 'is_dir': False,
|
||||
# 'extension': '.txt',
|
||||
# 'parent': '/absolute/path/to'
|
||||
# }
|
||||
```
|
||||
|
||||
### copy_file(src: str, dst: str)
|
||||
|
||||
Copies a file with metadata:
|
||||
- Preserves timestamps
|
||||
- Creates destination directories
|
||||
- Handles existing files
|
||||
|
||||
```python
|
||||
# Basic copy
|
||||
success = copy_file("source.txt", "destination.txt")
|
||||
|
||||
# Copy to new directory
|
||||
success = copy_file(
|
||||
"data.txt",
|
||||
"backup/2023/data_backup.txt"
|
||||
)
|
||||
# Returns: bool (True if successful)
|
||||
```
|
||||
|
||||
### move_file(src: str, dst: str)
|
||||
|
||||
Moves or renames a file:
|
||||
- Creates destination directories
|
||||
- Handles existing files
|
||||
- Cross-device moves
|
||||
|
||||
```python
|
||||
# Move file
|
||||
success = move_file("old/path/file.txt", "new/path/file.txt")
|
||||
|
||||
# Rename file
|
||||
success = move_file(
|
||||
"document.txt",
|
||||
"document_v2.txt"
|
||||
)
|
||||
# Returns: bool (True if successful)
|
||||
```
|
||||
|
||||
### delete_file(filepath: str)
|
||||
|
||||
Deletes a file:
|
||||
- Safe deletion
|
||||
- Error handling
|
||||
- Non-recursive (files only)
|
||||
|
||||
```python
|
||||
# Delete file
|
||||
success = delete_file("unwanted.txt")
|
||||
# Returns: bool (True if successful)
|
||||
```
|
||||
|
||||
## Example Agent Configuration
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent
|
||||
from praisonaiagents.tools import (
|
||||
read_file, write_file, list_files,
|
||||
get_file_info, copy_file, move_file, delete_file
|
||||
)
|
||||
|
||||
agent = Agent(
|
||||
name="FileManager",
|
||||
description="An agent that manages files",
|
||||
tools=[
|
||||
read_file, write_file, list_files,
|
||||
get_file_info, copy_file, move_file, delete_file
|
||||
]
|
||||
)
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
All functions include comprehensive error handling:
|
||||
- File not found errors
|
||||
- Permission errors
|
||||
- Path errors
|
||||
- I/O errors
|
||||
- Encoding errors
|
||||
|
||||
Errors are handled consistently:
|
||||
- File operations return bool for success/failure
|
||||
- Information functions return error details in result
|
||||
- All errors are logged for debugging
|
||||
|
||||
## Common Use Cases
|
||||
|
||||
1. File Organization:
|
||||
```python
|
||||
# List and organize files by extension
|
||||
files = list_files("downloads", pattern="*.*")
|
||||
for file in files:
|
||||
ext = file['extension']
|
||||
if ext:
|
||||
dst = f"organized/{ext[1:]}/{file['name']}"
|
||||
move_file(file['path'], dst)
|
||||
```
|
||||
|
||||
2. File Backup:
|
||||
```python
|
||||
# Create timestamped backups
|
||||
import time
|
||||
files = list_files("important_data")
|
||||
backup_time = time.strftime("%Y%m%d_%H%M%S")
|
||||
for file in files:
|
||||
dst = f"backup/{backup_time}/{file['name']}"
|
||||
copy_file(file['path'], dst)
|
||||
```
|
||||
|
||||
3. File Processing:
|
||||
```python
|
||||
# Read, process, and write files
|
||||
content = read_file("input.txt")
|
||||
processed = process_content(content) # Your processing function
|
||||
write_file("output.txt", processed)
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Basic File Management Agent
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from praisonaiagents.tools import file_tools
|
||||
|
||||
# Create file management agent
|
||||
file_agent = Agent(
|
||||
name="FileOrganizer",
|
||||
role="File System Manager",
|
||||
goal="Organize and manage files efficiently.",
|
||||
backstory="Expert in file organization and system management.",
|
||||
tools=[file_tools],
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Define file task
|
||||
file_task = Task(
|
||||
description="Sort documents by type and create backup copies.",
|
||||
expected_output="Organized file structure with backups.",
|
||||
agent=file_agent,
|
||||
name="file_organization"
|
||||
)
|
||||
|
||||
# Run agent
|
||||
agents = PraisonAIAgents(
|
||||
agents=[file_agent],
|
||||
tasks=[file_task],
|
||||
process="sequential"
|
||||
)
|
||||
agents.start()
|
||||
```
|
||||
|
||||
### Advanced File Management with Multiple Agents
|
||||
|
||||
```python
|
||||
# Create file organization agent
|
||||
organizer_agent = Agent(
|
||||
name="Organizer",
|
||||
role="File Organizer",
|
||||
goal="Sort and organize files systematically.",
|
||||
tools=[file_tools],
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Create backup agent
|
||||
backup_agent = Agent(
|
||||
name="Backup",
|
||||
role="Backup Manager",
|
||||
goal="Create and manage file backups.",
|
||||
backstory="Expert in data backup and recovery.",
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Define tasks
|
||||
organize_task = Task(
|
||||
description="Organize files by type and date.",
|
||||
agent=organizer_agent,
|
||||
name="organize_files"
|
||||
)
|
||||
|
||||
backup_task = Task(
|
||||
description="Create backups of organized files.",
|
||||
agent=backup_agent,
|
||||
name="backup_files"
|
||||
)
|
||||
|
||||
# Run agents
|
||||
agents = PraisonAIAgents(
|
||||
agents=[organizer_agent, backup_agent],
|
||||
tasks=[organize_task, backup_task],
|
||||
process="sequential"
|
||||
)
|
||||
agents.start()
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Agent Configuration">
|
||||
Configure agents with clear file management focus:
|
||||
```python
|
||||
Agent(
|
||||
name="FileManager",
|
||||
role="File System Specialist",
|
||||
goal="Manage files efficiently and safely",
|
||||
tools=[file_tools]
|
||||
)
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Task Definition">
|
||||
Define specific file operations:
|
||||
```python
|
||||
Task(
|
||||
description="Clean up downloads folder and organize by file type",
|
||||
expected_output="Organized directory structure"
|
||||
)
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### File Organization Pipeline
|
||||
```python
|
||||
# Organization agent
|
||||
organizer = Agent(
|
||||
name="Organizer",
|
||||
role="File Organizer",
|
||||
tools=[file_tools]
|
||||
)
|
||||
|
||||
# Cleanup agent
|
||||
cleaner = Agent(
|
||||
name="Cleaner",
|
||||
role="File Cleaner"
|
||||
)
|
||||
|
||||
# Define tasks
|
||||
organize_task = Task(
|
||||
description="Organize files by type",
|
||||
agent=organizer
|
||||
)
|
||||
|
||||
cleanup_task = Task(
|
||||
description="Remove temporary files",
|
||||
agent=cleaner
|
||||
)
|
||||
|
||||
# Run workflow
|
||||
agents = PraisonAIAgents(
|
||||
agents=[organizer, cleaner],
|
||||
tasks=[organize_task, cleanup_task]
|
||||
)
|
||||
@@ -0,0 +1,546 @@
|
||||
---
|
||||
title: "JSON Tools"
|
||||
description: "Tools for working with JSON files in AI agents."
|
||||
---
|
||||
|
||||
<Note>
|
||||
**Prerequisites**
|
||||
- Python 3.10 or higher
|
||||
- PraisonAI Agents package installed
|
||||
- Basic understanding of JSON format
|
||||
</Note>
|
||||
|
||||
## Quick Start
|
||||
|
||||
Use JSON Tools to process and manipulate JSON files with AI agents.
|
||||
|
||||
<Steps>
|
||||
<Step title="Install Dependencies">
|
||||
First, install the required package:
|
||||
```bash
|
||||
pip install praisonaiagents
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Import Components">
|
||||
Import the necessary components:
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from praisonaiagents.tools import (
|
||||
read_json, write_json, merge_json,
|
||||
validate_json, analyze_json, transform_json
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Create Agent">
|
||||
Create a JSON processing agent:
|
||||
```python
|
||||
json_agent = Agent(
|
||||
name="JSONProcessor",
|
||||
role="JSON Processing Specialist",
|
||||
goal="Process JSON files efficiently and accurately.",
|
||||
backstory="Expert in JSON file manipulation and validation.",
|
||||
tools=[
|
||||
read_json, write_json, merge_json,
|
||||
validate_json, analyze_json, transform_json
|
||||
],
|
||||
self_reflect=False
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Define Task">
|
||||
Define the JSON processing task:
|
||||
```python
|
||||
json_task = Task(
|
||||
description="Parse and validate API response data.",
|
||||
expected_output="Validated and processed JSON data.",
|
||||
agent=json_agent,
|
||||
name="json_processing"
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Run Agent">
|
||||
Initialize and run the agent:
|
||||
```python
|
||||
agents = PraisonAIAgents(
|
||||
agents=[json_agent],
|
||||
tasks=[json_task],
|
||||
process="sequential"
|
||||
)
|
||||
agents.start()
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Available Functions
|
||||
|
||||
```python
|
||||
from praisonaiagents.tools import read_json
|
||||
from praisonaiagents.tools import write_json
|
||||
from praisonaiagents.tools import merge_json
|
||||
from praisonaiagents.tools import validate_json
|
||||
from praisonaiagents.tools import analyze_json
|
||||
from praisonaiagents.tools import transform_json
|
||||
```
|
||||
|
||||
## Function Details
|
||||
|
||||
### read_json(filepath: str, encoding: str = 'utf-8', validate_schema: Optional[Dict[str, Any]] = None)
|
||||
|
||||
Reads JSON files with schema validation:
|
||||
- Optional schema validation
|
||||
- Custom encoding support
|
||||
- Error handling
|
||||
|
||||
```python
|
||||
# Basic usage
|
||||
data = read_json("config.json")
|
||||
|
||||
# With schema validation
|
||||
schema = {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {"type": "string"},
|
||||
"age": {"type": "integer"}
|
||||
}
|
||||
}
|
||||
data = read_json(
|
||||
"user.json",
|
||||
encoding="utf-8",
|
||||
validate_schema=schema
|
||||
)
|
||||
|
||||
# Returns: Dict[str, Any] (JSON data)
|
||||
# Error case: Returns dict with 'error' key
|
||||
```
|
||||
|
||||
### write_json(data: Union[Dict[str, Any], List[Any]], filepath: str, encoding: str = 'utf-8', indent: int = 2, sort_keys: bool = False, ensure_ascii: bool = False)
|
||||
|
||||
Writes data to JSON files:
|
||||
- Pretty printing with indentation
|
||||
- Optional key sorting
|
||||
- Unicode support
|
||||
- Directory creation
|
||||
|
||||
```python
|
||||
# Basic usage
|
||||
data = {"name": "Alice", "age": 30}
|
||||
success = write_json(data, "output.json")
|
||||
|
||||
# With formatting options
|
||||
data = {
|
||||
"users": [
|
||||
{"name": "Alice", "age": 30},
|
||||
{"name": "Bob", "age": 25}
|
||||
]
|
||||
}
|
||||
success = write_json(
|
||||
data,
|
||||
"users.json",
|
||||
indent=4,
|
||||
sort_keys=True,
|
||||
ensure_ascii=False
|
||||
)
|
||||
# Returns: bool (True if successful)
|
||||
```
|
||||
|
||||
### merge_json(files: List[str], output_file: str, merge_arrays: bool = True, overwrite_duplicates: bool = True)
|
||||
|
||||
Merges multiple JSON files:
|
||||
- Deep merging of objects
|
||||
- Array handling options
|
||||
- Duplicate key handling
|
||||
- Nested structure support
|
||||
|
||||
```python
|
||||
# Merge configuration files
|
||||
success = merge_json(
|
||||
files=["config1.json", "config2.json"],
|
||||
output_file="merged_config.json"
|
||||
)
|
||||
|
||||
# Advanced merge with options
|
||||
success = merge_json(
|
||||
files=["base.json", "override.json"],
|
||||
output_file="final.json",
|
||||
merge_arrays=True,
|
||||
overwrite_duplicates=False
|
||||
)
|
||||
# Returns: bool (True if successful)
|
||||
```
|
||||
|
||||
### validate_json(data: Union[Dict[str, Any], str], schema: Dict[str, Any])
|
||||
|
||||
Validates JSON against a schema:
|
||||
- JSON Schema support
|
||||
- Detailed error messages
|
||||
- File or data validation
|
||||
|
||||
```python
|
||||
# Validate data
|
||||
schema = {
|
||||
"type": "object",
|
||||
"required": ["name", "email"],
|
||||
"properties": {
|
||||
"name": {"type": "string"},
|
||||
"email": {"type": "string", "format": "email"},
|
||||
"age": {"type": "integer", "minimum": 0}
|
||||
}
|
||||
}
|
||||
|
||||
# Validate data directly
|
||||
data = {"name": "Alice", "email": "[email protected]", "age": 25}
|
||||
is_valid, error = validate_json(data, schema)
|
||||
|
||||
# Validate file
|
||||
is_valid, error = validate_json("user.json", schema)
|
||||
# Returns: Tuple[bool, Optional[str]]
|
||||
```
|
||||
|
||||
### analyze_json(data: Union[Dict[str, Any], str], max_depth: int = 10)
|
||||
|
||||
Analyzes JSON structure:
|
||||
- Type information
|
||||
- Size metrics
|
||||
- Nested structure analysis
|
||||
- Sample data
|
||||
|
||||
```python
|
||||
# Analyze file
|
||||
analysis = analyze_json("data.json", max_depth=5)
|
||||
|
||||
# Analyze data structure
|
||||
data = {
|
||||
"users": [
|
||||
{"name": "Alice", "scores": [95, 87, 92]},
|
||||
{"name": "Bob", "scores": [88, 85, 90]}
|
||||
]
|
||||
}
|
||||
analysis = analyze_json(data)
|
||||
|
||||
# Returns: Dict[str, Any]
|
||||
# Example output:
|
||||
# {
|
||||
# 'analysis_time': '2023-01-01T12:00:00',
|
||||
# 'structure': {
|
||||
# 'type': 'dict',
|
||||
# 'size': 1,
|
||||
# 'keys': ['users'],
|
||||
# 'children': {
|
||||
# 'users': {
|
||||
# 'type': 'list',
|
||||
# 'length': 2,
|
||||
# 'element_types': ['dict'],
|
||||
# 'sample_elements': [...]
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
```
|
||||
|
||||
### transform_json(data: Union[Dict[str, Any], str], transformations: List[Dict[str, Any]])
|
||||
|
||||
Transforms JSON data:
|
||||
- Multiple operations
|
||||
- Path-based modifications
|
||||
- Nested transformations
|
||||
- Operation types: set, delete, rename, move
|
||||
|
||||
```python
|
||||
# Transform data
|
||||
transformations = [
|
||||
{
|
||||
"operation": "set",
|
||||
"path": "user.settings.theme",
|
||||
"value": "dark"
|
||||
},
|
||||
{
|
||||
"operation": "move",
|
||||
"path": "old.config",
|
||||
"value": "new.config"
|
||||
},
|
||||
{
|
||||
"operation": "delete",
|
||||
"path": "temporary.data"
|
||||
}
|
||||
]
|
||||
|
||||
# Transform file
|
||||
result = transform_json("config.json", transformations)
|
||||
|
||||
# Transform data directly
|
||||
data = {"user": {"name": "Alice"}}
|
||||
result = transform_json(data, transformations)
|
||||
# Returns: Dict[str, Any] (transformed data)
|
||||
```
|
||||
|
||||
## Example Agent Configuration
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent
|
||||
from praisonaiagents.tools import (
|
||||
read_json, write_json, merge_json,
|
||||
validate_json, analyze_json, transform_json
|
||||
)
|
||||
|
||||
agent = Agent(
|
||||
name="JSONProcessor",
|
||||
description="An agent that processes JSON data",
|
||||
tools=[
|
||||
read_json, write_json, merge_json,
|
||||
validate_json, analyze_json, transform_json
|
||||
]
|
||||
)
|
||||
```
|
||||
|
||||
## Dependencies
|
||||
|
||||
The JSON tools require the following Python packages:
|
||||
- jsonschema: For JSON schema validation
|
||||
|
||||
These will be automatically installed when needed.
|
||||
|
||||
## Error Handling
|
||||
|
||||
All functions include comprehensive error handling:
|
||||
- File I/O errors
|
||||
- JSON parsing errors
|
||||
- Schema validation errors
|
||||
- Transformation errors
|
||||
|
||||
Errors are handled consistently:
|
||||
- File operations return bool for success/failure
|
||||
- Data operations return error details in result
|
||||
- All errors are logged for debugging
|
||||
|
||||
## Common Use Cases
|
||||
|
||||
1. Configuration Management:
|
||||
```python
|
||||
# Merge multiple config files
|
||||
success = merge_json(
|
||||
["base_config.json", "env_config.json", "user_config.json"],
|
||||
"final_config.json",
|
||||
merge_arrays=True,
|
||||
overwrite_duplicates=True
|
||||
)
|
||||
|
||||
# Validate configuration
|
||||
schema = {
|
||||
"type": "object",
|
||||
"required": ["database", "api"],
|
||||
"properties": {
|
||||
"database": {
|
||||
"type": "object",
|
||||
"required": ["host", "port"]
|
||||
},
|
||||
"api": {
|
||||
"type": "object",
|
||||
"required": ["key"]
|
||||
}
|
||||
}
|
||||
}
|
||||
is_valid, error = validate_json("final_config.json", schema)
|
||||
```
|
||||
|
||||
2. Data Analysis:
|
||||
```python
|
||||
# Analyze data structure
|
||||
analysis = analyze_json("large_dataset.json", max_depth=3)
|
||||
print(f"Dataset size: {analysis['structure']['size']} entries")
|
||||
print(f"Available fields: {analysis['structure']['keys']}")
|
||||
```
|
||||
|
||||
3. Data Transformation:
|
||||
```python
|
||||
# Transform data format
|
||||
transformations = [
|
||||
{"operation": "rename", "path": "firstName", "value": "first_name"},
|
||||
{"operation": "rename", "path": "lastName", "value": "last_name"},
|
||||
{"operation": "move", "path": "address.zip", "value": "address.postal_code"},
|
||||
{"operation": "delete", "path": "temporary_data"}
|
||||
]
|
||||
result = transform_json("user_data.json", transformations)
|
||||
write_json(result, "transformed_data.json")
|
||||
```
|
||||
|
||||
## Understanding JSON Tools
|
||||
|
||||
<Card title="What are JSON Tools?" icon="question">
|
||||
JSON Tools provide JSON processing capabilities for AI agents:
|
||||
- JSON parsing
|
||||
- File validation
|
||||
- Data extraction
|
||||
- Structure manipulation
|
||||
- Format conversion
|
||||
</Card>
|
||||
|
||||
## Key Components
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="JSON Agent" icon="user-robot">
|
||||
Create specialized JSON agents:
|
||||
```python
|
||||
Agent(tools=[json])
|
||||
```
|
||||
</Card>
|
||||
<Card title="JSON Task" icon="list-check">
|
||||
Define JSON tasks:
|
||||
```python
|
||||
Task(description="json_operation")
|
||||
```
|
||||
</Card>
|
||||
<Card title="Process Types" icon="arrows-split-up-and-left">
|
||||
Sequential or parallel processing:
|
||||
```python
|
||||
process="sequential"
|
||||
```
|
||||
</Card>
|
||||
<Card title="JSON Options" icon="sliders">
|
||||
Customize JSON parameters:
|
||||
```python
|
||||
indent=2, encoding="utf-8"
|
||||
```
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Examples
|
||||
|
||||
### Basic JSON Processing Agent
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from praisonaiagents.tools import json
|
||||
|
||||
# Create JSON agent
|
||||
json_agent = Agent(
|
||||
name="JSONExpert",
|
||||
role="JSON Processing Specialist",
|
||||
goal="Process JSON files efficiently and accurately.",
|
||||
backstory="Expert in JSON file handling and validation.",
|
||||
tools=[json],
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Define JSON task
|
||||
json_task = Task(
|
||||
description="Parse and validate API configurations.",
|
||||
expected_output="Processed and validated JSON data.",
|
||||
agent=json_agent,
|
||||
name="config_processing"
|
||||
)
|
||||
|
||||
# Run agent
|
||||
agents = PraisonAIAgents(
|
||||
agents=[json_agent],
|
||||
tasks=[json_task],
|
||||
process="sequential"
|
||||
)
|
||||
agents.start()
|
||||
```
|
||||
|
||||
### Advanced JSON Processing with Multiple Agents
|
||||
|
||||
```python
|
||||
# Create JSON processing agent
|
||||
processor_agent = Agent(
|
||||
name="Processor",
|
||||
role="JSON Processor",
|
||||
goal="Process JSON files systematically.",
|
||||
tools=[json],
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Create validation agent
|
||||
validator_agent = Agent(
|
||||
name="Validator",
|
||||
role="Data Validator",
|
||||
goal="Validate JSON structure and content.",
|
||||
backstory="Expert in data validation and verification.",
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Define tasks
|
||||
processing_task = Task(
|
||||
description="Process and transform JSON configurations.",
|
||||
agent=processor_agent,
|
||||
name="json_processing"
|
||||
)
|
||||
|
||||
validation_task = Task(
|
||||
description="Validate processed JSON data.",
|
||||
agent=validator_agent,
|
||||
name="data_validation"
|
||||
)
|
||||
|
||||
# Run agents
|
||||
agents = PraisonAIAgents(
|
||||
agents=[processor_agent, validator_agent],
|
||||
tasks=[processing_task, validation_task],
|
||||
process="sequential"
|
||||
)
|
||||
agents.start()
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Agent Configuration">
|
||||
Configure agents with clear JSON focus:
|
||||
```python
|
||||
Agent(
|
||||
name="JSONProcessor",
|
||||
role="JSON Processing Specialist",
|
||||
goal="Process JSON files accurately and safely",
|
||||
tools=[json]
|
||||
)
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Task Definition">
|
||||
Define specific JSON operations:
|
||||
```python
|
||||
Task(
|
||||
description="Parse and validate API response data",
|
||||
expected_output="Validated data structure"
|
||||
)
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### JSON Processing Pipeline
|
||||
```python
|
||||
# Processing agent
|
||||
processor = Agent(
|
||||
name="Processor",
|
||||
role="JSON Processor",
|
||||
tools=[json]
|
||||
)
|
||||
|
||||
# Validation agent
|
||||
validator = Agent(
|
||||
name="Validator",
|
||||
role="Data Validator"
|
||||
)
|
||||
|
||||
# Define tasks
|
||||
process_task = Task(
|
||||
description="Process JSON files",
|
||||
agent=processor
|
||||
)
|
||||
|
||||
validate_task = Task(
|
||||
description="Validate processed data",
|
||||
agent=validator
|
||||
)
|
||||
|
||||
# Run workflow
|
||||
agents = PraisonAIAgents(
|
||||
agents=[processor, validator],
|
||||
tasks=[process_task, validate_task]
|
||||
)
|
||||
@@ -0,0 +1,464 @@
|
||||
---
|
||||
title: "Newspaper Tools"
|
||||
description: "News article scraping and analysis tools for AI agents."
|
||||
icon: "newspaper"
|
||||
---
|
||||
|
||||
<Note>
|
||||
**Prerequisites**
|
||||
- Python 3.10 or higher
|
||||
- PraisonAI Agents package installed
|
||||
- `newspaper3k` package installed
|
||||
</Note>
|
||||
|
||||
## Quick Start
|
||||
|
||||
Use Newspaper Tools to scrape and analyze news articles with AI agents.
|
||||
|
||||
<Steps>
|
||||
<Step title="Install Dependencies">
|
||||
First, install the required packages:
|
||||
```bash
|
||||
pip install praisonaiagents newspaper3k
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Import Components">
|
||||
Import the necessary components:
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from praisonaiagents.tools import newspaper
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Create Agent">
|
||||
Create a news agent:
|
||||
```python
|
||||
news_agent = Agent(
|
||||
name="NewsAgent",
|
||||
role="News Analyst",
|
||||
goal="Collect and analyze news articles from various sources.",
|
||||
backstory="Expert in news gathering and content analysis.",
|
||||
tools=[newspaper],
|
||||
self_reflect=False
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Define Task">
|
||||
Define the news task:
|
||||
```python
|
||||
news_task = Task(
|
||||
description="Analyze news articles about 'AI developments' from major tech news sources.",
|
||||
expected_output="Summary of key AI developments with source articles.",
|
||||
agent=news_agent,
|
||||
name="ai_news"
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Run Agent">
|
||||
Initialize and run the agent:
|
||||
```python
|
||||
agents = PraisonAIAgents(
|
||||
agents=[news_agent],
|
||||
tasks=[news_task],
|
||||
process="sequential"
|
||||
)
|
||||
agents.start()
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Understanding Newspaper Tools
|
||||
|
||||
<Card title="What are Newspaper Tools?" icon="question">
|
||||
Newspaper Tools provide news article processing capabilities for AI agents:
|
||||
- Article extraction
|
||||
- Source management
|
||||
- Content analysis
|
||||
- Trend detection
|
||||
- Multi-language support
|
||||
</Card>
|
||||
|
||||
## Key Components
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="News Agent" icon="user-robot">
|
||||
Create specialized news agents:
|
||||
```python
|
||||
Agent(tools=[newspaper])
|
||||
```
|
||||
</Card>
|
||||
<Card title="News Task" icon="list-check">
|
||||
Define news tasks:
|
||||
```python
|
||||
Task(description="news_query")
|
||||
```
|
||||
</Card>
|
||||
<Card title="Process Types" icon="arrows-split-up-and-left">
|
||||
Sequential or parallel processing:
|
||||
```python
|
||||
process="sequential"
|
||||
```
|
||||
</Card>
|
||||
<Card title="Article Options" icon="sliders">
|
||||
Customize article retrieval:
|
||||
```python
|
||||
language="en", limit=10
|
||||
```
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Available Functions
|
||||
|
||||
```python
|
||||
from praisonaiagents.tools import get_article
|
||||
from praisonaiagents.tools import get_news_sources
|
||||
from praisonaiagents.tools import get_articles_from_source
|
||||
from praisonaiagents.tools import get_trending_topics
|
||||
```
|
||||
|
||||
## Function Details
|
||||
|
||||
### get_article(url: str, language: str = 'en')
|
||||
|
||||
Extracts and parses news articles:
|
||||
- Full text extraction
|
||||
- Author detection
|
||||
- Date parsing
|
||||
- Image extraction
|
||||
- NLP processing
|
||||
|
||||
```python
|
||||
# Basic usage
|
||||
article = get_article("https://example.com/article")
|
||||
|
||||
# With language specification
|
||||
article = get_article(
|
||||
"https://lemonde.fr/article",
|
||||
language="fr"
|
||||
)
|
||||
|
||||
# Returns: Dict[str, Any]
|
||||
# Example output:
|
||||
# {
|
||||
# "url": "https://example.com/article",
|
||||
# "title": "Breaking News Story",
|
||||
# "text": "Full article text...",
|
||||
# "authors": ["John Doe", "Jane Smith"],
|
||||
# "publish_date": "2025-01-07T05:31:38",
|
||||
# "top_image": "https://example.com/image.jpg",
|
||||
# "images": ["https://example.com/image1.jpg", ...],
|
||||
# "movies": ["https://example.com/video1.mp4", ...],
|
||||
# "source_domain": "example.com",
|
||||
# "keywords": ["technology", "ai", ...],
|
||||
# "summary": "Article summary..."
|
||||
# }
|
||||
```
|
||||
|
||||
### get_news_sources(category: Optional[str] = None, language: str = 'en', country: Optional[str] = None)
|
||||
|
||||
Gets news sources by category:
|
||||
- Category filtering
|
||||
- Language support
|
||||
- Country filtering
|
||||
- Domain information
|
||||
|
||||
```python
|
||||
# Get all sources
|
||||
sources = get_news_sources()
|
||||
|
||||
# Get technology news sources
|
||||
tech_sources = get_news_sources(
|
||||
category="technology",
|
||||
language="en",
|
||||
country="us"
|
||||
)
|
||||
|
||||
# Returns: List[Dict[str, str]]
|
||||
# Example output:
|
||||
# [
|
||||
# {
|
||||
# "url": "https://techcrunch.com",
|
||||
# "domain": "techcrunch.com",
|
||||
# "name": "TechCrunch",
|
||||
# "category": "technology"
|
||||
# },
|
||||
# ...
|
||||
# ]
|
||||
```
|
||||
|
||||
### get_articles_from_source(source_url: str, limit: int = 10, language: str = 'en')
|
||||
|
||||
Gets recent articles from a source:
|
||||
- Configurable limit
|
||||
- Language support
|
||||
- Full article parsing
|
||||
- Error handling
|
||||
|
||||
```python
|
||||
# Get latest articles
|
||||
articles = get_articles_from_source(
|
||||
"https://techcrunch.com",
|
||||
limit=5
|
||||
)
|
||||
|
||||
# Get articles in specific language
|
||||
articles = get_articles_from_source(
|
||||
"https://lemonde.fr",
|
||||
limit=10,
|
||||
language="fr"
|
||||
)
|
||||
|
||||
# Returns: List[Dict[str, Any]]
|
||||
# Each article has the same structure as get_article()
|
||||
```
|
||||
|
||||
### get_trending_topics(sources: Optional[List[str]] = None, limit: int = 10, language: str = 'en')
|
||||
|
||||
Analyzes trending topics:
|
||||
- Cross-source analysis
|
||||
- Keyword extraction
|
||||
- Customizable sources
|
||||
- Topic ranking
|
||||
|
||||
```python
|
||||
# Get trending topics from default sources
|
||||
topics = get_trending_topics(limit=5)
|
||||
|
||||
# Get topics from specific sources
|
||||
topics = get_trending_topics(
|
||||
sources=[
|
||||
"https://techcrunch.com",
|
||||
"https://wired.com"
|
||||
],
|
||||
limit=10,
|
||||
language="en"
|
||||
)
|
||||
|
||||
# Returns: List[str]
|
||||
# Example: ["artificial intelligence", "climate change", ...]
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Basic News Agent
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from praisonaiagents.tools import newspaper
|
||||
|
||||
# Create news agent
|
||||
news_agent = Agent(
|
||||
name="NewsCollector",
|
||||
role="News Analyst",
|
||||
goal="Collect and analyze news articles on specific topics.",
|
||||
backstory="Expert in news gathering and content analysis.",
|
||||
tools=[newspaper],
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Define news task
|
||||
news_task = Task(
|
||||
description="Analyze recent tech news articles about 'artificial intelligence'.",
|
||||
expected_output="Summary of key AI developments with source articles.",
|
||||
agent=news_agent,
|
||||
name="tech_news"
|
||||
)
|
||||
|
||||
# Run agent
|
||||
agents = PraisonAIAgents(
|
||||
agents=[news_agent],
|
||||
tasks=[news_task],
|
||||
process="sequential"
|
||||
)
|
||||
agents.start()
|
||||
```
|
||||
|
||||
### Advanced News Analysis with Multiple Agents
|
||||
|
||||
```python
|
||||
# Create news collection agent
|
||||
collector_agent = Agent(
|
||||
name="Collector",
|
||||
role="News Collector",
|
||||
goal="Gather comprehensive news coverage.",
|
||||
tools=[newspaper],
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Create analysis agent
|
||||
analysis_agent = Agent(
|
||||
name="Analyzer",
|
||||
role="Content Analyst",
|
||||
goal="Analyze news content and identify trends.",
|
||||
backstory="Expert in news analysis and trend identification.",
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Define tasks
|
||||
collection_task = Task(
|
||||
description="Collect news articles about renewable energy developments.",
|
||||
agent=collector_agent,
|
||||
name="energy_news"
|
||||
)
|
||||
|
||||
analysis_task = Task(
|
||||
description="Analyze the articles and identify key trends and breakthroughs.",
|
||||
agent=analysis_agent,
|
||||
name="news_analysis"
|
||||
)
|
||||
|
||||
# Run agents
|
||||
agents = PraisonAIAgents(
|
||||
agents=[collector_agent, analysis_agent],
|
||||
tasks=[collection_task, analysis_task],
|
||||
process="sequential"
|
||||
)
|
||||
agents.start()
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Agent Configuration">
|
||||
Configure agents with clear news focus:
|
||||
```python
|
||||
Agent(
|
||||
name="NewsAnalyst",
|
||||
role="News Specialist",
|
||||
goal="Analyze news content effectively",
|
||||
tools=[newspaper]
|
||||
)
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Task Definition">
|
||||
Define specific news objectives:
|
||||
```python
|
||||
Task(
|
||||
description="Analyze tech news from major sources for AI developments",
|
||||
expected_output="Trend analysis with key findings"
|
||||
)
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### News Monitoring
|
||||
```python
|
||||
# News monitor agent
|
||||
monitor = Agent(
|
||||
name="Monitor",
|
||||
role="News Monitor",
|
||||
tools=[newspaper]
|
||||
)
|
||||
|
||||
# Analysis agent
|
||||
analyst = Agent(
|
||||
name="Analyst",
|
||||
role="News Analyst"
|
||||
)
|
||||
|
||||
# Define tasks
|
||||
monitor_task = Task(
|
||||
description="Monitor tech news sources",
|
||||
agent=monitor
|
||||
)
|
||||
|
||||
analysis_task = Task(
|
||||
description="Analyze news trends",
|
||||
agent=analyst
|
||||
)
|
||||
|
||||
# Run workflow
|
||||
agents = PraisonAIAgents(
|
||||
agents=[monitor, analyst],
|
||||
tasks=[monitor_task, analysis_task]
|
||||
)
|
||||
|
||||
```
|
||||
|
||||
## Example Agent Configuration
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent
|
||||
from praisonaiagents.tools import (
|
||||
get_article, get_news_sources,
|
||||
get_articles_from_source, get_trending_topics
|
||||
)
|
||||
|
||||
agent = Agent(
|
||||
name="NewsAnalyzer",
|
||||
description="An agent that analyzes news articles",
|
||||
tools=[
|
||||
get_article, get_news_sources,
|
||||
get_articles_from_source, get_trending_topics
|
||||
]
|
||||
)
|
||||
```
|
||||
|
||||
## Dependencies
|
||||
|
||||
The newspaper tools require the following Python packages:
|
||||
- newspaper3k: For article extraction and parsing
|
||||
- nltk: For NLP processing (automatically installed with newspaper3k)
|
||||
|
||||
These will be automatically installed when needed.
|
||||
|
||||
## Error Handling
|
||||
|
||||
All functions include comprehensive error handling:
|
||||
- Network errors
|
||||
- Parsing errors
|
||||
- Language errors
|
||||
- Source availability errors
|
||||
|
||||
Errors are handled consistently:
|
||||
- Success cases return the expected data type
|
||||
- Error cases return a dict with an "error" key
|
||||
- All errors are logged for debugging
|
||||
|
||||
## Common Use Cases
|
||||
|
||||
1. News Monitoring:
|
||||
```python
|
||||
# Monitor tech news
|
||||
sources = get_news_sources(category="technology")
|
||||
for source in sources:
|
||||
articles = get_articles_from_source(
|
||||
source["url"],
|
||||
limit=5
|
||||
)
|
||||
for article in articles:
|
||||
if "ai" in article.get("keywords", []):
|
||||
print(f"AI article found: {article['title']}")
|
||||
```
|
||||
|
||||
2. Trend Analysis:
|
||||
```python
|
||||
# Analyze trending topics
|
||||
topics = get_trending_topics(limit=10)
|
||||
print("Current hot topics:")
|
||||
for i, topic in enumerate(topics, 1):
|
||||
print(f"{i}. {topic}")
|
||||
```
|
||||
|
||||
3. Content Aggregation:
|
||||
```python
|
||||
# Aggregate news from multiple sources
|
||||
def aggregate_news(categories):
|
||||
all_articles = []
|
||||
for category in categories:
|
||||
sources = get_news_sources(category=category)
|
||||
for source in sources[:3]: # Top 3 sources per category
|
||||
articles = get_articles_from_source(
|
||||
source["url"],
|
||||
limit=3
|
||||
)
|
||||
all_articles.extend(articles)
|
||||
return all_articles
|
||||
|
||||
news = aggregate_news(["technology", "business", "science"])
|
||||
@@ -0,0 +1,584 @@
|
||||
---
|
||||
title: "Pandas Tools"
|
||||
description: "Data manipulation and analysis tools for AI agents using pandas."
|
||||
icon: "table"
|
||||
---
|
||||
|
||||
<Note>
|
||||
**Prerequisites**
|
||||
- Python 3.10 or higher
|
||||
- PraisonAI Agents package installed
|
||||
- `pandas` package installed
|
||||
</Note>
|
||||
|
||||
## Quick Start
|
||||
|
||||
Use Pandas Tools to manipulate and analyze data with AI agents.
|
||||
|
||||
<Steps>
|
||||
<Step title="Install Dependencies">
|
||||
First, install the required packages:
|
||||
```bash
|
||||
pip install praisonaiagents pandas
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Import Components">
|
||||
Import the necessary components:
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from praisonaiagents.tools import pandas_tools
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Create Agent">
|
||||
Create a data analysis agent:
|
||||
```python
|
||||
data_agent = Agent(
|
||||
name="DataAnalyst",
|
||||
role="Data Analysis Specialist",
|
||||
goal="Analyze and transform data efficiently.",
|
||||
backstory="Expert in data manipulation and statistical analysis.",
|
||||
tools=[pandas_tools],
|
||||
self_reflect=False
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Define Task">
|
||||
Define the analysis task:
|
||||
```python
|
||||
analysis_task = Task(
|
||||
description="Analyze sales data to identify trends and patterns.",
|
||||
expected_output="Statistical summary and key insights.",
|
||||
agent=data_agent,
|
||||
name="sales_analysis"
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Run Agent">
|
||||
Initialize and run the agent:
|
||||
```python
|
||||
agents = PraisonAIAgents(
|
||||
agents=[data_agent],
|
||||
tasks=[analysis_task],
|
||||
process="sequential"
|
||||
)
|
||||
agents.start()
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Understanding Pandas Tools
|
||||
|
||||
<Card title="What are Pandas Tools?" icon="question">
|
||||
Pandas Tools provide data analysis capabilities for AI agents:
|
||||
- Data filtering and selection
|
||||
- Statistical analysis
|
||||
- Data transformation
|
||||
- Group operations
|
||||
- Pivot table creation
|
||||
</Card>
|
||||
|
||||
## Key Components
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Data Agent" icon="user-robot">
|
||||
Create specialized data agents:
|
||||
```python
|
||||
Agent(tools=[pandas_tools])
|
||||
```
|
||||
</Card>
|
||||
<Card title="Analysis Task" icon="list-check">
|
||||
Define analysis tasks:
|
||||
```python
|
||||
Task(description="analysis_query")
|
||||
```
|
||||
</Card>
|
||||
<Card title="Process Types" icon="arrows-split-up-and-left">
|
||||
Sequential or parallel processing:
|
||||
```python
|
||||
process="sequential"
|
||||
```
|
||||
</Card>
|
||||
<Card title="Analysis Options" icon="sliders">
|
||||
Customize analysis parameters:
|
||||
```python
|
||||
group_by="category", agg_func="mean"
|
||||
```
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Available Functions
|
||||
|
||||
```python
|
||||
from praisonaiagents.tools import read_csv
|
||||
from praisonaiagents.tools import read_excel
|
||||
from praisonaiagents.tools import write_csv
|
||||
from praisonaiagents.tools import write_excel
|
||||
from praisonaiagents.tools import filter_data
|
||||
from praisonaiagents.tools import get_summary
|
||||
from praisonaiagents.tools import group_by
|
||||
from praisonaiagents.tools import pivot_table
|
||||
```
|
||||
|
||||
## Function Details
|
||||
|
||||
### read_csv(filepath: str, **kwargs)
|
||||
|
||||
Reads CSV files into pandas DataFrames:
|
||||
- Flexible data import
|
||||
- Error handling
|
||||
- Additional pandas options
|
||||
|
||||
```python
|
||||
# Basic usage
|
||||
df = read_csv("data.csv")
|
||||
|
||||
# With additional options
|
||||
df = read_csv(
|
||||
"data.csv",
|
||||
encoding="utf-8",
|
||||
sep=",",
|
||||
header=0,
|
||||
usecols=["name", "age", "salary"]
|
||||
)
|
||||
|
||||
# Returns: pd.DataFrame
|
||||
# Error case: Returns dict with 'error' key
|
||||
```
|
||||
|
||||
### read_excel(filepath: str, **kwargs)
|
||||
|
||||
Reads Excel files into pandas DataFrames:
|
||||
- Multiple sheet support
|
||||
- Error handling
|
||||
- Additional pandas options
|
||||
|
||||
```python
|
||||
# Basic usage
|
||||
df = read_excel("data.xlsx")
|
||||
|
||||
# With sheet specification
|
||||
df = read_excel(
|
||||
"data.xlsx",
|
||||
sheet_name="Sheet1",
|
||||
header=0,
|
||||
usecols="A:D"
|
||||
)
|
||||
|
||||
# Returns: pd.DataFrame
|
||||
# Error case: Returns dict with 'error' key
|
||||
```
|
||||
|
||||
### write_csv(df: pd.DataFrame, filepath: str, **kwargs)
|
||||
|
||||
Writes DataFrames to CSV files:
|
||||
- Directory creation
|
||||
- Error handling
|
||||
- Formatting options
|
||||
|
||||
```python
|
||||
# Basic usage
|
||||
success = write_csv(df, "output.csv")
|
||||
|
||||
# With formatting options
|
||||
success = write_csv(
|
||||
df,
|
||||
"output.csv",
|
||||
index=False,
|
||||
encoding="utf-8",
|
||||
sep=",",
|
||||
date_format="%Y-%m-%d"
|
||||
)
|
||||
# Returns: bool (True if successful)
|
||||
```
|
||||
|
||||
### write_excel(df: pd.DataFrame, filepath: str, **kwargs)
|
||||
|
||||
Writes DataFrames to Excel files:
|
||||
- Directory creation
|
||||
- Error handling
|
||||
- Excel-specific options
|
||||
|
||||
```python
|
||||
# Basic usage
|
||||
success = write_excel(df, "output.xlsx")
|
||||
|
||||
# With formatting options
|
||||
success = write_excel(
|
||||
df,
|
||||
"output.xlsx",
|
||||
sheet_name="Data",
|
||||
index=False,
|
||||
freeze_panes=(1,0)
|
||||
)
|
||||
# Returns: bool (True if successful)
|
||||
```
|
||||
|
||||
### filter_data(df: pd.DataFrame, query: str)
|
||||
|
||||
Filters DataFrames using query strings:
|
||||
- SQL-like syntax
|
||||
- Complex conditions
|
||||
- Efficient filtering
|
||||
|
||||
```python
|
||||
# Basic filtering
|
||||
filtered_df = filter_data(df, "age > 25")
|
||||
|
||||
# Complex conditions
|
||||
filtered_df = filter_data(
|
||||
df,
|
||||
"age > 25 and salary >= 50000 and city == 'New York'"
|
||||
)
|
||||
|
||||
# Returns: pd.DataFrame
|
||||
# Error case: Returns dict with 'error' key
|
||||
```
|
||||
|
||||
### get_summary(df: pd.DataFrame)
|
||||
|
||||
Generates comprehensive data summaries:
|
||||
- Basic statistics
|
||||
- Data types
|
||||
- Memory usage
|
||||
- Null counts
|
||||
|
||||
```python
|
||||
# Get data summary
|
||||
summary = get_summary(df)
|
||||
|
||||
# Returns: Dict[str, Any]
|
||||
# Example output:
|
||||
# {
|
||||
# "shape": [1000, 5],
|
||||
# "columns": ["name", "age", "salary", "city"],
|
||||
# "dtypes": {
|
||||
# "name": "object",
|
||||
# "age": "int64",
|
||||
# "salary": "float64",
|
||||
# "city": "object"
|
||||
# },
|
||||
# "null_counts": {
|
||||
# "name": 0,
|
||||
# "age": 2,
|
||||
# "salary": 1,
|
||||
# "city": 0
|
||||
# },
|
||||
# "numeric_summary": {
|
||||
# "age": {
|
||||
# "count": 998,
|
||||
# "mean": 35.5,
|
||||
# "std": 12.3,
|
||||
# "min": 18,
|
||||
# "25%": 28,
|
||||
# "50%": 35,
|
||||
# "75%": 45,
|
||||
# "max": 65
|
||||
# },
|
||||
# ...
|
||||
# },
|
||||
# "memory_usage": 40960
|
||||
# }
|
||||
```
|
||||
|
||||
### group_by(df: pd.DataFrame, columns: Union[str, List[str]], agg_dict: Dict[str, Union[str, List[str]]])
|
||||
|
||||
Groups and aggregates data:
|
||||
- Multiple grouping columns
|
||||
- Multiple aggregations
|
||||
- Custom functions
|
||||
|
||||
```python
|
||||
# Basic grouping
|
||||
grouped_df = group_by(
|
||||
df,
|
||||
columns="city",
|
||||
agg_dict={"salary": "mean"}
|
||||
)
|
||||
|
||||
# Complex grouping
|
||||
grouped_df = group_by(
|
||||
df,
|
||||
columns=["city", "department"],
|
||||
agg_dict={
|
||||
"salary": ["mean", "sum", "count"],
|
||||
"age": ["min", "max", "mean"]
|
||||
}
|
||||
)
|
||||
|
||||
# Returns: pd.DataFrame
|
||||
# Error case: Returns dict with 'error' key
|
||||
```
|
||||
|
||||
### pivot_table(df: pd.DataFrame, index: Union[str, List[str]], columns: Optional[Union[str, List[str]]] = None, values: Optional[Union[str, List[str]]] = None, aggfunc: str = "mean")
|
||||
|
||||
Creates pivot tables:
|
||||
- Multiple index levels
|
||||
- Column pivoting
|
||||
- Custom aggregations
|
||||
- Flexible reshaping
|
||||
|
||||
```python
|
||||
# Basic pivot
|
||||
pivot_df = pivot_table(
|
||||
df,
|
||||
index="city",
|
||||
columns="department",
|
||||
values="salary"
|
||||
)
|
||||
|
||||
# Complex pivot
|
||||
pivot_df = pivot_table(
|
||||
df,
|
||||
index=["city", "department"],
|
||||
columns="year",
|
||||
values=["salary", "headcount"],
|
||||
aggfunc={
|
||||
"salary": "mean",
|
||||
"headcount": "sum"
|
||||
}
|
||||
)
|
||||
|
||||
# Returns: pd.DataFrame
|
||||
# Error case: Returns dict with 'error' key
|
||||
```
|
||||
|
||||
## Example Agent Configuration
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent
|
||||
from praisonaiagents.tools import (
|
||||
read_csv, read_excel, write_csv, write_excel,
|
||||
filter_data, get_summary, group_by, pivot_table
|
||||
)
|
||||
|
||||
agent = Agent(
|
||||
name="DataAnalyzer",
|
||||
description="An agent that analyzes data using pandas",
|
||||
tools=[
|
||||
read_csv, read_excel, write_csv, write_excel,
|
||||
filter_data, get_summary, group_by, pivot_table
|
||||
]
|
||||
)
|
||||
```
|
||||
|
||||
## Dependencies
|
||||
|
||||
The pandas tools require the following Python packages:
|
||||
- pandas: For data manipulation and analysis
|
||||
- numpy: For numerical operations (automatically installed with pandas)
|
||||
- openpyxl: For Excel file support (optional)
|
||||
|
||||
These will be automatically installed when needed.
|
||||
|
||||
## Error Handling
|
||||
|
||||
All functions include comprehensive error handling:
|
||||
- File I/O errors
|
||||
- Data format errors
|
||||
- Query syntax errors
|
||||
- Memory errors
|
||||
|
||||
Errors are handled consistently:
|
||||
- File operations return bool for success/failure
|
||||
- Data operations return error details in result
|
||||
- All errors are logged for debugging
|
||||
|
||||
## Common Use Cases
|
||||
|
||||
1. Data Analysis:
|
||||
```python
|
||||
# Load and analyze sales data
|
||||
df = read_csv("sales_data.csv")
|
||||
summary = get_summary(df)
|
||||
print(f"Total records: {summary['shape'][0]}")
|
||||
print(f"Missing values: {summary['null_counts']}")
|
||||
|
||||
# Filter high-value transactions
|
||||
high_value = filter_data(df, "amount > 10000")
|
||||
write_excel(high_value, "high_value_sales.xlsx")
|
||||
```
|
||||
|
||||
2. Sales Reporting:
|
||||
```python
|
||||
# Create sales summary by region and product
|
||||
sales_summary = group_by(
|
||||
df,
|
||||
columns=["region", "product"],
|
||||
agg_dict={
|
||||
"amount": ["sum", "mean", "count"],
|
||||
"profit": ["sum", "mean"]
|
||||
}
|
||||
)
|
||||
|
||||
# Create pivot table for quarterly analysis
|
||||
quarterly_sales = pivot_table(
|
||||
df,
|
||||
index="product",
|
||||
columns="quarter",
|
||||
values="amount",
|
||||
aggfunc="sum"
|
||||
)
|
||||
```
|
||||
|
||||
3. Data Transformation:
|
||||
```python
|
||||
# Load and clean customer data
|
||||
customers = read_excel("customers.xlsx")
|
||||
filtered = filter_data(
|
||||
customers,
|
||||
"age >= 18 and status == 'active'"
|
||||
)
|
||||
|
||||
# Group by demographics
|
||||
demographics = group_by(
|
||||
filtered,
|
||||
columns=["age_group", "region"],
|
||||
agg_dict={
|
||||
"spending": ["mean", "sum"],
|
||||
"visits": "count"
|
||||
}
|
||||
)
|
||||
write_csv(demographics, "demographic_analysis.csv")
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Basic Data Analysis Agent
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from praisonaiagents.tools import pandas_tools
|
||||
|
||||
# Create data analysis agent
|
||||
data_agent = Agent(
|
||||
name="DataAnalyst",
|
||||
role="Data Analysis Specialist",
|
||||
goal="Perform comprehensive data analysis.",
|
||||
backstory="Expert in statistical analysis and data visualization.",
|
||||
tools=[pandas_tools],
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Define analysis task
|
||||
analysis_task = Task(
|
||||
description="Analyze customer demographics and purchase patterns.",
|
||||
expected_output="Customer segmentation analysis with insights.",
|
||||
agent=data_agent,
|
||||
name="customer_analysis"
|
||||
)
|
||||
|
||||
# Run agent
|
||||
agents = PraisonAIAgents(
|
||||
agents=[data_agent],
|
||||
tasks=[analysis_task],
|
||||
process="sequential"
|
||||
)
|
||||
agents.start()
|
||||
```
|
||||
|
||||
### Advanced Analysis with Multiple Agents
|
||||
|
||||
```python
|
||||
# Create data preparation agent
|
||||
prep_agent = Agent(
|
||||
name="DataPrep",
|
||||
role="Data Preparation Specialist",
|
||||
goal="Clean and prepare data for analysis.",
|
||||
tools=[pandas_tools],
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Create analysis agent
|
||||
analysis_agent = Agent(
|
||||
name="Analyzer",
|
||||
role="Statistical Analyst",
|
||||
goal="Perform advanced statistical analysis.",
|
||||
backstory="Expert in statistical modeling and interpretation.",
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Define tasks
|
||||
prep_task = Task(
|
||||
description="Clean and prepare sales data for analysis.",
|
||||
agent=prep_agent,
|
||||
name="data_prep"
|
||||
)
|
||||
|
||||
analysis_task = Task(
|
||||
description="Perform statistical analysis and generate insights.",
|
||||
agent=analysis_agent,
|
||||
name="statistical_analysis"
|
||||
)
|
||||
|
||||
# Run agents
|
||||
agents = PraisonAIAgents(
|
||||
agents=[prep_agent, analysis_agent],
|
||||
tasks=[prep_task, analysis_task],
|
||||
process="sequential"
|
||||
)
|
||||
agents.start()
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Agent Configuration">
|
||||
Configure agents with clear analysis focus:
|
||||
```python
|
||||
Agent(
|
||||
name="DataScientist",
|
||||
role="Data Analysis Specialist",
|
||||
goal="Extract meaningful insights from data",
|
||||
tools=[pandas_tools]
|
||||
)
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Task Definition">
|
||||
Define specific analysis objectives:
|
||||
```python
|
||||
Task(
|
||||
description="Analyze sales trends and forecast future growth",
|
||||
expected_output="Growth analysis with forecasts"
|
||||
)
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Data Analysis Pipeline
|
||||
```python
|
||||
# Data preparation agent
|
||||
prep_agent = Agent(
|
||||
name="Preparer",
|
||||
role="Data Preparation",
|
||||
tools=[pandas_tools]
|
||||
)
|
||||
|
||||
# Analysis agent
|
||||
analyst = Agent(
|
||||
name="Analyst",
|
||||
role="Data Analyst"
|
||||
)
|
||||
|
||||
# Define tasks
|
||||
prep_task = Task(
|
||||
description="Clean and prepare data",
|
||||
agent=prep_agent
|
||||
)
|
||||
|
||||
analysis_task = Task(
|
||||
description="Analyze prepared data",
|
||||
agent=analyst
|
||||
)
|
||||
|
||||
# Run workflow
|
||||
agents = PraisonAIAgents(
|
||||
agents=[prep_agent, analyst],
|
||||
tasks=[prep_task, analysis_task]
|
||||
)
|
||||
@@ -0,0 +1,527 @@
|
||||
---
|
||||
title: "Python Tools"
|
||||
description: "Tools for Python code execution, analysis, and formatting in AI agents."
|
||||
---
|
||||
|
||||
<Note>
|
||||
**Prerequisites**
|
||||
- Python 3.10 or higher
|
||||
- PraisonAI Agents package installed
|
||||
- Basic understanding of Python programming
|
||||
</Note>
|
||||
|
||||
## Quick Start
|
||||
|
||||
Use Python Tools to execute and manage Python code with AI agents.
|
||||
|
||||
<Steps>
|
||||
<Step title="Install Dependencies">
|
||||
First, install the required package:
|
||||
```bash
|
||||
pip install praisonaiagents
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Import Components">
|
||||
Import the necessary components:
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from praisonaiagents.tools import (
|
||||
execute_code, analyze_code, format_code,
|
||||
lint_code, disassemble_code
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Create Agent">
|
||||
Create a Python execution agent:
|
||||
```python
|
||||
python_agent = Agent(
|
||||
name="PythonExecutor",
|
||||
role="Python Code Specialist",
|
||||
goal="Execute Python code efficiently and safely.",
|
||||
backstory="Expert in Python programming and code execution.",
|
||||
tools=[
|
||||
execute_code, analyze_code, format_code,
|
||||
lint_code, disassemble_code
|
||||
],
|
||||
self_reflect=False
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Define Task">
|
||||
Define the Python execution task:
|
||||
```python
|
||||
python_task = Task(
|
||||
description="Execute and manage Python code.",
|
||||
expected_output="Code execution results.",
|
||||
agent=python_agent,
|
||||
name="code_execution"
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Run Agent">
|
||||
Initialize and run the agent:
|
||||
```python
|
||||
agents = PraisonAIAgents(
|
||||
agents=[python_agent],
|
||||
tasks=[python_task],
|
||||
process="sequential"
|
||||
)
|
||||
agents.start()
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Available Functions
|
||||
|
||||
```python
|
||||
from praisonaiagents.tools import execute_code
|
||||
from praisonaiagents.tools import analyze_code
|
||||
from praisonaiagents.tools import format_code
|
||||
from praisonaiagents.tools import lint_code
|
||||
from praisonaiagents.tools import disassemble_code
|
||||
```
|
||||
|
||||
## Function Details
|
||||
|
||||
### execute_code(code: str, globals_dict: Optional[Dict[str, Any]] = None, locals_dict: Optional[Dict[str, Any]] = None, timeout: int = 30, max_output_size: int = 10000)
|
||||
|
||||
Safely executes Python code:
|
||||
- Isolated execution environment
|
||||
- Output capture
|
||||
- Error handling
|
||||
- Timeout protection
|
||||
- Output size limits
|
||||
|
||||
```python
|
||||
# Basic execution
|
||||
result = execute_code("print('Hello, World!')")
|
||||
|
||||
# With custom environment
|
||||
result = execute_code(
|
||||
"""
|
||||
x = 10
|
||||
y = 20
|
||||
print(f'Sum: {x + y}')
|
||||
""",
|
||||
globals_dict={'__builtins__': __builtins__},
|
||||
timeout=5
|
||||
)
|
||||
|
||||
# Returns: Dict[str, Any]
|
||||
# Example output:
|
||||
# {
|
||||
# 'result': None,
|
||||
# 'stdout': 'Hello, World!\n',
|
||||
# 'stderr': '',
|
||||
# 'success': True
|
||||
# }
|
||||
```
|
||||
|
||||
### analyze_code(code: str)
|
||||
|
||||
Analyzes Python code structure:
|
||||
- Import statements
|
||||
- Function definitions
|
||||
- Class definitions
|
||||
- Variable usage
|
||||
- Code complexity
|
||||
|
||||
```python
|
||||
# Analyze code structure
|
||||
analysis = analyze_code("""
|
||||
def greet(name):
|
||||
return f"Hello, {name}!"
|
||||
|
||||
class Person:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
""")
|
||||
|
||||
# Returns: Dict[str, Any]
|
||||
# Example output:
|
||||
# {
|
||||
# 'imports': [],
|
||||
# 'functions': [
|
||||
# {
|
||||
# 'name': 'greet',
|
||||
# 'args': ['name'],
|
||||
# 'decorators': []
|
||||
# }
|
||||
# ],
|
||||
# 'classes': [
|
||||
# {
|
||||
# 'name': 'Person',
|
||||
# 'bases': [],
|
||||
# 'decorators': []
|
||||
# }
|
||||
# ],
|
||||
# 'variables': ['name'],
|
||||
# 'complexity': {
|
||||
# 'lines': 6,
|
||||
# 'functions': 2,
|
||||
# 'classes': 1,
|
||||
# 'branches': 0
|
||||
# }
|
||||
# }
|
||||
```
|
||||
|
||||
### format_code(code: str, style: str = 'black', line_length: int = 88)
|
||||
|
||||
Formats Python code:
|
||||
- Multiple style options
|
||||
- Line length control
|
||||
- PEP 8 compliance
|
||||
- Consistent formatting
|
||||
|
||||
```python
|
||||
# Format with black
|
||||
formatted = format_code("""
|
||||
def messy_function(x,y, z):
|
||||
if x>0:
|
||||
return y+z
|
||||
else:
|
||||
return y-z
|
||||
""")
|
||||
|
||||
# Format with PEP 8
|
||||
formatted = format_code(
|
||||
"""
|
||||
def messy_function(x,y, z):
|
||||
if x>0:
|
||||
return y+z
|
||||
else:
|
||||
return y-z
|
||||
""",
|
||||
style='pep8',
|
||||
line_length=79
|
||||
)
|
||||
|
||||
# Returns: str
|
||||
# Example output:
|
||||
# def messy_function(x, y, z):
|
||||
# if x > 0:
|
||||
# return y + z
|
||||
# else:
|
||||
# return y - z
|
||||
```
|
||||
|
||||
### lint_code(code: str)
|
||||
|
||||
Lints Python code for issues:
|
||||
- Code quality checks
|
||||
- Style violations
|
||||
- Potential bugs
|
||||
- Best practices
|
||||
|
||||
```python
|
||||
# Lint code for issues
|
||||
results = lint_code("""
|
||||
def bad_function():
|
||||
unused_var = 42
|
||||
return 'result'
|
||||
""")
|
||||
|
||||
# Returns: Dict[str, List[Dict[str, Any]]]
|
||||
# Example output:
|
||||
# {
|
||||
# 'errors': [],
|
||||
# 'warnings': [
|
||||
# {
|
||||
# 'type': 'warning',
|
||||
# 'module': 'bad_function',
|
||||
# 'obj': 'unused_var',
|
||||
# 'line': 2,
|
||||
# 'column': 4,
|
||||
# 'path': '<string>',
|
||||
# 'symbol': 'unused-variable',
|
||||
# 'message': 'Unused variable "unused_var"',
|
||||
# 'message-id': 'W0612'
|
||||
# }
|
||||
# ],
|
||||
# 'conventions': []
|
||||
# }
|
||||
```
|
||||
|
||||
### disassemble_code(code: str)
|
||||
|
||||
Disassembles Python code to bytecode:
|
||||
- Bytecode inspection
|
||||
- Performance analysis
|
||||
- Code optimization
|
||||
- Debugging support
|
||||
|
||||
```python
|
||||
# Disassemble code to bytecode
|
||||
bytecode = disassemble_code("""
|
||||
def add(a, b):
|
||||
return a + b
|
||||
""")
|
||||
|
||||
# Returns: str
|
||||
# Example output:
|
||||
# 1 0 LOAD_CONST 0 (<code object add at ...>)
|
||||
# 2 LOAD_CONST 1 ('add')
|
||||
# 4 MAKE_FUNCTION 0
|
||||
# 6 STORE_NAME 0 (add)
|
||||
# 8 LOAD_CONST 2 (None)
|
||||
# 10 RETURN_VALUE
|
||||
```
|
||||
|
||||
## Example Agent Configuration
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent
|
||||
from praisonaiagents.tools import (
|
||||
execute_code, analyze_code, format_code,
|
||||
lint_code, disassemble_code
|
||||
)
|
||||
|
||||
agent = Agent(
|
||||
name="PythonDeveloper",
|
||||
description="An agent that helps with Python development",
|
||||
tools=[
|
||||
execute_code, analyze_code, format_code,
|
||||
lint_code, disassemble_code
|
||||
]
|
||||
)
|
||||
```
|
||||
|
||||
## Dependencies
|
||||
|
||||
The Python tools require the following packages:
|
||||
- black: For code formatting (black style)
|
||||
- autopep8: For code formatting (PEP 8 style)
|
||||
- pylint: For code linting
|
||||
|
||||
These will be automatically installed when needed.
|
||||
|
||||
## Error Handling
|
||||
|
||||
All functions include comprehensive error handling:
|
||||
- Code execution errors
|
||||
- Syntax errors
|
||||
- Import errors
|
||||
- Timeout errors
|
||||
- Memory errors
|
||||
|
||||
Errors are handled consistently:
|
||||
- Success cases return expected data type
|
||||
- Error cases return None or error details
|
||||
- All errors are logged for debugging
|
||||
|
||||
## Common Use Cases
|
||||
|
||||
1. Code Testing:
|
||||
```python
|
||||
# Test code execution
|
||||
test_code = """
|
||||
def factorial(n):
|
||||
return 1 if n <= 1 else n * factorial(n - 1)
|
||||
|
||||
result = factorial(5)
|
||||
print(f"Factorial: {result}")
|
||||
"""
|
||||
result = execute_code(test_code)
|
||||
print(f"Output: {result['stdout']}")
|
||||
```
|
||||
|
||||
2. Code Quality:
|
||||
```python
|
||||
# Check code quality
|
||||
code = """
|
||||
def process_data(data):
|
||||
processed = []
|
||||
for item in data:
|
||||
if item > 0:
|
||||
processed.append(item * 2)
|
||||
return processed
|
||||
"""
|
||||
analysis = analyze_code(code)
|
||||
lint_results = lint_code(code)
|
||||
formatted = format_code(code)
|
||||
```
|
||||
|
||||
3. Code Analysis:
|
||||
```python
|
||||
# Analyze code structure
|
||||
code = """
|
||||
class DataProcessor:
|
||||
def __init__(self, data):
|
||||
self.data = data
|
||||
|
||||
def process(self):
|
||||
return [x * 2 for x in self.data]
|
||||
"""
|
||||
structure = analyze_code(code)
|
||||
bytecode = disassemble_code(code)
|
||||
print(f"Classes: {structure['classes']}")
|
||||
print(f"Functions: {structure['functions']}")
|
||||
```
|
||||
|
||||
## Understanding Python Tools
|
||||
|
||||
<Card title="What are Python Tools?" icon="question">
|
||||
Python Tools provide code execution capabilities for AI agents:
|
||||
- Code execution
|
||||
- Module management
|
||||
- Error handling
|
||||
- Output capture
|
||||
- Environment control
|
||||
</Card>
|
||||
|
||||
## Examples
|
||||
|
||||
### Basic Python Execution Agent
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from praisonaiagents.tools import (
|
||||
execute_code, analyze_code, format_code,
|
||||
lint_code, disassemble_code
|
||||
)
|
||||
|
||||
# Create Python agent
|
||||
python_agent = Agent(
|
||||
name="PythonExpert",
|
||||
role="Code Execution Specialist",
|
||||
goal="Execute Python code efficiently and safely.",
|
||||
backstory="Expert in Python programming and execution.",
|
||||
tools=[
|
||||
execute_code, analyze_code, format_code,
|
||||
lint_code, disassemble_code
|
||||
],
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Define Python task
|
||||
python_task = Task(
|
||||
description="Execute data processing scripts.",
|
||||
expected_output="Processing results.",
|
||||
agent=python_agent,
|
||||
name="data_processing"
|
||||
)
|
||||
|
||||
# Run agent
|
||||
agents = PraisonAIAgents(
|
||||
agents=[python_agent],
|
||||
tasks=[python_task],
|
||||
process="sequential"
|
||||
)
|
||||
agents.start()
|
||||
```
|
||||
|
||||
### Advanced Python Operations with Multiple Agents
|
||||
|
||||
```python
|
||||
# Create execution agent
|
||||
executor_agent = Agent(
|
||||
name="CodeExecutor",
|
||||
role="Code Execution Specialist",
|
||||
goal="Execute Python code efficiently.",
|
||||
tools=[
|
||||
execute_code, analyze_code, format_code,
|
||||
lint_code, disassemble_code
|
||||
],
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Create monitoring agent
|
||||
monitor_agent = Agent(
|
||||
name="CodeMonitor",
|
||||
role="Execution Monitor",
|
||||
goal="Monitor code execution and handle errors.",
|
||||
backstory="Expert in code monitoring and error handling.",
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Define tasks
|
||||
execution_task = Task(
|
||||
description="Execute Python scripts.",
|
||||
agent=executor_agent,
|
||||
name="code_execution"
|
||||
)
|
||||
|
||||
monitoring_task = Task(
|
||||
description="Monitor execution and handle errors.",
|
||||
agent=monitor_agent,
|
||||
name="execution_monitoring"
|
||||
)
|
||||
|
||||
# Run agents
|
||||
agents = PraisonAIAgents(
|
||||
agents=[executor_agent, monitor_agent],
|
||||
tasks=[execution_task, monitoring_task],
|
||||
process="sequential"
|
||||
)
|
||||
agents.start()
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Agent Configuration">
|
||||
Configure agents with clear Python focus:
|
||||
```python
|
||||
Agent(
|
||||
name="PythonExecutor",
|
||||
role="Code Execution Specialist",
|
||||
goal="Execute code safely and efficiently",
|
||||
tools=[
|
||||
execute_code, analyze_code, format_code,
|
||||
lint_code, disassemble_code
|
||||
]
|
||||
)
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Task Definition">
|
||||
Define specific Python operations:
|
||||
```python
|
||||
Task(
|
||||
description="Execute data processing scripts",
|
||||
expected_output="Processing results"
|
||||
)
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Python Execution Pipeline
|
||||
```python
|
||||
# Execution agent
|
||||
executor = Agent(
|
||||
name="Executor",
|
||||
role="Code Executor",
|
||||
tools=[
|
||||
execute_code, analyze_code, format_code,
|
||||
lint_code, disassemble_code
|
||||
]
|
||||
)
|
||||
|
||||
# Monitor agent
|
||||
monitor = Agent(
|
||||
name="Monitor",
|
||||
role="Execution Monitor"
|
||||
)
|
||||
|
||||
# Define tasks
|
||||
execute_task = Task(
|
||||
description="Execute Python code",
|
||||
agent=executor
|
||||
)
|
||||
|
||||
monitor_task = Task(
|
||||
description="Monitor execution",
|
||||
agent=monitor
|
||||
)
|
||||
|
||||
# Run workflow
|
||||
agents = PraisonAIAgents(
|
||||
agents=[executor, monitor],
|
||||
tasks=[execute_task, monitor_task]
|
||||
)
|
||||
@@ -0,0 +1,462 @@
|
||||
---
|
||||
title: "Shell Tools"
|
||||
description: "Tools for executing shell commands and managing system processes in AI agents."
|
||||
---
|
||||
|
||||
<Note>
|
||||
**Prerequisites**
|
||||
- Python 3.10 or higher
|
||||
- PraisonAI Agents package installed
|
||||
- Basic understanding of shell commands
|
||||
</Note>
|
||||
|
||||
## Quick Start
|
||||
|
||||
Use Shell Tools to execute and manage shell commands with AI agents.
|
||||
|
||||
<Steps>
|
||||
<Step title="Install Dependencies">
|
||||
First, install the required package:
|
||||
```bash
|
||||
pip install praisonaiagents
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Import Components">
|
||||
Import the necessary components:
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from praisonaiagents.tools import shell, execute_command, list_processes, kill_process, get_system_info
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Create Agent">
|
||||
Create a shell command agent:
|
||||
```python
|
||||
shell_agent = Agent(
|
||||
name="ShellCommander",
|
||||
role="Shell Command Specialist",
|
||||
goal="Execute shell commands efficiently and safely.",
|
||||
backstory="Expert in command-line operations and automation.",
|
||||
tools=[shell],
|
||||
self_reflect=False
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Define Task">
|
||||
Define the shell task:
|
||||
```python
|
||||
shell_task = Task(
|
||||
description="List and organize files in the current directory.",
|
||||
expected_output="Organized file structure with detailed listing.",
|
||||
agent=shell_agent,
|
||||
name="file_organization"
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Run Agent">
|
||||
Initialize and run the agent:
|
||||
```python
|
||||
agents = PraisonAIAgents(
|
||||
agents=[shell_agent],
|
||||
tasks=[shell_task],
|
||||
process="sequential"
|
||||
)
|
||||
agents.start()
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Understanding Shell Tools
|
||||
|
||||
<Card title="What are Shell Tools?" icon="question">
|
||||
Shell Tools provide command-line capabilities for AI agents:
|
||||
- Command execution
|
||||
- Process management
|
||||
- Output handling
|
||||
- Error handling
|
||||
- Environment management
|
||||
</Card>
|
||||
|
||||
## Examples
|
||||
|
||||
### Basic Shell Command Agent
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from praisonaiagents.tools import shell, execute_command, list_processes, kill_process, get_system_info
|
||||
|
||||
# Create shell agent
|
||||
shell_agent = Agent(
|
||||
name="CommandExecutor",
|
||||
role="Shell Command Specialist",
|
||||
goal="Execute shell commands efficiently and safely.",
|
||||
backstory="Expert in command-line operations and scripting.",
|
||||
tools=[shell],
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Define shell task
|
||||
shell_task = Task(
|
||||
description="Clean up temporary files and organize downloads.",
|
||||
expected_output="Cleaned and organized file system.",
|
||||
agent=shell_agent,
|
||||
name="system_cleanup"
|
||||
)
|
||||
|
||||
# Run agent
|
||||
agents = PraisonAIAgents(
|
||||
agents=[shell_agent],
|
||||
tasks=[shell_task],
|
||||
process="sequential"
|
||||
)
|
||||
agents.start()
|
||||
```
|
||||
|
||||
### Advanced Shell Management with Multiple Agents
|
||||
|
||||
```python
|
||||
# Create command agent
|
||||
command_agent = Agent(
|
||||
name="Commander",
|
||||
role="Command Executor",
|
||||
goal="Execute shell commands systematically.",
|
||||
tools=[shell],
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Create monitoring agent
|
||||
monitor_agent = Agent(
|
||||
name="Monitor",
|
||||
role="Process Monitor",
|
||||
goal="Monitor and manage running processes.",
|
||||
backstory="Expert in system monitoring and process control.",
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Define tasks
|
||||
command_task = Task(
|
||||
description="Execute system maintenance commands.",
|
||||
agent=command_agent,
|
||||
name="system_maintenance"
|
||||
)
|
||||
|
||||
monitor_task = Task(
|
||||
description="Monitor system resources and processes.",
|
||||
agent=monitor_agent,
|
||||
name="process_monitoring"
|
||||
)
|
||||
|
||||
# Run agents
|
||||
agents = PraisonAIAgents(
|
||||
agents=[command_agent, monitor_agent],
|
||||
tasks=[command_task, monitor_task],
|
||||
process="sequential"
|
||||
)
|
||||
agents.start()
|
||||
```
|
||||
|
||||
## Available Functions
|
||||
|
||||
```python
|
||||
from praisonaiagents.tools import execute_command
|
||||
from praisonaiagents.tools import list_processes
|
||||
from praisonaiagents.tools import kill_process
|
||||
from praisonaiagents.tools import get_system_info
|
||||
```
|
||||
|
||||
## Function Details
|
||||
|
||||
### execute_command(command: str, cwd: Optional[str] = None, timeout: int = 30, shell: bool = False, env: Optional[Dict[str, str]] = None, max_output_size: int = 10000)
|
||||
|
||||
Safely executes shell commands:
|
||||
- Timeout protection
|
||||
- Output capture
|
||||
- Error handling
|
||||
- Environment control
|
||||
- Working directory control
|
||||
|
||||
```python
|
||||
# Basic command execution
|
||||
result = execute_command("ls -la")
|
||||
|
||||
# Advanced execution
|
||||
result = execute_command(
|
||||
"python script.py",
|
||||
cwd="/path/to/scripts",
|
||||
timeout=60,
|
||||
env={"PYTHONPATH": "/custom/path"},
|
||||
shell=True
|
||||
)
|
||||
|
||||
# Returns: Dict[str, Union[str, int, bool]]
|
||||
# Example output:
|
||||
# {
|
||||
# 'stdout': 'command output...',
|
||||
# 'stderr': 'error output if any',
|
||||
# 'exit_code': 0,
|
||||
# 'success': True,
|
||||
# 'execution_time': 0.123
|
||||
# }
|
||||
```
|
||||
|
||||
### list_processes()
|
||||
|
||||
Lists running system processes:
|
||||
- Process details
|
||||
- Resource usage
|
||||
- User information
|
||||
- Performance metrics
|
||||
|
||||
```python
|
||||
# Get list of running processes
|
||||
processes = list_processes()
|
||||
|
||||
# Sort by CPU usage
|
||||
cpu_intensive = sorted(
|
||||
processes,
|
||||
key=lambda x: x['cpu_percent'],
|
||||
reverse=True
|
||||
)[:5]
|
||||
|
||||
# Returns: List[Dict[str, Union[int, str, float]]]
|
||||
# Example output:
|
||||
# [
|
||||
# {
|
||||
# 'pid': 1234,
|
||||
# 'name': 'python',
|
||||
# 'username': 'user',
|
||||
# 'memory_percent': 2.5,
|
||||
# 'cpu_percent': 15.3
|
||||
# },
|
||||
# ...
|
||||
# ]
|
||||
```
|
||||
|
||||
### kill_process(pid: int, force: bool = False)
|
||||
|
||||
Terminates system processes:
|
||||
- Graceful termination
|
||||
- Force kill option
|
||||
- Error handling
|
||||
- Access control
|
||||
|
||||
```python
|
||||
# Graceful termination
|
||||
result = kill_process(1234)
|
||||
|
||||
# Force kill
|
||||
result = kill_process(
|
||||
pid=1234,
|
||||
force=True # Use SIGKILL
|
||||
)
|
||||
|
||||
# Returns: Dict[str, Union[bool, str]]
|
||||
# Example output:
|
||||
# {
|
||||
# 'success': True,
|
||||
# 'message': 'Process 1234 killed successfully'
|
||||
# }
|
||||
# or
|
||||
# {
|
||||
# 'success': False,
|
||||
# 'message': 'Access denied to kill process 1234'
|
||||
# }
|
||||
```
|
||||
|
||||
### get_system_info()
|
||||
|
||||
Retrieves system information:
|
||||
- CPU statistics
|
||||
- Memory usage
|
||||
- Disk space
|
||||
- Platform details
|
||||
- Boot time
|
||||
|
||||
```python
|
||||
# Get system information
|
||||
info = get_system_info()
|
||||
|
||||
# Access specific metrics
|
||||
print(f"CPU Usage: {info['cpu']['percent']}%")
|
||||
print(f"Memory Free: {info['memory']['free']} bytes")
|
||||
|
||||
# Returns: Dict[str, Union[float, int, str, Dict]]
|
||||
# Example output:
|
||||
# {
|
||||
# 'cpu': {
|
||||
# 'percent': 45.2,
|
||||
# 'cores': 8,
|
||||
# 'physical_cores': 4
|
||||
# },
|
||||
# 'memory': {
|
||||
# 'total': 16000000000,
|
||||
# 'available': 8000000000,
|
||||
# 'percent': 50.0,
|
||||
# 'used': 8000000000,
|
||||
# 'free': 4000000000
|
||||
# },
|
||||
# 'disk': {
|
||||
# 'total': 500000000000,
|
||||
# 'used': 250000000000,
|
||||
# 'free': 250000000000,
|
||||
# 'percent': 50.0
|
||||
# },
|
||||
# 'boot_time': 1641544800,
|
||||
# 'platform': 'Darwin'
|
||||
# }
|
||||
```
|
||||
|
||||
## Example Agent Configuration
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent
|
||||
from praisonaiagents.tools import (
|
||||
execute_command, list_processes,
|
||||
kill_process, get_system_info
|
||||
)
|
||||
|
||||
agent = Agent(
|
||||
name="SystemManager",
|
||||
description="An agent that manages system processes and executes commands",
|
||||
tools=[
|
||||
execute_command, list_processes,
|
||||
kill_process, get_system_info
|
||||
]
|
||||
)
|
||||
```
|
||||
|
||||
## Dependencies
|
||||
|
||||
The shell tools require the following package:
|
||||
- psutil: For system and process information
|
||||
|
||||
This will be automatically installed when needed.
|
||||
|
||||
## Error Handling
|
||||
|
||||
All functions include comprehensive error handling:
|
||||
- Command execution errors
|
||||
- Process access errors
|
||||
- Permission errors
|
||||
- Timeout errors
|
||||
- Resource errors
|
||||
|
||||
Errors are handled consistently:
|
||||
- Success cases return expected data type
|
||||
- Error cases return error details in result
|
||||
- All errors are logged for debugging
|
||||
|
||||
## Common Use Cases
|
||||
|
||||
1. System Monitoring:
|
||||
```python
|
||||
# Monitor system resources
|
||||
info = get_system_info()
|
||||
if info['cpu']['percent'] > 90:
|
||||
print("High CPU usage detected!")
|
||||
if info['memory']['percent'] > 80:
|
||||
print("Low memory warning!")
|
||||
|
||||
# List resource-intensive processes
|
||||
processes = sorted(
|
||||
list_processes(),
|
||||
key=lambda x: x['memory_percent'],
|
||||
reverse=True
|
||||
)[:5]
|
||||
print("Top memory users:", processes)
|
||||
```
|
||||
|
||||
2. Process Management:
|
||||
```python
|
||||
# Find and kill zombie processes
|
||||
for process in list_processes():
|
||||
if process['name'] == 'zombie_process':
|
||||
result = kill_process(
|
||||
process['pid'],
|
||||
force=True
|
||||
)
|
||||
print(f"Kill result: {result['message']}")
|
||||
```
|
||||
|
||||
3. Command Execution:
|
||||
```python
|
||||
# Run a series of maintenance commands
|
||||
commands = [
|
||||
"apt-get update",
|
||||
"apt-get upgrade -y",
|
||||
"apt-get autoremove -y"
|
||||
]
|
||||
for cmd in commands:
|
||||
result = execute_command(
|
||||
cmd,
|
||||
timeout=300,
|
||||
shell=True
|
||||
)
|
||||
if result['success']:
|
||||
print(f"Command succeeded: {cmd}")
|
||||
else:
|
||||
print(f"Command failed: {result['stderr']}")
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Agent Configuration">
|
||||
Configure agents with clear shell focus:
|
||||
```python
|
||||
Agent(
|
||||
name="ShellManager",
|
||||
role="Command Line Specialist",
|
||||
goal="Execute shell commands safely and efficiently",
|
||||
tools=[shell]
|
||||
)
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Task Definition">
|
||||
Define specific shell operations:
|
||||
```python
|
||||
Task(
|
||||
description="Clean up system temp files and optimize storage",
|
||||
expected_output="Optimized system storage"
|
||||
)
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Shell Command Pipeline
|
||||
```python
|
||||
# Command agent
|
||||
commander = Agent(
|
||||
name="Commander",
|
||||
role="Shell Commander",
|
||||
tools=[shell]
|
||||
)
|
||||
|
||||
# Monitor agent
|
||||
monitor = Agent(
|
||||
name="Monitor",
|
||||
role="Process Monitor"
|
||||
)
|
||||
|
||||
# Define tasks
|
||||
command_task = Task(
|
||||
description="Execute maintenance commands",
|
||||
agent=commander
|
||||
)
|
||||
|
||||
monitor_task = Task(
|
||||
description="Monitor command execution",
|
||||
agent=monitor
|
||||
)
|
||||
|
||||
# Run workflow
|
||||
agents = PraisonAIAgents(
|
||||
agents=[commander, monitor],
|
||||
tasks=[command_task, monitor_task]
|
||||
)
|
||||
@@ -0,0 +1,250 @@
|
||||
---
|
||||
title: "Spider Tools"
|
||||
description: "Web scraping and crawling tools for AI agents."
|
||||
icon: "spider"
|
||||
---
|
||||
|
||||
<Note>
|
||||
**Prerequisites**
|
||||
- Python 3.10 or higher
|
||||
- PraisonAI Agents package installed
|
||||
- `beautifulsoup4` package installed
|
||||
- `requests` package installed
|
||||
</Note>
|
||||
|
||||
## Quick Start
|
||||
|
||||
Use Spider Tools to scrape and crawl web content with AI agents.
|
||||
|
||||
<Steps>
|
||||
<Step title="Install Dependencies">
|
||||
First, install the required packages:
|
||||
```bash
|
||||
pip install praisonaiagents beautifulsoup4 requests
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Import Components">
|
||||
Import the necessary components:
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from praisonaiagents.tools import spider
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Create Agent">
|
||||
Create a web scraping agent:
|
||||
```python
|
||||
spider_agent = Agent(
|
||||
name="WebSpider",
|
||||
role="Web Scraping Specialist",
|
||||
goal="Extract and analyze web content efficiently.",
|
||||
backstory="Expert in web scraping and content extraction.",
|
||||
tools=[spider],
|
||||
self_reflect=False
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Define Task">
|
||||
Define the scraping task:
|
||||
```python
|
||||
scraping_task = Task(
|
||||
description="Scrape product information from an e-commerce website.",
|
||||
expected_output="Structured product data with prices and descriptions.",
|
||||
agent=spider_agent,
|
||||
name="product_scraping"
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Run Agent">
|
||||
Initialize and run the agent:
|
||||
```python
|
||||
agents = PraisonAIAgents(
|
||||
agents=[spider_agent],
|
||||
tasks=[scraping_task],
|
||||
process="sequential"
|
||||
)
|
||||
agents.start()
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Understanding Spider Tools
|
||||
|
||||
<Card title="What are Spider Tools?" icon="question">
|
||||
Spider Tools provide web scraping capabilities for AI agents:
|
||||
- Web page scraping
|
||||
- Content extraction
|
||||
- Link crawling
|
||||
- HTML parsing
|
||||
- Data structuring
|
||||
</Card>
|
||||
|
||||
## Key Components
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Spider Agent" icon="user-robot">
|
||||
Create specialized scraping agents:
|
||||
```python
|
||||
Agent(tools=[spider])
|
||||
```
|
||||
</Card>
|
||||
<Card title="Spider Task" icon="list-check">
|
||||
Define scraping tasks:
|
||||
```python
|
||||
Task(description="scraping_query")
|
||||
```
|
||||
</Card>
|
||||
<Card title="Process Types" icon="arrows-split-up-and-left">
|
||||
Sequential or parallel processing:
|
||||
```python
|
||||
process="sequential"
|
||||
```
|
||||
</Card>
|
||||
<Card title="Scraping Options" icon="sliders">
|
||||
Customize scraping parameters:
|
||||
```python
|
||||
max_depth=2, delay=1
|
||||
```
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Examples
|
||||
|
||||
### Basic Web Scraping Agent
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from praisonaiagents.tools import spider
|
||||
|
||||
# Create scraping agent
|
||||
spider_agent = Agent(
|
||||
name="WebCrawler",
|
||||
role="Web Scraping Specialist",
|
||||
goal="Extract web content efficiently and ethically.",
|
||||
backstory="Expert in web crawling and data extraction.",
|
||||
tools=[spider],
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Define scraping task
|
||||
scraping_task = Task(
|
||||
description="Extract article content from news websites.",
|
||||
expected_output="Structured article data with text and metadata.",
|
||||
agent=spider_agent,
|
||||
name="news_scraping"
|
||||
)
|
||||
|
||||
# Run agent
|
||||
agents = PraisonAIAgents(
|
||||
agents=[spider_agent],
|
||||
tasks=[scraping_task],
|
||||
process="sequential"
|
||||
)
|
||||
agents.start()
|
||||
```
|
||||
|
||||
### Advanced Scraping with Multiple Agents
|
||||
|
||||
```python
|
||||
# Create scraping agent
|
||||
scraper_agent = Agent(
|
||||
name="Scraper",
|
||||
role="Content Scraper",
|
||||
goal="Extract web content systematically.",
|
||||
tools=[spider],
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Create analysis agent
|
||||
analysis_agent = Agent(
|
||||
name="Analyzer",
|
||||
role="Content Analyst",
|
||||
goal="Analyze and structure scraped content.",
|
||||
backstory="Expert in data analysis and organization.",
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Define tasks
|
||||
scraping_task = Task(
|
||||
description="Scrape product data from multiple pages.",
|
||||
agent=scraper_agent,
|
||||
name="product_scraping"
|
||||
)
|
||||
|
||||
analysis_task = Task(
|
||||
description="Analyze and structure the scraped product data.",
|
||||
agent=analysis_agent,
|
||||
name="data_analysis"
|
||||
)
|
||||
|
||||
# Run agents
|
||||
agents = PraisonAIAgents(
|
||||
agents=[scraper_agent, analysis_agent],
|
||||
tasks=[scraping_task, analysis_task],
|
||||
process="sequential"
|
||||
)
|
||||
agents.start()
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Agent Configuration">
|
||||
Configure agents with clear scraping focus:
|
||||
```python
|
||||
Agent(
|
||||
name="WebScraper",
|
||||
role="Content Extraction Specialist",
|
||||
goal="Extract web content ethically and efficiently",
|
||||
tools=[spider]
|
||||
)
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Task Definition">
|
||||
Define specific scraping objectives:
|
||||
```python
|
||||
Task(
|
||||
description="Extract product prices and descriptions from e-commerce site",
|
||||
expected_output="Structured product database"
|
||||
)
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Web Scraping Pipeline
|
||||
```python
|
||||
# Scraping agent
|
||||
scraper = Agent(
|
||||
name="Scraper",
|
||||
role="Web Scraper",
|
||||
tools=[spider]
|
||||
)
|
||||
|
||||
# Processing agent
|
||||
processor = Agent(
|
||||
name="Processor",
|
||||
role="Data Processor"
|
||||
)
|
||||
|
||||
# Define tasks
|
||||
scrape_task = Task(
|
||||
description="Scrape website content",
|
||||
agent=scraper
|
||||
)
|
||||
|
||||
process_task = Task(
|
||||
description="Process scraped content",
|
||||
agent=processor
|
||||
)
|
||||
|
||||
# Run workflow
|
||||
agents = PraisonAIAgents(
|
||||
agents=[scraper, processor],
|
||||
tasks=[scrape_task, process_task]
|
||||
)
|
||||
@@ -0,0 +1,250 @@
|
||||
---
|
||||
title: "Wikipedia Tools"
|
||||
description: "Wikipedia data retrieval tools for AI agents."
|
||||
icon: "book"
|
||||
---
|
||||
|
||||
<Note>
|
||||
**Prerequisites**
|
||||
- Python 3.10 or higher
|
||||
- PraisonAI Agents package installed
|
||||
- `wikipedia` package installed
|
||||
- Basic understanding of Wikipedia APIs
|
||||
</Note>
|
||||
|
||||
## Quick Start
|
||||
|
||||
Use Wikipedia Tools to retrieve and analyze Wikipedia content with AI agents.
|
||||
|
||||
<Steps>
|
||||
<Step title="Install Dependencies">
|
||||
First, install the required packages:
|
||||
```bash
|
||||
pip install praisonaiagents wikipedia
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Import Components">
|
||||
Import the necessary components:
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from praisonaiagents.tools import wikipedia
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Create Agent">
|
||||
Create a Wikipedia research agent:
|
||||
```python
|
||||
wiki_agent = Agent(
|
||||
name="WikiResearcher",
|
||||
role="Wikipedia Research Specialist",
|
||||
goal="Research and analyze Wikipedia content efficiently.",
|
||||
backstory="Expert in information retrieval and content analysis.",
|
||||
tools=[wikipedia],
|
||||
self_reflect=False
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Define Task">
|
||||
Define the research task:
|
||||
```python
|
||||
research_task = Task(
|
||||
description="Research historical events and gather information.",
|
||||
expected_output="Comprehensive research summary with citations.",
|
||||
agent=wiki_agent,
|
||||
name="historical_research"
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Run Agent">
|
||||
Initialize and run the agent:
|
||||
```python
|
||||
agents = PraisonAIAgents(
|
||||
agents=[wiki_agent],
|
||||
tasks=[research_task],
|
||||
process="sequential"
|
||||
)
|
||||
agents.start()
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Understanding Wikipedia Tools
|
||||
|
||||
<Card title="What are Wikipedia Tools?" icon="question">
|
||||
Wikipedia Tools provide research capabilities for AI agents:
|
||||
- Article retrieval
|
||||
- Content search
|
||||
- Information extraction
|
||||
- Summary generation
|
||||
- Reference collection
|
||||
</Card>
|
||||
|
||||
## Key Components
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Wiki Agent" icon="user-robot">
|
||||
Create specialized research agents:
|
||||
```python
|
||||
Agent(tools=[wikipedia])
|
||||
```
|
||||
</Card>
|
||||
<Card title="Wiki Task" icon="list-check">
|
||||
Define research tasks:
|
||||
```python
|
||||
Task(description="wiki_query")
|
||||
```
|
||||
</Card>
|
||||
<Card title="Process Types" icon="arrows-split-up-and-left">
|
||||
Sequential or parallel processing:
|
||||
```python
|
||||
process="sequential"
|
||||
```
|
||||
</Card>
|
||||
<Card title="Wiki Options" icon="sliders">
|
||||
Customize search parameters:
|
||||
```python
|
||||
language="en", sentences=3
|
||||
```
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Examples
|
||||
|
||||
### Basic Wikipedia Research Agent
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from praisonaiagents.tools import wikipedia
|
||||
|
||||
# Create Wikipedia agent
|
||||
wiki_agent = Agent(
|
||||
name="WikiExpert",
|
||||
role="Research Specialist",
|
||||
goal="Research topics efficiently and accurately.",
|
||||
backstory="Expert in information gathering and analysis.",
|
||||
tools=[wikipedia],
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Define research task
|
||||
research_task = Task(
|
||||
description="Research scientific discoveries and breakthroughs.",
|
||||
expected_output="Detailed research report with references.",
|
||||
agent=wiki_agent,
|
||||
name="science_research"
|
||||
)
|
||||
|
||||
# Run agent
|
||||
agents = PraisonAIAgents(
|
||||
agents=[wiki_agent],
|
||||
tasks=[research_task],
|
||||
process="sequential"
|
||||
)
|
||||
agents.start()
|
||||
```
|
||||
|
||||
### Advanced Research with Multiple Agents
|
||||
|
||||
```python
|
||||
# Create research agent
|
||||
researcher_agent = Agent(
|
||||
name="Researcher",
|
||||
role="Content Researcher",
|
||||
goal="Research topics systematically.",
|
||||
tools=[wikipedia],
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Create analysis agent
|
||||
analysis_agent = Agent(
|
||||
name="Analyzer",
|
||||
role="Content Analyst",
|
||||
goal="Analyze and summarize research findings.",
|
||||
backstory="Expert in content analysis and synthesis.",
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Define tasks
|
||||
research_task = Task(
|
||||
description="Research technological advancements.",
|
||||
agent=researcher_agent,
|
||||
name="tech_research"
|
||||
)
|
||||
|
||||
analysis_task = Task(
|
||||
description="Analyze and synthesize research findings.",
|
||||
agent=analysis_agent,
|
||||
name="content_analysis"
|
||||
)
|
||||
|
||||
# Run agents
|
||||
agents = PraisonAIAgents(
|
||||
agents=[researcher_agent, analysis_agent],
|
||||
tasks=[research_task, analysis_task],
|
||||
process="sequential"
|
||||
)
|
||||
agents.start()
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Agent Configuration">
|
||||
Configure agents with clear research focus:
|
||||
```python
|
||||
Agent(
|
||||
name="WikiResearcher",
|
||||
role="Research Specialist",
|
||||
goal="Research topics accurately and efficiently",
|
||||
tools=[wikipedia]
|
||||
)
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Task Definition">
|
||||
Define specific research objectives:
|
||||
```python
|
||||
Task(
|
||||
description="Research historical events and gather sources",
|
||||
expected_output="Detailed research summary"
|
||||
)
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Research Pipeline
|
||||
```python
|
||||
# Research agent
|
||||
researcher = Agent(
|
||||
name="Researcher",
|
||||
role="Wiki Researcher",
|
||||
tools=[wikipedia]
|
||||
)
|
||||
|
||||
# Analysis agent
|
||||
analyzer = Agent(
|
||||
name="Analyzer",
|
||||
role="Content Analyzer"
|
||||
)
|
||||
|
||||
# Define tasks
|
||||
research_task = Task(
|
||||
description="Research topic",
|
||||
agent=researcher
|
||||
)
|
||||
|
||||
analyze_task = Task(
|
||||
description="Analyze findings",
|
||||
agent=analyzer
|
||||
)
|
||||
|
||||
# Run workflow
|
||||
agents = PraisonAIAgents(
|
||||
agents=[researcher, analyzer],
|
||||
tasks=[research_task, analyze_task]
|
||||
)
|
||||
@@ -0,0 +1,249 @@
|
||||
---
|
||||
title: "XML Tools"
|
||||
description: "XML file processing tools for AI agents."
|
||||
icon: "code"
|
||||
---
|
||||
|
||||
<Note>
|
||||
**Prerequisites**
|
||||
- Python 3.10 or higher
|
||||
- PraisonAI Agents package installed
|
||||
- Basic understanding of XML format
|
||||
</Note>
|
||||
|
||||
## Quick Start
|
||||
|
||||
Use XML Tools to process and manipulate XML files with AI agents.
|
||||
|
||||
<Steps>
|
||||
<Step title="Install Dependencies">
|
||||
First, install the required package:
|
||||
```bash
|
||||
pip install praisonaiagents
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Import Components">
|
||||
Import the necessary components:
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from praisonaiagents.tools import xml
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Create Agent">
|
||||
Create an XML processing agent:
|
||||
```python
|
||||
xml_agent = Agent(
|
||||
name="XMLProcessor",
|
||||
role="XML Processing Specialist",
|
||||
goal="Process XML files efficiently and accurately.",
|
||||
backstory="Expert in XML file manipulation and validation.",
|
||||
tools=[xml],
|
||||
self_reflect=False
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Define Task">
|
||||
Define the XML processing task:
|
||||
```python
|
||||
xml_task = Task(
|
||||
description="Parse and validate XML configuration files.",
|
||||
expected_output="Validated and processed XML data.",
|
||||
agent=xml_agent,
|
||||
name="xml_processing"
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Run Agent">
|
||||
Initialize and run the agent:
|
||||
```python
|
||||
agents = PraisonAIAgents(
|
||||
agents=[xml_agent],
|
||||
tasks=[xml_task],
|
||||
process="sequential"
|
||||
)
|
||||
agents.start()
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Understanding XML Tools
|
||||
|
||||
<Card title="What are XML Tools?" icon="question">
|
||||
XML Tools provide XML processing capabilities for AI agents:
|
||||
- XML parsing
|
||||
- File validation
|
||||
- Data extraction
|
||||
- Structure manipulation
|
||||
- Format conversion
|
||||
</Card>
|
||||
|
||||
## Key Components
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="XML Agent" icon="user-robot">
|
||||
Create specialized XML agents:
|
||||
```python
|
||||
Agent(tools=[xml])
|
||||
```
|
||||
</Card>
|
||||
<Card title="XML Task" icon="list-check">
|
||||
Define XML tasks:
|
||||
```python
|
||||
Task(description="xml_operation")
|
||||
```
|
||||
</Card>
|
||||
<Card title="Process Types" icon="arrows-split-up-and-left">
|
||||
Sequential or parallel processing:
|
||||
```python
|
||||
process="sequential"
|
||||
```
|
||||
</Card>
|
||||
<Card title="XML Options" icon="sliders">
|
||||
Customize XML parameters:
|
||||
```python
|
||||
encoding="utf-8", pretty_print=True
|
||||
```
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Examples
|
||||
|
||||
### Basic XML Processing Agent
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from praisonaiagents.tools import xml
|
||||
|
||||
# Create XML agent
|
||||
xml_agent = Agent(
|
||||
name="XMLExpert",
|
||||
role="XML Processing Specialist",
|
||||
goal="Process XML files efficiently and accurately.",
|
||||
backstory="Expert in XML file handling and validation.",
|
||||
tools=[xml],
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Define XML task
|
||||
xml_task = Task(
|
||||
description="Parse and validate XML configurations.",
|
||||
expected_output="Processed and validated XML data.",
|
||||
agent=xml_agent,
|
||||
name="config_processing"
|
||||
)
|
||||
|
||||
# Run agent
|
||||
agents = PraisonAIAgents(
|
||||
agents=[xml_agent],
|
||||
tasks=[xml_task],
|
||||
process="sequential"
|
||||
)
|
||||
agents.start()
|
||||
```
|
||||
|
||||
### Advanced XML Processing with Multiple Agents
|
||||
|
||||
```python
|
||||
# Create XML processing agent
|
||||
processor_agent = Agent(
|
||||
name="Processor",
|
||||
role="XML Processor",
|
||||
goal="Process XML files systematically.",
|
||||
tools=[xml],
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Create validation agent
|
||||
validator_agent = Agent(
|
||||
name="Validator",
|
||||
role="Data Validator",
|
||||
goal="Validate XML structure and content.",
|
||||
backstory="Expert in data validation and verification.",
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Define tasks
|
||||
processing_task = Task(
|
||||
description="Process and transform XML configurations.",
|
||||
agent=processor_agent,
|
||||
name="xml_processing"
|
||||
)
|
||||
|
||||
validation_task = Task(
|
||||
description="Validate processed XML data.",
|
||||
agent=validator_agent,
|
||||
name="data_validation"
|
||||
)
|
||||
|
||||
# Run agents
|
||||
agents = PraisonAIAgents(
|
||||
agents=[processor_agent, validator_agent],
|
||||
tasks=[processing_task, validation_task],
|
||||
process="sequential"
|
||||
)
|
||||
agents.start()
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Agent Configuration">
|
||||
Configure agents with clear XML focus:
|
||||
```python
|
||||
Agent(
|
||||
name="XMLProcessor",
|
||||
role="XML Processing Specialist",
|
||||
goal="Process XML files accurately and safely",
|
||||
tools=[xml]
|
||||
)
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Task Definition">
|
||||
Define specific XML operations:
|
||||
```python
|
||||
Task(
|
||||
description="Parse and validate XML configurations",
|
||||
expected_output="Validated data structure"
|
||||
)
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### XML Processing Pipeline
|
||||
```python
|
||||
# Processing agent
|
||||
processor = Agent(
|
||||
name="Processor",
|
||||
role="XML Processor",
|
||||
tools=[xml]
|
||||
)
|
||||
|
||||
# Validation agent
|
||||
validator = Agent(
|
||||
name="Validator",
|
||||
role="Data Validator"
|
||||
)
|
||||
|
||||
# Define tasks
|
||||
process_task = Task(
|
||||
description="Process XML files",
|
||||
agent=processor
|
||||
)
|
||||
|
||||
validate_task = Task(
|
||||
description="Validate processed data",
|
||||
agent=validator
|
||||
)
|
||||
|
||||
# Run workflow
|
||||
agents = PraisonAIAgents(
|
||||
agents=[processor, validator],
|
||||
tasks=[process_task, validate_task]
|
||||
)
|
||||
@@ -0,0 +1,250 @@
|
||||
---
|
||||
title: "YAML Tools"
|
||||
description: "YAML file processing tools for AI agents."
|
||||
icon: "file-code"
|
||||
---
|
||||
|
||||
<Note>
|
||||
**Prerequisites**
|
||||
- Python 3.10 or higher
|
||||
- PraisonAI Agents package installed
|
||||
- `pyyaml` package installed
|
||||
- Basic understanding of YAML format
|
||||
</Note>
|
||||
|
||||
## Quick Start
|
||||
|
||||
Use YAML Tools to process and manipulate YAML files with AI agents.
|
||||
|
||||
<Steps>
|
||||
<Step title="Install Dependencies">
|
||||
First, install the required packages:
|
||||
```bash
|
||||
pip install praisonaiagents pyyaml
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Import Components">
|
||||
Import the necessary components:
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from praisonaiagents.tools import yaml
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Create Agent">
|
||||
Create a YAML processing agent:
|
||||
```python
|
||||
yaml_agent = Agent(
|
||||
name="YAMLProcessor",
|
||||
role="YAML Processing Specialist",
|
||||
goal="Process YAML files efficiently and accurately.",
|
||||
backstory="Expert in YAML file manipulation and validation.",
|
||||
tools=[yaml],
|
||||
self_reflect=False
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Define Task">
|
||||
Define the YAML processing task:
|
||||
```python
|
||||
yaml_task = Task(
|
||||
description="Parse and validate configuration files.",
|
||||
expected_output="Validated and processed YAML configurations.",
|
||||
agent=yaml_agent,
|
||||
name="yaml_processing"
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Run Agent">
|
||||
Initialize and run the agent:
|
||||
```python
|
||||
agents = PraisonAIAgents(
|
||||
agents=[yaml_agent],
|
||||
tasks=[yaml_task],
|
||||
process="sequential"
|
||||
)
|
||||
agents.start()
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Understanding YAML Tools
|
||||
|
||||
<Card title="What are YAML Tools?" icon="question">
|
||||
YAML Tools provide YAML processing capabilities for AI agents:
|
||||
- YAML parsing
|
||||
- File validation
|
||||
- Data extraction
|
||||
- Structure manipulation
|
||||
- Format conversion
|
||||
</Card>
|
||||
|
||||
## Key Components
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="YAML Agent" icon="user-robot">
|
||||
Create specialized YAML agents:
|
||||
```python
|
||||
Agent(tools=[yaml])
|
||||
```
|
||||
</Card>
|
||||
<Card title="YAML Task" icon="list-check">
|
||||
Define YAML tasks:
|
||||
```python
|
||||
Task(description="yaml_operation")
|
||||
```
|
||||
</Card>
|
||||
<Card title="Process Types" icon="arrows-split-up-and-left">
|
||||
Sequential or parallel processing:
|
||||
```python
|
||||
process="sequential"
|
||||
```
|
||||
</Card>
|
||||
<Card title="YAML Options" icon="sliders">
|
||||
Customize YAML parameters:
|
||||
```python
|
||||
safe_load=True, encoding="utf-8"
|
||||
```
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Examples
|
||||
|
||||
### Basic YAML Processing Agent
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from praisonaiagents.tools import yaml
|
||||
|
||||
# Create YAML agent
|
||||
yaml_agent = Agent(
|
||||
name="YAMLExpert",
|
||||
role="YAML Processing Specialist",
|
||||
goal="Process YAML files efficiently and accurately.",
|
||||
backstory="Expert in YAML file handling and validation.",
|
||||
tools=[yaml],
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Define YAML task
|
||||
yaml_task = Task(
|
||||
description="Parse and validate configuration files.",
|
||||
expected_output="Processed and validated YAML data.",
|
||||
agent=yaml_agent,
|
||||
name="config_processing"
|
||||
)
|
||||
|
||||
# Run agent
|
||||
agents = PraisonAIAgents(
|
||||
agents=[yaml_agent],
|
||||
tasks=[yaml_task],
|
||||
process="sequential"
|
||||
)
|
||||
agents.start()
|
||||
```
|
||||
|
||||
### Advanced YAML Processing with Multiple Agents
|
||||
|
||||
```python
|
||||
# Create YAML processing agent
|
||||
processor_agent = Agent(
|
||||
name="Processor",
|
||||
role="YAML Processor",
|
||||
goal="Process YAML files systematically.",
|
||||
tools=[yaml],
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Create validation agent
|
||||
validator_agent = Agent(
|
||||
name="Validator",
|
||||
role="Data Validator",
|
||||
goal="Validate YAML structure and content.",
|
||||
backstory="Expert in data validation and verification.",
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Define tasks
|
||||
processing_task = Task(
|
||||
description="Process and transform YAML configurations.",
|
||||
agent=processor_agent,
|
||||
name="yaml_processing"
|
||||
)
|
||||
|
||||
validation_task = Task(
|
||||
description="Validate processed YAML data.",
|
||||
agent=validator_agent,
|
||||
name="data_validation"
|
||||
)
|
||||
|
||||
# Run agents
|
||||
agents = PraisonAIAgents(
|
||||
agents=[processor_agent, validator_agent],
|
||||
tasks=[processing_task, validation_task],
|
||||
process="sequential"
|
||||
)
|
||||
agents.start()
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Agent Configuration">
|
||||
Configure agents with clear YAML focus:
|
||||
```python
|
||||
Agent(
|
||||
name="YAMLProcessor",
|
||||
role="YAML Processing Specialist",
|
||||
goal="Process YAML files accurately and safely",
|
||||
tools=[yaml]
|
||||
)
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Task Definition">
|
||||
Define specific YAML operations:
|
||||
```python
|
||||
Task(
|
||||
description="Parse and validate deployment configurations",
|
||||
expected_output="Validated configuration set"
|
||||
)
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### YAML Processing Pipeline
|
||||
```python
|
||||
# Processing agent
|
||||
processor = Agent(
|
||||
name="Processor",
|
||||
role="YAML Processor",
|
||||
tools=[yaml]
|
||||
)
|
||||
|
||||
# Validation agent
|
||||
validator = Agent(
|
||||
name="Validator",
|
||||
role="Data Validator"
|
||||
)
|
||||
|
||||
# Define tasks
|
||||
process_task = Task(
|
||||
description="Process YAML files",
|
||||
agent=processor
|
||||
)
|
||||
|
||||
validate_task = Task(
|
||||
description="Validate processed data",
|
||||
agent=validator
|
||||
)
|
||||
|
||||
# Run workflow
|
||||
agents = PraisonAIAgents(
|
||||
agents=[processor, validator],
|
||||
tasks=[process_task, validate_task]
|
||||
)
|
||||
@@ -0,0 +1,250 @@
|
||||
---
|
||||
title: "YFinance Tools"
|
||||
description: "Yahoo Finance data retrieval tools for AI agents."
|
||||
icon: "chart-line"
|
||||
---
|
||||
|
||||
<Note>
|
||||
**Prerequisites**
|
||||
- Python 3.10 or higher
|
||||
- PraisonAI Agents package installed
|
||||
- `yfinance` package installed
|
||||
- Basic understanding of financial data
|
||||
</Note>
|
||||
|
||||
## Quick Start
|
||||
|
||||
Use YFinance Tools to retrieve and analyze financial data with AI agents.
|
||||
|
||||
<Steps>
|
||||
<Step title="Install Dependencies">
|
||||
First, install the required packages:
|
||||
```bash
|
||||
pip install praisonaiagents yfinance
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Import Components">
|
||||
Import the necessary components:
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from praisonaiagents.tools import yfinance
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Create Agent">
|
||||
Create a financial data agent:
|
||||
```python
|
||||
finance_agent = Agent(
|
||||
name="FinanceAnalyst",
|
||||
role="Financial Data Specialist",
|
||||
goal="Retrieve and analyze financial data efficiently.",
|
||||
backstory="Expert in financial data analysis and market research.",
|
||||
tools=[yfinance],
|
||||
self_reflect=False
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Define Task">
|
||||
Define the financial analysis task:
|
||||
```python
|
||||
finance_task = Task(
|
||||
description="Analyze stock performance and market trends.",
|
||||
expected_output="Detailed financial analysis with market insights.",
|
||||
agent=finance_agent,
|
||||
name="market_analysis"
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Run Agent">
|
||||
Initialize and run the agent:
|
||||
```python
|
||||
agents = PraisonAIAgents(
|
||||
agents=[finance_agent],
|
||||
tasks=[finance_task],
|
||||
process="sequential"
|
||||
)
|
||||
agents.start()
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Understanding YFinance Tools
|
||||
|
||||
<Card title="What are YFinance Tools?" icon="question">
|
||||
YFinance Tools provide financial data capabilities for AI agents:
|
||||
- Stock data retrieval
|
||||
- Market analysis
|
||||
- Historical data
|
||||
- Company information
|
||||
- Financial metrics
|
||||
</Card>
|
||||
|
||||
## Key Components
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Finance Agent" icon="user-robot">
|
||||
Create specialized finance agents:
|
||||
```python
|
||||
Agent(tools=[yfinance])
|
||||
```
|
||||
</Card>
|
||||
<Card title="Finance Task" icon="list-check">
|
||||
Define finance tasks:
|
||||
```python
|
||||
Task(description="finance_query")
|
||||
```
|
||||
</Card>
|
||||
<Card title="Process Types" icon="arrows-split-up-and-left">
|
||||
Sequential or parallel processing:
|
||||
```python
|
||||
process="sequential"
|
||||
```
|
||||
</Card>
|
||||
<Card title="Finance Options" icon="sliders">
|
||||
Customize data parameters:
|
||||
```python
|
||||
period="1y", interval="1d"
|
||||
```
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Examples
|
||||
|
||||
### Basic Financial Data Agent
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from praisonaiagents.tools import yfinance
|
||||
|
||||
# Create finance agent
|
||||
finance_agent = Agent(
|
||||
name="MarketAnalyst",
|
||||
role="Financial Data Specialist",
|
||||
goal="Analyze market data efficiently and accurately.",
|
||||
backstory="Expert in financial analysis and market research.",
|
||||
tools=[yfinance],
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Define finance task
|
||||
finance_task = Task(
|
||||
description="Analyze tech sector performance and trends.",
|
||||
expected_output="Comprehensive market analysis report.",
|
||||
agent=finance_agent,
|
||||
name="sector_analysis"
|
||||
)
|
||||
|
||||
# Run agent
|
||||
agents = PraisonAIAgents(
|
||||
agents=[finance_agent],
|
||||
tasks=[finance_task],
|
||||
process="sequential"
|
||||
)
|
||||
agents.start()
|
||||
```
|
||||
|
||||
### Advanced Market Analysis with Multiple Agents
|
||||
|
||||
```python
|
||||
# Create data retrieval agent
|
||||
data_agent = Agent(
|
||||
name="DataCollector",
|
||||
role="Market Data Collector",
|
||||
goal="Retrieve financial data systematically.",
|
||||
tools=[yfinance],
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Create analysis agent
|
||||
analysis_agent = Agent(
|
||||
name="Analyst",
|
||||
role="Market Analyst",
|
||||
goal="Analyze market trends and patterns.",
|
||||
backstory="Expert in financial market analysis.",
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Define tasks
|
||||
data_task = Task(
|
||||
description="Collect historical market data for analysis.",
|
||||
agent=data_agent,
|
||||
name="data_collection"
|
||||
)
|
||||
|
||||
analysis_task = Task(
|
||||
description="Analyze collected market data for insights.",
|
||||
agent=analysis_agent,
|
||||
name="trend_analysis"
|
||||
)
|
||||
|
||||
# Run agents
|
||||
agents = PraisonAIAgents(
|
||||
agents=[data_agent, analysis_agent],
|
||||
tasks=[data_task, analysis_task],
|
||||
process="sequential"
|
||||
)
|
||||
agents.start()
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Agent Configuration">
|
||||
Configure agents with clear finance focus:
|
||||
```python
|
||||
Agent(
|
||||
name="FinanceAnalyst",
|
||||
role="Market Analysis Specialist",
|
||||
goal="Analyze financial data accurately and efficiently",
|
||||
tools=[yfinance]
|
||||
)
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Task Definition">
|
||||
Define specific analysis objectives:
|
||||
```python
|
||||
Task(
|
||||
description="Analyze market trends and generate insights",
|
||||
expected_output="Detailed market analysis"
|
||||
)
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Market Analysis Pipeline
|
||||
```python
|
||||
# Data agent
|
||||
collector = Agent(
|
||||
name="Collector",
|
||||
role="Data Collector",
|
||||
tools=[yfinance]
|
||||
)
|
||||
|
||||
# Analysis agent
|
||||
analyst = Agent(
|
||||
name="Analyst",
|
||||
role="Market Analyst"
|
||||
)
|
||||
|
||||
# Define tasks
|
||||
collect_task = Task(
|
||||
description="Collect market data",
|
||||
agent=collector
|
||||
)
|
||||
|
||||
analyze_task = Task(
|
||||
description="Analyze market trends",
|
||||
agent=analyst
|
||||
)
|
||||
|
||||
# Run workflow
|
||||
agents = PraisonAIAgents(
|
||||
agents=[collector, analyst],
|
||||
tasks=[collect_task, analyze_task]
|
||||
)
|
||||
Generated
+189
-182
@@ -244,13 +244,13 @@ vertex = ["google-auth (>=2,<3)"]
|
||||
|
||||
[[package]]
|
||||
name = "anyio"
|
||||
version = "4.7.0"
|
||||
version = "4.8.0"
|
||||
description = "High level compatibility layer for multiple asynchronous event loop implementations"
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
files = [
|
||||
{file = "anyio-4.7.0-py3-none-any.whl", hash = "sha256:ea60c3723ab42ba6fff7e8ccb0488c898ec538ff4df1f1d5e642c3601d07e352"},
|
||||
{file = "anyio-4.7.0.tar.gz", hash = "sha256:2f834749c602966b7d456a7567cafcb309f96482b5081d14ac93ccd457f9dd48"},
|
||||
{file = "anyio-4.8.0-py3-none-any.whl", hash = "sha256:b5011f270ab5eb0abf13385f851315585cc37ef330dd88e27ec3d34d651fd47a"},
|
||||
{file = "anyio-4.8.0.tar.gz", hash = "sha256:1d9fe889df5212298c0c0723fa20479d1b94883a2df44bd3897aa91083316f7a"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -261,7 +261,7 @@ typing_extensions = {version = ">=4.5", markers = "python_version < \"3.13\""}
|
||||
|
||||
[package.extras]
|
||||
doc = ["Sphinx (>=7.4,<8.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx_rtd_theme"]
|
||||
test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "truststore (>=0.9.1)", "uvloop (>=0.21)"]
|
||||
test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "trustme", "truststore (>=0.9.1)", "uvloop (>=0.21)"]
|
||||
trio = ["trio (>=0.26.1)"]
|
||||
|
||||
[[package]]
|
||||
@@ -480,6 +480,7 @@ files = [
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
tinycss2 = {version = ">=1.1.0,<1.5", optional = true, markers = "extra == \"css\""}
|
||||
webencodings = "*"
|
||||
|
||||
[package.extras]
|
||||
@@ -1091,13 +1092,13 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""}
|
||||
|
||||
[[package]]
|
||||
name = "cohere"
|
||||
version = "5.13.4"
|
||||
version = "5.13.5"
|
||||
description = ""
|
||||
optional = false
|
||||
python-versions = "<4.0,>=3.9"
|
||||
files = [
|
||||
{file = "cohere-5.13.4-py3-none-any.whl", hash = "sha256:f3d81cef93ded8ea57dde6d4a547598846c9e836c18834fe0c6d2bb3da1d8e8f"},
|
||||
{file = "cohere-5.13.4.tar.gz", hash = "sha256:ade5e817368a73dbdaa2bf5a812ad0952d59bdf3e583928e5207774b964d7d6b"},
|
||||
{file = "cohere-5.13.5-py3-none-any.whl", hash = "sha256:cce9754003239f7a1c862ed6ebb54aad7996da2c1225688e8af9b91b0845cab5"},
|
||||
{file = "cohere-5.13.5.tar.gz", hash = "sha256:036ffe2da54a2928412d5895c79f0bf11c91c51f6f562cb2b8fb85ed48c68ed7"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -1483,19 +1484,19 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "duckduckgo-search"
|
||||
version = "7.1.1"
|
||||
version = "7.2.0"
|
||||
description = "Search for words, documents, images, news, maps and text translation using the DuckDuckGo.com search engine."
|
||||
optional = true
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "duckduckgo_search-7.1.1-py3-none-any.whl", hash = "sha256:753b2237fd8a9a4cbf06c788aaf0cfc7e00f4623e8f854d0525682ff31770093"},
|
||||
{file = "duckduckgo_search-7.1.1.tar.gz", hash = "sha256:1874e55aa6eac3de2d0e9b556b70f35ed0cd7a4544d7417cf38216275b3de009"},
|
||||
{file = "duckduckgo_search-7.2.0-py3-none-any.whl", hash = "sha256:511abfa5e3e98592ae6a155d819b981adaac9e66c1ee2bb2eb0d7086e29316e2"},
|
||||
{file = "duckduckgo_search-7.2.0.tar.gz", hash = "sha256:2163d4b78388ab70731094fdc86f4474d9fb9027c975e5aa2f0638e596a7e7b8"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
click = ">=8.1.7"
|
||||
lxml = ">=5.3.0"
|
||||
primp = ">=0.9.2"
|
||||
primp = ">=0.9.3"
|
||||
|
||||
[package.extras]
|
||||
dev = ["mypy (>=1.13.0)", "pytest (>=8.3.4)", "pytest-dependency (>=0.6.0)", "ruff (>=0.8.3)"]
|
||||
@@ -2086,13 +2087,13 @@ grpcio-gcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"]
|
||||
|
||||
[[package]]
|
||||
name = "google-api-python-client"
|
||||
version = "2.156.0"
|
||||
version = "2.157.0"
|
||||
description = "Google API Client Library for Python"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "google_api_python_client-2.156.0-py2.py3-none-any.whl", hash = "sha256:6352185c505e1f311f11b0b96c1b636dcb0fec82cd04b80ac5a671ac4dcab339"},
|
||||
{file = "google_api_python_client-2.156.0.tar.gz", hash = "sha256:b809c111ded61716a9c1c7936e6899053f13bae3defcdfda904bd2ca68065b9c"},
|
||||
{file = "google_api_python_client-2.157.0-py2.py3-none-any.whl", hash = "sha256:0b0231db106324c659bf8b85f390391c00da57a60ebc4271e33def7aac198c75"},
|
||||
{file = "google_api_python_client-2.157.0.tar.gz", hash = "sha256:2ee342d0967ad1cedec43ccd7699671d94bff151e1f06833ea81303f9a6d86fd"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -2539,13 +2540,13 @@ colorama = ">=0.4"
|
||||
|
||||
[[package]]
|
||||
name = "grpc-google-iam-v1"
|
||||
version = "0.13.1"
|
||||
version = "0.14.0"
|
||||
description = "IAM API client library"
|
||||
optional = true
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "grpc-google-iam-v1-0.13.1.tar.gz", hash = "sha256:3ff4b2fd9d990965e410965253c0da6f66205d5a8291c4c31c6ebecca18a9001"},
|
||||
{file = "grpc_google_iam_v1-0.13.1-py2.py3-none-any.whl", hash = "sha256:c3e86151a981811f30d5e7330f271cee53e73bb87755e88cc3b6f0c7b5fe374e"},
|
||||
{file = "grpc_google_iam_v1-0.14.0-py2.py3-none-any.whl", hash = "sha256:fb4a084b30099ba3ab07d61d620a0d4429570b13ff53bd37bac75235f98b7da4"},
|
||||
{file = "grpc_google_iam_v1-0.14.0.tar.gz", hash = "sha256:c66e07aa642e39bb37950f9e7f491f70dad150ac9801263b42b2814307c2df99"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -2555,70 +2556,70 @@ protobuf = ">=3.20.2,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4
|
||||
|
||||
[[package]]
|
||||
name = "grpcio"
|
||||
version = "1.68.1"
|
||||
version = "1.69.0"
|
||||
description = "HTTP/2-based RPC framework"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "grpcio-1.68.1-cp310-cp310-linux_armv7l.whl", hash = "sha256:d35740e3f45f60f3c37b1e6f2f4702c23867b9ce21c6410254c9c682237da68d"},
|
||||
{file = "grpcio-1.68.1-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:d99abcd61760ebb34bdff37e5a3ba333c5cc09feda8c1ad42547bea0416ada78"},
|
||||
{file = "grpcio-1.68.1-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:f8261fa2a5f679abeb2a0a93ad056d765cdca1c47745eda3f2d87f874ff4b8c9"},
|
||||
{file = "grpcio-1.68.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0feb02205a27caca128627bd1df4ee7212db051019a9afa76f4bb6a1a80ca95e"},
|
||||
{file = "grpcio-1.68.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:919d7f18f63bcad3a0f81146188e90274fde800a94e35d42ffe9eadf6a9a6330"},
|
||||
{file = "grpcio-1.68.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:963cc8d7d79b12c56008aabd8b457f400952dbea8997dd185f155e2f228db079"},
|
||||
{file = "grpcio-1.68.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ccf2ebd2de2d6661e2520dae293298a3803a98ebfc099275f113ce1f6c2a80f1"},
|
||||
{file = "grpcio-1.68.1-cp310-cp310-win32.whl", hash = "sha256:2cc1fd04af8399971bcd4f43bd98c22d01029ea2e56e69c34daf2bf8470e47f5"},
|
||||
{file = "grpcio-1.68.1-cp310-cp310-win_amd64.whl", hash = "sha256:ee2e743e51cb964b4975de572aa8fb95b633f496f9fcb5e257893df3be854746"},
|
||||
{file = "grpcio-1.68.1-cp311-cp311-linux_armv7l.whl", hash = "sha256:55857c71641064f01ff0541a1776bfe04a59db5558e82897d35a7793e525774c"},
|
||||
{file = "grpcio-1.68.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4b177f5547f1b995826ef529d2eef89cca2f830dd8b2c99ffd5fde4da734ba73"},
|
||||
{file = "grpcio-1.68.1-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:3522c77d7e6606d6665ec8d50e867f13f946a4e00c7df46768f1c85089eae515"},
|
||||
{file = "grpcio-1.68.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9d1fae6bbf0816415b81db1e82fb3bf56f7857273c84dcbe68cbe046e58e1ccd"},
|
||||
{file = "grpcio-1.68.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:298ee7f80e26f9483f0b6f94cc0a046caf54400a11b644713bb5b3d8eb387600"},
|
||||
{file = "grpcio-1.68.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:cbb5780e2e740b6b4f2d208e90453591036ff80c02cc605fea1af8e6fc6b1bbe"},
|
||||
{file = "grpcio-1.68.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ddda1aa22495d8acd9dfbafff2866438d12faec4d024ebc2e656784d96328ad0"},
|
||||
{file = "grpcio-1.68.1-cp311-cp311-win32.whl", hash = "sha256:b33bd114fa5a83f03ec6b7b262ef9f5cac549d4126f1dc702078767b10c46ed9"},
|
||||
{file = "grpcio-1.68.1-cp311-cp311-win_amd64.whl", hash = "sha256:7f20ebec257af55694d8f993e162ddf0d36bd82d4e57f74b31c67b3c6d63d8b2"},
|
||||
{file = "grpcio-1.68.1-cp312-cp312-linux_armv7l.whl", hash = "sha256:8829924fffb25386995a31998ccbbeaa7367223e647e0122043dfc485a87c666"},
|
||||
{file = "grpcio-1.68.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:3aed6544e4d523cd6b3119b0916cef3d15ef2da51e088211e4d1eb91a6c7f4f1"},
|
||||
{file = "grpcio-1.68.1-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:4efac5481c696d5cb124ff1c119a78bddbfdd13fc499e3bc0ca81e95fc573684"},
|
||||
{file = "grpcio-1.68.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ab2d912ca39c51f46baf2a0d92aa265aa96b2443266fc50d234fa88bf877d8e"},
|
||||
{file = "grpcio-1.68.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95c87ce2a97434dffe7327a4071839ab8e8bffd0054cc74cbe971fba98aedd60"},
|
||||
{file = "grpcio-1.68.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:e4842e4872ae4ae0f5497bf60a0498fa778c192cc7a9e87877abd2814aca9475"},
|
||||
{file = "grpcio-1.68.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:255b1635b0ed81e9f91da4fcc8d43b7ea5520090b9a9ad9340d147066d1d3613"},
|
||||
{file = "grpcio-1.68.1-cp312-cp312-win32.whl", hash = "sha256:7dfc914cc31c906297b30463dde0b9be48e36939575eaf2a0a22a8096e69afe5"},
|
||||
{file = "grpcio-1.68.1-cp312-cp312-win_amd64.whl", hash = "sha256:a0c8ddabef9c8f41617f213e527254c41e8b96ea9d387c632af878d05db9229c"},
|
||||
{file = "grpcio-1.68.1-cp313-cp313-linux_armv7l.whl", hash = "sha256:a47faedc9ea2e7a3b6569795c040aae5895a19dde0c728a48d3c5d7995fda385"},
|
||||
{file = "grpcio-1.68.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:390eee4225a661c5cd133c09f5da1ee3c84498dc265fd292a6912b65c421c78c"},
|
||||
{file = "grpcio-1.68.1-cp313-cp313-manylinux_2_17_aarch64.whl", hash = "sha256:66a24f3d45c33550703f0abb8b656515b0ab777970fa275693a2f6dc8e35f1c1"},
|
||||
{file = "grpcio-1.68.1-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c08079b4934b0bf0a8847f42c197b1d12cba6495a3d43febd7e99ecd1cdc8d54"},
|
||||
{file = "grpcio-1.68.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8720c25cd9ac25dd04ee02b69256d0ce35bf8a0f29e20577427355272230965a"},
|
||||
{file = "grpcio-1.68.1-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:04cfd68bf4f38f5bb959ee2361a7546916bd9a50f78617a346b3aeb2b42e2161"},
|
||||
{file = "grpcio-1.68.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:c28848761a6520c5c6071d2904a18d339a796ebe6b800adc8b3f474c5ce3c3ad"},
|
||||
{file = "grpcio-1.68.1-cp313-cp313-win32.whl", hash = "sha256:77d65165fc35cff6e954e7fd4229e05ec76102d4406d4576528d3a3635fc6172"},
|
||||
{file = "grpcio-1.68.1-cp313-cp313-win_amd64.whl", hash = "sha256:a8040f85dcb9830d8bbb033ae66d272614cec6faceee88d37a88a9bd1a7a704e"},
|
||||
{file = "grpcio-1.68.1-cp38-cp38-linux_armv7l.whl", hash = "sha256:eeb38ff04ab6e5756a2aef6ad8d94e89bb4a51ef96e20f45c44ba190fa0bcaad"},
|
||||
{file = "grpcio-1.68.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:8a3869a6661ec8f81d93f4597da50336718bde9eb13267a699ac7e0a1d6d0bea"},
|
||||
{file = "grpcio-1.68.1-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:2c4cec6177bf325eb6faa6bd834d2ff6aa8bb3b29012cceb4937b86f8b74323c"},
|
||||
{file = "grpcio-1.68.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:12941d533f3cd45d46f202e3667be8ebf6bcb3573629c7ec12c3e211d99cfccf"},
|
||||
{file = "grpcio-1.68.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80af6f1e69c5e68a2be529990684abdd31ed6622e988bf18850075c81bb1ad6e"},
|
||||
{file = "grpcio-1.68.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:e8dbe3e00771bfe3d04feed8210fc6617006d06d9a2679b74605b9fed3e8362c"},
|
||||
{file = "grpcio-1.68.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:83bbf5807dc3ee94ce1de2dfe8a356e1d74101e4b9d7aa8c720cc4818a34aded"},
|
||||
{file = "grpcio-1.68.1-cp38-cp38-win32.whl", hash = "sha256:8cb620037a2fd9eeee97b4531880e439ebfcd6d7d78f2e7dcc3726428ab5ef63"},
|
||||
{file = "grpcio-1.68.1-cp38-cp38-win_amd64.whl", hash = "sha256:52fbf85aa71263380d330f4fce9f013c0798242e31ede05fcee7fbe40ccfc20d"},
|
||||
{file = "grpcio-1.68.1-cp39-cp39-linux_armv7l.whl", hash = "sha256:cb400138e73969eb5e0535d1d06cae6a6f7a15f2cc74add320e2130b8179211a"},
|
||||
{file = "grpcio-1.68.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a1b988b40f2fd9de5c820f3a701a43339d8dcf2cb2f1ca137e2c02671cc83ac1"},
|
||||
{file = "grpcio-1.68.1-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:96f473cdacfdd506008a5d7579c9f6a7ff245a9ade92c3c0265eb76cc591914f"},
|
||||
{file = "grpcio-1.68.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:37ea3be171f3cf3e7b7e412a98b77685eba9d4fd67421f4a34686a63a65d99f9"},
|
||||
{file = "grpcio-1.68.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ceb56c4285754e33bb3c2fa777d055e96e6932351a3082ce3559be47f8024f0"},
|
||||
{file = "grpcio-1.68.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:dffd29a2961f3263a16d73945b57cd44a8fd0b235740cb14056f0612329b345e"},
|
||||
{file = "grpcio-1.68.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:025f790c056815b3bf53da850dd70ebb849fd755a4b1ac822cb65cd631e37d43"},
|
||||
{file = "grpcio-1.68.1-cp39-cp39-win32.whl", hash = "sha256:1098f03dedc3b9810810568060dea4ac0822b4062f537b0f53aa015269be0a76"},
|
||||
{file = "grpcio-1.68.1-cp39-cp39-win_amd64.whl", hash = "sha256:334ab917792904245a028f10e803fcd5b6f36a7b2173a820c0b5b076555825e1"},
|
||||
{file = "grpcio-1.68.1.tar.gz", hash = "sha256:44a8502dd5de653ae6a73e2de50a401d84184f0331d0ac3daeb044e66d5c5054"},
|
||||
{file = "grpcio-1.69.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:2060ca95a8db295ae828d0fc1c7f38fb26ccd5edf9aa51a0f44251f5da332e97"},
|
||||
{file = "grpcio-1.69.0-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:2e52e107261fd8fa8fa457fe44bfadb904ae869d87c1280bf60f93ecd3e79278"},
|
||||
{file = "grpcio-1.69.0-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:316463c0832d5fcdb5e35ff2826d9aa3f26758d29cdfb59a368c1d6c39615a11"},
|
||||
{file = "grpcio-1.69.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:26c9a9c4ac917efab4704b18eed9082ed3b6ad19595f047e8173b5182fec0d5e"},
|
||||
{file = "grpcio-1.69.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90b3646ced2eae3a0599658eeccc5ba7f303bf51b82514c50715bdd2b109e5ec"},
|
||||
{file = "grpcio-1.69.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:3b75aea7c6cb91b341c85e7c1d9db1e09e1dd630b0717f836be94971e015031e"},
|
||||
{file = "grpcio-1.69.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5cfd14175f9db33d4b74d63de87c64bb0ee29ce475ce3c00c01ad2a3dc2a9e51"},
|
||||
{file = "grpcio-1.69.0-cp310-cp310-win32.whl", hash = "sha256:9031069d36cb949205293cf0e243abd5e64d6c93e01b078c37921493a41b72dc"},
|
||||
{file = "grpcio-1.69.0-cp310-cp310-win_amd64.whl", hash = "sha256:cc89b6c29f3dccbe12d7a3b3f1b3999db4882ae076c1c1f6df231d55dbd767a5"},
|
||||
{file = "grpcio-1.69.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:8de1b192c29b8ce45ee26a700044717bcbbd21c697fa1124d440548964328561"},
|
||||
{file = "grpcio-1.69.0-cp311-cp311-macosx_10_14_universal2.whl", hash = "sha256:7e76accf38808f5c5c752b0ab3fd919eb14ff8fafb8db520ad1cc12afff74de6"},
|
||||
{file = "grpcio-1.69.0-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:d5658c3c2660417d82db51e168b277e0ff036d0b0f859fa7576c0ffd2aec1442"},
|
||||
{file = "grpcio-1.69.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5494d0e52bf77a2f7eb17c6da662886ca0a731e56c1c85b93505bece8dc6cf4c"},
|
||||
{file = "grpcio-1.69.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ed866f9edb574fd9be71bf64c954ce1b88fc93b2a4cbf94af221e9426eb14d6"},
|
||||
{file = "grpcio-1.69.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c5ba38aeac7a2fe353615c6b4213d1fbb3a3c34f86b4aaa8be08baaaee8cc56d"},
|
||||
{file = "grpcio-1.69.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f79e05f5bbf551c4057c227d1b041ace0e78462ac8128e2ad39ec58a382536d2"},
|
||||
{file = "grpcio-1.69.0-cp311-cp311-win32.whl", hash = "sha256:bf1f8be0da3fcdb2c1e9f374f3c2d043d606d69f425cd685110dd6d0d2d61258"},
|
||||
{file = "grpcio-1.69.0-cp311-cp311-win_amd64.whl", hash = "sha256:fb9302afc3a0e4ba0b225cd651ef8e478bf0070cf11a529175caecd5ea2474e7"},
|
||||
{file = "grpcio-1.69.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:fc18a4de8c33491ad6f70022af5c460b39611e39578a4d84de0fe92f12d5d47b"},
|
||||
{file = "grpcio-1.69.0-cp312-cp312-macosx_10_14_universal2.whl", hash = "sha256:0f0270bd9ffbff6961fe1da487bdcd594407ad390cc7960e738725d4807b18c4"},
|
||||
{file = "grpcio-1.69.0-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:dc48f99cc05e0698e689b51a05933253c69a8c8559a47f605cff83801b03af0e"},
|
||||
{file = "grpcio-1.69.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e925954b18d41aeb5ae250262116d0970893b38232689c4240024e4333ac084"},
|
||||
{file = "grpcio-1.69.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87d222569273720366f68a99cb62e6194681eb763ee1d3b1005840678d4884f9"},
|
||||
{file = "grpcio-1.69.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:b62b0f41e6e01a3e5082000b612064c87c93a49b05f7602fe1b7aa9fd5171a1d"},
|
||||
{file = "grpcio-1.69.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:db6f9fd2578dbe37db4b2994c94a1d9c93552ed77dca80e1657bb8a05b898b55"},
|
||||
{file = "grpcio-1.69.0-cp312-cp312-win32.whl", hash = "sha256:b192b81076073ed46f4b4dd612b8897d9a1e39d4eabd822e5da7b38497ed77e1"},
|
||||
{file = "grpcio-1.69.0-cp312-cp312-win_amd64.whl", hash = "sha256:1227ff7836f7b3a4ab04e5754f1d001fa52a730685d3dc894ed8bc262cc96c01"},
|
||||
{file = "grpcio-1.69.0-cp313-cp313-linux_armv7l.whl", hash = "sha256:a78a06911d4081a24a1761d16215a08e9b6d4d29cdbb7e427e6c7e17b06bcc5d"},
|
||||
{file = "grpcio-1.69.0-cp313-cp313-macosx_10_14_universal2.whl", hash = "sha256:dc5a351927d605b2721cbb46158e431dd49ce66ffbacb03e709dc07a491dde35"},
|
||||
{file = "grpcio-1.69.0-cp313-cp313-manylinux_2_17_aarch64.whl", hash = "sha256:3629d8a8185f5139869a6a17865d03113a260e311e78fbe313f1a71603617589"},
|
||||
{file = "grpcio-1.69.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c9a281878feeb9ae26db0622a19add03922a028d4db684658f16d546601a4870"},
|
||||
{file = "grpcio-1.69.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cc614e895177ab7e4b70f154d1a7c97e152577ea101d76026d132b7aaba003b"},
|
||||
{file = "grpcio-1.69.0-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:1ee76cd7e2e49cf9264f6812d8c9ac1b85dda0eaea063af07292400f9191750e"},
|
||||
{file = "grpcio-1.69.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:0470fa911c503af59ec8bc4c82b371ee4303ececbbdc055f55ce48e38b20fd67"},
|
||||
{file = "grpcio-1.69.0-cp313-cp313-win32.whl", hash = "sha256:b650f34aceac8b2d08a4c8d7dc3e8a593f4d9e26d86751ebf74ebf5107d927de"},
|
||||
{file = "grpcio-1.69.0-cp313-cp313-win_amd64.whl", hash = "sha256:028337786f11fecb5d7b7fa660475a06aabf7e5e52b5ac2df47414878c0ce7ea"},
|
||||
{file = "grpcio-1.69.0-cp38-cp38-linux_armv7l.whl", hash = "sha256:b7f693db593d6bf285e015d5538bf1c86cf9c60ed30b6f7da04a00ed052fe2f3"},
|
||||
{file = "grpcio-1.69.0-cp38-cp38-macosx_10_14_universal2.whl", hash = "sha256:8b94e83f66dbf6fd642415faca0608590bc5e8d30e2c012b31d7d1b91b1de2fd"},
|
||||
{file = "grpcio-1.69.0-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:b634851b92c090763dde61df0868c730376cdb73a91bcc821af56ae043b09596"},
|
||||
{file = "grpcio-1.69.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bf5f680d3ed08c15330d7830d06bc65f58ca40c9999309517fd62880d70cb06e"},
|
||||
{file = "grpcio-1.69.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:200e48a6e7b00f804cf00a1c26292a5baa96507c7749e70a3ec10ca1a288936e"},
|
||||
{file = "grpcio-1.69.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:45a4704339b6e5b24b0e136dea9ad3815a94f30eb4f1e1d44c4ac484ef11d8dd"},
|
||||
{file = "grpcio-1.69.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:85d347cb8237751b23539981dbd2d9d8f6e9ff90082b427b13022b948eb6347a"},
|
||||
{file = "grpcio-1.69.0-cp38-cp38-win32.whl", hash = "sha256:60e5de105dc02832dc8f120056306d0ef80932bcf1c0e2b4ca3b676de6dc6505"},
|
||||
{file = "grpcio-1.69.0-cp38-cp38-win_amd64.whl", hash = "sha256:282f47d0928e40f25d007f24eb8fa051cb22551e3c74b8248bc9f9bea9c35fe0"},
|
||||
{file = "grpcio-1.69.0-cp39-cp39-linux_armv7l.whl", hash = "sha256:dd034d68a2905464c49479b0c209c773737a4245d616234c79c975c7c90eca03"},
|
||||
{file = "grpcio-1.69.0-cp39-cp39-macosx_10_14_universal2.whl", hash = "sha256:01f834732c22a130bdf3dc154d1053bdbc887eb3ccb7f3e6285cfbfc33d9d5cc"},
|
||||
{file = "grpcio-1.69.0-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:a7f4ed0dcf202a70fe661329f8874bc3775c14bb3911d020d07c82c766ce0eb1"},
|
||||
{file = "grpcio-1.69.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cd7ea241b10bc5f0bb0f82c0d7896822b7ed122b3ab35c9851b440c1ccf81588"},
|
||||
{file = "grpcio-1.69.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f03dc9b4da4c0dc8a1db7a5420f575251d7319b7a839004d8916257ddbe4816"},
|
||||
{file = "grpcio-1.69.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:ca71d73a270dff052fe4edf74fef142d6ddd1f84175d9ac4a14b7280572ac519"},
|
||||
{file = "grpcio-1.69.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5ccbed100dc43704e94ccff9e07680b540d64e4cc89213ab2832b51b4f68a520"},
|
||||
{file = "grpcio-1.69.0-cp39-cp39-win32.whl", hash = "sha256:1514341def9c6ec4b7f0b9628be95f620f9d4b99331b7ef0a1845fd33d9b579c"},
|
||||
{file = "grpcio-1.69.0-cp39-cp39-win_amd64.whl", hash = "sha256:c1fea55d26d647346acb0069b08dca70984101f2dc95066e003019207212e303"},
|
||||
{file = "grpcio-1.69.0.tar.gz", hash = "sha256:936fa44241b5379c5afc344e1260d467bee495747eaf478de825bab2791da6f5"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
protobuf = ["grpcio-tools (>=1.68.1)"]
|
||||
protobuf = ["grpcio-tools (>=1.69.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "grpcio-status"
|
||||
@@ -2805,13 +2806,13 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "huggingface-hub"
|
||||
version = "0.27.0"
|
||||
version = "0.27.1"
|
||||
description = "Client library to download and publish models, datasets and other repos on the huggingface.co hub"
|
||||
optional = false
|
||||
python-versions = ">=3.8.0"
|
||||
files = [
|
||||
{file = "huggingface_hub-0.27.0-py3-none-any.whl", hash = "sha256:8f2e834517f1f1ddf1ecc716f91b120d7333011b7485f665a9a412eacb1a2a81"},
|
||||
{file = "huggingface_hub-0.27.0.tar.gz", hash = "sha256:902cce1a1be5739f5589e560198a65a8edcfd3b830b1666f36e4b961f0454fac"},
|
||||
{file = "huggingface_hub-0.27.1-py3-none-any.whl", hash = "sha256:1c5155ca7d60b60c2e2fc38cbb3ffb7f7c3adf48f824015b219af9061771daec"},
|
||||
{file = "huggingface_hub-0.27.1.tar.gz", hash = "sha256:c004463ca870283909d715d20f066ebd6968c2207dae9393fdffb3c1d4d8f98b"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -2853,13 +2854,13 @@ pyreadline3 = {version = "*", markers = "sys_platform == \"win32\" and python_ve
|
||||
|
||||
[[package]]
|
||||
name = "identify"
|
||||
version = "2.6.4"
|
||||
version = "2.6.5"
|
||||
description = "File identification library for Python"
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
files = [
|
||||
{file = "identify-2.6.4-py2.py3-none-any.whl", hash = "sha256:993b0f01b97e0568c179bb9196391ff391bfb88a99099dbf5ce392b68f42d0af"},
|
||||
{file = "identify-2.6.4.tar.gz", hash = "sha256:285a7d27e397652e8cafe537a6cc97dd470a970f48fb2e9d979aa38eae5513ac"},
|
||||
{file = "identify-2.6.5-py2.py3-none-any.whl", hash = "sha256:14181a47091eb75b337af4c23078c9d09225cd4c48929f521f3bf16b09d02566"},
|
||||
{file = "identify-2.6.5.tar.gz", hash = "sha256:c10b33f250e5bba374fae86fb57f3adcebf1161bce7cdf92031915fd480c13bc"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
@@ -2900,13 +2901,13 @@ test = ["flufl.flake8", "importlib-resources (>=1.3)", "jaraco.test (>=5.4)", "p
|
||||
|
||||
[[package]]
|
||||
name = "importlib-resources"
|
||||
version = "6.4.5"
|
||||
version = "6.5.2"
|
||||
description = "Read resources from Python packages"
|
||||
optional = true
|
||||
python-versions = ">=3.8"
|
||||
python-versions = ">=3.9"
|
||||
files = [
|
||||
{file = "importlib_resources-6.4.5-py3-none-any.whl", hash = "sha256:ac29d5f956f01d5e4bb63102a5a19957f1b9175e45649977264a1416783bb717"},
|
||||
{file = "importlib_resources-6.4.5.tar.gz", hash = "sha256:980862a1d16c9e147a59603677fa2aa5fd82b87f223b6cb870695bcfce830065"},
|
||||
{file = "importlib_resources-6.5.2-py3-none-any.whl", hash = "sha256:789cfdc3ed28c78b67a06acb8126751ced69a3d5f79c095a98298cd8a760ccec"},
|
||||
{file = "importlib_resources-6.5.2.tar.gz", hash = "sha256:185f87adef5bcc288449d98fb4fba07cea78bc036455dd44c5fc4a2fe78fed2c"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
@@ -3975,13 +3976,13 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "marshmallow"
|
||||
version = "3.23.2"
|
||||
version = "3.24.0"
|
||||
description = "A lightweight library for converting complex datatypes to and from native Python datatypes."
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
files = [
|
||||
{file = "marshmallow-3.23.2-py3-none-any.whl", hash = "sha256:bcaf2d6fd74fb1459f8450e85d994997ad3e70036452cbfa4ab685acb19479b3"},
|
||||
{file = "marshmallow-3.23.2.tar.gz", hash = "sha256:c448ac6455ca4d794773f00bae22c2f351d62d739929f761dce5eacb5c468d7f"},
|
||||
{file = "marshmallow-3.24.0-py3-none-any.whl", hash = "sha256:459922b7a1fd3d29d5082ddcadfcea0efd98985030e71d3ef0dd8f44f406e41d"},
|
||||
{file = "marshmallow-3.24.0.tar.gz", hash = "sha256:378572f727e52123d00de1bdd9b7ea7bed18bbfedc7f9bfbcddaf78925a8d602"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -3989,7 +3990,7 @@ packaging = ">=17.0"
|
||||
|
||||
[package.extras]
|
||||
dev = ["marshmallow[tests]", "pre-commit (>=3.5,<5.0)", "tox"]
|
||||
docs = ["alabaster (==1.0.0)", "autodocsumm (==0.2.14)", "sphinx (==8.1.3)", "sphinx-issues (==5.0.0)", "sphinx-version-warning (==1.1.2)"]
|
||||
docs = ["alabaster (==1.0.0)", "autodocsumm (==0.2.14)", "sphinx (==8.1.3)", "sphinx-issues (==5.0.0)"]
|
||||
tests = ["pytest", "simplejson"]
|
||||
|
||||
[[package]]
|
||||
@@ -4548,18 +4549,18 @@ test = ["flaky", "ipykernel (>=6.19.3)", "ipython", "ipywidgets", "nbconvert (>=
|
||||
|
||||
[[package]]
|
||||
name = "nbconvert"
|
||||
version = "7.16.4"
|
||||
version = "7.16.5"
|
||||
description = "Converting Jupyter Notebooks (.ipynb files) to other formats. Output formats include asciidoc, html, latex, markdown, pdf, py, rst, script. nbconvert can be used both as a Python library (`import nbconvert`) or as a command line tool (invoked as `jupyter nbconvert ...`)."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "nbconvert-7.16.4-py3-none-any.whl", hash = "sha256:05873c620fe520b6322bf8a5ad562692343fe3452abda5765c7a34b7d1aa3eb3"},
|
||||
{file = "nbconvert-7.16.4.tar.gz", hash = "sha256:86ca91ba266b0a448dc96fa6c5b9d98affabde2867b363258703536807f9f7f4"},
|
||||
{file = "nbconvert-7.16.5-py3-none-any.whl", hash = "sha256:e12eac052d6fd03040af4166c563d76e7aeead2e9aadf5356db552a1784bd547"},
|
||||
{file = "nbconvert-7.16.5.tar.gz", hash = "sha256:c83467bb5777fdfaac5ebbb8e864f300b277f68692ecc04d6dab72f2d8442344"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
beautifulsoup4 = "*"
|
||||
bleach = "!=5.0.0"
|
||||
bleach = {version = "!=5.0.0", extras = ["css"]}
|
||||
defusedxml = "*"
|
||||
jinja2 = ">=3.0"
|
||||
jupyter-core = ">=4.7"
|
||||
@@ -4571,7 +4572,6 @@ nbformat = ">=5.7"
|
||||
packaging = "*"
|
||||
pandocfilters = ">=1.4.1"
|
||||
pygments = ">=2.4.1"
|
||||
tinycss2 = "*"
|
||||
traitlets = ">=5.1"
|
||||
|
||||
[package.extras]
|
||||
@@ -4727,13 +4727,13 @@ sympy = "*"
|
||||
|
||||
[[package]]
|
||||
name = "openai"
|
||||
version = "1.58.1"
|
||||
version = "1.59.3"
|
||||
description = "The official Python library for the openai API"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "openai-1.58.1-py3-none-any.whl", hash = "sha256:e2910b1170a6b7f88ef491ac3a42c387f08bd3db533411f7ee391d166571d63c"},
|
||||
{file = "openai-1.58.1.tar.gz", hash = "sha256:f5a035fd01e141fc743f4b0e02c41ca49be8fab0866d3b67f5f29b4f4d3c0973"},
|
||||
{file = "openai-1.59.3-py3-none-any.whl", hash = "sha256:b041887a0d8f3e70d1fc6ffbb2bf7661c3b9a2f3e806c04bf42f572b9ac7bc37"},
|
||||
{file = "openai-1.59.3.tar.gz", hash = "sha256:7f7fff9d8729968588edf1524e73266e8593bb6cab09298340efb755755bb66f"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -5438,13 +5438,13 @@ testing = ["pytest", "pytest-benchmark"]
|
||||
|
||||
[[package]]
|
||||
name = "posthog"
|
||||
version = "3.7.4"
|
||||
version = "3.7.5"
|
||||
description = "Integrate PostHog into any python application."
|
||||
optional = true
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "posthog-3.7.4-py2.py3-none-any.whl", hash = "sha256:21c18c6bf43b2de303ea4cd6e95804cc0f24c20cb2a96a8fd09da2ed50b62faa"},
|
||||
{file = "posthog-3.7.4.tar.gz", hash = "sha256:19384bd09d330f9787a7e2446aba14c8057ece56144970ea2791072d4e40cd36"},
|
||||
{file = "posthog-3.7.5-py2.py3-none-any.whl", hash = "sha256:022132c17069dde03c5c5904e2ae1b9bd68d5059cbc5a8dffc5c1537a1b71cb5"},
|
||||
{file = "posthog-3.7.5.tar.gz", hash = "sha256:8ba40ab623da35db72715fc87fe7dccb7fc272ced92581fe31db2d4dbe7ad761"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -5488,13 +5488,13 @@ selenium = ">=4.18.1,<5.0.0"
|
||||
|
||||
[[package]]
|
||||
name = "praisonaiagents"
|
||||
version = "0.0.14"
|
||||
version = "0.0.23"
|
||||
description = "Praison AI agents for completing complex tasks with Self Reflection Agents"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "praisonaiagents-0.0.14-py3-none-any.whl", hash = "sha256:6d239d91911ca289aa7be0badebc7c18e187bdae7dc9248072a8c570fe0fbeef"},
|
||||
{file = "praisonaiagents-0.0.14.tar.gz", hash = "sha256:1acb94dc5e2fa677f922e0d3d23df0748f02982ebb52d3309c5f2295e49b39cc"},
|
||||
{file = "praisonaiagents-0.0.23-py3-none-any.whl", hash = "sha256:d6aaa406fc993ccd0a763aa426b7139c955e1cd99e6b204b06817ebc1a5855e3"},
|
||||
{file = "praisonaiagents-0.0.23.tar.gz", hash = "sha256:1814d537b2625a5c7d4b61d07f5d5bd043f0ad8afc31fe9d4eb99a5ca54101bf"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -5522,20 +5522,20 @@ virtualenv = ">=20.10.0"
|
||||
|
||||
[[package]]
|
||||
name = "primp"
|
||||
version = "0.9.2"
|
||||
version = "0.9.3"
|
||||
description = "HTTP client that can impersonate web browsers, mimicking their headers and `TLS/JA3/JA4/HTTP2` fingerprints"
|
||||
optional = true
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "primp-0.9.2-cp38-abi3-macosx_10_12_x86_64.whl", hash = "sha256:a3179640e633be843ed5daba5c4e3086ad91f77c7bb40a9db06326f28d56b12b"},
|
||||
{file = "primp-0.9.2-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:94a5da8ba25f74152b43bc16a7591dfb5d7d30a5827dc0a0f96a956f7d3616be"},
|
||||
{file = "primp-0.9.2-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0668c0abb6d56fc8b0a918179b1d0f68e7267c1dc632e2b683c618317e13143f"},
|
||||
{file = "primp-0.9.2-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:a9c29a4b8eabfc28a1746d2fe93d33b9fcf2e81e642dd0e3eaecede60cc36b7d"},
|
||||
{file = "primp-0.9.2-cp38-abi3-manylinux_2_34_armv7l.whl", hash = "sha256:04d499308a101b06b40f5fda1bdc795db5731cd0dfbb1a8873f4acd07c085b1d"},
|
||||
{file = "primp-0.9.2-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:4cd5daf39034a0a8c96cdc0c4c306184c6f2b1b2a0b39dc3294d79ed28a6f7fe"},
|
||||
{file = "primp-0.9.2-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:8d14653434837eb431b3cf7ca006647d7a196906e48bba96bb600ba2ba70bcdc"},
|
||||
{file = "primp-0.9.2-cp38-abi3-win_amd64.whl", hash = "sha256:80d9f07564dc9b25b1a9676df770561418557c124fedecae84f6491a1974b61d"},
|
||||
{file = "primp-0.9.2.tar.gz", hash = "sha256:5b95666c25b9107eab3c05a89cb7b1748d5122e57c57b25bfc3249d525c45300"},
|
||||
{file = "primp-0.9.3-cp38-abi3-macosx_10_12_x86_64.whl", hash = "sha256:30d5c4f03abeab8fd307ddf4c615d8d093367f3be1a5299078f811982db7cb6f"},
|
||||
{file = "primp-0.9.3-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:3e3bff0bcffdf746b68486db24ac6dc6db2f202f048f82e0303385ef76dc5c1e"},
|
||||
{file = "primp-0.9.3-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15325ec0b916e48a65929f647d7dd12fb1400e76a6aeba72f7e205c94c4aaa82"},
|
||||
{file = "primp-0.9.3-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:de97cc10130a68edcd4e173cf01c628a10b9b6a6e19393200b12f1a1ddcb863d"},
|
||||
{file = "primp-0.9.3-cp38-abi3-manylinux_2_34_armv7l.whl", hash = "sha256:cba94e48c9b245a9daac96807aa020525c1a66c1141d4c2b11db4e2ccb69da33"},
|
||||
{file = "primp-0.9.3-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:1d1df5a9808b82b960df1f72ff53a9ab9c77dce61fcbe5776a11cf5f59dd7f28"},
|
||||
{file = "primp-0.9.3-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:484fc69dbed5ca14561d54aecd17f011c8ffa495023134bb9a94edb808ae3e1b"},
|
||||
{file = "primp-0.9.3-cp38-abi3-win_amd64.whl", hash = "sha256:824a5606ad67cb842ccc5158f19f9ccd1387e25e1374edd69f87cd7616cf3ea9"},
|
||||
{file = "primp-0.9.3.tar.gz", hash = "sha256:bc6490c659c741c6586bd160ed51b2e04f9dbc3b61bc1dd1af1ce66eefea663e"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
@@ -6161,13 +6161,13 @@ requests = ">=2.14.0"
|
||||
|
||||
[[package]]
|
||||
name = "pygments"
|
||||
version = "2.18.0"
|
||||
version = "2.19.1"
|
||||
description = "Pygments is a syntax highlighting package written in Python."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"},
|
||||
{file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"},
|
||||
{file = "pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c"},
|
||||
{file = "pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
@@ -7168,29 +7168,29 @@ pyasn1 = ">=0.1.3"
|
||||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.8.4"
|
||||
version = "0.8.6"
|
||||
description = "An extremely fast Python linter and code formatter, written in Rust."
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "ruff-0.8.4-py3-none-linux_armv6l.whl", hash = "sha256:58072f0c06080276804c6a4e21a9045a706584a958e644353603d36ca1eb8a60"},
|
||||
{file = "ruff-0.8.4-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ffb60904651c00a1e0b8df594591770018a0f04587f7deeb3838344fe3adabac"},
|
||||
{file = "ruff-0.8.4-py3-none-macosx_11_0_arm64.whl", hash = "sha256:6ddf5d654ac0d44389f6bf05cee4caeefc3132a64b58ea46738111d687352296"},
|
||||
{file = "ruff-0.8.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e248b1f0fa2749edd3350a2a342b67b43a2627434c059a063418e3d375cfe643"},
|
||||
{file = "ruff-0.8.4-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bf197b98ed86e417412ee3b6c893f44c8864f816451441483253d5ff22c0e81e"},
|
||||
{file = "ruff-0.8.4-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c41319b85faa3aadd4d30cb1cffdd9ac6b89704ff79f7664b853785b48eccdf3"},
|
||||
{file = "ruff-0.8.4-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:9f8402b7c4f96463f135e936d9ab77b65711fcd5d72e5d67597b543bbb43cf3f"},
|
||||
{file = "ruff-0.8.4-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e4e56b3baa9c23d324ead112a4fdf20db9a3f8f29eeabff1355114dd96014604"},
|
||||
{file = "ruff-0.8.4-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:736272574e97157f7edbbb43b1d046125fce9e7d8d583d5d65d0c9bf2c15addf"},
|
||||
{file = "ruff-0.8.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5fe710ab6061592521f902fca7ebcb9fabd27bc7c57c764298b1c1f15fff720"},
|
||||
{file = "ruff-0.8.4-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:13e9ec6d6b55f6da412d59953d65d66e760d583dd3c1c72bf1f26435b5bfdbae"},
|
||||
{file = "ruff-0.8.4-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:97d9aefef725348ad77d6db98b726cfdb075a40b936c7984088804dfd38268a7"},
|
||||
{file = "ruff-0.8.4-py3-none-musllinux_1_2_i686.whl", hash = "sha256:ab78e33325a6f5374e04c2ab924a3367d69a0da36f8c9cb6b894a62017506111"},
|
||||
{file = "ruff-0.8.4-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:8ef06f66f4a05c3ddbc9121a8b0cecccd92c5bf3dd43b5472ffe40b8ca10f0f8"},
|
||||
{file = "ruff-0.8.4-py3-none-win32.whl", hash = "sha256:552fb6d861320958ca5e15f28b20a3d071aa83b93caee33a87b471f99a6c0835"},
|
||||
{file = "ruff-0.8.4-py3-none-win_amd64.whl", hash = "sha256:f21a1143776f8656d7f364bd264a9d60f01b7f52243fbe90e7670c0dfe0cf65d"},
|
||||
{file = "ruff-0.8.4-py3-none-win_arm64.whl", hash = "sha256:9183dd615d8df50defa8b1d9a074053891ba39025cf5ae88e8bcb52edcc4bf08"},
|
||||
{file = "ruff-0.8.4.tar.gz", hash = "sha256:0d5f89f254836799af1615798caa5f80b7f935d7a670fad66c5007928e57ace8"},
|
||||
{file = "ruff-0.8.6-py3-none-linux_armv6l.whl", hash = "sha256:defed167955d42c68b407e8f2e6f56ba52520e790aba4ca707a9c88619e580e3"},
|
||||
{file = "ruff-0.8.6-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:54799ca3d67ae5e0b7a7ac234baa657a9c1784b48ec954a094da7c206e0365b1"},
|
||||
{file = "ruff-0.8.6-py3-none-macosx_11_0_arm64.whl", hash = "sha256:e88b8f6d901477c41559ba540beeb5a671e14cd29ebd5683903572f4b40a9807"},
|
||||
{file = "ruff-0.8.6-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0509e8da430228236a18a677fcdb0c1f102dd26d5520f71f79b094963322ed25"},
|
||||
{file = "ruff-0.8.6-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:91a7ddb221779871cf226100e677b5ea38c2d54e9e2c8ed847450ebbdf99b32d"},
|
||||
{file = "ruff-0.8.6-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:248b1fb3f739d01d528cc50b35ee9c4812aa58cc5935998e776bf8ed5b251e75"},
|
||||
{file = "ruff-0.8.6-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:bc3c083c50390cf69e7e1b5a5a7303898966be973664ec0c4a4acea82c1d4315"},
|
||||
{file = "ruff-0.8.6-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:52d587092ab8df308635762386f45f4638badb0866355b2b86760f6d3c076188"},
|
||||
{file = "ruff-0.8.6-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:61323159cf21bc3897674e5adb27cd9e7700bab6b84de40d7be28c3d46dc67cf"},
|
||||
{file = "ruff-0.8.6-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ae4478b1471fc0c44ed52a6fb787e641a2ac58b1c1f91763bafbc2faddc5117"},
|
||||
{file = "ruff-0.8.6-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:0c000a471d519b3e6cfc9c6680025d923b4ca140ce3e4612d1a2ef58e11f11fe"},
|
||||
{file = "ruff-0.8.6-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:9257aa841e9e8d9b727423086f0fa9a86b6b420fbf4bf9e1465d1250ce8e4d8d"},
|
||||
{file = "ruff-0.8.6-py3-none-musllinux_1_2_i686.whl", hash = "sha256:45a56f61b24682f6f6709636949ae8cc82ae229d8d773b4c76c09ec83964a95a"},
|
||||
{file = "ruff-0.8.6-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:496dd38a53aa173481a7d8866bcd6451bd934d06976a2505028a50583e001b76"},
|
||||
{file = "ruff-0.8.6-py3-none-win32.whl", hash = "sha256:e169ea1b9eae61c99b257dc83b9ee6c76f89042752cb2d83486a7d6e48e8f764"},
|
||||
{file = "ruff-0.8.6-py3-none-win_amd64.whl", hash = "sha256:f1d70bef3d16fdc897ee290d7d20da3cbe4e26349f62e8a0274e7a3f4ce7a905"},
|
||||
{file = "ruff-0.8.6-py3-none-win_arm64.whl", hash = "sha256:7d7fc2377a04b6e04ffe588caad613d0c460eb2ecba4c0ccbbfe2bc973cbc162"},
|
||||
{file = "ruff-0.8.6.tar.gz", hash = "sha256:dcad24b81b62650b0eb8814f576fc65cfee8674772a6e24c9b747911801eeaa5"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -7263,53 +7263,60 @@ tests = ["black (>=24.3.0)", "matplotlib (>=3.3.4)", "mypy (>=1.9)", "numpydoc (
|
||||
|
||||
[[package]]
|
||||
name = "scipy"
|
||||
version = "1.14.1"
|
||||
version = "1.15.0"
|
||||
description = "Fundamental algorithms for scientific computing in Python"
|
||||
optional = true
|
||||
python-versions = ">=3.10"
|
||||
files = [
|
||||
{file = "scipy-1.14.1-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:b28d2ca4add7ac16ae8bb6632a3c86e4b9e4d52d3e34267f6e1b0c1f8d87e389"},
|
||||
{file = "scipy-1.14.1-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:d0d2821003174de06b69e58cef2316a6622b60ee613121199cb2852a873f8cf3"},
|
||||
{file = "scipy-1.14.1-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:8bddf15838ba768bb5f5083c1ea012d64c9a444e16192762bd858f1e126196d0"},
|
||||
{file = "scipy-1.14.1-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:97c5dddd5932bd2a1a31c927ba5e1463a53b87ca96b5c9bdf5dfd6096e27efc3"},
|
||||
{file = "scipy-1.14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ff0a7e01e422c15739ecd64432743cf7aae2b03f3084288f399affcefe5222d"},
|
||||
{file = "scipy-1.14.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e32dced201274bf96899e6491d9ba3e9a5f6b336708656466ad0522d8528f69"},
|
||||
{file = "scipy-1.14.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8426251ad1e4ad903a4514712d2fa8fdd5382c978010d1c6f5f37ef286a713ad"},
|
||||
{file = "scipy-1.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:a49f6ed96f83966f576b33a44257d869756df6cf1ef4934f59dd58b25e0327e5"},
|
||||
{file = "scipy-1.14.1-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:2da0469a4ef0ecd3693761acbdc20f2fdeafb69e6819cc081308cc978153c675"},
|
||||
{file = "scipy-1.14.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:c0ee987efa6737242745f347835da2cc5bb9f1b42996a4d97d5c7ff7928cb6f2"},
|
||||
{file = "scipy-1.14.1-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:3a1b111fac6baec1c1d92f27e76511c9e7218f1695d61b59e05e0fe04dc59617"},
|
||||
{file = "scipy-1.14.1-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:8475230e55549ab3f207bff11ebfc91c805dc3463ef62eda3ccf593254524ce8"},
|
||||
{file = "scipy-1.14.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:278266012eb69f4a720827bdd2dc54b2271c97d84255b2faaa8f161a158c3b37"},
|
||||
{file = "scipy-1.14.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fef8c87f8abfb884dac04e97824b61299880c43f4ce675dd2cbeadd3c9b466d2"},
|
||||
{file = "scipy-1.14.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b05d43735bb2f07d689f56f7b474788a13ed8adc484a85aa65c0fd931cf9ccd2"},
|
||||
{file = "scipy-1.14.1-cp311-cp311-win_amd64.whl", hash = "sha256:716e389b694c4bb564b4fc0c51bc84d381735e0d39d3f26ec1af2556ec6aad94"},
|
||||
{file = "scipy-1.14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:631f07b3734d34aced009aaf6fedfd0eb3498a97e581c3b1e5f14a04164a456d"},
|
||||
{file = "scipy-1.14.1-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:af29a935803cc707ab2ed7791c44288a682f9c8107bc00f0eccc4f92c08d6e07"},
|
||||
{file = "scipy-1.14.1-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:2843f2d527d9eebec9a43e6b406fb7266f3af25a751aa91d62ff416f54170bc5"},
|
||||
{file = "scipy-1.14.1-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:eb58ca0abd96911932f688528977858681a59d61a7ce908ffd355957f7025cfc"},
|
||||
{file = "scipy-1.14.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:30ac8812c1d2aab7131a79ba62933a2a76f582d5dbbc695192453dae67ad6310"},
|
||||
{file = "scipy-1.14.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f9ea80f2e65bdaa0b7627fb00cbeb2daf163caa015e59b7516395fe3bd1e066"},
|
||||
{file = "scipy-1.14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:edaf02b82cd7639db00dbff629995ef185c8df4c3ffa71a5562a595765a06ce1"},
|
||||
{file = "scipy-1.14.1-cp312-cp312-win_amd64.whl", hash = "sha256:2ff38e22128e6c03ff73b6bb0f85f897d2362f8c052e3b8ad00532198fbdae3f"},
|
||||
{file = "scipy-1.14.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1729560c906963fc8389f6aac023739ff3983e727b1a4d87696b7bf108316a79"},
|
||||
{file = "scipy-1.14.1-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:4079b90df244709e675cdc8b93bfd8a395d59af40b72e339c2287c91860deb8e"},
|
||||
{file = "scipy-1.14.1-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:e0cf28db0f24a38b2a0ca33a85a54852586e43cf6fd876365c86e0657cfe7d73"},
|
||||
{file = "scipy-1.14.1-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:0c2f95de3b04e26f5f3ad5bb05e74ba7f68b837133a4492414b3afd79dfe540e"},
|
||||
{file = "scipy-1.14.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b99722ea48b7ea25e8e015e8341ae74624f72e5f21fc2abd45f3a93266de4c5d"},
|
||||
{file = "scipy-1.14.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5149e3fd2d686e42144a093b206aef01932a0059c2a33ddfa67f5f035bdfe13e"},
|
||||
{file = "scipy-1.14.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e4f5a7c49323533f9103d4dacf4e4f07078f360743dec7f7596949149efeec06"},
|
||||
{file = "scipy-1.14.1-cp313-cp313-win_amd64.whl", hash = "sha256:baff393942b550823bfce952bb62270ee17504d02a1801d7fd0719534dfb9c84"},
|
||||
{file = "scipy-1.14.1.tar.gz", hash = "sha256:5a275584e726026a5699459aa72f828a610821006228e841b94275c4a7c08417"},
|
||||
{file = "scipy-1.15.0-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:aeac60d3562a7bf2f35549bdfdb6b1751c50590f55ce7322b4b2fc821dc27fca"},
|
||||
{file = "scipy-1.15.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:5abbdc6ede5c5fed7910cf406a948e2c0869231c0db091593a6b2fa78be77e5d"},
|
||||
{file = "scipy-1.15.0-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:eb1533c59f0ec6c55871206f15a5c72d1fae7ad3c0a8ca33ca88f7c309bbbf8c"},
|
||||
{file = "scipy-1.15.0-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:de112c2dae53107cfeaf65101419662ac0a54e9a088c17958b51c95dac5de56d"},
|
||||
{file = "scipy-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2240e1fd0782e62e1aacdc7234212ee271d810f67e9cd3b8d521003a82603ef8"},
|
||||
{file = "scipy-1.15.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d35aef233b098e4de88b1eac29f0df378278e7e250a915766786b773309137c4"},
|
||||
{file = "scipy-1.15.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:1b29e4fc02e155a5fd1165f1e6a73edfdd110470736b0f48bcbe48083f0eee37"},
|
||||
{file = "scipy-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:0e5b34f8894f9904cc578008d1a9467829c1817e9f9cb45e6d6eeb61d2ab7731"},
|
||||
{file = "scipy-1.15.0-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:46e91b5b16909ff79224b56e19cbad65ca500b3afda69225820aa3afbf9ec020"},
|
||||
{file = "scipy-1.15.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:82bff2eb01ccf7cea8b6ee5274c2dbeadfdac97919da308ee6d8e5bcbe846443"},
|
||||
{file = "scipy-1.15.0-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:9c8254fe21dd2c6c8f7757035ec0c31daecf3bb3cffd93bc1ca661b731d28136"},
|
||||
{file = "scipy-1.15.0-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:c9624eeae79b18cab1a31944b5ef87aa14b125d6ab69b71db22f0dbd962caf1e"},
|
||||
{file = "scipy-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d13bbc0658c11f3d19df4138336e4bce2c4fbd78c2755be4bf7b8e235481557f"},
|
||||
{file = "scipy-1.15.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bdca4c7bb8dc41307e5f39e9e5d19c707d8e20a29845e7533b3bb20a9d4ccba0"},
|
||||
{file = "scipy-1.15.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6f376d7c767731477bac25a85d0118efdc94a572c6b60decb1ee48bf2391a73b"},
|
||||
{file = "scipy-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:61513b989ee8d5218fbeb178b2d51534ecaddba050db949ae99eeb3d12f6825d"},
|
||||
{file = "scipy-1.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:5beb0a2200372b7416ec73fdae94fe81a6e85e44eb49c35a11ac356d2b8eccc6"},
|
||||
{file = "scipy-1.15.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:fde0f3104dfa1dfbc1f230f65506532d0558d43188789eaf68f97e106249a913"},
|
||||
{file = "scipy-1.15.0-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:35c68f7044b4e7ad73a3e68e513dda946989e523df9b062bd3cf401a1a882192"},
|
||||
{file = "scipy-1.15.0-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:52475011be29dfcbecc3dfe3060e471ac5155d72e9233e8d5616b84e2b542054"},
|
||||
{file = "scipy-1.15.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5972e3f96f7dda4fd3bb85906a17338e65eaddfe47f750e240f22b331c08858e"},
|
||||
{file = "scipy-1.15.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe00169cf875bed0b3c40e4da45b57037dc21d7c7bf0c85ed75f210c281488f1"},
|
||||
{file = "scipy-1.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:161f80a98047c219c257bf5ce1777c574bde36b9d962a46b20d0d7e531f86863"},
|
||||
{file = "scipy-1.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:327163ad73e54541a675240708244644294cb0a65cca420c9c79baeb9648e479"},
|
||||
{file = "scipy-1.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0fcb16eb04d84670722ce8d93b05257df471704c913cb0ff9dc5a1c31d1e9422"},
|
||||
{file = "scipy-1.15.0-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:767e8cf6562931f8312f4faa7ddea412cb783d8df49e62c44d00d89f41f9bbe8"},
|
||||
{file = "scipy-1.15.0-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:37ce9394cdcd7c5f437583fc6ef91bd290014993900643fdfc7af9b052d1613b"},
|
||||
{file = "scipy-1.15.0-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:6d26f17c64abd6c6c2dfb39920f61518cc9e213d034b45b2380e32ba78fde4c0"},
|
||||
{file = "scipy-1.15.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e2448acd79c6374583581a1ded32ac71a00c2b9c62dfa87a40e1dd2520be111"},
|
||||
{file = "scipy-1.15.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36be480e512d38db67f377add5b759fb117edd987f4791cdf58e59b26962bee4"},
|
||||
{file = "scipy-1.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ccb6248a9987193fe74363a2d73b93bc2c546e0728bd786050b7aef6e17db03c"},
|
||||
{file = "scipy-1.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:952d2e9eaa787f0a9e95b6e85da3654791b57a156c3e6609e65cc5176ccfe6f2"},
|
||||
{file = "scipy-1.15.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:b1432102254b6dc7766d081fa92df87832ac25ff0b3d3a940f37276e63eb74ff"},
|
||||
{file = "scipy-1.15.0-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:4e08c6a36f46abaedf765dd2dfcd3698fa4bd7e311a9abb2d80e33d9b2d72c34"},
|
||||
{file = "scipy-1.15.0-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:ec915cd26d76f6fc7ae8522f74f5b2accf39546f341c771bb2297f3871934a52"},
|
||||
{file = "scipy-1.15.0-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:351899dd2a801edd3691622172bc8ea01064b1cada794f8641b89a7dc5418db6"},
|
||||
{file = "scipy-1.15.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9baff912ea4f78a543d183ed6f5b3bea9784509b948227daaf6f10727a0e2e5"},
|
||||
{file = "scipy-1.15.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:cd9d9198a7fd9a77f0eb5105ea9734df26f41faeb2a88a0e62e5245506f7b6df"},
|
||||
{file = "scipy-1.15.0-cp313-cp313t-win_amd64.whl", hash = "sha256:129f899ed275c0515d553b8d31696924e2ca87d1972421e46c376b9eb87de3d2"},
|
||||
{file = "scipy-1.15.0.tar.gz", hash = "sha256:300742e2cc94e36a2880ebe464a1c8b4352a7b0f3e36ec3d2ac006cdbe0219ac"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
numpy = ">=1.23.5,<2.3"
|
||||
numpy = ">=1.23.5,<2.5"
|
||||
|
||||
[package.extras]
|
||||
dev = ["cython-lint (>=0.12.2)", "doit (>=0.36.0)", "mypy (==1.10.0)", "pycodestyle", "pydevtool", "rich-click", "ruff (>=0.0.292)", "types-psutil", "typing_extensions"]
|
||||
doc = ["jupyterlite-pyodide-kernel", "jupyterlite-sphinx (>=0.13.1)", "jupytext", "matplotlib (>=3.5)", "myst-nb", "numpydoc", "pooch", "pydata-sphinx-theme (>=0.15.2)", "sphinx (>=5.0.0,<=7.3.7)", "sphinx-design (>=0.4.0)"]
|
||||
test = ["Cython", "array-api-strict (>=2.0)", "asv", "gmpy2", "hypothesis (>=6.30)", "meson", "mpmath", "ninja", "pooch", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "scikit-umfpack", "threadpoolctl"]
|
||||
doc = ["intersphinx_registry", "jupyterlite-pyodide-kernel", "jupyterlite-sphinx (>=0.16.5)", "jupytext", "matplotlib (>=3.5)", "myst-nb", "numpydoc", "pooch", "pydata-sphinx-theme (>=0.15.2)", "sphinx (>=5.0.0,<8.0.0)", "sphinx-copybutton", "sphinx-design (>=0.4.0)"]
|
||||
test = ["Cython", "array-api-strict (>=2.0,<2.1.1)", "asv", "gmpy2", "hypothesis (>=6.30)", "meson", "mpmath", "ninja", "pooch", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "scikit-umfpack", "threadpoolctl"]
|
||||
|
||||
[[package]]
|
||||
name = "selenium"
|
||||
@@ -7358,23 +7365,23 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "setuptools"
|
||||
version = "75.6.0"
|
||||
version = "75.7.0"
|
||||
description = "Easily download, build, install, upgrade, and uninstall Python packages"
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
files = [
|
||||
{file = "setuptools-75.6.0-py3-none-any.whl", hash = "sha256:ce74b49e8f7110f9bf04883b730f4765b774ef3ef28f722cce7c273d253aaf7d"},
|
||||
{file = "setuptools-75.6.0.tar.gz", hash = "sha256:8199222558df7c86216af4f84c30e9b34a61d8ba19366cc914424cdbd28252f6"},
|
||||
{file = "setuptools-75.7.0-py3-none-any.whl", hash = "sha256:84fb203f278ebcf5cd08f97d3fb96d3fbed4b629d500b29ad60d11e00769b183"},
|
||||
{file = "setuptools-75.7.0.tar.gz", hash = "sha256:886ff7b16cd342f1d1defc16fc98c9ce3fde69e087a4e1983d7ab634e5f41f4f"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)", "ruff (>=0.7.0)"]
|
||||
check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)", "ruff (>=0.8.0)"]
|
||||
core = ["importlib_metadata (>=6)", "jaraco.collections", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more_itertools", "more_itertools (>=8.8)", "packaging", "packaging (>=24.2)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"]
|
||||
cover = ["pytest-cov"]
|
||||
doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"]
|
||||
enabler = ["pytest-enabler (>=2.2)"]
|
||||
test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"]
|
||||
type = ["importlib_metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (>=1.12,<1.14)", "pytest-mypy"]
|
||||
test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.7.2)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"]
|
||||
type = ["importlib_metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (==1.14.*)", "pytest-mypy"]
|
||||
|
||||
[[package]]
|
||||
name = "shapely"
|
||||
@@ -8271,13 +8278,13 @@ test = ["aiohttp (>=3.10.5)", "flake8 (>=5.0,<6.0)", "mypy (>=0.800)", "psutil",
|
||||
|
||||
[[package]]
|
||||
name = "virtualenv"
|
||||
version = "20.28.0"
|
||||
version = "20.28.1"
|
||||
description = "Virtual Python Environment builder"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "virtualenv-20.28.0-py3-none-any.whl", hash = "sha256:23eae1b4516ecd610481eda647f3a7c09aea295055337331bb4e6892ecce47b0"},
|
||||
{file = "virtualenv-20.28.0.tar.gz", hash = "sha256:2c9c3262bb8e7b87ea801d715fae4495e6032450c71d2309be9550e7364049aa"},
|
||||
{file = "virtualenv-20.28.1-py3-none-any.whl", hash = "sha256:412773c85d4dab0409b83ec36f7a6499e72eaf08c80e81e9576bca61831c71cb"},
|
||||
{file = "virtualenv-20.28.1.tar.gz", hash = "sha256:5d34ab240fdb5d21549b76f9e8ff3af28252f5499fb6d6f031adac4e5a8c5329"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -8822,9 +8829,9 @@ gradio = ["gradio"]
|
||||
openai = ["langchain-openai"]
|
||||
realtime = ["aiosqlite", "chainlit", "crawl4ai", "duckduckgo_search", "greenlet", "litellm", "plotly", "sqlalchemy", "tavily-python", "websockets", "yfinance"]
|
||||
train = []
|
||||
ui = ["chainlit"]
|
||||
ui = ["aiosqlite", "chainlit", "greenlet", "pydantic", "sqlalchemy"]
|
||||
|
||||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = ">=3.10,<3.13"
|
||||
content-hash = "eb9727e6cb210753564b5c109a9e353f65d5f4c79889e0a3c4e8ce5080ee23e4"
|
||||
content-hash = "596dee1ab307caacfd8041e13a29b60d0b793274e7ea45890b827a92e8c2dd40"
|
||||
+1
-1
@@ -3,7 +3,7 @@ class Praisonai < Formula
|
||||
|
||||
desc "AI tools for various AI applications"
|
||||
homepage "https://github.com/MervinPraison/PraisonAI"
|
||||
url "https://github.com/MervinPraison/PraisonAI/archive/refs/tags/2.0.31.tar.gz"
|
||||
url "https://github.com/MervinPraison/PraisonAI/archive/refs/tags/2.0.34.tar.gz"
|
||||
sha256 "1828fb9227d10f991522c3f24f061943a254b667196b40b1a3e4a54a8d30ce32" # Replace with actual SHA256 checksum
|
||||
license "MIT"
|
||||
|
||||
|
||||
+1
-1
@@ -56,7 +56,7 @@ class CloudDeployer:
|
||||
file.write("FROM python:3.11-slim\n")
|
||||
file.write("WORKDIR /app\n")
|
||||
file.write("COPY . .\n")
|
||||
file.write("RUN pip install flask praisonai==2.0.31 gunicorn markdown\n")
|
||||
file.write("RUN pip install flask praisonai==2.0.34 gunicorn markdown\n")
|
||||
file.write("EXPOSE 8080\n")
|
||||
file.write('CMD ["gunicorn", "-b", "0.0.0.0:8080", "api:app"]\n')
|
||||
|
||||
|
||||
+4
-4
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "PraisonAI"
|
||||
version = "2.0.31"
|
||||
version = "2.0.34"
|
||||
description = "PraisonAI is an AI Agents Framework with Self Reflection. PraisonAI application combines PraisonAI Agents, AutoGen, and CrewAI into a low-code solution for building and managing multi-agent LLM systems, focusing on simplicity, customisation, and efficient human–agent collaboration."
|
||||
readme = "README.md"
|
||||
license = ""
|
||||
@@ -12,7 +12,7 @@ dependencies = [
|
||||
"rich>=13.7",
|
||||
"markdown>=3.5",
|
||||
"pyparsing>=3.0.0",
|
||||
"praisonaiagents>=0.0.22",
|
||||
"praisonaiagents>=0.0.25",
|
||||
"python-dotenv>=0.19.0",
|
||||
"instructor>=1.3.3",
|
||||
"PyYAML>=6.0",
|
||||
@@ -84,7 +84,7 @@ autogen = ["pyautogen>=0.2.19", "praisonai-tools>=0.0.7", "crewai"]
|
||||
|
||||
[tool.poetry]
|
||||
name = "PraisonAI"
|
||||
version = "2.0.31"
|
||||
version = "2.0.34"
|
||||
description = "PraisonAI is an AI Agents Framework with Self Reflection. PraisonAI application combines PraisonAI Agents, AutoGen, and CrewAI into a low-code solution for building and managing multi-agent LLM systems, focusing on simplicity, customisation, and efficient human–agent collaboration."
|
||||
authors = ["Mervin Praison"]
|
||||
license = ""
|
||||
@@ -102,7 +102,7 @@ python = ">=3.10,<3.13"
|
||||
rich = ">=13.7"
|
||||
markdown = ">=3.5"
|
||||
pyparsing = ">=3.0.0"
|
||||
praisonaiagents = ">=0.0.22"
|
||||
praisonaiagents = ">=0.0.25"
|
||||
python-dotenv = ">=0.19.0"
|
||||
instructor = ">=1.3.3"
|
||||
PyYAML = ">=6.0"
|
||||
|
||||
@@ -672,7 +672,7 @@ name = "click"
|
||||
version = "8.1.8"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "colorama", marker = "platform_system == 'Windows'" },
|
||||
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/b9/2e/0090cbf739cee7d23781ad4b89a9894a41538e4fcf4c31dcdd705b78eb8b/click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a", size = 226593 }
|
||||
wheels = [
|
||||
@@ -3061,7 +3061,7 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "praisonai"
|
||||
version = "2.0.31"
|
||||
version = "2.0.34"
|
||||
source = { editable = "." }
|
||||
dependencies = [
|
||||
{ name = "instructor" },
|
||||
@@ -3198,7 +3198,7 @@ requires-dist = [
|
||||
{ name = "plotly", marker = "extra == 'realtime'", specifier = ">=5.24.0" },
|
||||
{ name = "praisonai-tools", marker = "extra == 'autogen'", specifier = ">=0.0.7" },
|
||||
{ name = "praisonai-tools", marker = "extra == 'crewai'", specifier = ">=0.0.7" },
|
||||
{ name = "praisonaiagents", specifier = ">=0.0.22" },
|
||||
{ name = "praisonaiagents", specifier = ">=0.0.25" },
|
||||
{ name = "pyautogen", marker = "extra == 'autogen'", specifier = ">=0.2.19" },
|
||||
{ name = "pydantic", marker = "extra == 'chat'", specifier = "<=2.10.1" },
|
||||
{ name = "pydantic", marker = "extra == 'code'", specifier = "<=2.10.1" },
|
||||
@@ -3251,16 +3251,16 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "praisonaiagents"
|
||||
version = "0.0.22"
|
||||
version = "0.0.25"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "openai" },
|
||||
{ name = "pydantic" },
|
||||
{ name = "rich" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/c8/8d/a11ac1cfb7be9e03b7b498ddc2f7881e25fbf3a7dd08f8907aaecb5bac86/praisonaiagents-0.0.22.tar.gz", hash = "sha256:e40b079b9760fe08150e6641edf532cc9078ab330d42f38899678042cdbb94ca", size = 25454 }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/6c/9c/07a6fd1d939eb98ae6399fb16aad870f16dba7ab5d64825af2420a46c09b/praisonaiagents-0.0.25.tar.gz", hash = "sha256:2ef1292fa5e0a5dc5d1b982670f3d0c6bb1cd9c59febbcbe6c2b8af5fa21ca43", size = 61241 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/3a/8d/e75e2be19ff20f382b58b73e451c7bc54ab7179a71510b1ebb33183c6361/praisonaiagents-0.0.22-py3-none-any.whl", hash = "sha256:727ee9ed1b51cee757c03bfffdf55df1909091572e892d5aeeb3c4f54d7fb6c9", size = 31817 },
|
||||
{ url = "https://files.pythonhosted.org/packages/50/78/1ab28fe9e32f2d765052b3870532238f6c4a72a98168b73b443d76c0235f/praisonaiagents-0.0.25-py3-none-any.whl", hash = "sha256:5b0cf04f294d81dbee8be855fc7026cc190a05b1d169e286eb7e387b8f8bd7de", size = 80127 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4641,7 +4641,7 @@ name = "tqdm"
|
||||
version = "4.67.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "colorama", marker = "platform_system == 'Windows'" },
|
||||
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/a8/4b/29b4ef32e036bb34e4ab51796dd745cdba7ed47ad142a9f4a1eb8e0c744d/tqdm-4.67.1.tar.gz", hash = "sha256:f8aef9c52c08c13a65f30ea34f4e5aac3fd1a34959879d7e59e63027286627f2", size = 169737 }
|
||||
wheels = [
|
||||
@@ -5021,7 +5021,7 @@ version = "2.1.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "numpy" },
|
||||
{ name = "nvidia-nccl-cu12", marker = "platform_machine != 'aarch64' and platform_system == 'Linux'" },
|
||||
{ name = "nvidia-nccl-cu12", marker = "platform_machine != 'aarch64' and sys_platform == 'linux'" },
|
||||
{ name = "scipy" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/48/b0/131ffc4a15fd3acee9be3a7baa6b2fa6faa479799c51b880de9fc3ddf550/xgboost-2.1.3.tar.gz", hash = "sha256:7699ec4226156887d3afc665c63ab87469db9d46e361c702ba9fccd22535730c", size = 1090326 }
|
||||
|
||||
Reference in new issue
Block a user