Skip to content

Commit

Permalink
Add EXASearchTool class and integrate with AI agents
Browse files Browse the repository at this point in the history
- Introduced a new `EXASearchTool` class to interact with the EXA Search API, allowing AI agents to perform searches and retrieve results.
- Implemented methods for running queries and parsing results into a readable format.
- Created a `SearchAgent` to utilize the `EXASearchTool` for searching information about the 'AI Agents Framework'.
- Added a task definition for the `SearchAgent` to demonstrate the tool's functionality.
- Updated documentation to include the new `tools_class` and provide a comprehensive guide on using class-based tools with AI agents.
  • Loading branch information
MervinPraison committed Jan 13, 2025
1 parent 9b30d1a commit 2a14508
Show file tree
Hide file tree
Showing 9 changed files with 584 additions and 0 deletions.
115 changes: 115 additions & 0 deletions agents/tools-class.py
Original file line number Diff line number Diff line change
@@ -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()
115 changes: 115 additions & 0 deletions cookbooks/general/tools-class.py
Original file line number Diff line number Diff line change
@@ -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()
20 changes: 20 additions & 0 deletions docs/features/async.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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

<Tabs>
Expand Down
41 changes: 41 additions & 0 deletions docs/features/autoagents.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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

<Tabs>
Expand Down
14 changes: 14 additions & 0 deletions docs/features/callbacks.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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

<Tabs>
Expand Down
18 changes: 18 additions & 0 deletions docs/features/reasoning.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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

<Tabs>
Expand Down
15 changes: 15 additions & 0 deletions docs/features/selfreflection.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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

<Tabs>
Expand Down
1 change: 1 addition & 0 deletions docs/mint.json
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@
"tools/yfinance_tools",
"tools",
"tools/custom",
"tools/tools_class",
"tools/gpt",
"tools/duckduckgo",
"tools/langchain",
Expand Down
Loading

0 comments on commit 2a14508

Please sign in to comment.