diff --git a/app/prompt/manus.py b/app/prompt/manus.py index e46c793..6dcca8a 100644 --- a/app/prompt/manus.py +++ b/app/prompt/manus.py @@ -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. diff --git a/app/tool/search/__init__.py b/app/tool/search/__init__.py new file mode 100644 index 0000000..509d16d --- /dev/null +++ b/app/tool/search/__init__.py @@ -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", +] \ No newline at end of file diff --git a/app/tool/search/baidu_search.py b/app/tool/search/baidu_search.py new file mode 100644 index 0000000..a398899 --- /dev/null +++ b/app/tool/search/baidu_search.py @@ -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) diff --git a/app/tool/search/base.py b/app/tool/search/base.py new file mode 100644 index 0000000..095c0b1 --- /dev/null +++ b/app/tool/search/base.py @@ -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 \ No newline at end of file diff --git a/app/tool/search/duckduckgo_search.py b/app/tool/search/duckduckgo_search.py new file mode 100644 index 0000000..738ecf5 --- /dev/null +++ b/app/tool/search/duckduckgo_search.py @@ -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) diff --git a/app/tool/search/google_search.py b/app/tool/search/google_search.py new file mode 100644 index 0000000..606f107 --- /dev/null +++ b/app/tool/search/google_search.py @@ -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) diff --git a/app/tool/web_search.py b/app/tool/web_search.py index 3beb4c4..9f55199 100644 --- a/app/tool/web_search.py +++ b/app/tool/web_search.py @@ -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]: @@ -53,11 +52,12 @@ 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) diff --git a/requirements.txt b/requirements.txt index c275e65..60ad38e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -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