feat: add duckduckgo img search, translate, ai chat (#5074)

This commit is contained in:
非法操作 2024-06-12 10:04:10 +08:00 committed by GitHub
parent 4d2e6c3391
commit 3b36ba797f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 340 additions and 195 deletions

View File

@ -1,5 +1,5 @@
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

View File

@ -0,0 +1,20 @@
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)

View File

@ -0,0 +1,41 @@
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

View File

@ -0,0 +1,25 @@
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

View File

@ -0,0 +1,88 @@
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

View File

@ -0,0 +1,29 @@
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)

View File

@ -0,0 +1,65 @@
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

View File

@ -0,0 +1,20 @@
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)

View File

@ -0,0 +1,51 @@
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

View File

@ -1,171 +0,0 @@
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))

View File

@ -1,23 +0,0 @@
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