Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Integrate Brave Web Search API in search toolkit (#1005) #1234

Merged
merged 5 commits into from
Dec 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
151 changes: 149 additions & 2 deletions camel/toolkits/search_toolkit.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
# ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
import os
import xml.etree.ElementTree as ET
from typing import Any, Dict, List, Union
from typing import Any, Dict, List, Optional, TypeAlias, Union

import requests

Expand All @@ -26,7 +26,7 @@ class SearchToolkit(BaseToolkit):
r"""A class representing a toolkit for web search.

This class provides methods for searching information on the web using
search engines like Google, DuckDuckGo, Wikipedia and Wolfram Alpha.
search engines like Google, DuckDuckGo, Wikipedia and Wolfram Alpha, Brave.
"""

@dependencies_required("wikipedia")
Expand Down Expand Up @@ -151,6 +151,152 @@ def search_duckduckgo(
# If no answer found, return an empty list
return responses

@api_keys_required("BRAVE_API_KEY")
def search_brave(
self,
q: str,
country: str = "US",
search_lang: str = "en",
ui_lang: str = "en-US",
count: int = 20,
offset: int = 0,
safesearch: str = "moderate",
freshness: Optional[str] = None,
text_decorations: bool = True,
spellcheck: bool = True,
result_filter: Optional[str] = None,
goggles_id: Optional[str] = None,
units: Optional[str] = None,
extra_snippets: Optional[bool] = None,
summary: Optional[bool] = None,
) -> Dict[str, Any]:
r"""This function queries the Brave search engine API and returns a
dictionary, representing a search result.
See https://api.search.brave.com/app/documentation/web-search/query
for more details.

Args:
q (str): The user's search query term. Query cannot be empty.
Maximum of 400 characters and 50 words in the query.
country (str): The search query country where results come from.
The country string is limited to 2 character country codes of
supported countries. For a list of supported values, see
Country Codes. (default::obj:`US `)
search_lang (str): The search language preference. The 2 or more
character language code for which search results are provided.
For a list of possible values, see Language Codes.
ui_lang (str): User interface language preferred in response.
Usually of the format '<language_code>-<country_code>'. For
more, see RFC 9110. For a list of supported values, see UI
Language Codes.
count (int): The number of search results returned in response.
The maximum is 20. The actual number delivered may be less than
requested. Combine this parameter with offset to paginate
search results.
offset (int): The zero based offset that indicates number of search
results per page (count) to skip before returning the result.
The maximum is 9. The actual number delivered may be less than
requested based on the query. In order to paginate results use
this parameter together with count. For example, if your user
interface displays 20 search results per page, set count to 20
and offset to 0 to show the first page of results. To get
subsequent pages, increment offset by 1 (e.g. 0, 1, 2). The
results may overlap across multiple pages.
safesearch (str): Filters search results for adult content.
The following values are supported:
- 'off': No filtering is done.
- 'moderate': Filters explicit content, like images and videos,
but allows adult domains in the search results.
- 'strict': Drops all adult content from search results.
freshness (Optional[str]): Filters search results by when they were
discovered:
- 'pd': Discovered within the last 24 hours.
- 'pw': Discovered within the last 7 Days.
- 'pm': Discovered within the last 31 Days.
- 'py': Discovered within the last 365 Days.
- 'YYYY-MM-DDtoYYYY-MM-DD': Timeframe is also supported by
specifying the date range e.g. '2022-04-01to2022-07-30'.
text_decorations (bool): Whether display strings (e.g. result
snippets) should include decoration markers (e.g. highlighting
characters).
spellcheck (bool): Whether to spellcheck provided query. If the
spellchecker is enabled, the modified query is always used for
search. The modified query can be found in altered key from the
query response model.
result_filter (Optional[str]): A comma delimited string of result
types to include in the search response. Not specifying this
parameter will return back all result types in search response
where data is available and a plan with the corresponding
option is subscribed. The response always includes query and
type to identify any query modifications and response type
respectively. Available result filter values are:
- 'discussions'
- 'faq'
- 'infobox'
- 'news'
- 'query'
- 'summarizer'
- 'videos'
- 'web'
- 'locations'
goggles_id (Optional[str]): Goggles act as a custom re-ranking on
top of Brave's search index. For more details, refer to the
Goggles repository.
units (Optional[str]): The measurement units. If not provided,
units are derived from search country. Possible values are:
- 'metric': The standardized measurement system
- 'imperial': The British Imperial system of units.
extra_snippets (Optional[bool]): A snippet is an excerpt from a
page you get as a result of the query, and extra_snippets
allow you to get up to 5 additional, alternative excerpts. Only
available under Free AI, Base AI, Pro AI, Base Data, Pro Data
and Custom plans.
summary (Optional[bool]): This parameter enables summary key
generation in web search results. This is required for
summarizer to be enabled.

Returns:
Dict[str, Any]: A dictionary representing a search result.
"""

import requests

BRAVE_API_KEY = os.getenv("BRAVE_API_KEY")

url = "https://api.search.brave.com/res/v1/web/search"
headers = {
"Content-Type": "application/json",
"X-BCP-APIV": "1.0",
"X-Subscription-Token": BRAVE_API_KEY,
}

ParamsType: TypeAlias = Dict[
str,
Union[str, int, float, List[Union[str, int, float]], None],
]

params: ParamsType = {
"q": q,
"country": country,
"search_lang": search_lang,
"ui_lang": ui_lang,
"count": count,
"offset": offset,
"safesearch": safesearch,
"freshness": freshness,
"text_decorations": text_decorations,
"spellcheck": spellcheck,
"result_filter": result_filter,
"goggles_id": goggles_id,
"units": units,
"extra_snippets": extra_snippets,
"summary": summary,
}

response = requests.get(url, headers=headers, params=params)
data = response.json()["web"]
return data

@api_keys_required("GOOGLE_API_KEY", "SEARCH_ENGINE_ID")
def search_google(
self, query: str, num_result_pages: int = 5
Expand Down Expand Up @@ -471,4 +617,5 @@ def get_tools(self) -> List[FunctionTool]:
FunctionTool(self.search_duckduckgo),
FunctionTool(self.query_wolfram_alpha),
FunctionTool(self.tavily_search),
FunctionTool(self.search_brave),
]
34 changes: 33 additions & 1 deletion examples/toolkits/search_toolkit.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
# limitations under the License.
# ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========

from camel.toolkits import SearchToolkit
from camel.agents import ChatAgent
from camel.toolkits import FunctionTool, SearchToolkit

res_simple = SearchToolkit().query_wolfram_alpha(
query="solve 3x-7=11", is_detailed=False
Expand Down Expand Up @@ -55,3 +56,34 @@
x 6 = 6\nAnswer: | \n | x = 6'}}
===============================================================================
'''

res_brave = SearchToolkit().search_brave(
q="What is the weather in Tokyo?",
search_lang="en",
)
print(res_brave)

# Example with ChatAgent using the Brave search engine

agent = ChatAgent(
system_message="""You are a helpful assistant that can use brave search
engine to answer questions.""",
tools=[FunctionTool(SearchToolkit().search_brave)],
)

usr_msg = "What is the temperature in Tokyo?"

response = agent.step(input_message=usr_msg, response_format=None)

print(response.msgs[0].content)
'''
The current temperature in Tokyo can be found on various weather websites.
Here are a couple of reliable sources where you can check the latest weather
conditions:

1. [AccuWeather - Tokyo Current Weather](https://www.accuweather.com/en/jp/tokyo/226396/current-weather/226396)
2. [Time and Date - Tokyo Weather](https://www.timeanddate.com/weather/japan/tokyo)

You can visit these links to get the most up-to-date temperature and weather
conditions in Tokyo.
'''
Loading