feat: implement duckduckgo search, abstract further

This commit is contained in:
Kingtous 2025-03-13 09:05:14 +08:00
parent b7774b18ef
commit 86d2a7d6bf
8 changed files with 65 additions and 11 deletions

View File

@ -8,7 +8,7 @@ FileSaver: Save files locally, such as txt, py, html, etc.
BrowserUseTool: Open, browse, and use web browsers.If you open a local HTML file, you must provide the absolute path to the file.
GoogleSearch: Perform web information retrieval
WebSearch: Perform web information retrieval
Terminate: End the current interaction when the task is complete or when you need additional information from the user. Use this tool to signal that you've finished addressing the user's request or need clarification before proceeding further.

View File

@ -0,0 +1,12 @@
from app.tool.search.base import WebSearchEngine
from app.tool.search.baidu_search import BaiduSearchEngine
from app.tool.search.duckduckgo_search import DuckDuckGoSearchEngine
from app.tool.search.google_search import GoogleSearchEngine
__all__ = [
"WebSearchEngine",
"BaiduSearchEngine",
"DuckDuckGoSearchEngine",
"GoogleSearchEngine",
]

View File

@ -0,0 +1,9 @@
from baidusearch.baidusearch import search
from app.tool.search.base import WebSearchEngine
class BaiduSearchEngine(WebSearchEngine):
def perform_search(self, query, num_results = 10, *args, **kwargs):
"""Baidu search engine."""
return search(query, num_results=num_results)

15
app/tool/search/base.py Normal file
View File

@ -0,0 +1,15 @@
class WebSearchEngine(object):
def perform_search(self, query: str, num_results: int = 10, *args, **kwargs) -> list[dict]:
"""
Perform a web search and return a list of URLs.
Args:
query (str): The search query to submit to the search engine.
num_results (int, optional): The number of search results to return. Default is 10.
args: Additional arguments.
kwargs: Additional keyword arguments.
Returns:
List: A list of dict matching the search query.
"""
raise NotImplementedError

View File

@ -0,0 +1,9 @@
from duckduckgo_search import DDGS
from app.tool.search.base import WebSearchEngine
class DuckDuckGoSearchEngine(WebSearchEngine):
async def perform_search(self, query, num_results = 10, *args, **kwargs):
"""DuckDuckGo search engine."""
return DDGS.text(query, num_results=num_results)

View File

@ -0,0 +1,8 @@
from app.tool.search.base import WebSearchEngine
from googlesearch import search
class GoogleSearchEngine(WebSearchEngine):
def perform_search(self, query, num_results = 10, *args, **kwargs):
"""Google search engine."""
return search(query, num_results=num_results)

View File

@ -1,11 +1,9 @@
import asyncio
from typing import List
from googlesearch import search as google_search
from baidusearch.baidusearch import search as baidu_search
from app.tool.base import BaseTool
from app.config import config
from app.tool.search import WebSearchEngine, BaiduSearchEngine, GoogleSearchEngine, DuckDuckGoSearchEngine
class WebSearch(BaseTool):
@ -29,9 +27,10 @@ The tool returns a list of URLs that match the search query.
},
"required": ["query"],
}
_search_engine: dict = {
"google": google_search,
"baidu": baidu_search,
_search_engine: dict[str, WebSearchEngine] = {
"google": GoogleSearchEngine(),
"baidu": BaiduSearchEngine(),
"duckduckgo": DuckDuckGoSearchEngine(),
}
async def execute(self, query: str, num_results: int = 10) -> List[str]:
@ -54,10 +53,11 @@ The tool returns a list of URLs that match the search query.
return links
def get_search_engine(self):
def get_search_engine(self) -> WebSearchEngine:
"""Determines the search engine to use based on the configuration."""
default_engine = self._search_engine.get("google")
if config.search_config is None:
return google_search
return default_engine
else:
engine = config.search_config.engine.lower()
return self._search_engine.get(engine, google_search)
return self._search_engine.get(engine, default_engine)

View File

@ -16,6 +16,7 @@ unidiff~=0.7.5
browser-use~=0.1.40
googlesearch-python~=1.3.0
baidusearch~=1.0.3
duckduckgo_search~=7.5.1
aiofiles~=24.1.0
pydantic_core~=2.27.2