Merge branch 'feat/dynamic-select' into feat/trigger

This commit is contained in:
Yeuoly
2025-06-25 15:04:23 +08:00
26 changed files with 53 additions and 384 deletions
@@ -232,19 +232,21 @@ class ToolProvider:
return self._validate_credentials(credentials)
def _validate_credentials(self, credentials: dict):
raise NotImplementedError("This method should be implemented by a subclass")
raise NotImplementedError(
"This plugin should implement `_validate_credentials` method to enable credentials validation"
)
def oauth_get_authorization_url(self, system_credentials: Mapping[str, Any]) -> str:
return self._oauth_get_authorization_url(system_credentials)
def _oauth_get_authorization_url(self, system_credentials: Mapping[str, Any]) -> str:
raise NotImplementedError("This method should be implemented by a subclass")
raise NotImplementedError("This plugin should implement `_oauth_get_authorization_url` method to enable oauth")
def oauth_get_credentials(self, system_credentials: Mapping[str, Any], request: Request) -> Mapping[str, Any]:
return self._oauth_get_credentials(system_credentials, request)
def _oauth_get_credentials(self, system_credentials: Mapping[str, Any], request: Request) -> Mapping[str, Any]:
raise NotImplementedError("This method should be implemented by a subclass")
raise NotImplementedError("This plugin should implement `_oauth_get_credentials` method to enable oauth")
class Tool(ToolLike[ToolInvokeMessage]):
@@ -294,7 +296,9 @@ class Tool(ToolLike[ToolInvokeMessage]):
Also, it's optional to implement, that's why it's not an abstract method.
"""
raise NotImplementedError("This method should be implemented by a subclass")
raise NotImplementedError(
"This plugin should implement `_fetch_parameter_options` method to enable dynamic select parameter"
)
############################################################
# For executor use only #
@@ -18,19 +18,21 @@ class TriggerProvider:
return self._validate_credentials(credentials)
def _validate_credentials(self, credentials: dict):
raise NotImplementedError("This method should be implemented by a subclass")
raise NotImplementedError(
"This plugin should implement `_validate_credentials` method to enable credentials validation"
)
def oauth_get_authorization_url(self, system_credentials: Mapping[str, Any]) -> str:
return self._oauth_get_authorization_url(system_credentials)
def _oauth_get_authorization_url(self, system_credentials: Mapping[str, Any]) -> str:
raise NotImplementedError("This method should be implemented by a subclass")
raise NotImplementedError("This plugin should implement `_oauth_get_authorization_url` method to enable oauth")
def oauth_get_credentials(self, system_credentials: Mapping[str, Any], request: Request) -> Mapping[str, Any]:
return self._oauth_get_credentials(system_credentials, request)
def _oauth_get_credentials(self, system_credentials: Mapping[str, Any], request: Request) -> Mapping[str, Any]:
raise NotImplementedError("This method should be implemented by a subclass")
raise NotImplementedError("This plugin should implement `_oauth_get_credentials` method to enable oauth")
class Trigger(ABC):
@@ -76,7 +78,9 @@ class Trigger(ABC):
Also, it's optional to implement, that's why it's not an abstract method.
"""
raise NotImplementedError("This method should be implemented by a subclass")
raise NotImplementedError(
"This plugin should implement `_fetch_parameter_options` method to enable dynamic select parameter"
)
############################################################
# For executor use only #
+7
View File
@@ -12,6 +12,7 @@ from dify_plugin.config.logger_format import plugin_logger_handler
from dify_plugin.core.entities.message import InitializeMessage
from dify_plugin.core.entities.plugin.request import (
AgentActions,
DynamicParameterActions,
EndpointActions,
ModelActions,
PluginInvokeType,
@@ -302,6 +303,12 @@ class Plugin(IOServer, Router):
and data.get("action") == ModelActions.GetAIModelSchemas.value,
)
self.register_route(
self.plugin_executer.fetch_parameter_options,
lambda data: data.get("type") == PluginInvokeType.DynamicParameter.value
and data.get("action") == DynamicParameterActions.FetchParameterOptions.value,
)
def _execute_request(
self,
session_id: str,
+1 -1
View File
@@ -1,4 +1,4 @@
INSTALL_METHOD=remote
REMOTE_INSTALL_HOST=localhost
REMOTE_INSTALL_PORT=5003
REMOTE_INSTALL_KEY=23620d39-d006-4613-85be-844874ed5d89
REMOTE_INSTALL_KEY=1fbe8953-7bf7-4d77-8916-ee217f7068df
@@ -13,16 +13,7 @@ identity:
tags:
- search
tools:
- tools/parameter_extractor.yaml
- tools/question_classifier.yaml
- tools/llm.yaml
- tools/tool.yaml
- tools/moderation.yaml
- tools/rerank.yaml
- tools/tts.yaml
- tools/upload_file.yaml
- tools/summary.yaml
- tools/transform_image.yaml
extra:
python:
source: provider/code_based_workflow.py
@@ -2,12 +2,21 @@ from collections.abc import Generator
from typing import Any
from dify_plugin import Tool
from dify_plugin.entities import I18nObject, ParameterOption
from dify_plugin.entities.model.llm import LLMModelConfig
from dify_plugin.entities.model.message import SystemPromptMessage, UserPromptMessage
from dify_plugin.entities.tool import ToolInvokeMessage
class LLMTool(Tool):
def _fetch_parameter_options(self, parameter: str) -> list[ParameterOption]:
return [
ParameterOption(
value="hello world",
label=I18nObject(en_US="Prompt string"),
)
]
def _invoke(self, tool_parameters: dict[str, Any]) -> Generator[ToolInvokeMessage]:
response = self.session.model.llm.invoke(
model_config=LLMModelConfig(
@@ -13,7 +13,7 @@ description:
llm: A tool for invoking a large language model
parameters:
- name: prompt
type: string
type: dynamic-select
required: true
label:
en_US: Prompt string
@@ -25,6 +25,25 @@ parameters:
pt_BR: used for searching
llm_description: key words for searching
form: llm
- name: prompt1
type: select
required: true
options:
- value: 1
label:
en_US: Prompt string
zh_Hans: 提示字符串
pt_BR: Prompt string
label:
en_US: Prompt string
zh_Hans: 提示字符串
pt_BR: Prompt string
human_description:
en_US: used for searching
zh_Hans: 用于搜索网页内容
pt_BR: used for searching
llm_description: key words for searching
form: llm
extra:
python:
source: tools/llm.py
@@ -1,22 +0,0 @@
from collections.abc import Generator
from dify_plugin.entities.model.moderation import ModerationModelConfig
from dify_plugin.entities.tool import ToolInvokeMessage
from dify_plugin.interfaces.tool import Tool
class Moderation(Tool):
def _invoke(self, tool_parameters: dict) -> Generator[ToolInvokeMessage, None, None]:
response = self.session.model.moderation.invoke(
model_config=ModerationModelConfig(
provider="openai",
model="text-moderation-stable",
),
text=tool_parameters["text"],
)
yield self.create_json_message(
{
"data": response,
}
)
@@ -1,30 +0,0 @@
identity:
name: moderation
author: Dify
label:
en_US: Moderation
zh_Hans: 内容审核
pt_BR: Moderation
description:
human:
en_US: A tool for moderation
zh_Hans: 用于内容审核的工具
pt_BR: A tool for moderation
llm: A tool for moderation
parameters:
- name: text
type: string
required: true
label:
en_US: Text to moderate
zh_Hans: 要审核的文本
pt_BR: Text to moderate
human_description:
en_US: Text to moderate
zh_Hans: 要审核的文本
pt_BR: Text to moderate
llm_description: Text to moderate
form: llm
extra:
python:
source: tools/moderation.py
@@ -1,28 +0,0 @@
from collections.abc import Generator
from dify_plugin import Tool
from dify_plugin.entities.tool import ToolInvokeMessage
from dify_plugin.entities.workflow_node import ModelConfig, ParameterConfig
class ParameterExtractorTool(Tool):
def _invoke(self, tool_parameters: dict) -> Generator[ToolInvokeMessage, None, None]:
response = self.session.workflow_node.parameter_extractor.invoke(
parameters=[
ParameterConfig(
name="name",
description="name of the person",
required=True,
type="string",
)
],
model=ModelConfig(
provider="openai",
name="gpt-4o-mini",
completion_params={},
),
query="My name is John Doe",
instruction="Extract the name of the person",
)
yield self.create_json_message(response.outputs)
@@ -1,30 +0,0 @@
identity:
name: parameter_extractor
author: Dify
label:
en_US: Parameter Extractor
zh_Hans: 参数提取器
pt_BR: Parameter Extractor
description:
human:
en_US: A tool for extracting parameters from a given string
zh_Hans: 从给定字符串中提取参数的工具
pt_BR: A tool for extracting parameters from a given string
llm: A tool for extracting parameters from a given string
parameters:
- name: prompt
type: string
required: true
label:
en_US: Prompt string
zh_Hans: 提示字符串
pt_BR: Prompt string
human_description:
en_US: used for extracting parameters
zh_Hans: 用于提取参数
pt_BR: used for extracting parameters
llm_description: key words for extracting parameters
form: llm
extra:
python:
source: tools/parameter_extractor.py
@@ -1,9 +0,0 @@
from collections.abc import Generator
from dify_plugin import Tool
from dify_plugin.entities.tool import ToolInvokeMessage
class QuestionClassifierTool(Tool):
def _invoke(self, tool_parameters: dict) -> Generator[ToolInvokeMessage, None, None]:
return super()._invoke(tool_parameters)
@@ -1,30 +0,0 @@
identity:
name: question_classifier
author: Dify
label:
en_US: Question Classifier
zh_Hans: 问题分类器
pt_BR: Question Classifier
description:
human:
en_US: A tool for classifying questions
zh_Hans: 用于分类问题的工具
pt_BR: A tool for classifying questions
llm: A tool for classifying questions
parameters:
- name: prompt
type: string
required: true
label:
en_US: Prompt string
zh_Hans: 提示字符串
pt_BR: Prompt string
human_description:
en_US: used for classifying questions
zh_Hans: 用于分类问题
pt_BR: used for classifying questions
llm_description: key words for classifying questions
form: llm
extra:
python:
source: tools/question_classifier.py
@@ -1,25 +0,0 @@
from collections.abc import Generator
from dify_plugin.entities.model.rerank import RerankModelConfig
from dify_plugin.entities.tool import ToolInvokeMessage
from dify_plugin.interfaces.tool import Tool
class Rerank(Tool):
def _invoke(self, tool_parameters: dict) -> Generator[ToolInvokeMessage, None, None]:
response = self.session.model.rerank.invoke(
model_config=RerankModelConfig(
provider="jina",
model="jina-embeddings-v2-base-v1.0",
score_threshold=0.5,
top_n=10,
),
docs=["Kasumi", "Utae", "Arisa"],
query="Utae",
)
yield self.create_json_message(
{
"data": response.docs,
}
)
@@ -1,17 +0,0 @@
identity:
name: rerank
author: Dify
label:
en_US: Rerank
zh_Hans: 重新排序
pt_BR: Rerank
description:
human:
en_US: A tool for reranking questions
zh_Hans: 用于重新排序问题的工具
pt_BR: A tool for reranking questions
llm: A tool for reranking questions
parameters:
extra:
python:
source: tools/rerank.py
@@ -1,19 +0,0 @@
from collections.abc import Generator
from dify_plugin.entities.tool import ToolInvokeMessage
from dify_plugin.interfaces.tool import Tool
class Summary(Tool):
def _invoke(self, tool_parameters: dict) -> Generator[ToolInvokeMessage, None, None]:
response = self.session.model.summary.invoke(
text="Hello, world!",
instruction="Summarize the text",
min_summarize_length=1,
)
yield self.create_json_message(
{
"data": response,
}
)
@@ -1,17 +0,0 @@
identity:
name: summary
author: Dify
label:
en_US: Summary
zh_Hans: 总结
pt_BR: Summary
description:
human:
en_US: A tool for summarizing questions
zh_Hans: 用于总结问题的工具
pt_BR: A tool for summarizing questions
llm: A tool for reranking questions
parameters:
extra:
python:
source: tools/summary.py
@@ -1,9 +0,0 @@
from collections.abc import Generator
from dify_plugin import Tool
from dify_plugin.entities.tool import ToolInvokeMessage
class ToolTool(Tool):
def _invoke(self, tool_parameters: dict) -> Generator[ToolInvokeMessage, None, None]:
yield self.create_image_message("https://assets.dify.ai/images/dify_logo_dark_s.png")
@@ -1,16 +0,0 @@
identity:
name: tool
author: Dify
label:
en_US: Tool
zh_Hans: 工具
pt_BR: Tool
description:
human:
en_US: invoke other tools
zh_Hans: 调用其他工具
pt_BR: invoke other tools
llm: invoke other tools
extra:
python:
source: tools/tool.py
@@ -1,19 +0,0 @@
from collections.abc import Generator
from dify_plugin import Tool
from dify_plugin.entities.tool import ToolInvokeMessage
from dify_plugin.file.file import File
class TransformImageTool(Tool):
def _invoke(self, tool_parameters: dict) -> Generator[ToolInvokeMessage, None, None]:
for image in tool_parameters["image"]:
assert isinstance(image, File)
yield self.create_json_message(
{
"mime_type": image.mime_type,
"type": image.type,
"length": len(image.blob),
}
)
yield self.create_blob_message(image.blob, {"mime_type": image.mime_type})
@@ -1,30 +0,0 @@
identity:
name: transform_image
author: Dify
label:
en_US: Transform Image
zh_Hans: 转换图片
pt_BR: Transformar Imagem
description:
human:
en_US: Transform image to another format
zh_Hans: 将图片转换为另一种格式
pt_BR: Transformar imagem para outro formato
llm: Transform image to another format
parameters:
- name: image
type: files
required: true
label:
en_US: Images
zh_Hans: 图片
pt_BR: Imagens
human_description:
en_US: Images to transform
zh_Hans: 需要转换的图片
pt_BR: Imagens para transformar
llm_description: Images to transform
form: llm
extra:
python:
source: tools/transform_image.py
@@ -1,21 +0,0 @@
import binascii
from collections.abc import Generator
from dify_plugin.entities.model.tts import TTSModelConfig
from dify_plugin.entities.tool import ToolInvokeMessage
from dify_plugin.interfaces.tool import Tool
class TTS(Tool):
def _invoke(self, tool_parameters: dict) -> Generator[ToolInvokeMessage, None, None]:
response = self.session.model.tts.invoke(
model_config=TTSModelConfig(
provider="openai",
model="tts-1",
voice="alloy",
),
content_text="Hello, world!",
)
for chunk in response:
yield self.create_text_message(binascii.hexlify(chunk).decode())
@@ -1,17 +0,0 @@
identity:
name: tts
author: Dify
label:
en_US: TTS
zh_Hans: 文本转语音
pt_BR: TTS
description:
human:
en_US: A tool for text to speech
zh_Hans: 用于文本转语音的工具
pt_BR: A tool for text to speech
llm: A tool for text to speech
parameters:
extra:
python:
source: tools/tts.py
@@ -1,10 +0,0 @@
from collections.abc import Generator
from dify_plugin import Tool
from dify_plugin.entities.tool import ToolInvokeMessage
class UploadFileTool(Tool):
def _invoke(self, tool_parameters: dict) -> Generator[ToolInvokeMessage, None, None]:
response = self.session.file.upload("1.txt", b"", "text/plain")
yield self.create_text_message(f"file id: {response.id}")
@@ -1,16 +0,0 @@
identity:
name: upload_file
author: Dify
label:
en_US: Upload File
zh_Hans: 上传文件
pt_BR: Upload File
description:
human:
en_US: upload file
zh_Hans: 上传文件
pt_BR: upload file
llm: upload file
extra:
python:
source: tools/upload_file.py