您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

plugin.py 8.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. import datetime
  2. import enum
  3. import re
  4. from collections.abc import Mapping
  5. from typing import Any, Optional
  6. from pydantic import BaseModel, Field, model_validator
  7. from werkzeug.exceptions import NotFound
  8. from core.agent.plugin_entities import AgentStrategyProviderEntity
  9. from core.datasource.entities.datasource_entities import DatasourceProviderEntity
  10. from core.model_runtime.entities.provider_entities import ProviderEntity
  11. from core.plugin.entities.base import BasePluginEntity
  12. from core.plugin.entities.endpoint import EndpointProviderDeclaration
  13. from core.tools.entities.common_entities import I18nObject
  14. from core.tools.entities.tool_entities import ToolProviderEntity
  15. class PluginInstallationSource(enum.StrEnum):
  16. Github = "github"
  17. Marketplace = "marketplace"
  18. Package = "package"
  19. Remote = "remote"
  20. class PluginResourceRequirements(BaseModel):
  21. memory: int
  22. class Permission(BaseModel):
  23. class Tool(BaseModel):
  24. enabled: Optional[bool] = Field(default=False)
  25. class Model(BaseModel):
  26. enabled: Optional[bool] = Field(default=False)
  27. llm: Optional[bool] = Field(default=False)
  28. text_embedding: Optional[bool] = Field(default=False)
  29. rerank: Optional[bool] = Field(default=False)
  30. tts: Optional[bool] = Field(default=False)
  31. speech2text: Optional[bool] = Field(default=False)
  32. moderation: Optional[bool] = Field(default=False)
  33. class Node(BaseModel):
  34. enabled: Optional[bool] = Field(default=False)
  35. class Endpoint(BaseModel):
  36. enabled: Optional[bool] = Field(default=False)
  37. class Storage(BaseModel):
  38. enabled: Optional[bool] = Field(default=False)
  39. size: int = Field(ge=1024, le=1073741824, default=1048576)
  40. tool: Optional[Tool] = Field(default=None)
  41. model: Optional[Model] = Field(default=None)
  42. node: Optional[Node] = Field(default=None)
  43. endpoint: Optional[Endpoint] = Field(default=None)
  44. storage: Optional[Storage] = Field(default=None)
  45. permission: Optional[Permission] = Field(default=None)
  46. class PluginCategory(enum.StrEnum):
  47. Tool = "tool"
  48. Model = "model"
  49. Extension = "extension"
  50. AgentStrategy = "agent-strategy"
  51. Datasource = "datasource"
  52. class PluginDeclaration(BaseModel):
  53. class Plugins(BaseModel):
  54. tools: Optional[list[str]] = Field(default_factory=list[str])
  55. models: Optional[list[str]] = Field(default_factory=list[str])
  56. endpoints: Optional[list[str]] = Field(default_factory=list[str])
  57. datasources: Optional[list[str]] = Field(default_factory=list[str])
  58. class Meta(BaseModel):
  59. minimum_dify_version: Optional[str] = Field(default=None, pattern=r"^\d{1,4}(\.\d{1,4}){1,3}(-\w{1,16})?$")
  60. version: Optional[str] = Field(default=None)
  61. version: str = Field(..., pattern=r"^\d{1,4}(\.\d{1,4}){1,3}(-\w{1,16})?$")
  62. author: Optional[str] = Field(..., pattern=r"^[a-zA-Z0-9_-]{1,64}$")
  63. name: str = Field(..., pattern=r"^[a-z0-9_-]{1,128}$")
  64. description: I18nObject
  65. icon: str
  66. icon_dark: Optional[str] = Field(default=None)
  67. label: I18nObject
  68. category: PluginCategory
  69. created_at: datetime.datetime
  70. resource: PluginResourceRequirements
  71. plugins: Plugins
  72. tags: list[str] = Field(default_factory=list)
  73. repo: Optional[str] = Field(default=None)
  74. verified: bool = Field(default=False)
  75. tool: Optional[ToolProviderEntity] = None
  76. model: Optional[ProviderEntity] = None
  77. endpoint: Optional[EndpointProviderDeclaration] = None
  78. agent_strategy: Optional[AgentStrategyProviderEntity] = None
  79. datasource: Optional[DatasourceProviderEntity] = None
  80. meta: Meta
  81. @model_validator(mode="before")
  82. @classmethod
  83. def validate_category(cls, values: dict) -> dict:
  84. # auto detect category
  85. if values.get("tool"):
  86. values["category"] = PluginCategory.Tool
  87. elif values.get("model"):
  88. values["category"] = PluginCategory.Model
  89. elif values.get("datasource"):
  90. values["category"] = PluginCategory.Datasource
  91. elif values.get("agent_strategy"):
  92. values["category"] = PluginCategory.AgentStrategy
  93. else:
  94. values["category"] = PluginCategory.Extension
  95. return values
  96. class PluginInstallation(BasePluginEntity):
  97. tenant_id: str
  98. endpoints_setups: int
  99. endpoints_active: int
  100. runtime_type: str
  101. source: PluginInstallationSource
  102. meta: Mapping[str, Any]
  103. plugin_id: str
  104. plugin_unique_identifier: str
  105. version: str
  106. checksum: str
  107. declaration: PluginDeclaration
  108. class PluginEntity(PluginInstallation):
  109. name: str
  110. installation_id: str
  111. version: str
  112. @model_validator(mode="after")
  113. def set_plugin_id(self):
  114. if self.declaration.tool:
  115. self.declaration.tool.plugin_id = self.plugin_id
  116. return self
  117. class GithubPackage(BaseModel):
  118. repo: str
  119. version: str
  120. package: str
  121. class GithubVersion(BaseModel):
  122. repo: str
  123. version: str
  124. class GenericProviderID:
  125. organization: str
  126. plugin_name: str
  127. provider_name: str
  128. is_hardcoded: bool
  129. def to_string(self) -> str:
  130. return str(self)
  131. def __str__(self) -> str:
  132. return f"{self.organization}/{self.plugin_name}/{self.provider_name}"
  133. def __init__(self, value: str, is_hardcoded: bool = False) -> None:
  134. if not value:
  135. raise NotFound("plugin not found, please add plugin")
  136. # check if the value is a valid plugin id with format: $organization/$plugin_name/$provider_name
  137. if not re.match(r"^[a-z0-9_-]+\/[a-z0-9_-]+\/[a-z0-9_-]+$", value):
  138. # check if matches [a-z0-9_-]+, if yes, append with langgenius/$value/$value
  139. if re.match(r"^[a-z0-9_-]+$", value):
  140. value = f"langgenius/{value}/{value}"
  141. else:
  142. raise ValueError(f"Invalid plugin id {value}")
  143. self.organization, self.plugin_name, self.provider_name = value.split("/")
  144. self.is_hardcoded = is_hardcoded
  145. def is_langgenius(self) -> bool:
  146. return self.organization == "langgenius"
  147. @property
  148. def plugin_id(self) -> str:
  149. return f"{self.organization}/{self.plugin_name}"
  150. class ModelProviderID(GenericProviderID):
  151. def __init__(self, value: str, is_hardcoded: bool = False) -> None:
  152. super().__init__(value, is_hardcoded)
  153. if self.organization == "langgenius" and self.provider_name == "google":
  154. self.plugin_name = "gemini"
  155. class ToolProviderID(GenericProviderID):
  156. def __init__(self, value: str, is_hardcoded: bool = False) -> None:
  157. super().__init__(value, is_hardcoded)
  158. if self.organization == "langgenius":
  159. if self.provider_name in ["jina", "siliconflow", "stepfun", "gitee_ai"]:
  160. self.plugin_name = f"{self.provider_name}_tool"
  161. class DatasourceProviderID(GenericProviderID):
  162. def __init__(self, value: str, is_hardcoded: bool = False) -> None:
  163. super().__init__(value, is_hardcoded)
  164. class PluginDependency(BaseModel):
  165. class Type(enum.StrEnum):
  166. Github = PluginInstallationSource.Github.value
  167. Marketplace = PluginInstallationSource.Marketplace.value
  168. Package = PluginInstallationSource.Package.value
  169. class Github(BaseModel):
  170. repo: str
  171. version: str
  172. package: str
  173. github_plugin_unique_identifier: str
  174. @property
  175. def plugin_unique_identifier(self) -> str:
  176. return self.github_plugin_unique_identifier
  177. class Marketplace(BaseModel):
  178. marketplace_plugin_unique_identifier: str
  179. @property
  180. def plugin_unique_identifier(self) -> str:
  181. return self.marketplace_plugin_unique_identifier
  182. class Package(BaseModel):
  183. plugin_unique_identifier: str
  184. type: Type
  185. value: Github | Marketplace | Package
  186. current_identifier: Optional[str] = None
  187. class MissingPluginDependency(BaseModel):
  188. plugin_unique_identifier: str
  189. current_identifier: Optional[str] = None