mirror of
https://github.com/langgenius/dify.git
synced 2024-11-15 19:22:36 +08:00
Add DuckDuckGo News Search and Video Search
This commit is contained in:
parent
ac0fed6402
commit
11e1720be0
|
@ -0,0 +1,83 @@
|
|||
from typing import Any
|
||||
|
||||
from duckduckgo_search import DDGS
|
||||
|
||||
from core.model_runtime.entities.message_entities import SystemPromptMessage
|
||||
from core.tools.entities.tool_entities import ToolInvokeMessage
|
||||
from core.tools.tool.builtin_tool import BuiltinTool
|
||||
|
||||
SUMMARY_PROMPT = """
|
||||
User's query:
|
||||
{query}
|
||||
|
||||
Here are the news results:
|
||||
{content}
|
||||
|
||||
Please summarize the news in a few sentences.
|
||||
"""
|
||||
|
||||
|
||||
class DuckDuckGoNewsSearchTool(BuiltinTool):
|
||||
"""
|
||||
Tool for performing a news search using DuckDuckGo search engine.
|
||||
"""
|
||||
|
||||
def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage | list[ToolInvokeMessage]:
|
||||
query_dict = {
|
||||
"keywords": tool_parameters.get("query"),
|
||||
"timelimit": tool_parameters.get("timelimit"),
|
||||
"max_results": tool_parameters.get("max_results"),
|
||||
"safesearch": "moderate",
|
||||
"region": "wt-wt"
|
||||
}
|
||||
try:
|
||||
response = list(DDGS().news(**query_dict))
|
||||
if not response:
|
||||
return [self.create_text_message("No news found matching your criteria.")]
|
||||
except Exception as e:
|
||||
return [self.create_text_message(f"Error searching news: {str(e)}")]
|
||||
|
||||
require_summary = tool_parameters.get("require_summary", False)
|
||||
|
||||
if require_summary:
|
||||
results = "\n".join([f"{res.get('title')}: {res.get('body')}" for res in response])
|
||||
results = self.summary_results(user_id=user_id, content=results, query=query_dict["keywords"])
|
||||
return self.create_text_message(text=results)
|
||||
|
||||
# Create rich markdown content for each news item
|
||||
markdown_result = "\n\n"
|
||||
json_result = []
|
||||
|
||||
for res in response:
|
||||
markdown_result += f"### {res.get('title', 'Untitled')}\n\n"
|
||||
if res.get('date'):
|
||||
markdown_result += f"**Date:** {res.get('date')}\n\n"
|
||||
if res.get('body'):
|
||||
markdown_result += f"{res.get('body')}\n\n"
|
||||
if res.get('source'):
|
||||
markdown_result += f"*Source: {res.get('source')}*\n\n"
|
||||
if res.get('image'):
|
||||
markdown_result += f"![{res.get('title', '')}]({res.get('image')})\n\n"
|
||||
markdown_result += f"[Read more]({res.get('url', '')})\n\n---\n\n"
|
||||
|
||||
json_result.append(self.create_json_message({
|
||||
"title": res.get("title", ""),
|
||||
"date": res.get("date", ""),
|
||||
"body": res.get("body", ""),
|
||||
"url": res.get("url", ""),
|
||||
"image": res.get("image", ""),
|
||||
"source": res.get("source", "")
|
||||
}))
|
||||
|
||||
return [self.create_text_message(markdown_result)] + json_result
|
||||
|
||||
def summary_results(self, user_id: str, content: str, query: str) -> str:
|
||||
prompt = SUMMARY_PROMPT.format(query=query, content=content)
|
||||
summary = self.invoke_model(
|
||||
user_id=user_id,
|
||||
prompt_messages=[
|
||||
SystemPromptMessage(content=prompt),
|
||||
],
|
||||
stop=[],
|
||||
)
|
||||
return summary.message.content
|
|
@ -0,0 +1,71 @@
|
|||
identity:
|
||||
name: ddgo_news
|
||||
author: Assistant
|
||||
label:
|
||||
en_US: DuckDuckGo News Search
|
||||
zh_Hans: DuckDuckGo 新闻搜索
|
||||
description:
|
||||
human:
|
||||
en_US: Perform news searches on DuckDuckGo and get results.
|
||||
zh_Hans: 在 DuckDuckGo 上进行新闻搜索并获取结果。
|
||||
llm: Perform news searches on DuckDuckGo and get results.
|
||||
parameters:
|
||||
- name: query
|
||||
type: string
|
||||
required: true
|
||||
label:
|
||||
en_US: Query String
|
||||
zh_Hans: 查询语句
|
||||
human_description:
|
||||
en_US: 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: 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: require_summary
|
||||
type: boolean
|
||||
default: false
|
||||
label:
|
||||
en_US: Require Summary
|
||||
zh_Hans: 是否总结
|
||||
human_description:
|
||||
en_US: Whether to pass the news results to llm for summarization.
|
||||
zh_Hans: 是否需要将新闻结果传给大模型总结
|
||||
form: form
|
|
@ -0,0 +1,61 @@
|
|||
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 DuckDuckGoVideoSearchTool(BuiltinTool):
|
||||
"""
|
||||
Tool for performing a video 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"),
|
||||
"region": tool_parameters.get("region", "wt-wt"),
|
||||
"safesearch": tool_parameters.get("safesearch", "moderate"),
|
||||
"timelimit": tool_parameters.get("timelimit"),
|
||||
"resolution": tool_parameters.get("resolution"),
|
||||
"duration": tool_parameters.get("duration"),
|
||||
"license_videos": tool_parameters.get("license_videos"),
|
||||
"max_results": tool_parameters.get("max_results"),
|
||||
}
|
||||
|
||||
# Remove None values to use API defaults
|
||||
query_dict = {k: v for k, v in query_dict.items() if v is not None}
|
||||
|
||||
response = DDGS().videos(**query_dict)
|
||||
|
||||
# Create HTML result with embedded iframes
|
||||
markdown_result = "\n\n"
|
||||
json_result = []
|
||||
|
||||
for res in response:
|
||||
title = res.get('title', '')
|
||||
embed_html = res.get('embed_html', '')
|
||||
description = res.get('description', '')
|
||||
|
||||
# Modify iframe to be responsive
|
||||
if embed_html:
|
||||
# Replace fixed dimensions with responsive wrapper and iframe
|
||||
embed_html = """
|
||||
<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden; max-width: 100%; border-radius: 8px;">
|
||||
<iframe
|
||||
style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;"
|
||||
src="{src}"
|
||||
frameborder="0"
|
||||
allowfullscreen>
|
||||
</iframe>
|
||||
</div>""".format(
|
||||
src=res.get('embed_url', '')
|
||||
)
|
||||
|
||||
markdown_result += f"{title}\n\n"
|
||||
markdown_result += f"{embed_html}\n\n"
|
||||
markdown_result += "---\n\n"
|
||||
|
||||
json_result.append(self.create_json_message(res))
|
||||
|
||||
return [self.create_text_message(markdown_result)] + json_result
|
|
@ -0,0 +1,86 @@
|
|||
identity:
|
||||
name: ddgo_video
|
||||
author: Assistant
|
||||
label:
|
||||
en_US: DuckDuckGo Video Search
|
||||
zh_Hans: DuckDuckGo 视频搜索
|
||||
description:
|
||||
human:
|
||||
en_US: Perform video searches on DuckDuckGo and get results with embedded videos.
|
||||
zh_Hans: 在 DuckDuckGo 上进行视频搜索并获取可嵌入的视频结果。
|
||||
llm: Perform video searches on DuckDuckGo and get results with embedded videos.
|
||||
parameters:
|
||||
- name: query
|
||||
type: string
|
||||
required: true
|
||||
label:
|
||||
en_US: Query String
|
||||
zh_Hans: 查询语句
|
||||
human_description:
|
||||
en_US: Search Query
|
||||
zh_Hans: 搜索查询语句。
|
||||
llm_description: Key words for searching
|
||||
form: llm
|
||||
- name: max_results
|
||||
type: number
|
||||
required: true
|
||||
default: 3
|
||||
minimum: 1
|
||||
maximum: 10
|
||||
label:
|
||||
en_US: Max Results
|
||||
zh_Hans: 最大结果数量
|
||||
human_description:
|
||||
en_US: The max results (1-10).
|
||||
zh_Hans: 最大结果数量(1-10)。
|
||||
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: duration
|
||||
type: select
|
||||
required: false
|
||||
options:
|
||||
- value: short
|
||||
label:
|
||||
en_US: Short (<4 minutes)
|
||||
zh_Hans: 短视频(<4分钟)
|
||||
- value: medium
|
||||
label:
|
||||
en_US: Medium (4-20 minutes)
|
||||
zh_Hans: 中等(4-20分钟)
|
||||
- value: long
|
||||
label:
|
||||
en_US: Long (>20 minutes)
|
||||
zh_Hans: 长视频(>20分钟)
|
||||
label:
|
||||
en_US: Video Duration
|
||||
zh_Hans: 视频时长
|
||||
human_description:
|
||||
en_US: Filter videos by duration
|
||||
zh_Hans: 按时长筛选视频
|
||||
form: form
|
|
@ -265,7 +265,7 @@ export function Markdown(props: { content: string; className?: string }) {
|
|||
}
|
||||
},
|
||||
]}
|
||||
disallowedElements={['script', 'iframe', 'head', 'html', 'meta', 'link', 'style', 'body']}
|
||||
disallowedElements={['script', 'head', 'html', 'meta', 'link', 'style', 'body']}
|
||||
components={{
|
||||
code: CodeBlock,
|
||||
img: Img,
|
||||
|
|
Loading…
Reference in New Issue
Block a user