| from core.tools.errors import ToolProviderCredentialValidationError | from core.tools.errors import ToolProviderCredentialValidationError | ||||
| from core.tools.provider.builtin.duckduckgo.tools.duckduckgo_search import DuckDuckGoSearchTool | |||||
| from core.tools.provider.builtin.duckduckgo.tools.ddgo_search import DuckDuckGoSearchTool | |||||
| from core.tools.provider.builtin_tool_provider import BuiltinToolProviderController | from core.tools.provider.builtin_tool_provider import BuiltinToolProviderController | ||||
| from typing import Any | |||||
| from duckduckgo_search import DDGS | |||||
| from core.tools.entities.tool_entities import ToolInvokeMessage | |||||
| from core.tools.tool.builtin_tool import BuiltinTool | |||||
| class DuckDuckGoAITool(BuiltinTool): | |||||
| """ | |||||
| Tool for performing a search using DuckDuckGo search engine. | |||||
| """ | |||||
| def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage: | |||||
| query_dict = { | |||||
| "keywords": tool_parameters.get('query'), | |||||
| "model": tool_parameters.get('model'), | |||||
| } | |||||
| response = DDGS().chat(**query_dict) | |||||
| return self.create_text_message(text=response) |
| identity: | |||||
| name: ddgo_ai | |||||
| author: hjlarry | |||||
| label: | |||||
| en_US: DuckDuckGo AI Chat | |||||
| zh_Hans: DuckDuckGo AI聊天 | |||||
| description: | |||||
| human: | |||||
| en_US: Use the anonymous private chat provided by DuckDuckGo. | |||||
| zh_Hans: 使用DuckDuckGo提供的匿名私密聊天。 | |||||
| llm: Use the anonymous private chat provided by DuckDuckGo. | |||||
| parameters: | |||||
| - name: query | |||||
| type: string | |||||
| required: true | |||||
| label: | |||||
| en_US: Chat Content | |||||
| zh_Hans: 聊天内容 | |||||
| human_description: | |||||
| en_US: The chat content. | |||||
| zh_Hans: 要聊天的内容。 | |||||
| llm_description: Key words for chat | |||||
| form: llm | |||||
| - name: model | |||||
| type: select | |||||
| required: true | |||||
| options: | |||||
| - value: gpt-3.5 | |||||
| label: | |||||
| en_US: GPT-3.5 | |||||
| - value: claude-3-haiku | |||||
| label: | |||||
| en_US: Claude 3 | |||||
| default: gpt-3.5 | |||||
| label: | |||||
| en_US: Choose Model | |||||
| zh_Hans: 选择模型 | |||||
| human_description: | |||||
| en_US: used to select the model for AI chat. | |||||
| zh_Hans: 用于选择使用AI聊天的模型 | |||||
| form: form |
| from typing import Any | |||||
| from duckduckgo_search import DDGS | |||||
| from core.tools.entities.tool_entities import ToolInvokeMessage | |||||
| from core.tools.tool.builtin_tool import BuiltinTool | |||||
| class DuckDuckGoImageSearchTool(BuiltinTool): | |||||
| """ | |||||
| Tool for performing an image search using DuckDuckGo search engine. | |||||
| """ | |||||
| def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> list[ToolInvokeMessage]: | |||||
| query_dict = { | |||||
| "keywords": tool_parameters.get('query'), | |||||
| "timelimit": tool_parameters.get('timelimit'), | |||||
| "size": tool_parameters.get('size'), | |||||
| "max_results": tool_parameters.get('max_results'), | |||||
| } | |||||
| response = DDGS().images(**query_dict) | |||||
| results = [] | |||||
| for res in response: | |||||
| results.append(self.create_image_message(image=res.get("image"))) | |||||
| return results |
| identity: | |||||
| name: ddgo_img | |||||
| author: hjlarry | |||||
| label: | |||||
| en_US: DuckDuckGo Image Search | |||||
| zh_Hans: DuckDuckGo 图片搜索 | |||||
| description: | |||||
| human: | |||||
| en_US: Perform image searches on DuckDuckGo and get results. | |||||
| zh_Hans: 在 DuckDuckGo 上进行图片搜索并获取结果。 | |||||
| llm: Perform image searches on DuckDuckGo and get results. | |||||
| parameters: | |||||
| - name: query | |||||
| type: string | |||||
| required: true | |||||
| label: | |||||
| en_US: Query string | |||||
| zh_Hans: 查询语句 | |||||
| human_description: | |||||
| en_US: The search query. | |||||
| zh_Hans: 搜索查询语句。 | |||||
| llm_description: Key words for searching | |||||
| form: llm | |||||
| - name: max_results | |||||
| type: number | |||||
| required: true | |||||
| default: 3 | |||||
| label: | |||||
| en_US: Max results | |||||
| zh_Hans: 最大结果数量 | |||||
| human_description: | |||||
| en_US: The max results. | |||||
| zh_Hans: 最大结果数量 | |||||
| form: form | |||||
| - name: timelimit | |||||
| type: select | |||||
| required: false | |||||
| options: | |||||
| - value: Day | |||||
| label: | |||||
| en_US: current day | |||||
| zh_Hans: 当天 | |||||
| - value: Week | |||||
| label: | |||||
| en_US: current week | |||||
| zh_Hans: 本周 | |||||
| - value: Month | |||||
| label: | |||||
| en_US: current month | |||||
| zh_Hans: 当月 | |||||
| - value: Year | |||||
| label: | |||||
| en_US: current year | |||||
| zh_Hans: 今年 | |||||
| label: | |||||
| en_US: Result time limit | |||||
| zh_Hans: 结果时间限制 | |||||
| human_description: | |||||
| en_US: Use when querying results within a specific time range only. | |||||
| zh_Hans: 只查询一定时间范围内的结果时使用 | |||||
| form: form | |||||
| - name: size | |||||
| type: select | |||||
| required: false | |||||
| options: | |||||
| - value: Small | |||||
| label: | |||||
| en_US: small | |||||
| zh_Hans: 小 | |||||
| - value: Medium | |||||
| label: | |||||
| en_US: medium | |||||
| zh_Hans: 中 | |||||
| - value: Large | |||||
| label: | |||||
| en_US: large | |||||
| zh_Hans: 大 | |||||
| - value: Wallpaper | |||||
| label: | |||||
| en_US: xl | |||||
| zh_Hans: 超大 | |||||
| label: | |||||
| en_US: image size | |||||
| zh_Hans: 图片大小 | |||||
| human_description: | |||||
| en_US: The size of the image to be searched. | |||||
| zh_Hans: 要搜索的图片的大小 | |||||
| form: form |
| from typing import Any | |||||
| from duckduckgo_search import DDGS | |||||
| from core.tools.entities.tool_entities import ToolInvokeMessage | |||||
| from core.tools.tool.builtin_tool import BuiltinTool | |||||
| class DuckDuckGoSearchTool(BuiltinTool): | |||||
| """ | |||||
| Tool for performing a search using DuckDuckGo search engine. | |||||
| """ | |||||
| def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage: | |||||
| query = tool_parameters.get('query', '') | |||||
| result_type = tool_parameters.get('result_type', 'text') | |||||
| max_results = tool_parameters.get('max_results', 10) | |||||
| require_summary = tool_parameters.get('require_summary', False) | |||||
| response = DDGS().text(query, max_results=max_results) | |||||
| if result_type == 'link': | |||||
| results = [f"[{res.get('title')}]({res.get('href')})" for res in response] | |||||
| results = "\n".join(results) | |||||
| return self.create_link_message(link=results) | |||||
| results = [res.get("body") for res in response] | |||||
| results = "\n".join(results) | |||||
| if require_summary: | |||||
| results = self.summary(user_id=user_id, content=results) | |||||
| return self.create_text_message(text=results) |
| identity: | |||||
| name: ddgo_search | |||||
| author: Yash Parmar | |||||
| label: | |||||
| en_US: DuckDuckGo Search | |||||
| zh_Hans: DuckDuckGo 搜索 | |||||
| description: | |||||
| human: | |||||
| en_US: Perform searches on DuckDuckGo and get results. | |||||
| zh_Hans: 在 DuckDuckGo 上进行搜索并获取结果。 | |||||
| llm: Perform searches on DuckDuckGo and get results. | |||||
| parameters: | |||||
| - name: query | |||||
| type: string | |||||
| required: true | |||||
| label: | |||||
| en_US: Query string | |||||
| zh_Hans: 查询语句 | |||||
| human_description: | |||||
| en_US: The search query. | |||||
| zh_Hans: 搜索查询语句。 | |||||
| llm_description: Key words for searching | |||||
| form: llm | |||||
| - name: max_results | |||||
| type: number | |||||
| required: true | |||||
| default: 5 | |||||
| label: | |||||
| en_US: Max results | |||||
| zh_Hans: 最大结果数量 | |||||
| human_description: | |||||
| en_US: The max results. | |||||
| zh_Hans: 最大结果数量 | |||||
| form: form | |||||
| - name: result_type | |||||
| type: select | |||||
| required: true | |||||
| options: | |||||
| - value: text | |||||
| label: | |||||
| en_US: text | |||||
| zh_Hans: 文本 | |||||
| - value: link | |||||
| label: | |||||
| en_US: link | |||||
| zh_Hans: 链接 | |||||
| default: text | |||||
| label: | |||||
| en_US: Result type | |||||
| zh_Hans: 结果类型 | |||||
| human_description: | |||||
| en_US: used for selecting the result type, text or link | |||||
| zh_Hans: 用于选择结果类型,使用文本还是链接进行展示 | |||||
| form: form | |||||
| - name: require_summary | |||||
| type: boolean | |||||
| required: true | |||||
| default: false | |||||
| label: | |||||
| en_US: Require Summary | |||||
| zh_Hans: 是否总结 | |||||
| human_description: | |||||
| en_US: Whether to pass the search results to llm for summarization. | |||||
| zh_Hans: 是否需要将搜索结果传给大模型总结 | |||||
| form: form |
| from typing import Any | |||||
| from duckduckgo_search import DDGS | |||||
| from core.tools.entities.tool_entities import ToolInvokeMessage | |||||
| from core.tools.tool.builtin_tool import BuiltinTool | |||||
| class DuckDuckGoTranslateTool(BuiltinTool): | |||||
| """ | |||||
| Tool for performing a search using DuckDuckGo search engine. | |||||
| """ | |||||
| def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage: | |||||
| query_dict = { | |||||
| "keywords": tool_parameters.get('query'), | |||||
| "to": tool_parameters.get('translate_to'), | |||||
| } | |||||
| response = DDGS().translate(**query_dict)[0].get('translated', 'Unable to translate!') | |||||
| return self.create_text_message(text=response) |
| identity: | |||||
| name: ddgo_translate | |||||
| author: hjlarry | |||||
| label: | |||||
| en_US: DuckDuckGo Translate | |||||
| zh_Hans: DuckDuckGo 翻译 | |||||
| description: | |||||
| human: | |||||
| en_US: Use DuckDuckGo's translation feature. | |||||
| zh_Hans: 使用DuckDuckGo的翻译功能。 | |||||
| llm: Use DuckDuckGo's translation feature. | |||||
| parameters: | |||||
| - name: query | |||||
| type: string | |||||
| required: true | |||||
| label: | |||||
| en_US: Translate Content | |||||
| zh_Hans: 翻译内容 | |||||
| human_description: | |||||
| en_US: The translate content. | |||||
| zh_Hans: 要翻译的内容。 | |||||
| llm_description: Key words for translate | |||||
| form: llm | |||||
| - name: translate_to | |||||
| type: select | |||||
| required: true | |||||
| options: | |||||
| - value: en | |||||
| label: | |||||
| en_US: English | |||||
| zh_Hans: 英语 | |||||
| - value: zh-Hans | |||||
| label: | |||||
| en_US: Simplified Chinese | |||||
| zh_Hans: 简体中文 | |||||
| - value: zh-Hant | |||||
| label: | |||||
| en_US: Traditional Chinese | |||||
| zh_Hans: 繁体中文 | |||||
| - value: ja | |||||
| label: | |||||
| en_US: Japanese | |||||
| zh_Hans: 日语 | |||||
| default: en | |||||
| label: | |||||
| en_US: Choose Language | |||||
| zh_Hans: 选择语言 | |||||
| human_description: | |||||
| en_US: select the language to translate. | |||||
| zh_Hans: 选择要翻译的语言 | |||||
| form: form |
| from typing import Any, Optional | |||||
| from pydantic import BaseModel, Field | |||||
| from core.tools.entities.tool_entities import ToolInvokeMessage | |||||
| from core.tools.tool.builtin_tool import BuiltinTool | |||||
| class DuckDuckGoSearchAPIWrapper(BaseModel): | |||||
| """Wrapper for DuckDuckGo Search API. | |||||
| Free and does not require any setup. | |||||
| """ | |||||
| region: Optional[str] = "wt-wt" | |||||
| safesearch: str = "moderate" | |||||
| time: Optional[str] = "y" | |||||
| max_results: int = 5 | |||||
| def get_snippets(self, query: str) -> list[str]: | |||||
| """Run query through DuckDuckGo and return concatenated results.""" | |||||
| from duckduckgo_search import DDGS | |||||
| with DDGS() as ddgs: | |||||
| results = ddgs.text( | |||||
| query, | |||||
| region=self.region, | |||||
| safesearch=self.safesearch, | |||||
| timelimit=self.time, | |||||
| ) | |||||
| if results is None: | |||||
| return ["No good DuckDuckGo Search Result was found"] | |||||
| snippets = [] | |||||
| for i, res in enumerate(results, 1): | |||||
| if res is not None: | |||||
| snippets.append(res["body"]) | |||||
| if len(snippets) == self.max_results: | |||||
| break | |||||
| return snippets | |||||
| def run(self, query: str) -> str: | |||||
| snippets = self.get_snippets(query) | |||||
| return " ".join(snippets) | |||||
| def results( | |||||
| self, query: str, num_results: int, backend: str = "api" | |||||
| ) -> list[dict[str, str]]: | |||||
| """Run query through DuckDuckGo and return metadata. | |||||
| Args: | |||||
| query: The query to search for. | |||||
| num_results: The number of results to return. | |||||
| Returns: | |||||
| A list of dictionaries with the following keys: | |||||
| snippet - The description of the result. | |||||
| title - The title of the result. | |||||
| link - The link to the result. | |||||
| """ | |||||
| from duckduckgo_search import DDGS | |||||
| with DDGS() as ddgs: | |||||
| results = ddgs.text( | |||||
| query, | |||||
| region=self.region, | |||||
| safesearch=self.safesearch, | |||||
| timelimit=self.time, | |||||
| backend=backend, | |||||
| ) | |||||
| if results is None: | |||||
| return [{"Result": "No good DuckDuckGo Search Result was found"}] | |||||
| def to_metadata(result: dict) -> dict[str, str]: | |||||
| if backend == "news": | |||||
| return { | |||||
| "date": result["date"], | |||||
| "title": result["title"], | |||||
| "snippet": result["body"], | |||||
| "source": result["source"], | |||||
| "link": result["url"], | |||||
| } | |||||
| return { | |||||
| "snippet": result["body"], | |||||
| "title": result["title"], | |||||
| "link": result["href"], | |||||
| } | |||||
| formatted_results = [] | |||||
| for i, res in enumerate(results, 1): | |||||
| if res is not None: | |||||
| formatted_results.append(to_metadata(res)) | |||||
| if len(formatted_results) == num_results: | |||||
| break | |||||
| return formatted_results | |||||
| class DuckDuckGoSearchRun(BaseModel): | |||||
| """Tool that queries the DuckDuckGo search API.""" | |||||
| name = "duckduckgo_search" | |||||
| description = ( | |||||
| "A wrapper around DuckDuckGo Search. " | |||||
| "Useful for when you need to answer questions about current events. " | |||||
| "Input should be a search query." | |||||
| ) | |||||
| api_wrapper: DuckDuckGoSearchAPIWrapper = Field( | |||||
| default_factory=DuckDuckGoSearchAPIWrapper | |||||
| ) | |||||
| def _run( | |||||
| self, | |||||
| query: str, | |||||
| ) -> str: | |||||
| """Use the tool.""" | |||||
| return self.api_wrapper.run(query) | |||||
| class DuckDuckGoSearchResults(BaseModel): | |||||
| """Tool that queries the DuckDuckGo search API and gets back json.""" | |||||
| name = "DuckDuckGo Results JSON" | |||||
| description = ( | |||||
| "A wrapper around Duck Duck Go Search. " | |||||
| "Useful for when you need to answer questions about current events. " | |||||
| "Input should be a search query. Output is a JSON array of the query results" | |||||
| ) | |||||
| num_results: int = 4 | |||||
| api_wrapper: DuckDuckGoSearchAPIWrapper = Field( | |||||
| default_factory=DuckDuckGoSearchAPIWrapper | |||||
| ) | |||||
| backend: str = "api" | |||||
| def _run( | |||||
| self, | |||||
| query: str, | |||||
| ) -> str: | |||||
| """Use the tool.""" | |||||
| res = self.api_wrapper.results(query, self.num_results, backend=self.backend) | |||||
| res_strs = [", ".join([f"{k}: {v}" for k, v in d.items()]) for d in res] | |||||
| return ", ".join([f"[{rs}]" for rs in res_strs]) | |||||
| class DuckDuckGoInput(BaseModel): | |||||
| query: str = Field(..., description="Search query.") | |||||
| class DuckDuckGoSearchTool(BuiltinTool): | |||||
| """ | |||||
| Tool for performing a search using DuckDuckGo search engine. | |||||
| """ | |||||
| def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage | list[ToolInvokeMessage]: | |||||
| """ | |||||
| Invoke the DuckDuckGo search tool. | |||||
| Args: | |||||
| user_id (str): The ID of the user invoking the tool. | |||||
| tool_parameters (dict[str, Any]): The parameters for the tool invocation. | |||||
| Returns: | |||||
| ToolInvokeMessage | list[ToolInvokeMessage]: The result of the tool invocation. | |||||
| """ | |||||
| query = tool_parameters.get('query', '') | |||||
| if not query: | |||||
| return self.create_text_message('Please input query') | |||||
| tool = DuckDuckGoSearchRun(args_schema=DuckDuckGoInput) | |||||
| result = tool._run(query) | |||||
| return self.create_text_message(self.summary(user_id=user_id, content=result)) | |||||
| identity: | |||||
| name: duckduckgo_search | |||||
| author: Yash Parmar | |||||
| label: | |||||
| en_US: DuckDuckGo Search | |||||
| zh_Hans: DuckDuckGo 搜索 | |||||
| description: | |||||
| human: | |||||
| en_US: Perform searches on DuckDuckGo and get results. | |||||
| zh_Hans: 在 DuckDuckGo 上进行搜索并获取结果。 | |||||
| llm: Perform searches on DuckDuckGo and get results. | |||||
| parameters: | |||||
| - name: query | |||||
| type: string | |||||
| required: true | |||||
| label: | |||||
| en_US: Query string | |||||
| zh_Hans: 查询语句 | |||||
| human_description: | |||||
| en_US: The search query. | |||||
| zh_Hans: 搜索查询语句。 | |||||
| llm_description: Key words for searching | |||||
| form: llm |