mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-01-24 07:38:14 +00:00
Squashed 'packages/tools/' content from commit 78317b9c
git-subtree-dir: packages/tools git-subtree-split: 78317b9c127f18bd040c1d77e3c0840cdc9a5b38
This commit is contained in:
32
crewai_tools/tools/serpapi_tool/README.md
Normal file
32
crewai_tools/tools/serpapi_tool/README.md
Normal file
@@ -0,0 +1,32 @@
|
||||
# SerpApi Tools
|
||||
|
||||
## Description
|
||||
[SerpApi](https://serpapi.com/) tools are built for searching information in the internet. It currently supports:
|
||||
- Google Search
|
||||
- Google Shopping
|
||||
|
||||
To successfully make use of SerpApi tools, you have to have `SERPAPI_API_KEY` set in the environment. To get the API key, register a free account at [SerpApi](https://serpapi.com/).
|
||||
|
||||
## Installation
|
||||
To start using the SerpApi Tools, you must first install the `crewai_tools` package. This can be easily done with the following command:
|
||||
|
||||
```shell
|
||||
pip install 'crewai[tools]'
|
||||
```
|
||||
|
||||
## Examples
|
||||
The following example demonstrates how to initialize the tool
|
||||
|
||||
### Google Search
|
||||
```python
|
||||
from crewai_tools import SerpApiGoogleSearchTool
|
||||
|
||||
tool = SerpApiGoogleSearchTool()
|
||||
```
|
||||
|
||||
### Google Shopping
|
||||
```python
|
||||
from crewai_tools import SerpApiGoogleShoppingTool
|
||||
|
||||
tool = SerpApiGoogleShoppingTool()
|
||||
```
|
||||
54
crewai_tools/tools/serpapi_tool/serpapi_base_tool.py
Normal file
54
crewai_tools/tools/serpapi_tool/serpapi_base_tool.py
Normal file
@@ -0,0 +1,54 @@
|
||||
import os
|
||||
import re
|
||||
from typing import Any, Optional, Union, List
|
||||
|
||||
from crewai.tools import BaseTool, EnvVar
|
||||
|
||||
|
||||
class SerpApiBaseTool(BaseTool):
|
||||
"""Base class for SerpApi functionality with shared capabilities."""
|
||||
|
||||
package_dependencies: List[str] = ["serpapi"]
|
||||
env_vars: List[EnvVar] = [
|
||||
EnvVar(name="SERPAPI_API_KEY", description="API key for SerpApi searches", required=True),
|
||||
]
|
||||
|
||||
client: Optional[Any] = None
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
try:
|
||||
from serpapi import Client # type: ignore
|
||||
except ImportError:
|
||||
import click
|
||||
|
||||
if click.confirm(
|
||||
"You are missing the 'serpapi' package. Would you like to install it?"
|
||||
):
|
||||
import subprocess
|
||||
|
||||
subprocess.run(["uv", "add", "serpapi"], check=True)
|
||||
from serpapi import Client
|
||||
else:
|
||||
raise ImportError(
|
||||
"`serpapi` package not found, please install with `uv add serpapi`"
|
||||
)
|
||||
api_key = os.getenv("SERPAPI_API_KEY")
|
||||
if not api_key:
|
||||
raise ValueError(
|
||||
"Missing API key, you can get the key from https://serpapi.com/manage-api-key"
|
||||
)
|
||||
self.client = Client(api_key=api_key)
|
||||
|
||||
def _omit_fields(self, data: Union[dict, list], omit_patterns: list[str]) -> None:
|
||||
if isinstance(data, dict):
|
||||
for field in list(data.keys()):
|
||||
if any(re.compile(p).match(field) for p in omit_patterns):
|
||||
data.pop(field, None)
|
||||
else:
|
||||
if isinstance(data[field], (dict, list)):
|
||||
self._omit_fields(data[field], omit_patterns)
|
||||
elif isinstance(data, list):
|
||||
for item in data:
|
||||
self._omit_fields(item, omit_patterns)
|
||||
@@ -0,0 +1,60 @@
|
||||
from typing import Any, Optional, Type
|
||||
|
||||
import re
|
||||
from pydantic import BaseModel, Field, ConfigDict
|
||||
from .serpapi_base_tool import SerpApiBaseTool
|
||||
|
||||
try:
|
||||
from serpapi import HTTPError
|
||||
except ImportError:
|
||||
HTTPError = Any
|
||||
|
||||
|
||||
class SerpApiGoogleSearchToolSchema(BaseModel):
|
||||
"""Input for Google Search."""
|
||||
|
||||
search_query: str = Field(
|
||||
..., description="Mandatory search query you want to use to Google search."
|
||||
)
|
||||
location: Optional[str] = Field(
|
||||
None, description="Location you want the search to be performed in."
|
||||
)
|
||||
|
||||
|
||||
class SerpApiGoogleSearchTool(SerpApiBaseTool):
|
||||
model_config = ConfigDict(
|
||||
arbitrary_types_allowed=True, validate_assignment=True, frozen=False
|
||||
)
|
||||
name: str = "Google Search"
|
||||
description: str = (
|
||||
"A tool to perform to perform a Google search with a search_query."
|
||||
)
|
||||
args_schema: Type[BaseModel] = SerpApiGoogleSearchToolSchema
|
||||
|
||||
def _run(
|
||||
self,
|
||||
**kwargs: Any,
|
||||
) -> Any:
|
||||
try:
|
||||
results = self.client.search(
|
||||
{
|
||||
"q": kwargs.get("search_query"),
|
||||
"location": kwargs.get("location"),
|
||||
}
|
||||
).as_dict()
|
||||
|
||||
self._omit_fields(
|
||||
results,
|
||||
[
|
||||
r"search_metadata",
|
||||
r"search_parameters",
|
||||
r"serpapi_.+",
|
||||
r".+_token",
|
||||
r"displayed_link",
|
||||
r"pagination",
|
||||
],
|
||||
)
|
||||
|
||||
return results
|
||||
except HTTPError as e:
|
||||
return f"An error occurred: {str(e)}. Some parameters may be invalid."
|
||||
@@ -0,0 +1,60 @@
|
||||
from typing import Any, Optional, Type
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
from .serpapi_base_tool import SerpApiBaseTool
|
||||
from pydantic import ConfigDict
|
||||
|
||||
try:
|
||||
from serpapi import HTTPError
|
||||
except ImportError:
|
||||
HTTPError = Any
|
||||
|
||||
|
||||
class SerpApiGoogleShoppingToolSchema(BaseModel):
|
||||
"""Input for Google Shopping."""
|
||||
|
||||
search_query: str = Field(
|
||||
..., description="Mandatory search query you want to use to Google shopping."
|
||||
)
|
||||
location: Optional[str] = Field(
|
||||
None, description="Location you want the search to be performed in."
|
||||
)
|
||||
|
||||
|
||||
class SerpApiGoogleShoppingTool(SerpApiBaseTool):
|
||||
model_config = ConfigDict(
|
||||
arbitrary_types_allowed=True, validate_assignment=True, frozen=False
|
||||
)
|
||||
name: str = "Google Shopping"
|
||||
description: str = (
|
||||
"A tool to perform search on Google shopping with a search_query."
|
||||
)
|
||||
args_schema: Type[BaseModel] = SerpApiGoogleShoppingToolSchema
|
||||
|
||||
def _run(
|
||||
self,
|
||||
**kwargs: Any,
|
||||
) -> Any:
|
||||
try:
|
||||
results = self.client.search(
|
||||
{
|
||||
"engine": "google_shopping",
|
||||
"q": kwargs.get("search_query"),
|
||||
"location": kwargs.get("location"),
|
||||
}
|
||||
).as_dict()
|
||||
|
||||
self._omit_fields(
|
||||
results,
|
||||
[
|
||||
r"search_metadata",
|
||||
r"search_parameters",
|
||||
r"serpapi_.+",
|
||||
r"filters",
|
||||
r"pagination",
|
||||
],
|
||||
)
|
||||
|
||||
return results
|
||||
except HTTPError as e:
|
||||
return f"An error occurred: {str(e)}. Some parameters may be invalid."
|
||||
Reference in New Issue
Block a user