plugin.py 5.8 KB

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