mirror of
https://github.com/langgenius/dify-plugin-sdks.git
synced 2026-07-22 10:25:23 -04:00
c6f83a63e1
* chore: fix ruff issue * feat(oauth): implement OAuth * feat(invoke-message): refactor message handling and introduce InvokeMessage class * feat(plugin-oauth): add credential_id and credential_type to tool parameters * feat(plugin-oauth): add credential_id and credential_type to tool parameters * chore: update dify_plugin version to 0.5.0b4 and clean up github.yaml * chore: update plugin version to 0.1.2 in manifest.yaml * feat(session): session context and tool backwards invocation credential support * feat(oauth): session context and tool backwards invocation credential support * feat: update README and requirements for OAuth support in version 0.4.2 * feat: add .gitignore to exclude IDE files and secret keys * chore: apply ruff * feat: bump version to 0.4.2b1 * feat: update GitHub plugin configuration for OAuth support and improve credential handling * feat: update .gitignore to exclude dify plugin files and public keys * feat: fix credential validation for GitHub API and bump version to 0.2.1 * feat: update GitHub plugin to support multiple access tokens and bump version to 0.2.5 * chore: apply ruff * feat: add ToolProviderOAuthError for improved OAuth error handling in GitHub plugin * chore: apply ruff * chore: bump version to 0.4.2 * chore: update examples sdk version to 0.4.2 * fix: thread deadlock in PluginRunner when running tests without gevent monkey patching * feat: add support for refreshing OAuth credentials in Plugin and GitHub provider * feat: refactor OAuth credential handling to return structured OAuthCredentials object * apply ruff * feat: refactor OAuth credential handling to use ToolOAuthCredentials for improved structure * feat: reorganize imports in __init__.py for improved clarity and structure * feat: add Microsoft To Do plugin for refresh token example * chore: apply ruff * fix: update author in GitHub configuration and clean up Microsoft To Do schema * chore: bump version to 0.4.2b2 in pyproject.toml * feat: update Microsoft To Do plugin to handle OAuth token encoding and version bump * feat:remove inelegant example * chore: update dify_plugin version to 0.4.2 * chore: bump version to 0.4.2 in pyproject.toml --------- Co-authored-by: Yeuoly <admin@srmxy.cn>
392 lines
12 KiB
Python
392 lines
12 KiB
Python
from decimal import Decimal
|
||
from enum import Enum
|
||
from typing import Any
|
||
|
||
from pydantic import BaseModel, ConfigDict, Field, model_validator
|
||
|
||
from dify_plugin.core.documentation.schema_doc import docs
|
||
from dify_plugin.entities import I18nObject
|
||
|
||
|
||
@docs(
|
||
description="The default parameter name",
|
||
)
|
||
class DefaultParameterName(Enum):
|
||
"""
|
||
Enum class for parameter template variable.
|
||
"""
|
||
|
||
TEMPERATURE = "temperature"
|
||
TOP_P = "top_p"
|
||
TOP_K = "top_k"
|
||
PRESENCE_PENALTY = "presence_penalty"
|
||
FREQUENCY_PENALTY = "frequency_penalty"
|
||
MAX_TOKENS = "max_tokens"
|
||
RESPONSE_FORMAT = "response_format"
|
||
JSON_SCHEMA = "json_schema"
|
||
|
||
@classmethod
|
||
def value_of(cls, value: Any) -> "DefaultParameterName":
|
||
"""
|
||
Get parameter name from value.
|
||
|
||
:param value: parameter value
|
||
:return: parameter name
|
||
"""
|
||
for name in cls:
|
||
if name.value == value:
|
||
return name
|
||
raise ValueError(f"invalid parameter name {value}")
|
||
|
||
|
||
PARAMETER_RULE_TEMPLATE: dict[DefaultParameterName, dict] = {
|
||
DefaultParameterName.TEMPERATURE: {
|
||
"label": {
|
||
"en_US": "Temperature",
|
||
"zh_Hans": "温度",
|
||
},
|
||
"type": "float",
|
||
"help": {
|
||
"en_US": "Controls randomness. Lower temperature results in less random completions. As the temperature approaches zero, the model will become deterministic and repetitive. Higher temperature results in more random completions.", # noqa: E501
|
||
"zh_Hans": "温度控制随机性。较低的温度会导致较少的随机完成。随着温度接近零,模型将变得确定性和重复性。"
|
||
"较高的温度会导致更多的随机完成。",
|
||
},
|
||
"required": False,
|
||
"default": 0.0,
|
||
"min": 0.0,
|
||
"max": 1.0,
|
||
"precision": 2,
|
||
},
|
||
DefaultParameterName.TOP_P: {
|
||
"label": {
|
||
"en_US": "Top P",
|
||
"zh_Hans": "Top P",
|
||
},
|
||
"type": "float",
|
||
"help": {
|
||
"en_US": "Controls diversity via nucleus sampling: "
|
||
"0.5 means half of all likelihood-weighted options are considered.",
|
||
"zh_Hans": "通过核心采样控制多样性:0.5表示考虑了一半的所有可能性加权选项。",
|
||
},
|
||
"required": False,
|
||
"default": 1.0,
|
||
"min": 0.0,
|
||
"max": 1.0,
|
||
"precision": 2,
|
||
},
|
||
DefaultParameterName.TOP_K: {
|
||
"label": {
|
||
"en_US": "Top K",
|
||
"zh_Hans": "Top K",
|
||
},
|
||
"type": "int",
|
||
"help": {
|
||
"en_US": "Limits the number of tokens to consider for each step by keeping only the k most likely tokens.",
|
||
"zh_Hans": "通过只保留每一步中最可能的 k 个标记来限制要考虑的标记数量。",
|
||
},
|
||
"required": False,
|
||
"default": 50,
|
||
"min": 1,
|
||
"max": 100,
|
||
"precision": 0,
|
||
},
|
||
DefaultParameterName.PRESENCE_PENALTY: {
|
||
"label": {
|
||
"en_US": "Presence Penalty",
|
||
"zh_Hans": "存在惩罚",
|
||
},
|
||
"type": "float",
|
||
"help": {
|
||
"en_US": "Applies a penalty to the log-probability of tokens already in the text.",
|
||
"zh_Hans": "对文本中已有的标记的对数概率施加惩罚。",
|
||
},
|
||
"required": False,
|
||
"default": 0.0,
|
||
"min": 0.0,
|
||
"max": 1.0,
|
||
"precision": 2,
|
||
},
|
||
DefaultParameterName.FREQUENCY_PENALTY: {
|
||
"label": {
|
||
"en_US": "Frequency Penalty",
|
||
"zh_Hans": "频率惩罚",
|
||
},
|
||
"type": "float",
|
||
"help": {
|
||
"en_US": "Applies a penalty to the log-probability of tokens that appear in the text.",
|
||
"zh_Hans": "对文本中出现的标记的对数概率施加惩罚。",
|
||
},
|
||
"required": False,
|
||
"default": 0.0,
|
||
"min": 0.0,
|
||
"max": 1.0,
|
||
"precision": 2,
|
||
},
|
||
DefaultParameterName.MAX_TOKENS: {
|
||
"label": {
|
||
"en_US": "Max Tokens",
|
||
"zh_Hans": "最大标记",
|
||
},
|
||
"type": "int",
|
||
"help": {
|
||
"en_US": "Specifies the upper limit on the length of generated results. "
|
||
"If the generated results are truncated, you can increase this parameter.",
|
||
"zh_Hans": "指定生成结果长度的上限。如果生成结果截断,可以调大该参数。",
|
||
},
|
||
"required": False,
|
||
"default": 64,
|
||
"min": 1,
|
||
"max": 2048,
|
||
"precision": 0,
|
||
},
|
||
DefaultParameterName.RESPONSE_FORMAT: {
|
||
"label": {
|
||
"en_US": "Response Format",
|
||
"zh_Hans": "回复格式",
|
||
},
|
||
"type": "string",
|
||
"help": {
|
||
"en_US": "Set a response format, ensure the output from llm is a valid code block as possible, "
|
||
"such as JSON, XML, etc.",
|
||
"zh_Hans": "设置一个返回格式,确保llm的输出尽可能是有效的代码块,如JSON、XML等",
|
||
},
|
||
"required": False,
|
||
"options": ["JSON", "XML"],
|
||
},
|
||
DefaultParameterName.JSON_SCHEMA: {
|
||
"label": {
|
||
"en_US": "JSON Schema",
|
||
},
|
||
"type": "text",
|
||
"help": {
|
||
"en_US": "Set a response json schema will ensure LLM to adhere it.",
|
||
"zh_Hans": "设置返回的json schema,llm将按照它返回",
|
||
},
|
||
"required": False,
|
||
},
|
||
}
|
||
|
||
|
||
@docs(
|
||
description="The model type",
|
||
)
|
||
class ModelType(Enum):
|
||
"""
|
||
Enum class for model type.
|
||
"""
|
||
|
||
LLM = "llm"
|
||
TEXT_EMBEDDING = "text-embedding"
|
||
RERANK = "rerank"
|
||
SPEECH2TEXT = "speech2text"
|
||
MODERATION = "moderation"
|
||
TTS = "tts"
|
||
TEXT2IMG = "text2img"
|
||
|
||
|
||
@docs(
|
||
description="The fetch from",
|
||
)
|
||
class FetchFrom(Enum):
|
||
"""
|
||
Enum class for fetch from.
|
||
"""
|
||
|
||
PREDEFINED_MODEL = "predefined-model"
|
||
CUSTOMIZABLE_MODEL = "customizable-model"
|
||
|
||
|
||
@docs(
|
||
description="The model feature",
|
||
)
|
||
class ModelFeature(Enum):
|
||
"""
|
||
Enum class for llm feature.
|
||
"""
|
||
|
||
TOOL_CALL = "tool-call"
|
||
MULTI_TOOL_CALL = "multi-tool-call"
|
||
AGENT_THOUGHT = "agent-thought"
|
||
VISION = "vision"
|
||
STREAM_TOOL_CALL = "stream-tool-call"
|
||
DOCUMENT = "document"
|
||
VIDEO = "video"
|
||
AUDIO = "audio"
|
||
STRUCTURED_OUTPUT = "structured-output"
|
||
|
||
|
||
@docs(
|
||
description="The parameter type",
|
||
)
|
||
class ParameterType(Enum):
|
||
"""
|
||
Enum class for parameter type.
|
||
"""
|
||
|
||
FLOAT = "float"
|
||
INT = "int"
|
||
STRING = "string"
|
||
BOOLEAN = "boolean"
|
||
TEXT = "text"
|
||
|
||
|
||
@docs(
|
||
description="The model property key",
|
||
)
|
||
class ModelPropertyKey(Enum):
|
||
"""
|
||
Enum class for model property key.
|
||
"""
|
||
|
||
MODE = "mode"
|
||
CONTEXT_SIZE = "context_size"
|
||
MAX_CHUNKS = "max_chunks"
|
||
FILE_UPLOAD_LIMIT = "file_upload_limit"
|
||
SUPPORTED_FILE_EXTENSIONS = "supported_file_extensions"
|
||
MAX_CHARACTERS_PER_CHUNK = "max_characters_per_chunk"
|
||
DEFAULT_VOICE = "default_voice"
|
||
VOICES = "voices"
|
||
WORD_LIMIT = "word_limit"
|
||
AUDIO_TYPE = "audio_type"
|
||
MAX_WORKERS = "max_workers"
|
||
|
||
|
||
@docs(
|
||
description="The provider model",
|
||
)
|
||
class ProviderModel(BaseModel):
|
||
"""
|
||
Model class for provider model.
|
||
"""
|
||
|
||
model: str = Field(..., description="The model name")
|
||
label: I18nObject = Field(..., description="The label of the model")
|
||
model_type: ModelType = Field(..., description="The model type")
|
||
features: list[ModelFeature] | None = Field(default=None, description="The features of the model")
|
||
fetch_from: FetchFrom = Field(default=FetchFrom.PREDEFINED_MODEL, description="The fetch from")
|
||
model_properties: dict[ModelPropertyKey, Any] = Field(..., description="The model properties")
|
||
deprecated: bool = Field(default=False, description="Whether the model is deprecated")
|
||
model_config = ConfigDict(protected_namespaces=())
|
||
|
||
"""
|
||
use model as label
|
||
"""
|
||
|
||
@model_validator(mode="before")
|
||
@classmethod
|
||
def validate_label(cls, data: dict) -> dict:
|
||
if isinstance(data, dict) and not data.get("label"):
|
||
data["label"] = I18nObject(en_US=data["model"])
|
||
|
||
return data
|
||
|
||
|
||
@docs(
|
||
description="The parameter rule of the model",
|
||
)
|
||
class ParameterRule(BaseModel):
|
||
"""
|
||
Model class for parameter rule.
|
||
"""
|
||
|
||
name: str = Field(..., description="The name of the parameter")
|
||
use_template: str | None = Field(default=None, description="The template of the parameter")
|
||
label: I18nObject = Field(..., description="The label of the parameter")
|
||
type: ParameterType = Field(..., description="The type of the parameter")
|
||
help: I18nObject | None = Field(default=None, description="The help of the parameter")
|
||
required: bool = Field(default=False, description="Whether the parameter is required")
|
||
default: Any | None = Field(default=None, description="The default value of the parameter")
|
||
min: float | None = Field(default=None, description="The minimum value of the parameter")
|
||
max: float | None = Field(default=None, description="The maximum value of the parameter")
|
||
precision: int | None = Field(default=None, description="The precision of the parameter")
|
||
options: list[str] = Field(default=[], description="The options of the parameter")
|
||
|
||
@model_validator(mode="before")
|
||
@classmethod
|
||
def validate_label(cls, data: dict) -> dict:
|
||
if isinstance(data, dict):
|
||
# check if there is a template
|
||
if "use_template" in data:
|
||
try:
|
||
default_parameter_name = DefaultParameterName.value_of(data["use_template"])
|
||
default_parameter_rule = PARAMETER_RULE_TEMPLATE.get(default_parameter_name)
|
||
if not default_parameter_rule:
|
||
raise Exception(f"Invalid model parameter rule name {default_parameter_name}")
|
||
copy_default_parameter_rule = default_parameter_rule.copy()
|
||
copy_default_parameter_rule.update(data)
|
||
data = copy_default_parameter_rule
|
||
except ValueError:
|
||
pass
|
||
|
||
if not data.get("label"):
|
||
data["label"] = I18nObject(en_US=data["name"])
|
||
|
||
return data
|
||
|
||
|
||
@docs(
|
||
description="The price config",
|
||
)
|
||
class PriceConfig(BaseModel):
|
||
"""
|
||
Model class for pricing info.
|
||
"""
|
||
|
||
input: Decimal = Field(..., description="Input price")
|
||
output: Decimal | None = Field(default=None, description="Output price")
|
||
unit: Decimal = Field(..., description="Unit, e.g. 0.0001 -> per 10000 tokens")
|
||
currency: str = Field(..., description="Currency, e.g. USD")
|
||
|
||
|
||
@docs(
|
||
description="AI model entity",
|
||
)
|
||
class AIModelEntity(ProviderModel):
|
||
"""
|
||
Model class for AI model.
|
||
"""
|
||
|
||
parameter_rules: list[ParameterRule] = []
|
||
pricing: PriceConfig | None = None
|
||
|
||
|
||
class ModelUsage(BaseModel):
|
||
pass
|
||
|
||
|
||
class PriceType(Enum):
|
||
"""
|
||
Enum class for price type.
|
||
"""
|
||
|
||
INPUT = "input"
|
||
OUTPUT = "output"
|
||
|
||
|
||
class PriceInfo(BaseModel):
|
||
"""
|
||
Model class for price info.
|
||
"""
|
||
|
||
unit_price: Decimal = Field(..., description="The unit price, e.g. 0.000001")
|
||
unit: Decimal = Field(..., description="The unit, e.g. 1000")
|
||
total_amount: Decimal = Field(..., description="The total amount")
|
||
currency: str = Field(..., description="The currency, e.g. USD")
|
||
|
||
|
||
class BaseModelConfig(BaseModel):
|
||
provider: str
|
||
model: str
|
||
model_type: ModelType
|
||
|
||
model_config = ConfigDict(protected_namespaces=())
|
||
|
||
|
||
class EmbeddingInputType(Enum):
|
||
"""
|
||
Enum for embedding input type.
|
||
"""
|
||
|
||
DOCUMENT = "document"
|
||
QUERY = "query"
|