diff --git a/api/core/tools/provider/_position.yaml b/api/core/tools/provider/_position.yaml index a39a00fffdc84..3b0f78cc76da3 100644 --- a/api/core/tools/provider/_position.yaml +++ b/api/core/tools/provider/_position.yaml @@ -1,6 +1,7 @@ - google - bing - duckduckgo +- searchapi - searxng - dalle - azuredalle diff --git a/api/core/tools/provider/builtin/searchapi/_assets/icon.svg b/api/core/tools/provider/builtin/searchapi/_assets/icon.svg new file mode 100644 index 0000000000000..7660b2f351c43 --- /dev/null +++ b/api/core/tools/provider/builtin/searchapi/_assets/icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/api/core/tools/provider/builtin/searchapi/searchapi.py b/api/core/tools/provider/builtin/searchapi/searchapi.py new file mode 100644 index 0000000000000..6fa4f05acd7b9 --- /dev/null +++ b/api/core/tools/provider/builtin/searchapi/searchapi.py @@ -0,0 +1,23 @@ +from typing import Any + +from core.tools.errors import ToolProviderCredentialValidationError +from core.tools.provider.builtin.searchapi.tools.google import GoogleTool +from core.tools.provider.builtin_tool_provider import BuiltinToolProviderController + + +class SearchAPIProvider(BuiltinToolProviderController): + def _validate_credentials(self, credentials: dict[str, Any]) -> None: + try: + GoogleTool().fork_tool_runtime( + runtime={ + "credentials": credentials, + } + ).invoke( + user_id='', + tool_parameters={ + "query": "SearchApi dify", + "result_type": "link" + }, + ) + except Exception as e: + raise ToolProviderCredentialValidationError(str(e)) diff --git a/api/core/tools/provider/builtin/searchapi/searchapi.yaml b/api/core/tools/provider/builtin/searchapi/searchapi.yaml new file mode 100644 index 0000000000000..c2fa3f398e192 --- /dev/null +++ b/api/core/tools/provider/builtin/searchapi/searchapi.yaml @@ -0,0 +1,34 @@ +identity: + author: SearchApi + name: searchapi + label: + en_US: SearchApi + zh_Hans: SearchApi + pt_BR: SearchApi + description: + en_US: SearchApi is a robust real-time SERP API delivering structured data from a collection of search engines including Google Search, Google Jobs, YouTube, Google News, and many more. + zh_Hans: SearchApi 是一个强大的实时 SERP API,可提供来自 Google 搜索、Google 招聘、YouTube、Google 新闻等搜索引擎集合的结构化数据。 + pt_BR: SearchApi is a robust real-time SERP API delivering structured data from a collection of search engines including Google Search, Google Jobs, YouTube, Google News, and many more. + icon: icon.svg + tags: + - search + - business + - news + - productivity +credentials_for_provider: + searchapi_api_key: + type: secret-input + required: true + label: + en_US: SearchApi API key + zh_Hans: SearchApi API key + pt_BR: SearchApi API key + placeholder: + en_US: Please input your SearchApi API key + zh_Hans: 请输入你的 SearchApi API key + pt_BR: Please input your SearchApi API key + help: + en_US: Get your SearchApi API key from SearchApi + zh_Hans: 从 SearchApi 获取您的 SearchApi API key + pt_BR: Get your SearchApi API key from SearchApi + url: https://www.searchapi.io/ diff --git a/api/core/tools/provider/builtin/searchapi/tools/google.py b/api/core/tools/provider/builtin/searchapi/tools/google.py new file mode 100644 index 0000000000000..d019fe7134f4a --- /dev/null +++ b/api/core/tools/provider/builtin/searchapi/tools/google.py @@ -0,0 +1,104 @@ +from typing import Any, Union + +import requests + +from core.tools.entities.tool_entities import ToolInvokeMessage +from core.tools.tool.builtin_tool import BuiltinTool + +SEARCH_API_URL = "https://www.searchapi.io/api/v1/search" + +class SearchAPI: + """ + SearchAPI tool provider. + """ + + def __init__(self, api_key: str) -> None: + """Initialize SearchAPI tool provider.""" + self.searchapi_api_key = api_key + + def run(self, query: str, **kwargs: Any) -> str: + """Run query through SearchAPI and parse result.""" + type = kwargs.get("result_type", "text") + return self._process_response(self.results(query, **kwargs), type=type) + + def results(self, query: str, **kwargs: Any) -> dict: + """Run query through SearchAPI and return the raw result.""" + params = self.get_params(query, **kwargs) + response = requests.get( + url=SEARCH_API_URL, + params=params, + headers={"Authorization": f"Bearer {self.searchapi_api_key}"}, + ) + response.raise_for_status() + return response.json() + + def get_params(self, query: str, **kwargs: Any) -> dict[str, str]: + """Get parameters for SearchAPI.""" + return { + "engine": "google", + "q": query, + **{key: value for key, value in kwargs.items() if value not in [None, ""]}, + } + + @staticmethod + def _process_response(res: dict, type: str) -> str: + """Process response from SearchAPI.""" + if "error" in res.keys(): + raise ValueError(f"Got error from SearchApi: {res['error']}") + + toret = "" + if type == "text": + if "answer_box" in res.keys() and "answer" in res["answer_box"].keys(): + toret += res["answer_box"]["answer"] + "\n" + if "answer_box" in res.keys() and "snippet" in res["answer_box"].keys(): + toret += res["answer_box"]["snippet"] + "\n" + if "knowledge_graph" in res.keys() and "description" in res["knowledge_graph"].keys(): + toret += res["knowledge_graph"]["description"] + "\n" + if "organic_results" in res.keys() and "snippet" in res["organic_results"][0].keys(): + for item in res["organic_results"]: + toret += "content: " + item["snippet"] + "\n" + "link: " + item["link"] + "\n" + if toret == "": + toret = "No good search result found" + + elif type == "link": + if "answer_box" in res.keys() and "organic_result" in res["answer_box"].keys(): + if "title" in res["answer_box"]["organic_result"].keys(): + toret = f"[{res['answer_box']['organic_result']['title']}]({res['answer_box']['organic_result']['link']})\n" + elif "organic_results" in res.keys() and "link" in res["organic_results"][0].keys(): + toret = "" + for item in res["organic_results"]: + toret += f"[{item['title']}]({item['link']})\n" + elif "related_questions" in res.keys() and "link" in res["related_questions"][0].keys(): + toret = "" + for item in res["related_questions"]: + toret += f"[{item['title']}]({item['link']})\n" + elif "related_searches" in res.keys() and "link" in res["related_searches"][0].keys(): + toret = "" + for item in res["related_searches"]: + toret += f"[{item['title']}]({item['link']})\n" + else: + toret = "No good search result found" + return toret + +class GoogleTool(BuiltinTool): + def _invoke(self, + user_id: str, + tool_parameters: dict[str, Any], + ) -> Union[ToolInvokeMessage, list[ToolInvokeMessage]]: + """ + Invoke the SearchApi tool. + """ + query = tool_parameters['query'] + result_type = tool_parameters['result_type'] + num = tool_parameters.get("num", 10) + google_domain = tool_parameters.get("google_domain", "google.com") + gl = tool_parameters.get("gl", "us") + hl = tool_parameters.get("hl", "en") + location = tool_parameters.get("location", None) + + api_key = self.runtime.credentials['searchapi_api_key'] + result = SearchAPI(api_key).run(query, result_type=result_type, num=num, google_domain=google_domain, gl=gl, hl=hl, location=location) + + if result_type == 'text': + return self.create_text_message(text=result) + return self.create_link_message(link=result) diff --git a/api/core/tools/provider/builtin/searchapi/tools/google.yaml b/api/core/tools/provider/builtin/searchapi/tools/google.yaml new file mode 100644 index 0000000000000..566de84b138ed --- /dev/null +++ b/api/core/tools/provider/builtin/searchapi/tools/google.yaml @@ -0,0 +1,481 @@ +identity: + name: google_search_api + author: SearchApi + label: + en_US: Google Search API + zh_Hans: Google Search API +description: + human: + en_US: A tool to retrieve answer boxes, knowledge graphs, snippets, and webpages from Google Search engine. + zh_Hans: 一种从 Google 搜索引擎检索答案框、知识图、片段和网页的工具。 + llm: A tool to retrieve answer boxes, knowledge graphs, snippets, and webpages from Google Search engine. +parameters: + - name: query + type: string + required: true + label: + en_US: Query + zh_Hans: 询问 + human_description: + en_US: Defines the query you want to search. + zh_Hans: 定义您要搜索的查询。 + llm_description: Defines the search query you want to search. + form: llm + - 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: location + type: string + required: false + label: + en_US: Location + zh_Hans: 询问 + human_description: + en_US: Defines from where you want the search to originate. (For example - New York) + zh_Hans: 定义您想要搜索的起始位置。 (例如 - 纽约) + llm_description: Defines from where you want the search to originate. (For example - New York) + form: llm + - name: gl + type: select + label: + en_US: Country + zh_Hans: 国家 + required: false + human_description: + en_US: Defines the country of the search. Default is "US". + zh_Hans: 定义搜索的国家/地区。默认为“美国”。 + llm_description: Defines the gl parameter of the Google search. + form: form + default: US + options: + - value: AR + label: + en_US: Argentina + zh_Hans: 阿根廷 + pt_BR: Argentina + - value: AU + label: + en_US: Australia + zh_Hans: 澳大利亚 + pt_BR: Australia + - value: AT + label: + en_US: Austria + zh_Hans: 奥地利 + pt_BR: Austria + - value: BE + label: + en_US: Belgium + zh_Hans: 比利时 + pt_BR: Belgium + - value: BR + label: + en_US: Brazil + zh_Hans: 巴西 + pt_BR: Brazil + - value: CA + label: + en_US: Canada + zh_Hans: 加拿大 + pt_BR: Canada + - value: CL + label: + en_US: Chile + zh_Hans: 智利 + pt_BR: Chile + - value: CO + label: + en_US: Colombia + zh_Hans: 哥伦比亚 + pt_BR: Colombia + - value: CN + label: + en_US: China + zh_Hans: 中国 + pt_BR: China + - value: CZ + label: + en_US: Czech Republic + zh_Hans: 捷克共和国 + pt_BR: Czech Republic + - value: DK + label: + en_US: Denmark + zh_Hans: 丹麦 + pt_BR: Denmark + - value: FI + label: + en_US: Finland + zh_Hans: 芬兰 + pt_BR: Finland + - value: FR + label: + en_US: France + zh_Hans: 法国 + pt_BR: France + - value: DE + label: + en_US: Germany + zh_Hans: 德国 + pt_BR: Germany + - value: HK + label: + en_US: Hong Kong + zh_Hans: 香港 + pt_BR: Hong Kong + - value: IN + label: + en_US: India + zh_Hans: 印度 + pt_BR: India + - value: ID + label: + en_US: Indonesia + zh_Hans: 印度尼西亚 + pt_BR: Indonesia + - value: IT + label: + en_US: Italy + zh_Hans: 意大利 + pt_BR: Italy + - value: JP + label: + en_US: Japan + zh_Hans: 日本 + pt_BR: Japan + - value: KR + label: + en_US: Korea + zh_Hans: 韩国 + pt_BR: Korea + - value: MY + label: + en_US: Malaysia + zh_Hans: 马来西亚 + pt_BR: Malaysia + - value: MX + label: + en_US: Mexico + zh_Hans: 墨西哥 + pt_BR: Mexico + - value: NL + label: + en_US: Netherlands + zh_Hans: 荷兰 + pt_BR: Netherlands + - value: NZ + label: + en_US: New Zealand + zh_Hans: 新西兰 + pt_BR: New Zealand + - value: NO + label: + en_US: Norway + zh_Hans: 挪威 + pt_BR: Norway + - value: PH + label: + en_US: Philippines + zh_Hans: 菲律宾 + pt_BR: Philippines + - value: PL + label: + en_US: Poland + zh_Hans: 波兰 + pt_BR: Poland + - value: PT + label: + en_US: Portugal + zh_Hans: 葡萄牙 + pt_BR: Portugal + - value: RU + label: + en_US: Russia + zh_Hans: 俄罗斯 + pt_BR: Russia + - value: SA + label: + en_US: Saudi Arabia + zh_Hans: 沙特阿拉伯 + pt_BR: Saudi Arabia + - value: SG + label: + en_US: Singapore + zh_Hans: 新加坡 + pt_BR: Singapore + - value: ZA + label: + en_US: South Africa + zh_Hans: 南非 + pt_BR: South Africa + - value: ES + label: + en_US: Spain + zh_Hans: 西班牙 + pt_BR: Spain + - value: SE + label: + en_US: Sweden + zh_Hans: 瑞典 + pt_BR: Sweden + - value: CH + label: + en_US: Switzerland + zh_Hans: 瑞士 + pt_BR: Switzerland + - value: TW + label: + en_US: Taiwan + zh_Hans: 台湾 + pt_BR: Taiwan + - value: TH + label: + en_US: Thailand + zh_Hans: 泰国 + pt_BR: Thailand + - value: TR + label: + en_US: Turkey + zh_Hans: 土耳其 + pt_BR: Turkey + - value: GB + label: + en_US: United Kingdom + zh_Hans: 英国 + pt_BR: United Kingdom + - value: US + label: + en_US: United States + zh_Hans: 美国 + pt_BR: United States + - name: hl + type: select + label: + en_US: Language + zh_Hans: 语言 + human_description: + en_US: Defines the interface language of the search. Default is "en". + zh_Hans: 定义搜索的界面语言。默认为“en”。 + required: false + default: en + form: form + options: + - value: ar + label: + en_US: Arabic + zh_Hans: 阿拉伯语 + - value: bg + label: + en_US: Bulgarian + zh_Hans: 保加利亚语 + - value: ca + label: + en_US: Catalan + zh_Hans: 加泰罗尼亚语 + - value: zh-cn + label: + en_US: Chinese (Simplified) + zh_Hans: 中文(简体) + - value: zh-tw + label: + en_US: Chinese (Traditional) + zh_Hans: 中文(繁体) + - value: cs + label: + en_US: Czech + zh_Hans: 捷克语 + - value: da + label: + en_US: Danish + zh_Hans: 丹麦语 + - value: nl + label: + en_US: Dutch + zh_Hans: 荷兰语 + - value: en + label: + en_US: English + zh_Hans: 英语 + - value: et + label: + en_US: Estonian + zh_Hans: 爱沙尼亚语 + - value: fi + label: + en_US: Finnish + zh_Hans: 芬兰语 + - value: fr + label: + en_US: French + zh_Hans: 法语 + - value: de + label: + en_US: German + zh_Hans: 德语 + - value: el + label: + en_US: Greek + zh_Hans: 希腊语 + - value: iw + label: + en_US: Hebrew + zh_Hans: 希伯来语 + - value: hi + label: + en_US: Hindi + zh_Hans: 印地语 + - value: hu + label: + en_US: Hungarian + zh_Hans: 匈牙利语 + - value: id + label: + en_US: Indonesian + zh_Hans: 印尼语 + - value: it + label: + en_US: Italian + zh_Hans: 意大利语 + - value: jp + label: + en_US: Japanese + zh_Hans: 日语 + - value: kn + label: + en_US: Kannada + zh_Hans: 卡纳达语 + - value: ko + label: + en_US: Korean + zh_Hans: 韩语 + - value: lv + label: + en_US: Latvian + zh_Hans: 拉脱维亚语 + - value: lt + label: + en_US: Lithuanian + zh_Hans: 立陶宛语 + - value: my + label: + en_US: Malay + zh_Hans: 马来语 + - value: ml + label: + en_US: Malayalam + zh_Hans: 马拉雅拉姆语 + - value: mr + label: + en_US: Marathi + zh_Hans: 马拉地语 + - value: "no" + label: + en_US: Norwegian + zh_Hans: 挪威语 + - value: pl + label: + en_US: Polish + zh_Hans: 波兰语 + - value: pt-br + label: + en_US: Portuguese (Brazil) + zh_Hans: 葡萄牙语(巴西) + - value: pt-pt + label: + en_US: Portuguese (Portugal) + zh_Hans: 葡萄牙语(葡萄牙) + - value: pa + label: + en_US: Punjabi + zh_Hans: 旁遮普语 + - value: ro + label: + en_US: Romanian + zh_Hans: 罗马尼亚语 + - value: ru + label: + en_US: Russian + zh_Hans: 俄语 + - value: sr + label: + en_US: Serbian + zh_Hans: 塞尔维亚语 + - value: sk + label: + en_US: Slovak + zh_Hans: 斯洛伐克语 + - value: sl + label: + en_US: Slovenian + zh_Hans: 斯洛文尼亚语 + - value: es + label: + en_US: Spanish + zh_Hans: 西班牙语 + - value: sv + label: + en_US: Swedish + zh_Hans: 瑞典语 + - value: ta + label: + en_US: Tamil + zh_Hans: 泰米尔语 + - value: te + label: + en_US: Telugu + zh_Hans: 泰卢固语 + - value: th + label: + en_US: Thai + zh_Hans: 泰语 + - value: tr + label: + en_US: Turkish + zh_Hans: 土耳其语 + - value: uk + label: + en_US: Ukrainian + zh_Hans: 乌克兰语 + - value: vi + label: + en_US: Vietnamese + zh_Hans: 越南语 + - name: google_domain + type: string + required: false + label: + en_US: google_domain + zh_Hans: google_domain + human_description: + en_US: Defines the Google domain of the search. Default is "google.com". + zh_Hans: 定义搜索的 Google 域。默认为“google.com”。 + llm_description: Defines Google domain in which you want to search. + form: llm + - name: num + type: number + required: false + label: + en_US: num + zh_Hans: num + human_description: + en_US: Specifies the number of results to display per page. Default is 10. Max number - 100, min - 1. + zh_Hans: 指定每页显示的结果数。默认值为 10。最大数量 - 100,最小数量 - 1。 + llm_description: Specifies the num of results to display per page. + form: llm diff --git a/api/core/tools/provider/builtin/searchapi/tools/google_jobs.py b/api/core/tools/provider/builtin/searchapi/tools/google_jobs.py new file mode 100644 index 0000000000000..1b8cfa7e30e9c --- /dev/null +++ b/api/core/tools/provider/builtin/searchapi/tools/google_jobs.py @@ -0,0 +1,88 @@ +from typing import Any, Union + +import requests + +from core.tools.entities.tool_entities import ToolInvokeMessage +from core.tools.tool.builtin_tool import BuiltinTool + +SEARCH_API_URL = "https://www.searchapi.io/api/v1/search" + +class SearchAPI: + """ + SearchAPI tool provider. + """ + + def __init__(self, api_key: str) -> None: + """Initialize SearchAPI tool provider.""" + self.searchapi_api_key = api_key + + def run(self, query: str, **kwargs: Any) -> str: + """Run query through SearchAPI and parse result.""" + type = kwargs.get("result_type", "text") + return self._process_response(self.results(query, **kwargs), type=type) + + def results(self, query: str, **kwargs: Any) -> dict: + """Run query through SearchAPI and return the raw result.""" + params = self.get_params(query, **kwargs) + response = requests.get( + url=SEARCH_API_URL, + params=params, + headers={"Authorization": f"Bearer {self.searchapi_api_key}"}, + ) + response.raise_for_status() + return response.json() + + def get_params(self, query: str, **kwargs: Any) -> dict[str, str]: + """Get parameters for SearchAPI.""" + return { + "engine": "google_jobs", + "q": query, + **{key: value for key, value in kwargs.items() if value not in [None, ""]}, + } + + @staticmethod + def _process_response(res: dict, type: str) -> str: + """Process response from SearchAPI.""" + if "error" in res.keys(): + raise ValueError(f"Got error from SearchApi: {res['error']}") + + toret = "" + if type == "text": + if "jobs" in res.keys() and "title" in res["jobs"][0].keys(): + for item in res["jobs"]: + toret += "title: " + item["title"] + "\n" + "company_name: " + item["company_name"] + "content: " + item["description"] + "\n" + if toret == "": + toret = "No good search result found" + + elif type == "link": + if "jobs" in res.keys() and "apply_link" in res["jobs"][0].keys(): + for item in res["jobs"]: + toret += f"[{item['title']} - {item['company_name']}]({item['apply_link']})\n" + else: + toret = "No good search result found" + return toret + +class GoogleJobsTool(BuiltinTool): + def _invoke(self, + user_id: str, + tool_parameters: dict[str, Any], + ) -> Union[ToolInvokeMessage, list[ToolInvokeMessage]]: + """ + Invoke the SearchApi tool. + """ + query = tool_parameters['query'] + result_type = tool_parameters['result_type'] + is_remote = tool_parameters.get("is_remote", None) + google_domain = tool_parameters.get("google_domain", "google.com") + gl = tool_parameters.get("gl", "us") + hl = tool_parameters.get("hl", "en") + location = tool_parameters.get("location", None) + + ltype = 1 if is_remote else None + + api_key = self.runtime.credentials['searchapi_api_key'] + result = SearchAPI(api_key).run(query, result_type=result_type, google_domain=google_domain, gl=gl, hl=hl, location=location, ltype=ltype) + + if result_type == 'text': + return self.create_text_message(text=result) + return self.create_link_message(link=result) diff --git a/api/core/tools/provider/builtin/searchapi/tools/google_jobs.yaml b/api/core/tools/provider/builtin/searchapi/tools/google_jobs.yaml new file mode 100644 index 0000000000000..486b193efa396 --- /dev/null +++ b/api/core/tools/provider/builtin/searchapi/tools/google_jobs.yaml @@ -0,0 +1,478 @@ +identity: + name: google_jobs_api + author: SearchApi + label: + en_US: Google Jobs API + zh_Hans: Google Jobs API +description: + human: + en_US: A tool to retrieve job titles, company names and description from Google Jobs engine. + zh_Hans: 一个从 Google 招聘引擎检索职位名称、公司名称和描述的工具。 + llm: A tool to retrieve job titles, company names and description from Google Jobs engine. +parameters: + - name: query + type: string + required: true + label: + en_US: Query + zh_Hans: 询问 + human_description: + en_US: Defines the query you want to search. + zh_Hans: 定义您要搜索的查询。 + llm_description: Defines the search query you want to search. + form: llm + - 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: location + type: string + required: false + label: + en_US: Location + zh_Hans: 询问 + human_description: + en_US: Defines from where you want the search to originate. (For example - New York) + zh_Hans: 定义您想要搜索的起始位置。 (例如 - 纽约) + llm_description: Defines from where you want the search to originate. (For example - New York) + form: llm + - name: gl + type: select + label: + en_US: Country + zh_Hans: 国家 + required: false + human_description: + en_US: Defines the country of the search. Default is "US". + zh_Hans: 定义搜索的国家/地区。默认为“美国”。 + llm_description: Defines the gl parameter of the Google search. + form: form + default: US + options: + - value: AR + label: + en_US: Argentina + zh_Hans: 阿根廷 + pt_BR: Argentina + - value: AU + label: + en_US: Australia + zh_Hans: 澳大利亚 + pt_BR: Australia + - value: AT + label: + en_US: Austria + zh_Hans: 奥地利 + pt_BR: Austria + - value: BE + label: + en_US: Belgium + zh_Hans: 比利时 + pt_BR: Belgium + - value: BR + label: + en_US: Brazil + zh_Hans: 巴西 + pt_BR: Brazil + - value: CA + label: + en_US: Canada + zh_Hans: 加拿大 + pt_BR: Canada + - value: CL + label: + en_US: Chile + zh_Hans: 智利 + pt_BR: Chile + - value: CO + label: + en_US: Colombia + zh_Hans: 哥伦比亚 + pt_BR: Colombia + - value: CN + label: + en_US: China + zh_Hans: 中国 + pt_BR: China + - value: CZ + label: + en_US: Czech Republic + zh_Hans: 捷克共和国 + pt_BR: Czech Republic + - value: DK + label: + en_US: Denmark + zh_Hans: 丹麦 + pt_BR: Denmark + - value: FI + label: + en_US: Finland + zh_Hans: 芬兰 + pt_BR: Finland + - value: FR + label: + en_US: France + zh_Hans: 法国 + pt_BR: France + - value: DE + label: + en_US: Germany + zh_Hans: 德国 + pt_BR: Germany + - value: HK + label: + en_US: Hong Kong + zh_Hans: 香港 + pt_BR: Hong Kong + - value: IN + label: + en_US: India + zh_Hans: 印度 + pt_BR: India + - value: ID + label: + en_US: Indonesia + zh_Hans: 印度尼西亚 + pt_BR: Indonesia + - value: IT + label: + en_US: Italy + zh_Hans: 意大利 + pt_BR: Italy + - value: JP + label: + en_US: Japan + zh_Hans: 日本 + pt_BR: Japan + - value: KR + label: + en_US: Korea + zh_Hans: 韩国 + pt_BR: Korea + - value: MY + label: + en_US: Malaysia + zh_Hans: 马来西亚 + pt_BR: Malaysia + - value: MX + label: + en_US: Mexico + zh_Hans: 墨西哥 + pt_BR: Mexico + - value: NL + label: + en_US: Netherlands + zh_Hans: 荷兰 + pt_BR: Netherlands + - value: NZ + label: + en_US: New Zealand + zh_Hans: 新西兰 + pt_BR: New Zealand + - value: NO + label: + en_US: Norway + zh_Hans: 挪威 + pt_BR: Norway + - value: PH + label: + en_US: Philippines + zh_Hans: 菲律宾 + pt_BR: Philippines + - value: PL + label: + en_US: Poland + zh_Hans: 波兰 + pt_BR: Poland + - value: PT + label: + en_US: Portugal + zh_Hans: 葡萄牙 + pt_BR: Portugal + - value: RU + label: + en_US: Russia + zh_Hans: 俄罗斯 + pt_BR: Russia + - value: SA + label: + en_US: Saudi Arabia + zh_Hans: 沙特阿拉伯 + pt_BR: Saudi Arabia + - value: SG + label: + en_US: Singapore + zh_Hans: 新加坡 + pt_BR: Singapore + - value: ZA + label: + en_US: South Africa + zh_Hans: 南非 + pt_BR: South Africa + - value: ES + label: + en_US: Spain + zh_Hans: 西班牙 + pt_BR: Spain + - value: SE + label: + en_US: Sweden + zh_Hans: 瑞典 + pt_BR: Sweden + - value: CH + label: + en_US: Switzerland + zh_Hans: 瑞士 + pt_BR: Switzerland + - value: TW + label: + en_US: Taiwan + zh_Hans: 台湾 + pt_BR: Taiwan + - value: TH + label: + en_US: Thailand + zh_Hans: 泰国 + pt_BR: Thailand + - value: TR + label: + en_US: Turkey + zh_Hans: 土耳其 + pt_BR: Turkey + - value: GB + label: + en_US: United Kingdom + zh_Hans: 英国 + pt_BR: United Kingdom + - value: US + label: + en_US: United States + zh_Hans: 美国 + pt_BR: United States + - name: hl + type: select + label: + en_US: Language + zh_Hans: 语言 + human_description: + en_US: Defines the interface language of the search. Default is "en". + zh_Hans: 定义搜索的界面语言。默认为“en”。 + required: false + default: en + form: form + options: + - value: ar + label: + en_US: Arabic + zh_Hans: 阿拉伯语 + - value: bg + label: + en_US: Bulgarian + zh_Hans: 保加利亚语 + - value: ca + label: + en_US: Catalan + zh_Hans: 加泰罗尼亚语 + - value: zh-cn + label: + en_US: Chinese (Simplified) + zh_Hans: 中文(简体) + - value: zh-tw + label: + en_US: Chinese (Traditional) + zh_Hans: 中文(繁体) + - value: cs + label: + en_US: Czech + zh_Hans: 捷克语 + - value: da + label: + en_US: Danish + zh_Hans: 丹麦语 + - value: nl + label: + en_US: Dutch + zh_Hans: 荷兰语 + - value: en + label: + en_US: English + zh_Hans: 英语 + - value: et + label: + en_US: Estonian + zh_Hans: 爱沙尼亚语 + - value: fi + label: + en_US: Finnish + zh_Hans: 芬兰语 + - value: fr + label: + en_US: French + zh_Hans: 法语 + - value: de + label: + en_US: German + zh_Hans: 德语 + - value: el + label: + en_US: Greek + zh_Hans: 希腊语 + - value: iw + label: + en_US: Hebrew + zh_Hans: 希伯来语 + - value: hi + label: + en_US: Hindi + zh_Hans: 印地语 + - value: hu + label: + en_US: Hungarian + zh_Hans: 匈牙利语 + - value: id + label: + en_US: Indonesian + zh_Hans: 印尼语 + - value: it + label: + en_US: Italian + zh_Hans: 意大利语 + - value: jp + label: + en_US: Japanese + zh_Hans: 日语 + - value: kn + label: + en_US: Kannada + zh_Hans: 卡纳达语 + - value: ko + label: + en_US: Korean + zh_Hans: 韩语 + - value: lv + label: + en_US: Latvian + zh_Hans: 拉脱维亚语 + - value: lt + label: + en_US: Lithuanian + zh_Hans: 立陶宛语 + - value: my + label: + en_US: Malay + zh_Hans: 马来语 + - value: ml + label: + en_US: Malayalam + zh_Hans: 马拉雅拉姆语 + - value: mr + label: + en_US: Marathi + zh_Hans: 马拉地语 + - value: "no" + label: + en_US: Norwegian + zh_Hans: 挪威语 + - value: pl + label: + en_US: Polish + zh_Hans: 波兰语 + - value: pt-br + label: + en_US: Portuguese (Brazil) + zh_Hans: 葡萄牙语(巴西) + - value: pt-pt + label: + en_US: Portuguese (Portugal) + zh_Hans: 葡萄牙语(葡萄牙) + - value: pa + label: + en_US: Punjabi + zh_Hans: 旁遮普语 + - value: ro + label: + en_US: Romanian + zh_Hans: 罗马尼亚语 + - value: ru + label: + en_US: Russian + zh_Hans: 俄语 + - value: sr + label: + en_US: Serbian + zh_Hans: 塞尔维亚语 + - value: sk + label: + en_US: Slovak + zh_Hans: 斯洛伐克语 + - value: sl + label: + en_US: Slovenian + zh_Hans: 斯洛文尼亚语 + - value: es + label: + en_US: Spanish + zh_Hans: 西班牙语 + - value: sv + label: + en_US: Swedish + zh_Hans: 瑞典语 + - value: ta + label: + en_US: Tamil + zh_Hans: 泰米尔语 + - value: te + label: + en_US: Telugu + zh_Hans: 泰卢固语 + - value: th + label: + en_US: Thai + zh_Hans: 泰语 + - value: tr + label: + en_US: Turkish + zh_Hans: 土耳其语 + - value: uk + label: + en_US: Ukrainian + zh_Hans: 乌克兰语 + - value: vi + label: + en_US: Vietnamese + zh_Hans: 越南语 + - name: is_remote + type: select + label: + en_US: is_remote + zh_Hans: 很遥远 + human_description: + en_US: Filter results based on the work arrangement. Set it to true to find jobs that offer work from home or remote work opportunities. + zh_Hans: 根据工作安排过滤结果。将其设置为 true 可查找提供在家工作或远程工作机会的工作。 + required: false + form: form + options: + - value: true + label: + en_US: "true" + zh_Hans: "true" + - value: false + label: + en_US: "false" + zh_Hans: "false" diff --git a/api/core/tools/provider/builtin/searchapi/tools/google_news.py b/api/core/tools/provider/builtin/searchapi/tools/google_news.py new file mode 100644 index 0000000000000..d592dc25aaf5b --- /dev/null +++ b/api/core/tools/provider/builtin/searchapi/tools/google_news.py @@ -0,0 +1,92 @@ +from typing import Any, Union + +import requests + +from core.tools.entities.tool_entities import ToolInvokeMessage +from core.tools.tool.builtin_tool import BuiltinTool + +SEARCH_API_URL = "https://www.searchapi.io/api/v1/search" + +class SearchAPI: + """ + SearchAPI tool provider. + """ + + def __init__(self, api_key: str) -> None: + """Initialize SearchAPI tool provider.""" + self.searchapi_api_key = api_key + + def run(self, query: str, **kwargs: Any) -> str: + """Run query through SearchAPI and parse result.""" + type = kwargs.get("result_type", "text") + return self._process_response(self.results(query, **kwargs), type=type) + + def results(self, query: str, **kwargs: Any) -> dict: + """Run query through SearchAPI and return the raw result.""" + params = self.get_params(query, **kwargs) + response = requests.get( + url=SEARCH_API_URL, + params=params, + headers={"Authorization": f"Bearer {self.searchapi_api_key}"}, + ) + response.raise_for_status() + return response.json() + + def get_params(self, query: str, **kwargs: Any) -> dict[str, str]: + """Get parameters for SearchAPI.""" + return { + "engine": "google_news", + "q": query, + **{key: value for key, value in kwargs.items() if value not in [None, ""]}, + } + + @staticmethod + def _process_response(res: dict, type: str) -> str: + """Process response from SearchAPI.""" + if "error" in res.keys(): + raise ValueError(f"Got error from SearchApi: {res['error']}") + + toret = "" + if type == "text": + if "organic_results" in res.keys() and "snippet" in res["organic_results"][0].keys(): + for item in res["organic_results"]: + toret += "content: " + item["snippet"] + "\n" + "link: " + item["link"] + "\n" + if "top_stories" in res.keys() and "title" in res["top_stories"][0].keys(): + for item in res["top_stories"]: + toret += "title: " + item["title"] + "\n" + "link: " + item["link"] + "\n" + if toret == "": + toret = "No good search result found" + + elif type == "link": + if "organic_results" in res.keys() and "title" in res["organic_results"][0].keys(): + for item in res["organic_results"]: + toret += f"[{item['title']}]({item['link']})\n" + elif "top_stories" in res.keys() and "title" in res["top_stories"][0].keys(): + for item in res["top_stories"]: + toret += f"[{item['title']}]({item['link']})\n" + else: + toret = "No good search result found" + return toret + +class GoogleNewsTool(BuiltinTool): + def _invoke(self, + user_id: str, + tool_parameters: dict[str, Any], + ) -> Union[ToolInvokeMessage, list[ToolInvokeMessage]]: + """ + Invoke the SearchApi tool. + """ + query = tool_parameters['query'] + result_type = tool_parameters['result_type'] + num = tool_parameters.get("num", 10) + google_domain = tool_parameters.get("google_domain", "google.com") + gl = tool_parameters.get("gl", "us") + hl = tool_parameters.get("hl", "en") + location = tool_parameters.get("location", None) + + api_key = self.runtime.credentials['searchapi_api_key'] + result = SearchAPI(api_key).run(query, result_type=result_type, num=num, google_domain=google_domain, gl=gl, hl=hl, location=location) + + if result_type == 'text': + return self.create_text_message(text=result) + return self.create_link_message(link=result) diff --git a/api/core/tools/provider/builtin/searchapi/tools/google_news.yaml b/api/core/tools/provider/builtin/searchapi/tools/google_news.yaml new file mode 100644 index 0000000000000..b0212952e6013 --- /dev/null +++ b/api/core/tools/provider/builtin/searchapi/tools/google_news.yaml @@ -0,0 +1,482 @@ +identity: + name: google_news_api + author: SearchApi + label: + en_US: Google News API + zh_Hans: Google News API +description: + human: + en_US: A tool to retrieve organic search results snippets and links from Google News engine. + zh_Hans: 一种从 Google 新闻引擎检索有机搜索结果片段和链接的工具。 + llm: A tool to retrieve organic search results snippets and links from Google News engine. +parameters: + - name: query + type: string + required: true + label: + en_US: Query + zh_Hans: 询问 + human_description: + en_US: Defines the query you want to search. + zh_Hans: 定义您要搜索的查询。 + llm_description: Defines the search query you want to search. + form: llm + - 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: location + type: string + required: false + label: + en_US: Location + zh_Hans: 询问 + human_description: + en_US: Defines from where you want the search to originate. (For example - New York) + zh_Hans: 定义您想要搜索的起始位置。 (例如 - 纽约) + llm_description: Defines from where you want the search to originate. (For example - New York) + form: llm + - name: gl + type: select + label: + en_US: Country + zh_Hans: 国家 + required: false + human_description: + en_US: Defines the country of the search. Default is "US". + zh_Hans: 定义搜索的国家/地区。默认为“美国”。 + llm_description: Defines the gl parameter of the Google search. + form: form + default: US + options: + - value: AR + label: + en_US: Argentina + zh_Hans: 阿根廷 + pt_BR: Argentina + - value: AU + label: + en_US: Australia + zh_Hans: 澳大利亚 + pt_BR: Australia + - value: AT + label: + en_US: Austria + zh_Hans: 奥地利 + pt_BR: Austria + - value: BE + label: + en_US: Belgium + zh_Hans: 比利时 + pt_BR: Belgium + - value: BR + label: + en_US: Brazil + zh_Hans: 巴西 + pt_BR: Brazil + - value: CA + label: + en_US: Canada + zh_Hans: 加拿大 + pt_BR: Canada + - value: CL + label: + en_US: Chile + zh_Hans: 智利 + pt_BR: Chile + - value: CO + label: + en_US: Colombia + zh_Hans: 哥伦比亚 + pt_BR: Colombia + - value: CN + label: + en_US: China + zh_Hans: 中国 + pt_BR: China + - value: CZ + label: + en_US: Czech Republic + zh_Hans: 捷克共和国 + pt_BR: Czech Republic + - value: DK + label: + en_US: Denmark + zh_Hans: 丹麦 + pt_BR: Denmark + - value: FI + label: + en_US: Finland + zh_Hans: 芬兰 + pt_BR: Finland + - value: FR + label: + en_US: France + zh_Hans: 法国 + pt_BR: France + - value: DE + label: + en_US: Germany + zh_Hans: 德国 + pt_BR: Germany + - value: HK + label: + en_US: Hong Kong + zh_Hans: 香港 + pt_BR: Hong Kong + - value: IN + label: + en_US: India + zh_Hans: 印度 + pt_BR: India + - value: ID + label: + en_US: Indonesia + zh_Hans: 印度尼西亚 + pt_BR: Indonesia + - value: IT + label: + en_US: Italy + zh_Hans: 意大利 + pt_BR: Italy + - value: JP + label: + en_US: Japan + zh_Hans: 日本 + pt_BR: Japan + - value: KR + label: + en_US: Korea + zh_Hans: 韩国 + pt_BR: Korea + - value: MY + label: + en_US: Malaysia + zh_Hans: 马来西亚 + pt_BR: Malaysia + - value: MX + label: + en_US: Mexico + zh_Hans: 墨西哥 + pt_BR: Mexico + - value: NL + label: + en_US: Netherlands + zh_Hans: 荷兰 + pt_BR: Netherlands + - value: NZ + label: + en_US: New Zealand + zh_Hans: 新西兰 + pt_BR: New Zealand + - value: NO + label: + en_US: Norway + zh_Hans: 挪威 + pt_BR: Norway + - value: PH + label: + en_US: Philippines + zh_Hans: 菲律宾 + pt_BR: Philippines + - value: PL + label: + en_US: Poland + zh_Hans: 波兰 + pt_BR: Poland + - value: PT + label: + en_US: Portugal + zh_Hans: 葡萄牙 + pt_BR: Portugal + - value: RU + label: + en_US: Russia + zh_Hans: 俄罗斯 + pt_BR: Russia + - value: SA + label: + en_US: Saudi Arabia + zh_Hans: 沙特阿拉伯 + pt_BR: Saudi Arabia + - value: SG + label: + en_US: Singapore + zh_Hans: 新加坡 + pt_BR: Singapore + - value: ZA + label: + en_US: South Africa + zh_Hans: 南非 + pt_BR: South Africa + - value: ES + label: + en_US: Spain + zh_Hans: 西班牙 + pt_BR: Spain + - value: SE + label: + en_US: Sweden + zh_Hans: 瑞典 + pt_BR: Sweden + - value: CH + label: + en_US: Switzerland + zh_Hans: 瑞士 + pt_BR: Switzerland + - value: TW + label: + en_US: Taiwan + zh_Hans: 台湾 + pt_BR: Taiwan + - value: TH + label: + en_US: Thailand + zh_Hans: 泰国 + pt_BR: Thailand + - value: TR + label: + en_US: Turkey + zh_Hans: 土耳其 + pt_BR: Turkey + - value: GB + label: + en_US: United Kingdom + zh_Hans: 英国 + pt_BR: United Kingdom + - value: US + label: + en_US: United States + zh_Hans: 美国 + pt_BR: United States + - name: hl + type: select + label: + en_US: Language + zh_Hans: 语言 + human_description: + en_US: Defines the interface language of the search. Default is "en". + zh_Hans: 定义搜索的界面语言。默认为“en”。 + required: false + default: en + form: form + options: + - value: ar + label: + en_US: Arabic + zh_Hans: 阿拉伯语 + - value: bg + label: + en_US: Bulgarian + zh_Hans: 保加利亚语 + - value: ca + label: + en_US: Catalan + zh_Hans: 加泰罗尼亚语 + - value: zh-cn + label: + en_US: Chinese (Simplified) + zh_Hans: 中文(简体) + - value: zh-tw + label: + en_US: Chinese (Traditional) + zh_Hans: 中文(繁体) + - value: cs + label: + en_US: Czech + zh_Hans: 捷克语 + - value: da + label: + en_US: Danish + zh_Hans: 丹麦语 + - value: nl + label: + en_US: Dutch + zh_Hans: 荷兰语 + - value: en + label: + en_US: English + zh_Hans: 英语 + - value: et + label: + en_US: Estonian + zh_Hans: 爱沙尼亚语 + - value: fi + label: + en_US: Finnish + zh_Hans: 芬兰语 + - value: fr + label: + en_US: French + zh_Hans: 法语 + - value: de + label: + en_US: German + zh_Hans: 德语 + - value: el + label: + en_US: Greek + zh_Hans: 希腊语 + - value: iw + label: + en_US: Hebrew + zh_Hans: 希伯来语 + - value: hi + label: + en_US: Hindi + zh_Hans: 印地语 + - value: hu + label: + en_US: Hungarian + zh_Hans: 匈牙利语 + - value: id + label: + en_US: Indonesian + zh_Hans: 印尼语 + - value: it + label: + en_US: Italian + zh_Hans: 意大利语 + - value: jp + label: + en_US: Japanese + zh_Hans: 日语 + - value: kn + label: + en_US: Kannada + zh_Hans: 卡纳达语 + - value: ko + label: + en_US: Korean + zh_Hans: 韩语 + - value: lv + label: + en_US: Latvian + zh_Hans: 拉脱维亚语 + - value: lt + label: + en_US: Lithuanian + zh_Hans: 立陶宛语 + - value: my + label: + en_US: Malay + zh_Hans: 马来语 + - value: ml + label: + en_US: Malayalam + zh_Hans: 马拉雅拉姆语 + - value: mr + label: + en_US: Marathi + zh_Hans: 马拉地语 + - value: "no" + label: + en_US: Norwegian + zh_Hans: 挪威语 + - value: pl + label: + en_US: Polish + zh_Hans: 波兰语 + - value: pt-br + label: + en_US: Portuguese (Brazil) + zh_Hans: 葡萄牙语(巴西) + - value: pt-pt + label: + en_US: Portuguese (Portugal) + zh_Hans: 葡萄牙语(葡萄牙) + - value: pa + label: + en_US: Punjabi + zh_Hans: 旁遮普语 + - value: ro + label: + en_US: Romanian + zh_Hans: 罗马尼亚语 + - value: ru + label: + en_US: Russian + zh_Hans: 俄语 + - value: sr + label: + en_US: Serbian + zh_Hans: 塞尔维亚语 + - value: sk + label: + en_US: Slovak + zh_Hans: 斯洛伐克语 + - value: sl + label: + en_US: Slovenian + zh_Hans: 斯洛文尼亚语 + - value: es + label: + en_US: Spanish + zh_Hans: 西班牙语 + - value: sv + label: + en_US: Swedish + zh_Hans: 瑞典语 + - value: ta + label: + en_US: Tamil + zh_Hans: 泰米尔语 + - value: te + label: + en_US: Telugu + zh_Hans: 泰卢固语 + - value: th + label: + en_US: Thai + zh_Hans: 泰语 + - value: tr + label: + en_US: Turkish + zh_Hans: 土耳其语 + - value: uk + label: + en_US: Ukrainian + zh_Hans: 乌克兰语 + - value: vi + label: + en_US: Vietnamese + zh_Hans: 越南语 + - name: google_domain + type: string + required: false + label: + en_US: google_domain + zh_Hans: google_domain + human_description: + en_US: Defines the Google domain of the search. Default is "google.com". + zh_Hans: 定义搜索的 Google 域。默认为“google.com”。 + llm_description: Defines Google domain in which you want to search. + form: llm + - name: num + type: number + required: false + label: + en_US: num + zh_Hans: num + human_description: + en_US: Specifies the number of results to display per page. Default is 10. Max number - 100, min - 1. + zh_Hans: 指定每页显示的结果数。默认值为 10。最大数量 - 100,最小数量 - 1。 + pt_BR: Specifies the number of results to display per page. Default is 10. Max number - 100, min - 1. + llm_description: Specifies the num of results to display per page. + form: llm diff --git a/api/core/tools/provider/builtin/searchapi/tools/youtube_transcripts.py b/api/core/tools/provider/builtin/searchapi/tools/youtube_transcripts.py new file mode 100644 index 0000000000000..6345b338011e7 --- /dev/null +++ b/api/core/tools/provider/builtin/searchapi/tools/youtube_transcripts.py @@ -0,0 +1,72 @@ +from typing import Any, Union + +import requests + +from core.tools.entities.tool_entities import ToolInvokeMessage +from core.tools.tool.builtin_tool import BuiltinTool + +SEARCH_API_URL = "https://www.searchapi.io/api/v1/search" + +class SearchAPI: + """ + SearchAPI tool provider. + """ + + def __init__(self, api_key: str) -> None: + """Initialize SearchAPI tool provider.""" + self.searchapi_api_key = api_key + + def run(self, video_id: str, language: str, **kwargs: Any) -> str: + """Run video_id through SearchAPI and parse result.""" + return self._process_response(self.results(video_id, language, **kwargs)) + + def results(self, video_id: str, language: str, **kwargs: Any) -> dict: + """Run video_id through SearchAPI and return the raw result.""" + params = self.get_params(video_id, language, **kwargs) + response = requests.get( + url=SEARCH_API_URL, + params=params, + headers={"Authorization": f"Bearer {self.searchapi_api_key}"}, + ) + response.raise_for_status() + return response.json() + + def get_params(self, video_id: str, language: str, **kwargs: Any) -> dict[str, str]: + """Get parameters for SearchAPI.""" + return { + "engine": "youtube_transcripts", + "video_id": video_id, + "lang": language if language else "en", + **{key: value for key, value in kwargs.items() if value not in [None, ""]}, + } + + @staticmethod + def _process_response(res: dict) -> str: + """Process response from SearchAPI.""" + if "error" in res.keys(): + raise ValueError(f"Got error from SearchApi: {res['error']}") + + toret = "" + if "transcripts" in res.keys() and "text" in res["transcripts"][0].keys(): + for item in res["transcripts"]: + toret += item["text"] + " " + if toret == "": + toret = "No good search result found" + + return toret + +class YoutubeTranscriptsTool(BuiltinTool): + def _invoke(self, + user_id: str, + tool_parameters: dict[str, Any], + ) -> Union[ToolInvokeMessage, list[ToolInvokeMessage]]: + """ + Invoke the SearchApi tool. + """ + video_id = tool_parameters['video_id'] + language = tool_parameters.get('language', "en") + + api_key = self.runtime.credentials['searchapi_api_key'] + result = SearchAPI(api_key).run(video_id, language=language) + + return self.create_text_message(text=result) diff --git a/api/core/tools/provider/builtin/searchapi/tools/youtube_transcripts.yaml b/api/core/tools/provider/builtin/searchapi/tools/youtube_transcripts.yaml new file mode 100644 index 0000000000000..8bdcd6bb936d9 --- /dev/null +++ b/api/core/tools/provider/builtin/searchapi/tools/youtube_transcripts.yaml @@ -0,0 +1,34 @@ +identity: + name: youtube_transcripts_api + author: SearchApi + label: + en_US: YouTube Transcripts API + zh_Hans: YouTube 脚本 API +description: + human: + en_US: A tool to retrieve transcripts from the specific YouTube video. + zh_Hans: 一种从特定 YouTube 视频检索文字记录的工具。 + llm: A tool to retrieve transcripts from the specific YouTube video. +parameters: + - name: video_id + type: string + required: true + label: + en_US: video_id + zh_Hans: 视频ID + human_description: + en_US: Used to define the video you want to search. You can find the video id's in YouTube page that appears in URL. For example - https://www.youtube.com/watch?v=video_id. + zh_Hans: 用于定义要搜索的视频。您可以在 URL 中显示的 YouTube 页面中找到视频 ID。例如 - https://www.youtube.com/watch?v=video_id。 + llm_description: Used to define the video you want to search. + form: llm + - name: language + type: string + required: false + label: + en_US: language + zh_Hans: 语言 + human_description: + en_US: Used to set the language for transcripts. The default value is "en". You can find all supported languages in SearchApi documentation. + zh_Hans: 用于设置成绩单的语言。默认值为“en”。您可以在 SearchApi 文档中找到所有支持的语言。 + llm_description: Used to set the language for transcripts. + form: llm