diff --git a/agents/tools-class.py b/agents/tools-class.py new file mode 100644 index 0000000..1f4f15c --- /dev/null +++ b/agents/tools-class.py @@ -0,0 +1,115 @@ +from praisonaiagents import Agent, Task, PraisonAIAgents +import os +import requests +from typing import Any, Dict, List, Optional +from pydantic import BaseModel, Field + +class EXASearchTool(BaseModel): + """Wrapper for EXA Search API.""" + search_url: str = "https://api.exa.ai/search" + headers: Dict = { + "accept": "application/json", + "content-type": "application/json", + } + max_results: Optional[int] = None + + def run(self, query: str) -> str: + """Run query through EXA and return concatenated results. + + Args: + query (str): The search query to use + + Returns: + str: The concatenated search results + """ + payload = { + "query": query, + "type": "magic", + } + + headers = self.headers.copy() + headers["x-api-key"] = os.environ['EXA_API_KEY'] + + response = requests.post(self.search_url, json=payload, headers=headers) + results = response.json() + + if 'results' in results: + return self._parse_results(results['results']) + return "" + + def results(self, query: str, max_results: Optional[int] = None) -> List[Dict[str, Any]]: + """Run query through EXA and return metadata. + + Args: + query (str): The search query to use + max_results (Optional[int]): Maximum number of results to return + + Returns: + List[Dict[str, Any]]: List of result dictionaries + """ + payload = { + "query": query, + "type": "magic", + } + + headers = self.headers.copy() + headers["x-api-key"] = os.environ['EXA_API_KEY'] + + response = requests.post(self.search_url, json=payload, headers=headers) + results = response.json() + + if 'results' in results: + return results['results'][:max_results] if max_results else results['results'] + return [] + + def _parse_results(self, results: List[Dict[str, Any]]) -> str: + """Parse results into a readable string format. + + Args: + results (List[Dict[str, Any]]): List of result dictionaries + + Returns: + str: Formatted string of results + """ + strings = [] + for result in results: + try: + strings.append('\n'.join([ + f"Title: {result['title']}", + f"Score: {result['score']}", + f"Url: {result['url']}", + f"ID: {result['id']}", + "---" + ])) + except KeyError: + continue + + content = '\n'.join(strings) + return f"\nSearch results: {content}\n" + +# Create an agent with the tool +agent = Agent( + name="SearchAgent", + role="Research Assistant", + goal="Search for information about 'AI Agents Framework'", + backstory="I am an AI assistant that can search GitHub.", + tools=[EXASearchTool], + self_reflect=False +) + +# Create tasks to demonstrate both tools +task = Task( + name="search_task", + description="Search for information about 'AI Agents Framework'", + expected_output="Information about AI Agents Framework", + agent=agent +) + +# Create and start the workflow +agents = PraisonAIAgents( + agents=[agent], + tasks=[task], + verbose=True +) + +agents.start() \ No newline at end of file diff --git a/cookbooks/general/tools-class.py b/cookbooks/general/tools-class.py new file mode 100644 index 0000000..1f4f15c --- /dev/null +++ b/cookbooks/general/tools-class.py @@ -0,0 +1,115 @@ +from praisonaiagents import Agent, Task, PraisonAIAgents +import os +import requests +from typing import Any, Dict, List, Optional +from pydantic import BaseModel, Field + +class EXASearchTool(BaseModel): + """Wrapper for EXA Search API.""" + search_url: str = "https://api.exa.ai/search" + headers: Dict = { + "accept": "application/json", + "content-type": "application/json", + } + max_results: Optional[int] = None + + def run(self, query: str) -> str: + """Run query through EXA and return concatenated results. + + Args: + query (str): The search query to use + + Returns: + str: The concatenated search results + """ + payload = { + "query": query, + "type": "magic", + } + + headers = self.headers.copy() + headers["x-api-key"] = os.environ['EXA_API_KEY'] + + response = requests.post(self.search_url, json=payload, headers=headers) + results = response.json() + + if 'results' in results: + return self._parse_results(results['results']) + return "" + + def results(self, query: str, max_results: Optional[int] = None) -> List[Dict[str, Any]]: + """Run query through EXA and return metadata. + + Args: + query (str): The search query to use + max_results (Optional[int]): Maximum number of results to return + + Returns: + List[Dict[str, Any]]: List of result dictionaries + """ + payload = { + "query": query, + "type": "magic", + } + + headers = self.headers.copy() + headers["x-api-key"] = os.environ['EXA_API_KEY'] + + response = requests.post(self.search_url, json=payload, headers=headers) + results = response.json() + + if 'results' in results: + return results['results'][:max_results] if max_results else results['results'] + return [] + + def _parse_results(self, results: List[Dict[str, Any]]) -> str: + """Parse results into a readable string format. + + Args: + results (List[Dict[str, Any]]): List of result dictionaries + + Returns: + str: Formatted string of results + """ + strings = [] + for result in results: + try: + strings.append('\n'.join([ + f"Title: {result['title']}", + f"Score: {result['score']}", + f"Url: {result['url']}", + f"ID: {result['id']}", + "---" + ])) + except KeyError: + continue + + content = '\n'.join(strings) + return f"\nSearch results: {content}\n" + +# Create an agent with the tool +agent = Agent( + name="SearchAgent", + role="Research Assistant", + goal="Search for information about 'AI Agents Framework'", + backstory="I am an AI assistant that can search GitHub.", + tools=[EXASearchTool], + self_reflect=False +) + +# Create tasks to demonstrate both tools +task = Task( + name="search_task", + description="Search for information about 'AI Agents Framework'", + expected_output="Information about AI Agents Framework", + agent=agent +) + +# Create and start the workflow +agents = PraisonAIAgents( + agents=[agent], + tasks=[task], + verbose=True +) + +agents.start() \ No newline at end of file diff --git a/docs/features/async.mdx b/docs/features/async.mdx index aa1c33e..d4ec473 100644 --- a/docs/features/async.mdx +++ b/docs/features/async.mdx @@ -4,6 +4,26 @@ description: "Async AI Agents allow you to run AI tasks asynchronously, improvin icon: "clock" --- +```mermaid +flowchart LR + In[In] --> Agent1[AI Agent] + Agent1 --> Agent2[AI Agent] + Agent1 --> Agent3[AI Agent] + Agent1 --> Agent4[AI Agent] + Agent2 --> Out[Out] + Agent3 --> Out + Agent4 --> Out + + style In fill:#8B0000,color:#fff + style Agent1 fill:#2E8B57,color:#fff + style Agent2 fill:#2E8B57,color:#fff + style Agent3 fill:#2E8B57,color:#fff + style Agent4 fill:#2E8B57,color:#fff + style Out fill:#8B0000,color:#fff +``` + +Async AI Agents allow you to run AI tasks asynchronously, improving performance and efficiency in your applications. + ## Quick Start diff --git a/docs/features/autoagents.mdx b/docs/features/autoagents.mdx index 2aa3595..a4d5c7a 100644 --- a/docs/features/autoagents.mdx +++ b/docs/features/autoagents.mdx @@ -4,6 +4,47 @@ description: "AutoAgents automatically creates and manages AI agents and tasks b icon: "robot" --- +```mermaid +flowchart LR + In[In] --> Plan[Plan Tasks] + + subgraph Creation[Automatic Agent Creation] + Plan --> Agent1[AI Agent 1] + Plan --> Agent2[AI Agent 2] + Plan --> Agent3[AI Agent 3] + end + + subgraph Tools[Automatic Tool Assignment] + Agent1 --> Tool1[Tools 1] + Agent2 --> Tool2[Tools 2] + Agent3 --> Tool3[Tools 3] + end + + Tools --> Execution + + subgraph Execution[Execution] + Exec1[AI Agent 1] --> Exec2[AI Agent 2] + Exec2 --> Exec3[AI Agent 3] + end + + Exec3 --> Out[Out] + + style In fill:#8B0000,color:#fff + style Plan fill:#2E8B57,color:#fff + style Agent1 fill:#2E8B57,color:#fff + style Agent2 fill:#2E8B57,color:#fff + style Agent3 fill:#2E8B57,color:#fff + style Tool1 fill:#2E8B57,color:#fff + style Tool2 fill:#2E8B57,color:#fff + style Tool3 fill:#2E8B57,color:#fff + style Exec1 fill:#2E8B57,color:#fff + style Exec2 fill:#2E8B57,color:#fff + style Exec3 fill:#2E8B57,color:#fff + style Out fill:#8B0000,color:#fff +``` + +AutoAgents automatically creates and manages AI agents and tasks based on high-level instructions. + ## Quick Start diff --git a/docs/features/callbacks.mdx b/docs/features/callbacks.mdx index e76bd8a..9137858 100644 --- a/docs/features/callbacks.mdx +++ b/docs/features/callbacks.mdx @@ -5,6 +5,20 @@ description: "Learn how to implement callbacks to monitor and log AI agent inter icon: "bell" --- +```mermaid +flowchart LR + In[In] --> Agent[AI Agent] + Agent --> Out[Out] + Agent --> Callback[Callback] + + style In fill:#8B0000,color:#fff + style Agent fill:#2E8B57,color:#fff + style Callback fill:#2E8B57,color:#fff + style Out fill:#8B0000,color:#fff +``` + +Learn how to implement callbacks to monitor and log AI agent interactions, errors, and task completions. + ## Quick Start diff --git a/docs/features/reasoning.mdx b/docs/features/reasoning.mdx index 7900abf..5277189 100644 --- a/docs/features/reasoning.mdx +++ b/docs/features/reasoning.mdx @@ -4,6 +4,24 @@ description: "Learn how to create AI agents with advanced reasoning capabilities icon: "brain" --- +```mermaid +flowchart LR + In[In] --> Agent[AI Agent] + Agent --> Think[Think] + Think --> Decide[Decide] + Decide --> Act[Act] + Act --> Out[Out] + + style In fill:#8B0000,color:#fff + style Agent fill:#2E8B57,color:#fff + style Think fill:#2E8B57,color:#fff + style Decide fill:#2E8B57,color:#fff + style Act fill:#2E8B57,color:#fff + style Out fill:#8B0000,color:#fff +``` + +Learn how to create AI agents with advanced reasoning capabilities for complex problem-solving. + ## Quick Start diff --git a/docs/features/selfreflection.mdx b/docs/features/selfreflection.mdx index 6e8a228..a4c83b4 100644 --- a/docs/features/selfreflection.mdx +++ b/docs/features/selfreflection.mdx @@ -5,6 +5,21 @@ description: "Self-reflection enables agents to evaluate and improve their own r icon: "brain" --- +```mermaid +flowchart LR + In[In] --> Agent[AI Agent] + Agent --> Reflect[Self Reflection] + Reflect --> Agent + Agent --> Out[Out] + + style In fill:#8B0000,color:#fff + style Agent fill:#2E8B57,color:#fff + style Reflect fill:#2E8B57,color:#fff + style Out fill:#8B0000,color:#fff +``` + +Self-reflection enables agents to evaluate and improve their own responses before delivering them. + ## Quick Start diff --git a/docs/mint.json b/docs/mint.json index 0a9e13d..c18c870 100644 --- a/docs/mint.json +++ b/docs/mint.json @@ -141,6 +141,7 @@ "tools/yfinance_tools", "tools", "tools/custom", + "tools/tools_class", "tools/gpt", "tools/duckduckgo", "tools/langchain", diff --git a/docs/tools/tools_class.mdx b/docs/tools/tools_class.mdx new file mode 100644 index 0000000..43abc65 --- /dev/null +++ b/docs/tools/tools_class.mdx @@ -0,0 +1,245 @@ +--- +title: "Tools as Class" +sidebarTitle: "Tools as Class" +description: "Learn how to create and use class-based tools with AI agents for enhanced functionality." +icon: "toolbox" +--- + +```mermaid +flowchart LR + In[In] --> Agent[AI Agent] + Agent --> Tool[Tool Call] + Tool --> Agent + Agent --> Out[Out] + + style In fill:#8B0000,color:#fff + style Agent fill:#2E8B57,color:#fff + style Tool fill:#2E8B57,color:#fff + style Out fill:#8B0000,color:#fff +``` + +A workflow demonstrating how to create and use class-based tools that can be integrated with AI agents to extend their capabilities with custom functionality. + +## Quick Start + + + + First, install the PraisonAI Agents package: + ```bash + pip install praisonaiagents + ``` + + + + Set your OpenAI API key and EXA API key as environment variables in your terminal: + ```bash + export OPENAI_API_KEY=your_api_key_here + export EXA_API_KEY=your_exa_api_key_here + ``` + + + + Create a new file `app.py` with the basic setup: + ```python + from praisonaiagents import Agent, Task, PraisonAIAgents + import os + import requests + from typing import Any, Dict, List, Optional + from pydantic import BaseModel, Field + + class EXASearchTool(BaseModel): + """Wrapper for EXA Search API.""" + search_url: str = "https://api.exa.ai/search" + headers: Dict = { + "accept": "application/json", + "content-type": "application/json", + } + max_results: Optional[int] = None + + def run(self, query: str) -> str: + """Run query through EXA and return concatenated results.""" + payload = { + "query": query, + "type": "magic", + } + + headers = self.headers.copy() + headers["x-api-key"] = os.environ['EXA_API_KEY'] + + response = requests.post(self.search_url, json=payload, headers=headers) + results = response.json() + + if 'results' in results: + return self._parse_results(results['results']) + return "" + + def results(self, query: str, max_results: Optional[int] = None) -> List[Dict[str, Any]]: + """Run query through EXA and return metadata.""" + payload = { + "query": query, + "type": "magic", + } + + headers = self.headers.copy() + headers["x-api-key"] = os.environ['EXA_API_KEY'] + + response = requests.post(self.search_url, json=payload, headers=headers) + results = response.json() + + if 'results' in results: + return results['results'][:max_results] if max_results else results['results'] + return [] + + def _parse_results(self, results: List[Dict[str, Any]]) -> str: + """Parse results into a readable string format.""" + strings = [] + for result in results: + try: + strings.append('\n'.join([ + f"Title: {result['title']}", + f"Score: {result['score']}", + f"Url: {result['url']}", + f"ID: {result['id']}", + "---" + ])) + except KeyError: + continue + + content = '\n'.join(strings) + return f"\nSearch results: {content}\n" + + # Create an agent with the tool + agent = Agent( + name="SearchAgent", + role="Research Assistant", + goal="Search for information about 'AI Agents Framework'", + backstory="I am an AI assistant that can search GitHub.", + tools=[EXASearchTool], + self_reflect=False + ) + + # Create task to demonstrate the tool + task = Task( + name="search_task", + description="Search for information about 'AI Agents Framework'", + expected_output="Information about AI Agents Framework", + agent=agent + ) + + # Create and start the workflow + agents = PraisonAIAgents( + agents=[agent], + tasks=[task], + verbose=True + ) + + agents.start() + ``` + + + + Type this in your terminal to run your agents: + ```bash + python app.py + ``` + + + + + **Requirements** + - Python 3.10 or higher + - OpenAI API key. Generate OpenAI API key [here](https://platform.openai.com/api-keys) + - EXA API key for search functionality + - Basic understanding of Python and Pydantic + + +## Understanding Tools as Class + + + Class-based tools enable: + - Custom functionality encapsulation + - Reusable tool components + - Type-safe tool interfaces + - Complex API integrations + + +## Features + + + + Built-in validation and type safety with Pydantic models. + + + Easily wrap external APIs as agent tools. + + + Support for multiple methods within a single tool. + + + Strong typing for better code reliability. + + + +## Configuration Options + +```python +# Create a custom tool class +class CustomTool(BaseModel): + """Custom tool with configuration options.""" + api_url: str = Field(default="https://api.example.com") + headers: Dict[str, str] = Field(default_factory=dict) + max_retries: int = Field(default=3) + + def run(self, input_data: str) -> str: + """Main execution method.""" + # Tool implementation + return "Result" + + def configure(self, **kwargs): + """Update tool configuration.""" + for key, value in kwargs.items(): + if hasattr(self, key): + setattr(self, key, value) + +# Use the tool with an agent +agent = Agent( + name="CustomAgent", + role="Tool User", + goal="Use custom tool functionality", + tools=[CustomTool], + verbose=True +) +``` + +## Troubleshooting + + + + If tool execution fails: + - Check API credentials + - Verify network connectivity + - Enable verbose logging + + + + If type validation fails: + - Review input types + - Check Pydantic model + - Verify method signatures + + + +## Next Steps + + + + Learn about function-based tools + + + Explore API integration tools + + + + + For optimal results, ensure your tool classes are well-documented and follow Pydantic best practices for model definition. +