mirror of
https://git.mirrors.martin98.com/https://github.com/langgenius/dify.git
synced 2025-08-15 12:25:57 +08:00
r2
This commit is contained in:
parent
5c4bf2a9e4
commit
c7f4b41920
@ -1,21 +1,22 @@
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
|
from core.datasource.datasource_tool.tool import DatasourceTool
|
||||||
|
from core.datasource.entities.datasource_entities import DatasourceProviderEntityWithPlugin, DatasourceProviderType
|
||||||
from core.plugin.manager.tool import PluginToolManager
|
from core.plugin.manager.tool import PluginToolManager
|
||||||
from core.tools.__base.tool_runtime import ToolRuntime
|
from core.tools.__base.tool_runtime import ToolRuntime
|
||||||
from core.tools.builtin_tool.provider import BuiltinToolProviderController
|
from core.tools.builtin_tool.provider import BuiltinToolProviderController
|
||||||
from core.tools.entities.tool_entities import ToolProviderEntityWithPlugin, ToolProviderType
|
from core.tools.entities.tool_entities import ToolProviderEntityWithPlugin, ToolProviderType
|
||||||
from core.tools.errors import ToolProviderCredentialValidationError
|
from core.tools.errors import ToolProviderCredentialValidationError
|
||||||
from core.tools.plugin_tool.tool import PluginTool
|
|
||||||
|
|
||||||
|
|
||||||
class PluginToolProviderController(BuiltinToolProviderController):
|
class DatasourceToolProviderController(BuiltinToolProviderController):
|
||||||
entity: ToolProviderEntityWithPlugin
|
entity: DatasourceProviderEntityWithPlugin
|
||||||
tenant_id: str
|
tenant_id: str
|
||||||
plugin_id: str
|
plugin_id: str
|
||||||
plugin_unique_identifier: str
|
plugin_unique_identifier: str
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self, entity: ToolProviderEntityWithPlugin, plugin_id: str, plugin_unique_identifier: str, tenant_id: str
|
self, entity: DatasourceProviderEntityWithPlugin, plugin_id: str, plugin_unique_identifier: str, tenant_id: str
|
||||||
) -> None:
|
) -> None:
|
||||||
self.entity = entity
|
self.entity = entity
|
||||||
self.tenant_id = tenant_id
|
self.tenant_id = tenant_id
|
||||||
@ -23,13 +24,13 @@ class PluginToolProviderController(BuiltinToolProviderController):
|
|||||||
self.plugin_unique_identifier = plugin_unique_identifier
|
self.plugin_unique_identifier = plugin_unique_identifier
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def provider_type(self) -> ToolProviderType:
|
def provider_type(self) -> DatasourceProviderType:
|
||||||
"""
|
"""
|
||||||
returns the type of the provider
|
returns the type of the provider
|
||||||
|
|
||||||
:return: type of the provider
|
:return: type of the provider
|
||||||
"""
|
"""
|
||||||
return ToolProviderType.PLUGIN
|
return DatasourceProviderType.RAG_PIPELINE
|
||||||
|
|
||||||
def _validate_credentials(self, user_id: str, credentials: dict[str, Any]) -> None:
|
def _validate_credentials(self, user_id: str, credentials: dict[str, Any]) -> None:
|
||||||
"""
|
"""
|
||||||
@ -44,36 +45,36 @@ class PluginToolProviderController(BuiltinToolProviderController):
|
|||||||
):
|
):
|
||||||
raise ToolProviderCredentialValidationError("Invalid credentials")
|
raise ToolProviderCredentialValidationError("Invalid credentials")
|
||||||
|
|
||||||
def get_tool(self, tool_name: str) -> PluginTool: # type: ignore
|
def get_datasource(self, datasource_name: str) -> DatasourceTool: # type: ignore
|
||||||
"""
|
"""
|
||||||
return tool with given name
|
return datasource with given name
|
||||||
"""
|
"""
|
||||||
tool_entity = next(
|
datasource_entity = next(
|
||||||
(tool_entity for tool_entity in self.entity.tools if tool_entity.identity.name == tool_name), None
|
(datasource_entity for datasource_entity in self.entity.datasources if datasource_entity.identity.name == datasource_name), None
|
||||||
)
|
)
|
||||||
|
|
||||||
if not tool_entity:
|
if not datasource_entity:
|
||||||
raise ValueError(f"Tool with name {tool_name} not found")
|
raise ValueError(f"Datasource with name {datasource_name} not found")
|
||||||
|
|
||||||
return PluginTool(
|
return DatasourceTool(
|
||||||
entity=tool_entity,
|
entity=datasource_entity,
|
||||||
runtime=ToolRuntime(tenant_id=self.tenant_id),
|
runtime=ToolRuntime(tenant_id=self.tenant_id),
|
||||||
tenant_id=self.tenant_id,
|
tenant_id=self.tenant_id,
|
||||||
icon=self.entity.identity.icon,
|
icon=self.entity.identity.icon,
|
||||||
plugin_unique_identifier=self.plugin_unique_identifier,
|
plugin_unique_identifier=self.plugin_unique_identifier,
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_tools(self) -> list[PluginTool]: # type: ignore
|
def get_datasources(self) -> list[DatasourceTool]: # type: ignore
|
||||||
"""
|
"""
|
||||||
get all tools
|
get all datasources
|
||||||
"""
|
"""
|
||||||
return [
|
return [
|
||||||
PluginTool(
|
DatasourceTool(
|
||||||
entity=tool_entity,
|
entity=datasource_entity,
|
||||||
runtime=ToolRuntime(tenant_id=self.tenant_id),
|
runtime=ToolRuntime(tenant_id=self.tenant_id),
|
||||||
tenant_id=self.tenant_id,
|
tenant_id=self.tenant_id,
|
||||||
icon=self.entity.identity.icon,
|
icon=self.entity.identity.icon,
|
||||||
plugin_unique_identifier=self.plugin_unique_identifier,
|
plugin_unique_identifier=self.plugin_unique_identifier,
|
||||||
)
|
)
|
||||||
for tool_entity in self.entity.tools
|
for datasource_entity in self.entity.datasources
|
||||||
]
|
]
|
@ -1,6 +1,7 @@
|
|||||||
from collections.abc import Generator
|
from collections.abc import Generator
|
||||||
from typing import Any, Optional
|
from typing import Any, Optional
|
||||||
|
|
||||||
|
from core.datasource.entities.datasource_entities import DatasourceEntity, DatasourceParameter, DatasourceProviderType
|
||||||
from core.plugin.manager.tool import PluginToolManager
|
from core.plugin.manager.tool import PluginToolManager
|
||||||
from core.plugin.utils.converter import convert_parameters_to_plugin_format
|
from core.plugin.utils.converter import convert_parameters_to_plugin_format
|
||||||
from core.tools.__base.tool import Tool
|
from core.tools.__base.tool import Tool
|
||||||
@ -8,14 +9,14 @@ from core.tools.__base.tool_runtime import ToolRuntime
|
|||||||
from core.tools.entities.tool_entities import ToolEntity, ToolInvokeMessage, ToolParameter, ToolProviderType
|
from core.tools.entities.tool_entities import ToolEntity, ToolInvokeMessage, ToolParameter, ToolProviderType
|
||||||
|
|
||||||
|
|
||||||
class PluginTool(Tool):
|
class DatasourceTool(Tool):
|
||||||
tenant_id: str
|
tenant_id: str
|
||||||
icon: str
|
icon: str
|
||||||
plugin_unique_identifier: str
|
plugin_unique_identifier: str
|
||||||
runtime_parameters: Optional[list[ToolParameter]]
|
runtime_parameters: Optional[list[DatasourceParameter]]
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self, entity: ToolEntity, runtime: ToolRuntime, tenant_id: str, icon: str, plugin_unique_identifier: str
|
self, entity: DatasourceEntity, runtime: ToolRuntime, tenant_id: str, icon: str, plugin_unique_identifier: str
|
||||||
) -> None:
|
) -> None:
|
||||||
super().__init__(entity, runtime)
|
super().__init__(entity, runtime)
|
||||||
self.tenant_id = tenant_id
|
self.tenant_id = tenant_id
|
||||||
@ -23,20 +24,44 @@ class PluginTool(Tool):
|
|||||||
self.plugin_unique_identifier = plugin_unique_identifier
|
self.plugin_unique_identifier = plugin_unique_identifier
|
||||||
self.runtime_parameters = None
|
self.runtime_parameters = None
|
||||||
|
|
||||||
def tool_provider_type(self) -> ToolProviderType:
|
def datasource_provider_type(self) -> DatasourceProviderType:
|
||||||
return ToolProviderType.PLUGIN
|
return DatasourceProviderType.RAG_PIPELINE
|
||||||
|
|
||||||
def _invoke(
|
def _invoke_first_step(
|
||||||
self,
|
self,
|
||||||
user_id: str,
|
user_id: str,
|
||||||
tool_parameters: dict[str, Any],
|
datasource_parameters: dict[str, Any],
|
||||||
conversation_id: Optional[str] = None,
|
conversation_id: Optional[str] = None,
|
||||||
app_id: Optional[str] = None,
|
rag_pipeline_id: Optional[str] = None,
|
||||||
message_id: Optional[str] = None,
|
message_id: Optional[str] = None,
|
||||||
) -> Generator[ToolInvokeMessage, None, None]:
|
) -> Generator[ToolInvokeMessage, None, None]:
|
||||||
manager = PluginToolManager()
|
manager = PluginToolManager()
|
||||||
|
|
||||||
tool_parameters = convert_parameters_to_plugin_format(tool_parameters)
|
datasource_parameters = convert_parameters_to_plugin_format(datasource_parameters)
|
||||||
|
|
||||||
|
yield from manager.invoke_first_step(
|
||||||
|
tenant_id=self.tenant_id,
|
||||||
|
user_id=user_id,
|
||||||
|
tool_provider=self.entity.identity.provider,
|
||||||
|
tool_name=self.entity.identity.name,
|
||||||
|
credentials=self.runtime.credentials,
|
||||||
|
tool_parameters=tool_parameters,
|
||||||
|
conversation_id=conversation_id,
|
||||||
|
app_id=app_id,
|
||||||
|
message_id=message_id,
|
||||||
|
)
|
||||||
|
|
||||||
|
def _invoke_second_step(
|
||||||
|
self,
|
||||||
|
user_id: str,
|
||||||
|
datasource_parameters: dict[str, Any],
|
||||||
|
conversation_id: Optional[str] = None,
|
||||||
|
rag_pipeline_id: Optional[str] = None,
|
||||||
|
message_id: Optional[str] = None,
|
||||||
|
) -> Generator[ToolInvokeMessage, None, None]:
|
||||||
|
manager = PluginToolManager()
|
||||||
|
|
||||||
|
datasource_parameters = convert_parameters_to_plugin_format(datasource_parameters)
|
||||||
|
|
||||||
yield from manager.invoke(
|
yield from manager.invoke(
|
||||||
tenant_id=self.tenant_id,
|
tenant_id=self.tenant_id,
|
||||||
@ -50,8 +75,9 @@ class PluginTool(Tool):
|
|||||||
message_id=message_id,
|
message_id=message_id,
|
||||||
)
|
)
|
||||||
|
|
||||||
def fork_tool_runtime(self, runtime: ToolRuntime) -> "PluginTool":
|
|
||||||
return PluginTool(
|
def fork_tool_runtime(self, runtime: ToolRuntime) -> "DatasourceTool":
|
||||||
|
return DatasourceTool(
|
||||||
entity=self.entity,
|
entity=self.entity,
|
||||||
runtime=runtime,
|
runtime=runtime,
|
||||||
tenant_id=self.tenant_id,
|
tenant_id=self.tenant_id,
|
||||||
@ -64,7 +90,7 @@ class PluginTool(Tool):
|
|||||||
conversation_id: Optional[str] = None,
|
conversation_id: Optional[str] = None,
|
||||||
app_id: Optional[str] = None,
|
app_id: Optional[str] = None,
|
||||||
message_id: Optional[str] = None,
|
message_id: Optional[str] = None,
|
||||||
) -> list[ToolParameter]:
|
) -> list[DatasourceParameter]:
|
||||||
"""
|
"""
|
||||||
get the runtime parameters
|
get the runtime parameters
|
||||||
"""
|
"""
|
@ -1,72 +0,0 @@
|
|||||||
from typing import Literal, Optional
|
|
||||||
|
|
||||||
from pydantic import BaseModel, Field, field_validator
|
|
||||||
|
|
||||||
from core.model_runtime.utils.encoders import jsonable_encoder
|
|
||||||
from core.tools.__base.tool import ToolParameter
|
|
||||||
from core.tools.entities.common_entities import I18nObject
|
|
||||||
from core.tools.entities.tool_entities import ToolProviderType
|
|
||||||
|
|
||||||
|
|
||||||
class ToolApiEntity(BaseModel):
|
|
||||||
author: str
|
|
||||||
name: str # identifier
|
|
||||||
label: I18nObject # label
|
|
||||||
description: I18nObject
|
|
||||||
parameters: Optional[list[ToolParameter]] = None
|
|
||||||
labels: list[str] = Field(default_factory=list)
|
|
||||||
output_schema: Optional[dict] = None
|
|
||||||
|
|
||||||
|
|
||||||
ToolProviderTypeApiLiteral = Optional[Literal["builtin", "api", "workflow"]]
|
|
||||||
|
|
||||||
|
|
||||||
class ToolProviderApiEntity(BaseModel):
|
|
||||||
id: str
|
|
||||||
author: str
|
|
||||||
name: str # identifier
|
|
||||||
description: I18nObject
|
|
||||||
icon: str | dict
|
|
||||||
label: I18nObject # label
|
|
||||||
type: ToolProviderType
|
|
||||||
masked_credentials: Optional[dict] = None
|
|
||||||
original_credentials: Optional[dict] = None
|
|
||||||
is_team_authorization: bool = False
|
|
||||||
allow_delete: bool = True
|
|
||||||
plugin_id: Optional[str] = Field(default="", description="The plugin id of the tool")
|
|
||||||
plugin_unique_identifier: Optional[str] = Field(default="", description="The unique identifier of the tool")
|
|
||||||
tools: list[ToolApiEntity] = Field(default_factory=list)
|
|
||||||
labels: list[str] = Field(default_factory=list)
|
|
||||||
|
|
||||||
@field_validator("tools", mode="before")
|
|
||||||
@classmethod
|
|
||||||
def convert_none_to_empty_list(cls, v):
|
|
||||||
return v if v is not None else []
|
|
||||||
|
|
||||||
def to_dict(self) -> dict:
|
|
||||||
# -------------
|
|
||||||
# overwrite tool parameter types for temp fix
|
|
||||||
tools = jsonable_encoder(self.tools)
|
|
||||||
for tool in tools:
|
|
||||||
if tool.get("parameters"):
|
|
||||||
for parameter in tool.get("parameters"):
|
|
||||||
if parameter.get("type") == ToolParameter.ToolParameterType.SYSTEM_FILES.value:
|
|
||||||
parameter["type"] = "files"
|
|
||||||
# -------------
|
|
||||||
|
|
||||||
return {
|
|
||||||
"id": self.id,
|
|
||||||
"author": self.author,
|
|
||||||
"name": self.name,
|
|
||||||
"plugin_id": self.plugin_id,
|
|
||||||
"plugin_unique_identifier": self.plugin_unique_identifier,
|
|
||||||
"description": self.description.to_dict(),
|
|
||||||
"icon": self.icon,
|
|
||||||
"label": self.label.to_dict(),
|
|
||||||
"type": self.type.value,
|
|
||||||
"team_credentials": self.masked_credentials,
|
|
||||||
"is_team_authorization": self.is_team_authorization,
|
|
||||||
"allow_delete": self.allow_delete,
|
|
||||||
"tools": tools,
|
|
||||||
"labels": self.labels,
|
|
||||||
}
|
|
@ -38,20 +38,15 @@ class ToolLabelEnum(Enum):
|
|||||||
OTHER = "other"
|
OTHER = "other"
|
||||||
|
|
||||||
|
|
||||||
class ToolProviderType(enum.StrEnum):
|
class DatasourceProviderType(enum.StrEnum):
|
||||||
"""
|
"""
|
||||||
Enum class for tool provider
|
Enum class for datasource provider
|
||||||
"""
|
"""
|
||||||
|
|
||||||
PLUGIN = "plugin"
|
RAG_PIPELINE = "rag_pipeline"
|
||||||
BUILT_IN = "builtin"
|
|
||||||
WORKFLOW = "workflow"
|
|
||||||
API = "api"
|
|
||||||
APP = "app"
|
|
||||||
DATASET_RETRIEVAL = "dataset-retrieval"
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def value_of(cls, value: str) -> "ToolProviderType":
|
def value_of(cls, value: str) -> "DatasourceProviderType":
|
||||||
"""
|
"""
|
||||||
Get value of given mode.
|
Get value of given mode.
|
||||||
|
|
||||||
@ -211,12 +206,12 @@ class ToolInvokeMessageBinary(BaseModel):
|
|||||||
file_var: Optional[dict[str, Any]] = None
|
file_var: Optional[dict[str, Any]] = None
|
||||||
|
|
||||||
|
|
||||||
class ToolParameter(PluginParameter):
|
class DatasourceParameter(PluginParameter):
|
||||||
"""
|
"""
|
||||||
Overrides type
|
Overrides type
|
||||||
"""
|
"""
|
||||||
|
|
||||||
class ToolParameterType(enum.StrEnum):
|
class DatasourceParameterType(enum.StrEnum):
|
||||||
"""
|
"""
|
||||||
removes TOOLS_SELECTOR from PluginParameterType
|
removes TOOLS_SELECTOR from PluginParameterType
|
||||||
"""
|
"""
|
||||||
@ -240,14 +235,14 @@ class ToolParameter(PluginParameter):
|
|||||||
def cast_value(self, value: Any):
|
def cast_value(self, value: Any):
|
||||||
return cast_parameter_value(self, value)
|
return cast_parameter_value(self, value)
|
||||||
|
|
||||||
class ToolParameterForm(Enum):
|
class DatasourceParameterForm(Enum):
|
||||||
SCHEMA = "schema" # should be set while adding tool
|
SCHEMA = "schema" # should be set while adding tool
|
||||||
FORM = "form" # should be set before invoking tool
|
FORM = "form" # should be set before invoking tool
|
||||||
LLM = "llm" # will be set by LLM
|
LLM = "llm" # will be set by LLM
|
||||||
|
|
||||||
type: ToolParameterType = Field(..., description="The type of the parameter")
|
type: DatasourceParameterType = Field(..., description="The type of the parameter")
|
||||||
human_description: Optional[I18nObject] = Field(default=None, description="The description presented to the user")
|
human_description: Optional[I18nObject] = Field(default=None, description="The description presented to the user")
|
||||||
form: ToolParameterForm = Field(..., description="The form of the parameter, schema/form/llm")
|
form: DatasourceParameterForm = Field(..., description="The form of the parameter, schema/form/llm")
|
||||||
llm_description: Optional[str] = None
|
llm_description: Optional[str] = None
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -255,12 +250,12 @@ class ToolParameter(PluginParameter):
|
|||||||
cls,
|
cls,
|
||||||
name: str,
|
name: str,
|
||||||
llm_description: str,
|
llm_description: str,
|
||||||
typ: ToolParameterType,
|
typ: DatasourceParameterType,
|
||||||
required: bool,
|
required: bool,
|
||||||
options: Optional[list[str]] = None,
|
options: Optional[list[str]] = None,
|
||||||
) -> "ToolParameter":
|
) -> "DatasourceParameter":
|
||||||
"""
|
"""
|
||||||
get a simple tool parameter
|
get a simple datasource parameter
|
||||||
|
|
||||||
:param name: the name of the parameter
|
:param name: the name of the parameter
|
||||||
:param llm_description: the description presented to the LLM
|
:param llm_description: the description presented to the LLM
|
||||||
@ -306,7 +301,7 @@ class ToolProviderIdentity(BaseModel):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class ToolIdentity(BaseModel):
|
class DatasourceIdentity(BaseModel):
|
||||||
author: str = Field(..., description="The author of the tool")
|
author: str = Field(..., description="The author of the tool")
|
||||||
name: str = Field(..., description="The name of the tool")
|
name: str = Field(..., description="The name of the tool")
|
||||||
label: I18nObject = Field(..., description="The label of the tool")
|
label: I18nObject = Field(..., description="The label of the tool")
|
||||||
@ -314,15 +309,15 @@ class ToolIdentity(BaseModel):
|
|||||||
icon: Optional[str] = None
|
icon: Optional[str] = None
|
||||||
|
|
||||||
|
|
||||||
class ToolDescription(BaseModel):
|
class DatasourceDescription(BaseModel):
|
||||||
human: I18nObject = Field(..., description="The description presented to the user")
|
human: I18nObject = Field(..., description="The description presented to the user")
|
||||||
llm: str = Field(..., description="The description presented to the LLM")
|
llm: str = Field(..., description="The description presented to the LLM")
|
||||||
|
|
||||||
|
|
||||||
class ToolEntity(BaseModel):
|
class DatasourceEntity(BaseModel):
|
||||||
identity: ToolIdentity
|
identity: DatasourceIdentity
|
||||||
parameters: list[ToolParameter] = Field(default_factory=list)
|
parameters: list[DatasourceParameter] = Field(default_factory=list)
|
||||||
description: Optional[ToolDescription] = None
|
description: Optional[DatasourceDescription] = None
|
||||||
output_schema: Optional[dict] = None
|
output_schema: Optional[dict] = None
|
||||||
has_runtime_parameters: bool = Field(default=False, description="Whether the tool has runtime parameters")
|
has_runtime_parameters: bool = Field(default=False, description="Whether the tool has runtime parameters")
|
||||||
|
|
||||||
@ -331,7 +326,7 @@ class ToolEntity(BaseModel):
|
|||||||
|
|
||||||
@field_validator("parameters", mode="before")
|
@field_validator("parameters", mode="before")
|
||||||
@classmethod
|
@classmethod
|
||||||
def set_parameters(cls, v, validation_info: ValidationInfo) -> list[ToolParameter]:
|
def set_parameters(cls, v, validation_info: ValidationInfo) -> list[DatasourceParameter]:
|
||||||
return v or []
|
return v or []
|
||||||
|
|
||||||
|
|
||||||
@ -341,8 +336,8 @@ class ToolProviderEntity(BaseModel):
|
|||||||
credentials_schema: list[ProviderConfig] = Field(default_factory=list)
|
credentials_schema: list[ProviderConfig] = Field(default_factory=list)
|
||||||
|
|
||||||
|
|
||||||
class ToolProviderEntityWithPlugin(ToolProviderEntity):
|
class DatasourceProviderEntityWithPlugin(ToolProviderEntity):
|
||||||
tools: list[ToolEntity] = Field(default_factory=list)
|
datasources: list[DatasourceEntity] = Field(default_factory=list)
|
||||||
|
|
||||||
|
|
||||||
class WorkflowToolParameterConfiguration(BaseModel):
|
class WorkflowToolParameterConfiguration(BaseModel):
|
||||||
@ -352,12 +347,12 @@ class WorkflowToolParameterConfiguration(BaseModel):
|
|||||||
|
|
||||||
name: str = Field(..., description="The name of the parameter")
|
name: str = Field(..., description="The name of the parameter")
|
||||||
description: str = Field(..., description="The description of the parameter")
|
description: str = Field(..., description="The description of the parameter")
|
||||||
form: ToolParameter.ToolParameterForm = Field(..., description="The form of the parameter")
|
form: DatasourceParameter.DatasourceParameterForm = Field(..., description="The form of the parameter")
|
||||||
|
|
||||||
|
|
||||||
class ToolInvokeMeta(BaseModel):
|
class DatasourceInvokeMeta(BaseModel):
|
||||||
"""
|
"""
|
||||||
Tool invoke meta
|
Datasource invoke meta
|
||||||
"""
|
"""
|
||||||
|
|
||||||
time_cost: float = Field(..., description="The time cost of the tool invoke")
|
time_cost: float = Field(..., description="The time cost of the tool invoke")
|
||||||
@ -365,16 +360,16 @@ class ToolInvokeMeta(BaseModel):
|
|||||||
tool_config: Optional[dict] = None
|
tool_config: Optional[dict] = None
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def empty(cls) -> "ToolInvokeMeta":
|
def empty(cls) -> "DatasourceInvokeMeta":
|
||||||
"""
|
"""
|
||||||
Get an empty instance of ToolInvokeMeta
|
Get an empty instance of DatasourceInvokeMeta
|
||||||
"""
|
"""
|
||||||
return cls(time_cost=0.0, error=None, tool_config={})
|
return cls(time_cost=0.0, error=None, tool_config={})
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def error_instance(cls, error: str) -> "ToolInvokeMeta":
|
def error_instance(cls, error: str) -> "DatasourceInvokeMeta":
|
||||||
"""
|
"""
|
||||||
Get an instance of ToolInvokeMeta with error
|
Get an instance of DatasourceInvokeMeta with error
|
||||||
"""
|
"""
|
||||||
return cls(time_cost=0.0, error=error, tool_config={})
|
return cls(time_cost=0.0, error=error, tool_config={})
|
||||||
|
|
||||||
@ -386,9 +381,9 @@ class ToolInvokeMeta(BaseModel):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class ToolLabel(BaseModel):
|
class DatasourceLabel(BaseModel):
|
||||||
"""
|
"""
|
||||||
Tool label
|
Datasource label
|
||||||
"""
|
"""
|
||||||
|
|
||||||
name: str = Field(..., description="The name of the tool")
|
name: str = Field(..., description="The name of the tool")
|
||||||
@ -396,32 +391,30 @@ class ToolLabel(BaseModel):
|
|||||||
icon: str = Field(..., description="The icon of the tool")
|
icon: str = Field(..., description="The icon of the tool")
|
||||||
|
|
||||||
|
|
||||||
class ToolInvokeFrom(Enum):
|
class DatasourceInvokeFrom(Enum):
|
||||||
"""
|
"""
|
||||||
Enum class for tool invoke
|
Enum class for datasource invoke
|
||||||
"""
|
"""
|
||||||
|
|
||||||
WORKFLOW = "workflow"
|
RAG_PIPELINE = "rag_pipeline"
|
||||||
AGENT = "agent"
|
|
||||||
PLUGIN = "plugin"
|
|
||||||
|
|
||||||
|
|
||||||
class ToolSelector(BaseModel):
|
class DatasourceSelector(BaseModel):
|
||||||
dify_model_identity: str = TOOL_SELECTOR_MODEL_IDENTITY
|
dify_model_identity: str = TOOL_SELECTOR_MODEL_IDENTITY
|
||||||
|
|
||||||
class Parameter(BaseModel):
|
class Parameter(BaseModel):
|
||||||
name: str = Field(..., description="The name of the parameter")
|
name: str = Field(..., description="The name of the parameter")
|
||||||
type: ToolParameter.ToolParameterType = Field(..., description="The type of the parameter")
|
type: DatasourceParameter.DatasourceParameterType = Field(..., description="The type of the parameter")
|
||||||
required: bool = Field(..., description="Whether the parameter is required")
|
required: bool = Field(..., description="Whether the parameter is required")
|
||||||
description: str = Field(..., description="The description of the parameter")
|
description: str = Field(..., description="The description of the parameter")
|
||||||
default: Optional[Union[int, float, str]] = None
|
default: Optional[Union[int, float, str]] = None
|
||||||
options: Optional[list[PluginParameterOption]] = None
|
options: Optional[list[PluginParameterOption]] = None
|
||||||
|
|
||||||
provider_id: str = Field(..., description="The id of the provider")
|
provider_id: str = Field(..., description="The id of the provider")
|
||||||
tool_name: str = Field(..., description="The name of the tool")
|
datasource_name: str = Field(..., description="The name of the datasource")
|
||||||
tool_description: str = Field(..., description="The description of the tool")
|
datasource_description: str = Field(..., description="The description of the datasource")
|
||||||
tool_configuration: Mapping[str, Any] = Field(..., description="Configuration, type form")
|
datasource_configuration: Mapping[str, Any] = Field(..., description="Configuration, type form")
|
||||||
tool_parameters: Mapping[str, Parameter] = Field(..., description="Parameters, type llm")
|
datasource_parameters: Mapping[str, Parameter] = Field(..., description="Parameters, type llm")
|
||||||
|
|
||||||
def to_plugin_parameter(self) -> dict[str, Any]:
|
def to_plugin_parameter(self) -> dict[str, Any]:
|
||||||
return self.model_dump()
|
return self.model_dump()
|
217
api/core/plugin/manager/datasource.py
Normal file
217
api/core/plugin/manager/datasource.py
Normal file
@ -0,0 +1,217 @@
|
|||||||
|
from collections.abc import Generator
|
||||||
|
from typing import Any, Optional
|
||||||
|
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
from core.plugin.entities.plugin import GenericProviderID, ToolProviderID
|
||||||
|
from core.plugin.entities.plugin_daemon import PluginBasicBooleanResponse, PluginToolProviderEntity
|
||||||
|
from core.plugin.manager.base import BasePluginManager
|
||||||
|
from core.tools.entities.tool_entities import ToolInvokeMessage, ToolParameter
|
||||||
|
|
||||||
|
|
||||||
|
class PluginDatasourceManager(BasePluginManager):
|
||||||
|
def fetch_datasource_providers(self, tenant_id: str) -> list[PluginToolProviderEntity]:
|
||||||
|
"""
|
||||||
|
Fetch datasource providers for the given tenant.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def transformer(json_response: dict[str, Any]) -> dict:
|
||||||
|
for provider in json_response.get("data", []):
|
||||||
|
declaration = provider.get("declaration", {}) or {}
|
||||||
|
provider_name = declaration.get("identity", {}).get("name")
|
||||||
|
for tool in declaration.get("tools", []):
|
||||||
|
tool["identity"]["provider"] = provider_name
|
||||||
|
|
||||||
|
return json_response
|
||||||
|
|
||||||
|
response = self._request_with_plugin_daemon_response(
|
||||||
|
"GET",
|
||||||
|
f"plugin/{tenant_id}/management/datasources",
|
||||||
|
list[PluginToolProviderEntity],
|
||||||
|
params={"page": 1, "page_size": 256},
|
||||||
|
transformer=transformer,
|
||||||
|
)
|
||||||
|
|
||||||
|
for provider in response:
|
||||||
|
provider.declaration.identity.name = f"{provider.plugin_id}/{provider.declaration.identity.name}"
|
||||||
|
|
||||||
|
# override the provider name for each tool to plugin_id/provider_name
|
||||||
|
for tool in provider.declaration.tools:
|
||||||
|
tool.identity.provider = provider.declaration.identity.name
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
def fetch_datasource_provider(self, tenant_id: str, provider: str) -> PluginToolProviderEntity:
|
||||||
|
"""
|
||||||
|
Fetch datasource provider for the given tenant and plugin.
|
||||||
|
"""
|
||||||
|
tool_provider_id = ToolProviderID(provider)
|
||||||
|
|
||||||
|
def transformer(json_response: dict[str, Any]) -> dict:
|
||||||
|
data = json_response.get("data")
|
||||||
|
if data:
|
||||||
|
for datasource in data.get("declaration", {}).get("datasources", []):
|
||||||
|
datasource["identity"]["provider"] = tool_provider_id.provider_name
|
||||||
|
|
||||||
|
return json_response
|
||||||
|
|
||||||
|
response = self._request_with_plugin_daemon_response(
|
||||||
|
"GET",
|
||||||
|
f"plugin/{tenant_id}/management/datasources",
|
||||||
|
PluginToolProviderEntity,
|
||||||
|
params={"provider": tool_provider_id.provider_name, "plugin_id": tool_provider_id.plugin_id},
|
||||||
|
transformer=transformer,
|
||||||
|
)
|
||||||
|
|
||||||
|
response.declaration.identity.name = f"{response.plugin_id}/{response.declaration.identity.name}"
|
||||||
|
|
||||||
|
# override the provider name for each tool to plugin_id/provider_name
|
||||||
|
for tool in response.declaration.tools:
|
||||||
|
tool.identity.provider = response.declaration.identity.name
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
def invoke_first_step(
|
||||||
|
self,
|
||||||
|
tenant_id: str,
|
||||||
|
user_id: str,
|
||||||
|
datasource_provider: str,
|
||||||
|
datasource_name: str,
|
||||||
|
credentials: dict[str, Any],
|
||||||
|
datasource_parameters: dict[str, Any],
|
||||||
|
) -> Generator[ToolInvokeMessage, None, None]:
|
||||||
|
"""
|
||||||
|
Invoke the datasource with the given tenant, user, plugin, provider, name, credentials and parameters.
|
||||||
|
"""
|
||||||
|
|
||||||
|
datasource_provider_id = GenericProviderID(datasource_provider)
|
||||||
|
|
||||||
|
response = self._request_with_plugin_daemon_response_stream(
|
||||||
|
"POST",
|
||||||
|
f"plugin/{tenant_id}/dispatch/datasource/invoke_first_step",
|
||||||
|
ToolInvokeMessage,
|
||||||
|
data={
|
||||||
|
"user_id": user_id,
|
||||||
|
"data": {
|
||||||
|
"provider": datasource_provider_id.provider_name,
|
||||||
|
"datasource": datasource_name,
|
||||||
|
"credentials": credentials,
|
||||||
|
"datasource_parameters": datasource_parameters,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
headers={
|
||||||
|
"X-Plugin-ID": datasource_provider_id.plugin_id,
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
return response
|
||||||
|
|
||||||
|
def invoke_second_step(
|
||||||
|
self,
|
||||||
|
tenant_id: str,
|
||||||
|
user_id: str,
|
||||||
|
datasource_provider: str,
|
||||||
|
datasource_name: str,
|
||||||
|
credentials: dict[str, Any],
|
||||||
|
datasource_parameters: dict[str, Any],
|
||||||
|
) -> Generator[ToolInvokeMessage, None, None]:
|
||||||
|
"""
|
||||||
|
Invoke the datasource with the given tenant, user, plugin, provider, name, credentials and parameters.
|
||||||
|
"""
|
||||||
|
|
||||||
|
datasource_provider_id = GenericProviderID(datasource_provider)
|
||||||
|
|
||||||
|
response = self._request_with_plugin_daemon_response_stream(
|
||||||
|
"POST",
|
||||||
|
f"plugin/{tenant_id}/dispatch/datasource/invoke_second_step",
|
||||||
|
ToolInvokeMessage,
|
||||||
|
data={
|
||||||
|
"user_id": user_id,
|
||||||
|
"data": {
|
||||||
|
"provider": datasource_provider_id.provider_name,
|
||||||
|
"datasource": datasource_name,
|
||||||
|
"credentials": credentials,
|
||||||
|
"datasource_parameters": datasource_parameters,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
headers={
|
||||||
|
"X-Plugin-ID": datasource_provider_id.plugin_id,
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
return response
|
||||||
|
|
||||||
|
def validate_provider_credentials(
|
||||||
|
self, tenant_id: str, user_id: str, provider: str, credentials: dict[str, Any]
|
||||||
|
) -> bool:
|
||||||
|
"""
|
||||||
|
validate the credentials of the provider
|
||||||
|
"""
|
||||||
|
tool_provider_id = GenericProviderID(provider)
|
||||||
|
|
||||||
|
response = self._request_with_plugin_daemon_response_stream(
|
||||||
|
"POST",
|
||||||
|
f"plugin/{tenant_id}/dispatch/tool/validate_credentials",
|
||||||
|
PluginBasicBooleanResponse,
|
||||||
|
data={
|
||||||
|
"user_id": user_id,
|
||||||
|
"data": {
|
||||||
|
"provider": tool_provider_id.provider_name,
|
||||||
|
"credentials": credentials,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
headers={
|
||||||
|
"X-Plugin-ID": tool_provider_id.plugin_id,
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
for resp in response:
|
||||||
|
return resp.result
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
def get_runtime_parameters(
|
||||||
|
self,
|
||||||
|
tenant_id: str,
|
||||||
|
user_id: str,
|
||||||
|
provider: str,
|
||||||
|
credentials: dict[str, Any],
|
||||||
|
datasource: str,
|
||||||
|
conversation_id: Optional[str] = None,
|
||||||
|
app_id: Optional[str] = None,
|
||||||
|
message_id: Optional[str] = None,
|
||||||
|
) -> list[ToolParameter]:
|
||||||
|
"""
|
||||||
|
get the runtime parameters of the datasource
|
||||||
|
"""
|
||||||
|
datasource_provider_id = GenericProviderID(provider)
|
||||||
|
|
||||||
|
class RuntimeParametersResponse(BaseModel):
|
||||||
|
parameters: list[ToolParameter]
|
||||||
|
|
||||||
|
response = self._request_with_plugin_daemon_response_stream(
|
||||||
|
"POST",
|
||||||
|
f"plugin/{tenant_id}/dispatch/datasource/get_runtime_parameters",
|
||||||
|
RuntimeParametersResponse,
|
||||||
|
data={
|
||||||
|
"user_id": user_id,
|
||||||
|
"conversation_id": conversation_id,
|
||||||
|
"app_id": app_id,
|
||||||
|
"message_id": message_id,
|
||||||
|
"data": {
|
||||||
|
"provider": datasource_provider_id.provider_name,
|
||||||
|
"datasource": datasource,
|
||||||
|
"credentials": credentials,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
headers={
|
||||||
|
"X-Plugin-ID": datasource_provider_id.plugin_id,
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
for resp in response:
|
||||||
|
return resp.parameters
|
||||||
|
|
||||||
|
return []
|
@ -1,5 +1,6 @@
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
|
from core.datasource.entities.datasource_entities import DatasourceSelector
|
||||||
from core.file.models import File
|
from core.file.models import File
|
||||||
from core.tools.entities.tool_entities import ToolSelector
|
from core.tools.entities.tool_entities import ToolSelector
|
||||||
|
|
||||||
@ -18,4 +19,10 @@ def convert_parameters_to_plugin_format(parameters: dict[str, Any]) -> dict[str,
|
|||||||
parameters[parameter_name] = []
|
parameters[parameter_name] = []
|
||||||
for p in parameter:
|
for p in parameter:
|
||||||
parameters[parameter_name].append(p.to_plugin_parameter())
|
parameters[parameter_name].append(p.to_plugin_parameter())
|
||||||
|
elif isinstance(parameter, DatasourceSelector):
|
||||||
|
parameters[parameter_name] = parameter.to_plugin_parameter()
|
||||||
|
elif isinstance(parameter, list) and all(isinstance(p, DatasourceSelector) for p in parameter):
|
||||||
|
parameters[parameter_name] = []
|
||||||
|
for p in parameter:
|
||||||
|
parameters[parameter_name].append(p.to_plugin_parameter())
|
||||||
return parameters
|
return parameters
|
||||||
|
Loading…
x
Reference in New Issue
Block a user