├── api
└── core
│ ├── moderation
│ └── cloud_service
│ │ ├── __init__.py
│ │ ├── schema.json
│ │ └── cloud_service.py
│ ├── external_data_tool
│ └── weather_search
│ │ ├── __init__.py
│ │ ├── schema.json
│ │ └── weather_search.py
│ └── tools
│ └── builtin_tool
│ └── providers
│ └── calculator
│ ├── calculator.yaml
│ ├── calculator.py
│ ├── tools
│ ├── add.yaml
│ └── add.py
│ └── _assets
│ └── icon.svg
├── plugins
├── mockgpt
│ ├── requirements.txt
│ ├── PRIVACY.md
│ ├── .env.example
│ ├── README.md
│ ├── main.py
│ ├── manifest.yaml
│ ├── models
│ │ └── llm
│ │ │ ├── llm.yaml
│ │ │ └── llm.py
│ ├── provider
│ │ ├── demo.py
│ │ └── demo.yaml
│ ├── .gitignore
│ ├── GUIDE.md
│ ├── _assets
│ │ ├── icon.svg
│ │ └── icon-dark.svg
│ ├── .difyignore
│ └── .github
│ │ └── workflows
│ │ └── plugin-publish.yml
├── calculator
│ ├── requirements.txt
│ ├── PRIVACY.md
│ ├── .env.example
│ ├── README.md
│ ├── main.py
│ ├── provider
│ │ ├── calculator.yaml
│ │ └── calculator.py
│ ├── tools
│ │ ├── add.py
│ │ └── add.yaml
│ ├── manifest.yaml
│ ├── _assets
│ │ ├── icon.svg
│ │ └── icon-dark.svg
│ ├── .gitignore
│ ├── GUIDE.md
│ ├── .difyignore
│ └── .github
│ │ └── workflows
│ │ └── plugin-publish.yml
├── demo.difypkg
├── calculator.difypkg
├── calculator.signed.difypkg
├── demo.public.pem
└── demo.private.pem
├── README.md
└── .gitignore
/api/core/moderation/cloud_service/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/api/core/external_data_tool/weather_search/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/plugins/mockgpt/requirements.txt:
--------------------------------------------------------------------------------
1 | dify_plugin>=0.4.0,<0.7.0
2 |
--------------------------------------------------------------------------------
/plugins/calculator/requirements.txt:
--------------------------------------------------------------------------------
1 | dify_plugin>=0.4.0,<0.7.0
2 |
--------------------------------------------------------------------------------
/plugins/mockgpt/PRIVACY.md:
--------------------------------------------------------------------------------
1 | ## Privacy
2 |
3 | !!! Please fill in the privacy policy of the plugin.
--------------------------------------------------------------------------------
/plugins/calculator/PRIVACY.md:
--------------------------------------------------------------------------------
1 | ## Privacy
2 |
3 | !!! Please fill in the privacy policy of the plugin.
--------------------------------------------------------------------------------
/plugins/demo.difypkg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aneasystone/dify-plugins/main/plugins/demo.difypkg
--------------------------------------------------------------------------------
/plugins/calculator.difypkg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aneasystone/dify-plugins/main/plugins/calculator.difypkg
--------------------------------------------------------------------------------
/plugins/calculator.signed.difypkg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aneasystone/dify-plugins/main/plugins/calculator.signed.difypkg
--------------------------------------------------------------------------------
/plugins/mockgpt/.env.example:
--------------------------------------------------------------------------------
1 | INSTALL_METHOD=remote
2 | REMOTE_INSTALL_URL=debug.dify.ai:5003
3 | REMOTE_INSTALL_KEY=********-****-****-****-************
4 |
--------------------------------------------------------------------------------
/plugins/calculator/.env.example:
--------------------------------------------------------------------------------
1 | INSTALL_METHOD=remote
2 | REMOTE_INSTALL_URL=debug.dify.ai:5003
3 | REMOTE_INSTALL_KEY=********-****-****-****-************
4 |
--------------------------------------------------------------------------------
/plugins/mockgpt/README.md:
--------------------------------------------------------------------------------
1 | ## demo
2 |
3 | **Author:** aneasystone
4 | **Version:** 0.0.1
5 | **Type:** model
6 |
7 | ### Description
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/plugins/calculator/README.md:
--------------------------------------------------------------------------------
1 | ## calculator
2 |
3 | **Author:** aneasystone
4 | **Version:** 0.0.1
5 | **Type:** tool
6 |
7 | ### Description
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/plugins/calculator/main.py:
--------------------------------------------------------------------------------
1 | from dify_plugin import Plugin, DifyPluginEnv
2 |
3 | plugin = Plugin(DifyPluginEnv(MAX_REQUEST_TIMEOUT=120))
4 |
5 | if __name__ == '__main__':
6 | plugin.run()
7 |
--------------------------------------------------------------------------------
/plugins/mockgpt/main.py:
--------------------------------------------------------------------------------
1 | from dify_plugin import Plugin, DifyPluginEnv
2 |
3 | plugin = Plugin(DifyPluginEnv(MAX_REQUEST_TIMEOUT=120))
4 |
5 | if __name__ == '__main__':
6 | plugin.run()
7 |
--------------------------------------------------------------------------------
/api/core/tools/builtin_tool/providers/calculator/calculator.yaml:
--------------------------------------------------------------------------------
1 | identity:
2 | author: Dify
3 | name: calculator
4 | label:
5 | en_US: Calculator
6 | zh_Hans: 计算器
7 | description:
8 | en_US: Calculator
9 | zh_Hans: 计算器
10 | icon: icon.svg
11 | tags:
12 | - productivity
13 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Dify 插件学习示例
2 |
3 | ### 扩展
4 |
5 | - `api/core/external_data_tool`:外部工具扩展,自定义基于 API 的变量
6 | - `api/core/moderation`:内容审核扩展,自定义审核策略
7 |
8 | ### 内置工具
9 |
10 | - `api/core/tools/builtin_tool`:自定义内置工具
11 |
12 | ### 插件
13 |
14 | - `plugins/mockgpt`:自定义模型插件,简单的模拟流式输出
15 | - `plugins/calculator`:自定义工具插件,简单的计算器
16 |
--------------------------------------------------------------------------------
/api/core/tools/builtin_tool/providers/calculator/calculator.py:
--------------------------------------------------------------------------------
1 | from typing import Any
2 |
3 | from core.tools.builtin_tool.provider import BuiltinToolProviderController
4 |
5 |
6 | class CalculatorToolProvider(BuiltinToolProviderController):
7 | def _validate_credentials(self, user_id: str, credentials: dict[str, Any]) -> None:
8 | pass
9 |
--------------------------------------------------------------------------------
/plugins/calculator/provider/calculator.yaml:
--------------------------------------------------------------------------------
1 | identity:
2 | author: aneasystone
3 | name: calculator
4 | label:
5 | en_US: Calculator
6 | zh_Hans: 计算器
7 | description:
8 | en_US: Calculator
9 | zh_Hans: 计算器
10 | icon: icon.svg
11 | tools:
12 | - tools/add.yaml
13 | extra:
14 | python:
15 | source: provider/calculator.py
16 |
--------------------------------------------------------------------------------
/plugins/calculator/tools/add.py:
--------------------------------------------------------------------------------
1 | from collections.abc import Generator
2 | from typing import Any
3 |
4 | from dify_plugin import Tool
5 | from dify_plugin.entities.tool import ToolInvokeMessage
6 |
7 | class AddTool(Tool):
8 |
9 | def _invoke(self, tool_parameters: dict[str, Any]) -> Generator[ToolInvokeMessage]:
10 | """
11 | 加法运算
12 | """
13 |
14 | x = tool_parameters.get("x", 0)
15 | y = tool_parameters.get("y", 0)
16 |
17 | result = str(x + y)
18 | yield self.create_text_message(result)
19 |
--------------------------------------------------------------------------------
/plugins/calculator/manifest.yaml:
--------------------------------------------------------------------------------
1 | version: 0.0.1
2 | type: plugin
3 | author: aneasystone
4 | name: calculator
5 | label:
6 | en_US: Calculator
7 | zh_Hans: 计算器
8 | description:
9 | en_US: Calculator
10 | zh_Hans: 计算器
11 | icon: icon.svg
12 | icon_dark: icon-dark.svg
13 | resource:
14 | memory: 268435456
15 | permission: {}
16 | plugins:
17 | tools:
18 | - provider/calculator.yaml
19 | meta:
20 | version: 0.0.1
21 | arch:
22 | - amd64
23 | - arm64
24 | runner:
25 | language: python
26 | version: "3.12"
27 | entrypoint: main
28 | minimum_dify_version: null
29 | created_at: 2025-10-22T21:04:51.275866+08:00
30 | privacy: PRIVACY.md
31 | verified: false
32 |
--------------------------------------------------------------------------------
/plugins/mockgpt/manifest.yaml:
--------------------------------------------------------------------------------
1 | version: 0.0.1
2 | type: plugin
3 | author: aneasystone
4 | name: demo
5 | label:
6 | en_US: Demo AI Provider
7 | zh_Hans: 演示 AI 供应商
8 | description:
9 | en_US: A demo AI model provider for learning
10 | zh_Hans: 用于学习的演示 AI 模型供应商
11 | icon: icon.svg
12 | icon_dark: icon-dark.svg
13 | resource:
14 | memory: 268435456
15 | permission: {}
16 | plugins:
17 | models:
18 | - provider/demo.yaml
19 | meta:
20 | version: 0.0.1
21 | arch:
22 | - amd64
23 | - arm64
24 | runner:
25 | language: python
26 | version: "3.12"
27 | entrypoint: main
28 | minimum_dify_version: null
29 | created_at: 2025-10-22T07:45:17.322263+08:00
30 | privacy: PRIVACY.md
31 | verified: false
32 |
--------------------------------------------------------------------------------
/api/core/tools/builtin_tool/providers/calculator/tools/add.yaml:
--------------------------------------------------------------------------------
1 | identity:
2 | name: add
3 | author: Dify
4 | label:
5 | en_US: Add
6 | zh_Hans: 加法
7 | description:
8 | human:
9 | en_US: Calculate the value of x + y
10 | zh_Hans: 计算 x + y 的值
11 | llm: A tool for calculating the value of two numbers
12 | parameters:
13 | - name: x
14 | type: number
15 | required: true
16 | label:
17 | en_US: x
18 | zh_Hans: x
19 | human_description:
20 | en_US: x
21 | zh_Hans: x
22 | llm_description: x
23 | form: llm
24 | - name: y
25 | type: number
26 | required: true
27 | label:
28 | en_US: y
29 | zh_Hans: y
30 | human_description:
31 | en_US: y
32 | zh_Hans: y
33 | llm_description: y
34 | form: llm
35 |
--------------------------------------------------------------------------------
/plugins/calculator/tools/add.yaml:
--------------------------------------------------------------------------------
1 | identity:
2 | name: add
3 | author: aneasystone
4 | label:
5 | en_US: Add
6 | zh_Hans: 加法
7 | description:
8 | human:
9 | en_US: Calculate the value of x + y
10 | zh_Hans: 计算 x + y 的值
11 | llm: A tool for calculating the value of two numbers
12 | parameters:
13 | - name: x
14 | type: number
15 | required: true
16 | label:
17 | en_US: x
18 | zh_Hans: x
19 | human_description:
20 | en_US: x
21 | zh_Hans: x
22 | llm_description: x
23 | form: llm
24 | - name: y
25 | type: number
26 | required: true
27 | label:
28 | en_US: y
29 | zh_Hans: y
30 | human_description:
31 | en_US: y
32 | zh_Hans: y
33 | llm_description: y
34 | form: llm
35 | extra:
36 | python:
37 | source: tools/add.py
38 |
--------------------------------------------------------------------------------
/plugins/demo.public.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PUBLIC KEY-----
2 | MIICCgKCAgEAvZw32uVbXyNWkaw/5YbIoK+YqHfZWK65SXf5Mm2w08O7/XCysej1
3 | UYi2pdi8ULtgiIuj4+rGcZuPPX23viW/QKo+inIw+02sWKAwA7si71TWTjJZnHg5
4 | wc6K9s3hiqK2oCve/vshraJnsDspZaGbry+aqbXs71hGSWM8JBbq4XY9dnItqAUN
5 | zmLRV3IDe4ZaeKwIFT3+jS7kYoEz5T8WWBi67ulj+pQ6vMUwJza5E0KZIQdZy7al
6 | sswWVBYvnwR0LZwZHDRIbqFW2uJDTGXHoh/NB6d7xO6kTb2jfAf4NwTtGiFJLBRF
7 | G6WBI3tAZTTnNY6bETZ3UBEaWHWAP/9a5BbY/qCDHOyg9EpTZ5E6vw7a5SCD9Tej
8 | GwoH7Qmt9xCetIeQZ/IerVnMP1CV45elLab383jtm8b8BqNZmfD5tMhWULkpti2X
9 | JY5Tg728ua5CeD3Rq7KCUXJgo7I0SjPxMm+yFA/EXBqtljEzF+D06uk6gLLasGdq
10 | 5ijpx9CndgXGfTbkW2So8M7wnZuD+oDEawK9qLYCrUHvglrsmBxYPOtcRVJY1SZ7
11 | k3U756XXLLRvMIQcPsDi/T5W5aTZ38H0IJRAoMt3RHj/XdT/CfgmMHz+LJbcLELf
12 | Y2YresPGD5pSl147YAk9Jebd8OdVROOItPANEglHfq9RQKzF2wDuXrECAwEAAQ==
13 | -----END RSA PUBLIC KEY-----
14 |
--------------------------------------------------------------------------------
/plugins/mockgpt/models/llm/llm.yaml:
--------------------------------------------------------------------------------
1 | model: mock-gpt-v1
2 | label:
3 | zh_Hans: 模拟大模型 v1
4 | en_US: Mock GPT v1
5 | model_type: llm
6 | features:
7 | - multi-tool-call
8 | - agent-thought
9 | - stream-tool-call
10 | model_properties:
11 | mode: chat
12 | context_size: 16385
13 | parameter_rules:
14 | - name: temperature
15 | use_template: temperature
16 | - name: top_p
17 | use_template: top_p
18 | - name: presence_penalty
19 | use_template: presence_penalty
20 | - name: frequency_penalty
21 | use_template: frequency_penalty
22 | - name: max_tokens
23 | use_template: max_tokens
24 | default: 512
25 | min: 1
26 | max: 16385
27 | - name: response_format
28 | use_template: response_format
29 | pricing:
30 | input: '0.003'
31 | output: '0.004'
32 | unit: '0.001'
33 | currency: USD
34 |
--------------------------------------------------------------------------------
/api/core/tools/builtin_tool/providers/calculator/tools/add.py:
--------------------------------------------------------------------------------
1 | from collections.abc import Generator
2 | from typing import Any, Optional
3 |
4 | from core.helper.code_executor.code_executor import CodeExecutor, CodeLanguage
5 | from core.tools.builtin_tool.tool import BuiltinTool
6 | from core.tools.entities.tool_entities import ToolInvokeMessage
7 | from core.tools.errors import ToolInvokeError
8 |
9 |
10 | class Add(BuiltinTool):
11 | def _invoke(
12 | self,
13 | user_id: str,
14 | tool_parameters: dict[str, Any],
15 | conversation_id: Optional[str] = None,
16 | app_id: Optional[str] = None,
17 | message_id: Optional[str] = None,
18 | ) -> Generator[ToolInvokeMessage, None, None]:
19 | """
20 | 加法运算
21 | """
22 |
23 | x = tool_parameters.get("x", 0)
24 | y = tool_parameters.get("y", 0)
25 |
26 | result = str(x + y)
27 | yield self.create_text_message(result)
28 |
--------------------------------------------------------------------------------
/plugins/mockgpt/provider/demo.py:
--------------------------------------------------------------------------------
1 | import logging
2 | from collections.abc import Mapping
3 |
4 | from dify_plugin import ModelProvider
5 | from dify_plugin.entities.model import ModelType
6 | from dify_plugin.errors.model import CredentialsValidateFailedError
7 |
8 | logger = logging.getLogger(__name__)
9 |
10 |
11 | class DemoModelProvider(ModelProvider):
12 | def validate_provider_credentials(self, credentials: Mapping) -> None:
13 | """
14 | Validate provider credentials
15 | if validate failed, raise exception
16 |
17 | :param credentials: provider credentials, credentials form defined in `provider_credential_schema`.
18 | """
19 | try:
20 | pass
21 | except CredentialsValidateFailedError as ex:
22 | raise ex
23 | except Exception as ex:
24 | logger.exception(
25 | f"{self.get_provider_schema().provider} credentials validate failed"
26 | )
27 | raise ex
28 |
--------------------------------------------------------------------------------
/api/core/external_data_tool/weather_search/schema.json:
--------------------------------------------------------------------------------
1 | {
2 | "label": {
3 | "en-US": "Weather Search",
4 | "zh-Hans": "天气查询"
5 | },
6 | "form_schema": [
7 | {
8 | "type": "select",
9 | "label": {
10 | "en-US": "Temperature Unit",
11 | "zh-Hans": "温度单位"
12 | },
13 | "variable": "temperature_unit",
14 | "required": true,
15 | "options": [
16 | {
17 | "label": {
18 | "en-US": "Fahrenheit",
19 | "zh-Hans": "华氏度"
20 | },
21 | "value": "fahrenheit"
22 | },
23 | {
24 | "label": {
25 | "en-US": "Centigrade",
26 | "zh-Hans": "摄氏度"
27 | },
28 | "value": "centigrade"
29 | }
30 | ],
31 | "default": "centigrade",
32 | "placeholder": "Please select temperature unit"
33 | }
34 | ]
35 | }
--------------------------------------------------------------------------------
/api/core/tools/builtin_tool/providers/calculator/_assets/icon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/api/core/external_data_tool/weather_search/weather_search.py:
--------------------------------------------------------------------------------
1 | from typing import Optional
2 |
3 | from core.external_data_tool.base import ExternalDataTool
4 |
5 |
6 | class WeatherSearch(ExternalDataTool):
7 | """
8 | The name of custom type must be unique, keep the same with directory and file name.
9 | """
10 | name: str = "weather_search"
11 |
12 | @classmethod
13 | def validate_config(cls, tenant_id: str, config: dict) -> None:
14 | """
15 | schema.json validation. It will be called when user save the config.
16 |
17 | Example:
18 | .. code-block:: python
19 | config = {
20 | "temperature_unit": "centigrade"
21 | }
22 |
23 | :param tenant_id: the id of workspace
24 | :param config: the variables of form config
25 | :return:
26 | """
27 |
28 | if not config.get('temperature_unit'):
29 | raise ValueError('temperature unit is required')
30 |
31 | def query(self, inputs: dict, query: Optional[str] = None) -> str:
32 | """
33 | Query the external data tool.
34 |
35 | :param inputs: user inputs
36 | :param query: the query of chat app
37 | :return: the tool query result
38 | """
39 | city = inputs.get('city')
40 | temperature_unit = self.config.get('temperature_unit')
41 |
42 | if temperature_unit == 'fahrenheit':
43 | return f'Weather in {city} is 32°F'
44 | else:
45 | return f'Weather in {city} is 0°C'
--------------------------------------------------------------------------------
/plugins/mockgpt/provider/demo.yaml:
--------------------------------------------------------------------------------
1 | provider: demo
2 | label:
3 | en_US: "Demo"
4 | description:
5 | en_US: "Models provided by demo."
6 | zh_Hans: "Demo 提供的模型。"
7 | icon_small:
8 | en_US: "icon.svg" # 保证 _assets 目录下存在
9 | icon_large:
10 | en_US: "icon.svg" # 保证 _assets 目录下存在
11 | background: "#E5E7EB"
12 | help:
13 | title:
14 | en_US: "Get your API Key from demo"
15 | zh_Hans: "从 Demo 获取 API Key"
16 | url:
17 | en_US: "https://__put_your_url_here__/account/api-keys"
18 | supported_model_types:
19 | - llm
20 | configurate_methods:
21 | - predefined-model
22 | - customizable-model
23 | model_credential_schema:
24 | model:
25 | label:
26 | en_US: Model Name
27 | zh_Hans: 模型名称
28 | placeholder:
29 | en_US: Enter your model name
30 | zh_Hans: 输入模型名称
31 | credential_form_schemas:
32 | - variable: openai_api_key
33 | label:
34 | en_US: API Key
35 | type: secret-input
36 | required: true
37 | placeholder:
38 | zh_Hans: 在此输入您的 API Key
39 | en_US: Enter your API Key
40 | provider_credential_schema:
41 | credential_form_schemas:
42 | - variable: openai_api_key
43 | label:
44 | en_US: API Key
45 | type: secret-input
46 | required: true
47 | placeholder:
48 | zh_Hans: 在此输入您的 API Key
49 | en_US: Enter your API Key
50 | models:
51 | llm:
52 | predefined:
53 | - "models/llm/*.yaml"
54 | extra:
55 | python:
56 | provider_source: provider/demo.py # 修改
57 | model_sources:
58 | - "models/llm/llm.py"
59 |
--------------------------------------------------------------------------------
/api/core/moderation/cloud_service/schema.json:
--------------------------------------------------------------------------------
1 | {
2 | "label": {
3 | "en-US": "Cloud Service",
4 | "zh-Hans": "云服务"
5 | },
6 | "form_schema": [
7 | {
8 | "type": "select",
9 | "label": {
10 | "en-US": "Cloud Provider",
11 | "zh-Hans": "云厂商"
12 | },
13 | "variable": "cloud_provider",
14 | "required": true,
15 | "options": [
16 | {
17 | "label": {
18 | "en-US": "AWS",
19 | "zh-Hans": "亚马逊"
20 | },
21 | "value": "AWS"
22 | },
23 | {
24 | "label": {
25 | "en-US": "Google Cloud",
26 | "zh-Hans": "谷歌云"
27 | },
28 | "value": "GoogleCloud"
29 | },
30 | {
31 | "label": {
32 | "en-US": "Azure Cloud",
33 | "zh-Hans": "微软云"
34 | },
35 | "value": "Azure"
36 | }
37 | ],
38 | "default": "GoogleCloud",
39 | "placeholder": ""
40 | },
41 | {
42 | "type": "text-input",
43 | "label": {
44 | "en-US": "API Endpoint",
45 | "zh-Hans": "API Endpoint"
46 | },
47 | "variable": "api_endpoint",
48 | "required": true,
49 | "max_length": 100,
50 | "default": "",
51 | "placeholder": "https://api.example.com"
52 | },
53 | {
54 | "type": "paragraph",
55 | "label": {
56 | "en-US": "API Key",
57 | "zh-Hans": "API Key"
58 | },
59 | "variable": "api_keys",
60 | "required": true,
61 | "default": "",
62 | "placeholder": "Paste your API key here"
63 | }
64 | ]
65 | }
--------------------------------------------------------------------------------
/plugins/calculator/provider/calculator.py:
--------------------------------------------------------------------------------
1 | from typing import Any
2 |
3 | from dify_plugin import ToolProvider
4 | from dify_plugin.errors.tool import ToolProviderCredentialValidationError
5 |
6 |
7 | class CalculatorProvider(ToolProvider):
8 |
9 | def _validate_credentials(self, credentials: dict[str, Any]) -> None:
10 | try:
11 | """
12 | IMPLEMENT YOUR VALIDATION HERE
13 | """
14 | except Exception as e:
15 | raise ToolProviderCredentialValidationError(str(e))
16 |
17 | #########################################################################################
18 | # If OAuth is supported, uncomment the following functions.
19 | # Warning: please make sure that the sdk version is 0.4.2 or higher.
20 | #########################################################################################
21 | # def _oauth_get_authorization_url(self, redirect_uri: str, system_credentials: Mapping[str, Any]) -> str:
22 | # """
23 | # Generate the authorization URL for calculator OAuth.
24 | # """
25 | # try:
26 | # """
27 | # IMPLEMENT YOUR AUTHORIZATION URL GENERATION HERE
28 | # """
29 | # except Exception as e:
30 | # raise ToolProviderOAuthError(str(e))
31 | # return ""
32 |
33 | # def _oauth_get_credentials(
34 | # self, redirect_uri: str, system_credentials: Mapping[str, Any], request: Request
35 | # ) -> Mapping[str, Any]:
36 | # """
37 | # Exchange code for access_token.
38 | # """
39 | # try:
40 | # """
41 | # IMPLEMENT YOUR CREDENTIALS EXCHANGE HERE
42 | # """
43 | # except Exception as e:
44 | # raise ToolProviderOAuthError(str(e))
45 | # return dict()
46 |
47 | # def _oauth_refresh_credentials(
48 | # self, redirect_uri: str, system_credentials: Mapping[str, Any], credentials: Mapping[str, Any]
49 | # ) -> OAuthCredentials:
50 | # """
51 | # Refresh the credentials
52 | # """
53 | # return OAuthCredentials(credentials=credentials, expires_at=-1)
54 |
--------------------------------------------------------------------------------
/plugins/calculator/_assets/icon.svg:
--------------------------------------------------------------------------------
1 |
19 |
56 |
--------------------------------------------------------------------------------
/plugins/calculator/_assets/icon-dark.svg:
--------------------------------------------------------------------------------
1 |
19 |
56 |
--------------------------------------------------------------------------------
/plugins/demo.private.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | 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
51 | -----END RSA PRIVATE KEY-----
52 |
--------------------------------------------------------------------------------
/api/core/moderation/cloud_service/cloud_service.py:
--------------------------------------------------------------------------------
1 | from core.moderation.base import Moderation, ModerationAction, ModerationInputsResult, ModerationOutputsResult
2 |
3 | class CloudServiceModeration(Moderation):
4 | """
5 | The name of custom type must be unique, keep the same with directory and file name.
6 | """
7 | name: str = "cloud_service"
8 |
9 | @classmethod
10 | def validate_config(cls, tenant_id: str, config: dict) -> None:
11 | """
12 | schema.json validation. It will be called when user save the config.
13 |
14 | Example:
15 | .. code-block:: python
16 | config = {
17 | "cloud_provider": "GoogleCloud",
18 | "api_endpoint": "https://api.example.com",
19 | "api_keys": "123456",
20 | "inputs_config": {
21 | "enabled": True,
22 | "preset_response": "Your content violates our usage policy. Please revise and try again."
23 | },
24 | "outputs_config": {
25 | "enabled": True,
26 | "preset_response": "Your content violates our usage policy. Please revise and try again."
27 | }
28 | }
29 |
30 | :param tenant_id: the id of workspace
31 | :param config: the variables of form config
32 | :return:
33 | """
34 |
35 | cls._validate_inputs_and_outputs_config(config, True)
36 |
37 | if not config.get("cloud_provider"):
38 | raise ValueError("cloud_provider is required")
39 |
40 | if not config.get("api_endpoint"):
41 | raise ValueError("api_endpoint is required")
42 |
43 | if not config.get("api_keys"):
44 | raise ValueError("api_keys is required")
45 |
46 | def moderation_for_inputs(self, inputs: dict, query: str = "") -> ModerationInputsResult:
47 | """
48 | Moderation for inputs.
49 |
50 | :param inputs: user inputs
51 | :param query: the query of chat app, there is empty if is completion app
52 | :return: the moderation result
53 | """
54 | flagged = False
55 | preset_response = ""
56 |
57 | if self.config['inputs_config']['enabled']:
58 | preset_response = self.config['inputs_config']['preset_response']
59 |
60 | if query:
61 | inputs['query__'] = query
62 | flagged = self._is_violated(inputs)
63 |
64 | # return ModerationInputsResult(flagged=flagged, action=ModerationAction.overridden, inputs=inputs, query=query)
65 | return ModerationInputsResult(flagged=flagged, action=ModerationAction.DIRECT_OUTPUT, preset_response=preset_response)
66 |
67 | def moderation_for_outputs(self, text: str) -> ModerationOutputsResult:
68 | """
69 | Moderation for outputs.
70 |
71 | :param text: the text of LLM response
72 | :return: the moderation result
73 | """
74 | flagged = False
75 | preset_response = ""
76 |
77 | if self.config['outputs_config']['enabled']:
78 | preset_response = self.config['outputs_config']['preset_response']
79 |
80 | flagged = self._is_violated({'text': text})
81 |
82 | # return ModerationOutputsResult(flagged=flagged, action=ModerationAction.overridden, text=text)
83 | return ModerationOutputsResult(flagged=flagged, action=ModerationAction.DIRECT_OUTPUT, preset_response=preset_response)
84 |
85 | def _is_violated(self, inputs: dict):
86 | """
87 | The main logic of moderation.
88 |
89 | :param inputs:
90 | :return: the moderation result
91 | """
92 | return False
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | share/python-wheels/
24 | *.egg-info/
25 | .installed.cfg
26 | *.egg
27 | MANIFEST
28 |
29 | # PyInstaller
30 | # Usually these files are written by a python script from a template
31 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
32 | *.manifest
33 | *.spec
34 |
35 | # Installer logs
36 | pip-log.txt
37 | pip-delete-this-directory.txt
38 |
39 | # Unit test / coverage reports
40 | htmlcov/
41 | .tox/
42 | .nox/
43 | .coverage
44 | .coverage.*
45 | .cache
46 | nosetests.xml
47 | coverage.xml
48 | *.cover
49 | *.py,cover
50 | .hypothesis/
51 | .pytest_cache/
52 | cover/
53 |
54 | # Translations
55 | *.mo
56 | *.pot
57 |
58 | # Django stuff:
59 | *.log
60 | local_settings.py
61 | db.sqlite3
62 | db.sqlite3-journal
63 |
64 | # Flask stuff:
65 | instance/
66 | .webassets-cache
67 |
68 | # Scrapy stuff:
69 | .scrapy
70 |
71 | # Sphinx documentation
72 | docs/_build/
73 |
74 | # PyBuilder
75 | .pybuilder/
76 | target/
77 |
78 | # Jupyter Notebook
79 | .ipynb_checkpoints
80 |
81 | # IPython
82 | profile_default/
83 | ipython_config.py
84 |
85 | # pyenv
86 | # For a library or package, you might want to ignore these files since the code is
87 | # intended to run in multiple environments; otherwise, check them in:
88 | # .python-version
89 |
90 | # pipenv
91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
94 | # install all needed dependencies.
95 | #Pipfile.lock
96 |
97 | # UV
98 | # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
99 | # This is especially recommended for binary packages to ensure reproducibility, and is more
100 | # commonly ignored for libraries.
101 | #uv.lock
102 |
103 | # poetry
104 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
105 | # This is especially recommended for binary packages to ensure reproducibility, and is more
106 | # commonly ignored for libraries.
107 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
108 | #poetry.lock
109 |
110 | # pdm
111 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
112 | #pdm.lock
113 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
114 | # in version control.
115 | # https://pdm.fming.dev/latest/usage/project/#working-with-version-control
116 | .pdm.toml
117 | .pdm-python
118 | .pdm-build/
119 |
120 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
121 | __pypackages__/
122 |
123 | # Celery stuff
124 | celerybeat-schedule
125 | celerybeat.pid
126 |
127 | # SageMath parsed files
128 | *.sage.py
129 |
130 | # Environments
131 | .env
132 | .venv
133 | env/
134 | venv/
135 | ENV/
136 | env.bak/
137 | venv.bak/
138 |
139 | # Spyder project settings
140 | .spyderproject
141 | .spyproject
142 |
143 | # Rope project settings
144 | .ropeproject
145 |
146 | # mkdocs documentation
147 | /site
148 |
149 | # mypy
150 | .mypy_cache/
151 | .dmypy.json
152 | dmypy.json
153 |
154 | # Pyre type checker
155 | .pyre/
156 |
157 | # pytype static type analyzer
158 | .pytype/
159 |
160 | # Cython debug symbols
161 | cython_debug/
162 |
163 | # PyCharm
164 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
165 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
166 | # and can be added to the global gitignore or merged into this file. For a more nuclear
167 | # option (not recommended) you can uncomment the following to ignore the entire idea folder.
168 | .idea/
169 |
170 | # Vscode
171 | .vscode/
172 |
173 | # macOS
174 | .DS_Store
175 | .AppleDouble
176 | .LSOverride
--------------------------------------------------------------------------------
/plugins/calculator/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | share/python-wheels/
24 | *.egg-info/
25 | .installed.cfg
26 | *.egg
27 | MANIFEST
28 |
29 | # PyInstaller
30 | # Usually these files are written by a python script from a template
31 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
32 | *.manifest
33 | *.spec
34 |
35 | # Installer logs
36 | pip-log.txt
37 | pip-delete-this-directory.txt
38 |
39 | # Unit test / coverage reports
40 | htmlcov/
41 | .tox/
42 | .nox/
43 | .coverage
44 | .coverage.*
45 | .cache
46 | nosetests.xml
47 | coverage.xml
48 | *.cover
49 | *.py,cover
50 | .hypothesis/
51 | .pytest_cache/
52 | cover/
53 |
54 | # Translations
55 | *.mo
56 | *.pot
57 |
58 | # Django stuff:
59 | *.log
60 | local_settings.py
61 | db.sqlite3
62 | db.sqlite3-journal
63 |
64 | # Flask stuff:
65 | instance/
66 | .webassets-cache
67 |
68 | # Scrapy stuff:
69 | .scrapy
70 |
71 | # Sphinx documentation
72 | docs/_build/
73 |
74 | # PyBuilder
75 | .pybuilder/
76 | target/
77 |
78 | # Jupyter Notebook
79 | .ipynb_checkpoints
80 |
81 | # IPython
82 | profile_default/
83 | ipython_config.py
84 |
85 | # pyenv
86 | # For a library or package, you might want to ignore these files since the code is
87 | # intended to run in multiple environments; otherwise, check them in:
88 | # .python-version
89 |
90 | # pipenv
91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
94 | # install all needed dependencies.
95 | #Pipfile.lock
96 |
97 | # UV
98 | # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
99 | # This is especially recommended for binary packages to ensure reproducibility, and is more
100 | # commonly ignored for libraries.
101 | #uv.lock
102 |
103 | # poetry
104 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
105 | # This is especially recommended for binary packages to ensure reproducibility, and is more
106 | # commonly ignored for libraries.
107 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
108 | #poetry.lock
109 |
110 | # pdm
111 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
112 | #pdm.lock
113 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
114 | # in version control.
115 | # https://pdm.fming.dev/latest/usage/project/#working-with-version-control
116 | .pdm.toml
117 | .pdm-python
118 | .pdm-build/
119 |
120 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
121 | __pypackages__/
122 |
123 | # Celery stuff
124 | celerybeat-schedule
125 | celerybeat.pid
126 |
127 | # SageMath parsed files
128 | *.sage.py
129 |
130 | # Environments
131 | .env
132 | .venv
133 | env/
134 | venv/
135 | ENV/
136 | env.bak/
137 | venv.bak/
138 |
139 | # Spyder project settings
140 | .spyderproject
141 | .spyproject
142 |
143 | # Rope project settings
144 | .ropeproject
145 |
146 | # mkdocs documentation
147 | /site
148 |
149 | # mypy
150 | .mypy_cache/
151 | .dmypy.json
152 | dmypy.json
153 |
154 | # Pyre type checker
155 | .pyre/
156 |
157 | # pytype static type analyzer
158 | .pytype/
159 |
160 | # Cython debug symbols
161 | cython_debug/
162 |
163 | # PyCharm
164 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
165 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
166 | # and can be added to the global gitignore or merged into this file. For a more nuclear
167 | # option (not recommended) you can uncomment the following to ignore the entire idea folder.
168 | .idea/
169 |
170 | # Vscode
171 | .vscode/
172 |
173 | # macOS
174 | .DS_Store
175 | .AppleDouble
176 | .LSOverride
--------------------------------------------------------------------------------
/plugins/mockgpt/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | share/python-wheels/
24 | *.egg-info/
25 | .installed.cfg
26 | *.egg
27 | MANIFEST
28 |
29 | # PyInstaller
30 | # Usually these files are written by a python script from a template
31 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
32 | *.manifest
33 | *.spec
34 |
35 | # Installer logs
36 | pip-log.txt
37 | pip-delete-this-directory.txt
38 |
39 | # Unit test / coverage reports
40 | htmlcov/
41 | .tox/
42 | .nox/
43 | .coverage
44 | .coverage.*
45 | .cache
46 | nosetests.xml
47 | coverage.xml
48 | *.cover
49 | *.py,cover
50 | .hypothesis/
51 | .pytest_cache/
52 | cover/
53 |
54 | # Translations
55 | *.mo
56 | *.pot
57 |
58 | # Django stuff:
59 | *.log
60 | local_settings.py
61 | db.sqlite3
62 | db.sqlite3-journal
63 |
64 | # Flask stuff:
65 | instance/
66 | .webassets-cache
67 |
68 | # Scrapy stuff:
69 | .scrapy
70 |
71 | # Sphinx documentation
72 | docs/_build/
73 |
74 | # PyBuilder
75 | .pybuilder/
76 | target/
77 |
78 | # Jupyter Notebook
79 | .ipynb_checkpoints
80 |
81 | # IPython
82 | profile_default/
83 | ipython_config.py
84 |
85 | # pyenv
86 | # For a library or package, you might want to ignore these files since the code is
87 | # intended to run in multiple environments; otherwise, check them in:
88 | # .python-version
89 |
90 | # pipenv
91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
94 | # install all needed dependencies.
95 | #Pipfile.lock
96 |
97 | # UV
98 | # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
99 | # This is especially recommended for binary packages to ensure reproducibility, and is more
100 | # commonly ignored for libraries.
101 | #uv.lock
102 |
103 | # poetry
104 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
105 | # This is especially recommended for binary packages to ensure reproducibility, and is more
106 | # commonly ignored for libraries.
107 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
108 | #poetry.lock
109 |
110 | # pdm
111 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
112 | #pdm.lock
113 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
114 | # in version control.
115 | # https://pdm.fming.dev/latest/usage/project/#working-with-version-control
116 | .pdm.toml
117 | .pdm-python
118 | .pdm-build/
119 |
120 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
121 | __pypackages__/
122 |
123 | # Celery stuff
124 | celerybeat-schedule
125 | celerybeat.pid
126 |
127 | # SageMath parsed files
128 | *.sage.py
129 |
130 | # Environments
131 | .env
132 | .venv
133 | env/
134 | venv/
135 | ENV/
136 | env.bak/
137 | venv.bak/
138 |
139 | # Spyder project settings
140 | .spyderproject
141 | .spyproject
142 |
143 | # Rope project settings
144 | .ropeproject
145 |
146 | # mkdocs documentation
147 | /site
148 |
149 | # mypy
150 | .mypy_cache/
151 | .dmypy.json
152 | dmypy.json
153 |
154 | # Pyre type checker
155 | .pyre/
156 |
157 | # pytype static type analyzer
158 | .pytype/
159 |
160 | # Cython debug symbols
161 | cython_debug/
162 |
163 | # PyCharm
164 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
165 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
166 | # and can be added to the global gitignore or merged into this file. For a more nuclear
167 | # option (not recommended) you can uncomment the following to ignore the entire idea folder.
168 | .idea/
169 |
170 | # Vscode
171 | .vscode/
172 |
173 | # macOS
174 | .DS_Store
175 | .AppleDouble
176 | .LSOverride
--------------------------------------------------------------------------------
/plugins/calculator/GUIDE.md:
--------------------------------------------------------------------------------
1 | # Dify Plugin Development Guide
2 |
3 | Welcome to Dify plugin development! This guide will help you get started quickly.
4 |
5 | ## Plugin Types
6 |
7 | Dify plugins extend three main capabilities:
8 |
9 | | Type | Description | Example |
10 | |------|-------------|---------|
11 | | **Tool** | Perform specific tasks | Google Search, Stable Diffusion |
12 | | **Model** | AI model integrations | OpenAI, Anthropic |
13 | | **Endpoint** | HTTP services | Custom APIs, integrations |
14 |
15 | You can create:
16 | - **Tool**: Tool provider with optional endpoints (e.g., Discord bot)
17 | - **Model**: Model provider only
18 | - **Extension**: Simple HTTP service
19 |
20 | ## Setup
21 |
22 | ### Requirements
23 | - Python 3.11+
24 | - Dependencies: `pip install -r requirements.txt`
25 |
26 | ## Development Process
27 |
28 |
29 | 1. Manifest Structure
30 |
31 | Edit `manifest.yaml` to describe your plugin:
32 |
33 | ```yaml
34 | version: 0.1.0 # Required: Plugin version
35 | type: plugin # Required: plugin or bundle
36 | author: YourOrganization # Required: Organization name
37 | label: # Required: Multi-language names
38 | en_US: Plugin Name
39 | zh_Hans: 插件名称
40 | created_at: 2023-01-01T00:00:00Z # Required: Creation time (RFC3339)
41 | icon: assets/icon.png # Required: Icon path
42 |
43 | # Resources and permissions
44 | resource:
45 | memory: 268435456 # Max memory (bytes)
46 | permission:
47 | tool:
48 | enabled: true # Tool permission
49 | model:
50 | enabled: true # Model permission
51 | llm: true
52 | text_embedding: false
53 | # Other model types...
54 | # Other permissions...
55 |
56 | # Extensions definition
57 | plugins:
58 | tools:
59 | - tools/my_tool.yaml # Tool definition files
60 | models:
61 | - models/my_model.yaml # Model definition files
62 | endpoints:
63 | - endpoints/my_api.yaml # Endpoint definition files
64 |
65 | # Runtime metadata
66 | meta:
67 | version: 0.0.1 # Manifest format version
68 | arch:
69 | - amd64
70 | - arm64
71 | runner:
72 | language: python
73 | version: "3.12"
74 | entrypoint: main
75 | ```
76 |
77 | **Restrictions:**
78 | - Cannot extend both tools and models
79 | - Must have at least one extension
80 | - Cannot extend both models and endpoints
81 | - Limited to one supplier per extension type
82 |
83 |
84 |
85 | 2. Implementation Examples
86 |
87 | Study these examples to understand plugin implementation:
88 |
89 | - [OpenAI](https://github.com/langgenius/dify-plugin-sdks/tree/main/python/examples/openai) - Model provider
90 | - [Google Search](https://github.com/langgenius/dify-plugin-sdks/tree/main/python/examples/google) - Tool provider
91 | - [Neko](https://github.com/langgenius/dify-plugin-sdks/tree/main/python/examples/neko) - Endpoint group
92 |
93 |
94 |
95 | 3. Testing & Debugging
96 |
97 | 1. Copy `.env.example` to `.env` and configure:
98 | ```
99 | INSTALL_METHOD=remote
100 | REMOTE_INSTALL_URL=debug.dify.ai:5003
101 | REMOTE_INSTALL_KEY=your-debug-key
102 | ```
103 |
104 | 2. Run your plugin:
105 | ```bash
106 | python -m main
107 | ```
108 |
109 | 3. Refresh your Dify instance to see the plugin (marked as "debugging")
110 |
111 |
112 |
113 | 4. Publishing
114 |
115 | #### Manual Packaging
116 | ```bash
117 | dify-plugin plugin package ./YOUR_PLUGIN_DIR
118 | ```
119 |
120 | #### Automated GitHub Workflow
121 |
122 | Configure GitHub Actions to automate PR creation:
123 |
124 | 1. Create a Personal Access Token for your forked repository
125 | 2. Add it as `PLUGIN_ACTION` secret in your source repo
126 | 3. Create `.github/workflows/plugin-publish.yml`
127 |
128 | When you create a release, the action will:
129 | - Package your plugin
130 | - Create a PR to your fork
131 |
132 | [Detailed workflow documentation](https://docs.dify.ai/plugins/publish-plugins/plugin-auto-publish-pr)
133 |
134 |
135 | ## Privacy Policy
136 |
137 | If publishing to the Marketplace, provide a privacy policy in [PRIVACY.md](PRIVACY.md).
--------------------------------------------------------------------------------
/plugins/mockgpt/GUIDE.md:
--------------------------------------------------------------------------------
1 | # Dify Plugin Development Guide
2 |
3 | Welcome to Dify plugin development! This guide will help you get started quickly.
4 |
5 | ## Plugin Types
6 |
7 | Dify plugins extend three main capabilities:
8 |
9 | | Type | Description | Example |
10 | |------|-------------|---------|
11 | | **Tool** | Perform specific tasks | Google Search, Stable Diffusion |
12 | | **Model** | AI model integrations | OpenAI, Anthropic |
13 | | **Endpoint** | HTTP services | Custom APIs, integrations |
14 |
15 | You can create:
16 | - **Tool**: Tool provider with optional endpoints (e.g., Discord bot)
17 | - **Model**: Model provider only
18 | - **Extension**: Simple HTTP service
19 |
20 | ## Setup
21 |
22 | ### Requirements
23 | - Python 3.11+
24 | - Dependencies: `pip install -r requirements.txt`
25 |
26 | ## Development Process
27 |
28 |
29 | 1. Manifest Structure
30 |
31 | Edit `manifest.yaml` to describe your plugin:
32 |
33 | ```yaml
34 | version: 0.1.0 # Required: Plugin version
35 | type: plugin # Required: plugin or bundle
36 | author: YourOrganization # Required: Organization name
37 | label: # Required: Multi-language names
38 | en_US: Plugin Name
39 | zh_Hans: 插件名称
40 | created_at: 2023-01-01T00:00:00Z # Required: Creation time (RFC3339)
41 | icon: assets/icon.png # Required: Icon path
42 |
43 | # Resources and permissions
44 | resource:
45 | memory: 268435456 # Max memory (bytes)
46 | permission:
47 | tool:
48 | enabled: true # Tool permission
49 | model:
50 | enabled: true # Model permission
51 | llm: true
52 | text_embedding: false
53 | # Other model types...
54 | # Other permissions...
55 |
56 | # Extensions definition
57 | plugins:
58 | tools:
59 | - tools/my_tool.yaml # Tool definition files
60 | models:
61 | - models/my_model.yaml # Model definition files
62 | endpoints:
63 | - endpoints/my_api.yaml # Endpoint definition files
64 |
65 | # Runtime metadata
66 | meta:
67 | version: 0.0.1 # Manifest format version
68 | arch:
69 | - amd64
70 | - arm64
71 | runner:
72 | language: python
73 | version: "3.12"
74 | entrypoint: main
75 | ```
76 |
77 | **Restrictions:**
78 | - Cannot extend both tools and models
79 | - Must have at least one extension
80 | - Cannot extend both models and endpoints
81 | - Limited to one supplier per extension type
82 |
83 |
84 |
85 | 2. Implementation Examples
86 |
87 | Study these examples to understand plugin implementation:
88 |
89 | - [OpenAI](https://github.com/langgenius/dify-plugin-sdks/tree/main/python/examples/openai) - Model provider
90 | - [Google Search](https://github.com/langgenius/dify-plugin-sdks/tree/main/python/examples/google) - Tool provider
91 | - [Neko](https://github.com/langgenius/dify-plugin-sdks/tree/main/python/examples/neko) - Endpoint group
92 |
93 |
94 |
95 | 3. Testing & Debugging
96 |
97 | 1. Copy `.env.example` to `.env` and configure:
98 | ```
99 | INSTALL_METHOD=remote
100 | REMOTE_INSTALL_URL=debug.dify.ai:5003
101 | REMOTE_INSTALL_KEY=your-debug-key
102 | ```
103 |
104 | 2. Run your plugin:
105 | ```bash
106 | python -m main
107 | ```
108 |
109 | 3. Refresh your Dify instance to see the plugin (marked as "debugging")
110 |
111 |
112 |
113 | 4. Publishing
114 |
115 | #### Manual Packaging
116 | ```bash
117 | dify-plugin plugin package ./YOUR_PLUGIN_DIR
118 | ```
119 |
120 | #### Automated GitHub Workflow
121 |
122 | Configure GitHub Actions to automate PR creation:
123 |
124 | 1. Create a Personal Access Token for your forked repository
125 | 2. Add it as `PLUGIN_ACTION` secret in your source repo
126 | 3. Create `.github/workflows/plugin-publish.yml`
127 |
128 | When you create a release, the action will:
129 | - Package your plugin
130 | - Create a PR to your fork
131 |
132 | [Detailed workflow documentation](https://docs.dify.ai/plugins/publish-plugins/plugin-auto-publish-pr)
133 |
134 |
135 | ## Privacy Policy
136 |
137 | If publishing to the Marketplace, provide a privacy policy in [PRIVACY.md](PRIVACY.md).
--------------------------------------------------------------------------------
/plugins/mockgpt/_assets/icon.svg:
--------------------------------------------------------------------------------
1 |
19 |
56 |
--------------------------------------------------------------------------------
/plugins/mockgpt/_assets/icon-dark.svg:
--------------------------------------------------------------------------------
1 |
19 |
56 |
--------------------------------------------------------------------------------
/plugins/mockgpt/.difyignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # Distribution / packaging
7 | .Python
8 | build/
9 | develop-eggs/
10 | dist/
11 | downloads/
12 | eggs/
13 | .eggs/
14 | lib/
15 | lib64/
16 | parts/
17 | sdist/
18 | var/
19 | wheels/
20 | share/python-wheels/
21 | *.egg-info/
22 | .installed.cfg
23 | *.egg
24 | MANIFEST
25 |
26 | # PyInstaller
27 | # Usually these files are written by a python script from a template
28 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
29 | *.manifest
30 | *.spec
31 |
32 | # Installer logs
33 | pip-log.txt
34 | pip-delete-this-directory.txt
35 |
36 | # Unit test / coverage reports
37 | htmlcov/
38 | .tox/
39 | .nox/
40 | .coverage
41 | .coverage.*
42 | .cache
43 | nosetests.xml
44 | coverage.xml
45 | *.cover
46 | *.py,cover
47 | .hypothesis/
48 | .pytest_cache/
49 | cover/
50 |
51 | # Translations
52 | *.mo
53 | *.pot
54 |
55 | # Django stuff:
56 | *.log
57 | local_settings.py
58 | db.sqlite3
59 | db.sqlite3-journal
60 |
61 | # Flask stuff:
62 | instance/
63 | .webassets-cache
64 |
65 | # Scrapy stuff:
66 | .scrapy
67 |
68 | # Sphinx documentation
69 | docs/_build/
70 |
71 | # PyBuilder
72 | .pybuilder/
73 | target/
74 |
75 | # Jupyter Notebook
76 | .ipynb_checkpoints
77 |
78 | # IPython
79 | profile_default/
80 | ipython_config.py
81 |
82 | # pyenv
83 | # For a library or package, you might want to ignore these files since the code is
84 | # intended to run in multiple environments; otherwise, check them in:
85 | .python-version
86 |
87 | # pipenv
88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
91 | # install all needed dependencies.
92 | Pipfile.lock
93 |
94 | # UV
95 | # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
96 | # This is especially recommended for binary packages to ensure reproducibility, and is more
97 | # commonly ignored for libraries.
98 | uv.lock
99 |
100 | # poetry
101 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
102 | # This is especially recommended for binary packages to ensure reproducibility, and is more
103 | # commonly ignored for libraries.
104 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
105 | poetry.lock
106 |
107 | # pdm
108 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
109 | #pdm.lock
110 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
111 | # in version control.
112 | # https://pdm.fming.dev/latest/usage/project/#working-with-version-control
113 | .pdm.toml
114 | .pdm-python
115 | .pdm-build/
116 |
117 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
118 | __pypackages__/
119 |
120 | # Celery stuff
121 | celerybeat-schedule
122 | celerybeat.pid
123 |
124 | # SageMath parsed files
125 | *.sage.py
126 |
127 | # Environments
128 | .env
129 | .venv
130 | env/
131 | venv/
132 | ENV/
133 | env.bak/
134 | venv.bak/
135 |
136 | # Spyder project settings
137 | .spyderproject
138 | .spyproject
139 |
140 | # Rope project settings
141 | .ropeproject
142 |
143 | # mkdocs documentation
144 | /site
145 |
146 | # mypy
147 | .mypy_cache/
148 | .dmypy.json
149 | dmypy.json
150 |
151 | # Pyre type checker
152 | .pyre/
153 |
154 | # pytype static type analyzer
155 | .pytype/
156 |
157 | # Cython debug symbols
158 | cython_debug/
159 |
160 | # PyCharm
161 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
162 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
163 | # and can be added to the global gitignore or merged into this file. For a more nuclear
164 | # option (not recommended) you can uncomment the following to ignore the entire idea folder.
165 | .idea/
166 |
167 | # Vscode
168 | .vscode/
169 |
170 | # Git
171 | .git/
172 | .gitignore
173 | .github/
174 |
175 | # Mac
176 | .DS_Store
177 |
178 | # Windows
179 | Thumbs.db
180 |
181 | # Dify plugin packages
182 | # To prevent packaging repetitively
183 | *.difypkg
184 |
185 |
--------------------------------------------------------------------------------
/plugins/calculator/.difyignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # Distribution / packaging
7 | .Python
8 | build/
9 | develop-eggs/
10 | dist/
11 | downloads/
12 | eggs/
13 | .eggs/
14 | lib/
15 | lib64/
16 | parts/
17 | sdist/
18 | var/
19 | wheels/
20 | share/python-wheels/
21 | *.egg-info/
22 | .installed.cfg
23 | *.egg
24 | MANIFEST
25 |
26 | # PyInstaller
27 | # Usually these files are written by a python script from a template
28 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
29 | *.manifest
30 | *.spec
31 |
32 | # Installer logs
33 | pip-log.txt
34 | pip-delete-this-directory.txt
35 |
36 | # Unit test / coverage reports
37 | htmlcov/
38 | .tox/
39 | .nox/
40 | .coverage
41 | .coverage.*
42 | .cache
43 | nosetests.xml
44 | coverage.xml
45 | *.cover
46 | *.py,cover
47 | .hypothesis/
48 | .pytest_cache/
49 | cover/
50 |
51 | # Translations
52 | *.mo
53 | *.pot
54 |
55 | # Django stuff:
56 | *.log
57 | local_settings.py
58 | db.sqlite3
59 | db.sqlite3-journal
60 |
61 | # Flask stuff:
62 | instance/
63 | .webassets-cache
64 |
65 | # Scrapy stuff:
66 | .scrapy
67 |
68 | # Sphinx documentation
69 | docs/_build/
70 |
71 | # PyBuilder
72 | .pybuilder/
73 | target/
74 |
75 | # Jupyter Notebook
76 | .ipynb_checkpoints
77 |
78 | # IPython
79 | profile_default/
80 | ipython_config.py
81 |
82 | # pyenv
83 | # For a library or package, you might want to ignore these files since the code is
84 | # intended to run in multiple environments; otherwise, check them in:
85 | .python-version
86 |
87 | # pipenv
88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
91 | # install all needed dependencies.
92 | Pipfile.lock
93 |
94 | # UV
95 | # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
96 | # This is especially recommended for binary packages to ensure reproducibility, and is more
97 | # commonly ignored for libraries.
98 | uv.lock
99 |
100 | # poetry
101 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
102 | # This is especially recommended for binary packages to ensure reproducibility, and is more
103 | # commonly ignored for libraries.
104 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
105 | poetry.lock
106 |
107 | # pdm
108 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
109 | #pdm.lock
110 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
111 | # in version control.
112 | # https://pdm.fming.dev/latest/usage/project/#working-with-version-control
113 | .pdm.toml
114 | .pdm-python
115 | .pdm-build/
116 |
117 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
118 | __pypackages__/
119 |
120 | # Celery stuff
121 | celerybeat-schedule
122 | celerybeat.pid
123 |
124 | # SageMath parsed files
125 | *.sage.py
126 |
127 | # Environments
128 | .env
129 | .venv
130 | env/
131 | venv/
132 | ENV/
133 | env.bak/
134 | venv.bak/
135 |
136 | # Spyder project settings
137 | .spyderproject
138 | .spyproject
139 |
140 | # Rope project settings
141 | .ropeproject
142 |
143 | # mkdocs documentation
144 | /site
145 |
146 | # mypy
147 | .mypy_cache/
148 | .dmypy.json
149 | dmypy.json
150 |
151 | # Pyre type checker
152 | .pyre/
153 |
154 | # pytype static type analyzer
155 | .pytype/
156 |
157 | # Cython debug symbols
158 | cython_debug/
159 |
160 | # PyCharm
161 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
162 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
163 | # and can be added to the global gitignore or merged into this file. For a more nuclear
164 | # option (not recommended) you can uncomment the following to ignore the entire idea folder.
165 | .idea/
166 |
167 | # Vscode
168 | .vscode/
169 |
170 | # Git
171 | .git/
172 | .gitignore
173 | .github/
174 |
175 | # Mac
176 | .DS_Store
177 |
178 | # Windows
179 | Thumbs.db
180 |
181 | # Dify plugin packages
182 | # To prevent packaging repetitively
183 | *.difypkg
184 |
185 |
--------------------------------------------------------------------------------
/plugins/calculator/.github/workflows/plugin-publish.yml:
--------------------------------------------------------------------------------
1 | name: Plugin Publish Workflow
2 |
3 | on:
4 | release:
5 | types: [published]
6 |
7 | jobs:
8 | publish:
9 | runs-on: ubuntu-latest
10 | steps:
11 | - name: Checkout code
12 | uses: actions/checkout@v3
13 |
14 | - name: Download CLI tool
15 | run: |
16 | mkdir -p $RUNNER_TEMP/bin
17 | cd $RUNNER_TEMP/bin
18 |
19 | wget https://github.com/langgenius/dify-plugin-daemon/releases/download/0.0.6/dify-plugin-linux-amd64
20 | chmod +x dify-plugin-linux-amd64
21 |
22 | echo "CLI tool location:"
23 | pwd
24 | ls -la dify-plugin-linux-amd64
25 |
26 | - name: Get basic info from manifest
27 | id: get_basic_info
28 | run: |
29 | PLUGIN_NAME=$(grep "^name:" manifest.yaml | cut -d' ' -f2)
30 | echo "Plugin name: $PLUGIN_NAME"
31 | echo "plugin_name=$PLUGIN_NAME" >> $GITHUB_OUTPUT
32 |
33 | VERSION=$(grep "^version:" manifest.yaml | cut -d' ' -f2)
34 | echo "Plugin version: $VERSION"
35 | echo "version=$VERSION" >> $GITHUB_OUTPUT
36 |
37 | # If the author's name is not your github username, you can change the author here
38 | AUTHOR=$(grep "^author:" manifest.yaml | cut -d' ' -f2)
39 | echo "Plugin author: $AUTHOR"
40 | echo "author=$AUTHOR" >> $GITHUB_OUTPUT
41 |
42 | - name: Package Plugin
43 | id: package
44 | run: |
45 | cd $GITHUB_WORKSPACE
46 | PACKAGE_NAME="${{ steps.get_basic_info.outputs.plugin_name }}-${{ steps.get_basic_info.outputs.version }}.difypkg"
47 | $RUNNER_TEMP/bin/dify-plugin-linux-amd64 plugin package . -o "$PACKAGE_NAME"
48 |
49 | echo "Package result:"
50 | ls -la "$PACKAGE_NAME"
51 | echo "package_name=$PACKAGE_NAME" >> $GITHUB_OUTPUT
52 |
53 | echo "\nFull file path:"
54 | pwd
55 | echo "\nDirectory structure:"
56 | tree || ls -R
57 |
58 | - name: Checkout target repo
59 | uses: actions/checkout@v3
60 | with:
61 | repository: ${{steps.get_basic_info.outputs.author}}/dify-plugins
62 | path: dify-plugins
63 | token: ${{ secrets.PLUGIN_ACTION }}
64 | fetch-depth: 1
65 | persist-credentials: true
66 |
67 | - name: Prepare and create PR
68 | run: |
69 | PACKAGE_NAME="${{ steps.get_basic_info.outputs.plugin_name }}-${{ steps.get_basic_info.outputs.version }}.difypkg"
70 | mkdir -p dify-plugins/${{ steps.get_basic_info.outputs.author }}/${{ steps.get_basic_info.outputs.plugin_name }}
71 | mv "$PACKAGE_NAME" dify-plugins/${{ steps.get_basic_info.outputs.author }}/${{ steps.get_basic_info.outputs.plugin_name }}/
72 |
73 | cd dify-plugins
74 |
75 | git config user.name "GitHub Actions"
76 | git config user.email "actions@github.com"
77 |
78 | git fetch origin main
79 | git checkout main
80 | git pull origin main
81 |
82 | BRANCH_NAME="bump-${{ steps.get_basic_info.outputs.plugin_name }}-plugin-${{ steps.get_basic_info.outputs.version }}"
83 | git checkout -b "$BRANCH_NAME"
84 |
85 | git add .
86 | git commit -m "bump ${{ steps.get_basic_info.outputs.plugin_name }} plugin to version ${{ steps.get_basic_info.outputs.version }}"
87 |
88 | git push -u origin "$BRANCH_NAME" --force
89 |
90 | git branch -a
91 | echo "Waiting for branch to sync..."
92 | sleep 10 # Wait 10 seconds for branch sync
93 |
94 | - name: Create PR via GitHub API
95 | env:
96 | # How to config the token:
97 | # 1. Profile -> Settings -> Developer settings -> Personal access tokens -> Generate new token (with repo scope) -> Copy the token
98 | # 2. Go to the target repository -> Settings -> Secrets and variables -> Actions -> New repository secret -> Add the token as PLUGIN_ACTION
99 | GH_TOKEN: ${{ secrets.PLUGIN_ACTION }}
100 | run: |
101 | gh pr create \
102 | --repo langgenius/dify-plugins \
103 | --head "${{ steps.get_basic_info.outputs.author }}:${{ steps.get_basic_info.outputs.plugin_name }}-${{ steps.get_basic_info.outputs.version }}" \
104 | --base main \
105 | --title "bump ${{ steps.get_basic_info.outputs.plugin_name }} plugin to version ${{ steps.get_basic_info.outputs.version }}" \
106 | --body "bump ${{ steps.get_basic_info.outputs.plugin_name }} plugin package to version ${{ steps.get_basic_info.outputs.version }}
107 |
108 | Changes:
109 | - Updated plugin package file" || echo "PR already exists or creation skipped." # Handle cases where PR already exists
110 |
--------------------------------------------------------------------------------
/plugins/mockgpt/.github/workflows/plugin-publish.yml:
--------------------------------------------------------------------------------
1 | name: Plugin Publish Workflow
2 |
3 | on:
4 | release:
5 | types: [published]
6 |
7 | jobs:
8 | publish:
9 | runs-on: ubuntu-latest
10 | steps:
11 | - name: Checkout code
12 | uses: actions/checkout@v3
13 |
14 | - name: Download CLI tool
15 | run: |
16 | mkdir -p $RUNNER_TEMP/bin
17 | cd $RUNNER_TEMP/bin
18 |
19 | wget https://github.com/langgenius/dify-plugin-daemon/releases/download/0.0.6/dify-plugin-linux-amd64
20 | chmod +x dify-plugin-linux-amd64
21 |
22 | echo "CLI tool location:"
23 | pwd
24 | ls -la dify-plugin-linux-amd64
25 |
26 | - name: Get basic info from manifest
27 | id: get_basic_info
28 | run: |
29 | PLUGIN_NAME=$(grep "^name:" manifest.yaml | cut -d' ' -f2)
30 | echo "Plugin name: $PLUGIN_NAME"
31 | echo "plugin_name=$PLUGIN_NAME" >> $GITHUB_OUTPUT
32 |
33 | VERSION=$(grep "^version:" manifest.yaml | cut -d' ' -f2)
34 | echo "Plugin version: $VERSION"
35 | echo "version=$VERSION" >> $GITHUB_OUTPUT
36 |
37 | # If the author's name is not your github username, you can change the author here
38 | AUTHOR=$(grep "^author:" manifest.yaml | cut -d' ' -f2)
39 | echo "Plugin author: $AUTHOR"
40 | echo "author=$AUTHOR" >> $GITHUB_OUTPUT
41 |
42 | - name: Package Plugin
43 | id: package
44 | run: |
45 | cd $GITHUB_WORKSPACE
46 | PACKAGE_NAME="${{ steps.get_basic_info.outputs.plugin_name }}-${{ steps.get_basic_info.outputs.version }}.difypkg"
47 | $RUNNER_TEMP/bin/dify-plugin-linux-amd64 plugin package . -o "$PACKAGE_NAME"
48 |
49 | echo "Package result:"
50 | ls -la "$PACKAGE_NAME"
51 | echo "package_name=$PACKAGE_NAME" >> $GITHUB_OUTPUT
52 |
53 | echo "\nFull file path:"
54 | pwd
55 | echo "\nDirectory structure:"
56 | tree || ls -R
57 |
58 | - name: Checkout target repo
59 | uses: actions/checkout@v3
60 | with:
61 | repository: ${{steps.get_basic_info.outputs.author}}/dify-plugins
62 | path: dify-plugins
63 | token: ${{ secrets.PLUGIN_ACTION }}
64 | fetch-depth: 1
65 | persist-credentials: true
66 |
67 | - name: Prepare and create PR
68 | run: |
69 | PACKAGE_NAME="${{ steps.get_basic_info.outputs.plugin_name }}-${{ steps.get_basic_info.outputs.version }}.difypkg"
70 | mkdir -p dify-plugins/${{ steps.get_basic_info.outputs.author }}/${{ steps.get_basic_info.outputs.plugin_name }}
71 | mv "$PACKAGE_NAME" dify-plugins/${{ steps.get_basic_info.outputs.author }}/${{ steps.get_basic_info.outputs.plugin_name }}/
72 |
73 | cd dify-plugins
74 |
75 | git config user.name "GitHub Actions"
76 | git config user.email "actions@github.com"
77 |
78 | git fetch origin main
79 | git checkout main
80 | git pull origin main
81 |
82 | BRANCH_NAME="bump-${{ steps.get_basic_info.outputs.plugin_name }}-plugin-${{ steps.get_basic_info.outputs.version }}"
83 | git checkout -b "$BRANCH_NAME"
84 |
85 | git add .
86 | git commit -m "bump ${{ steps.get_basic_info.outputs.plugin_name }} plugin to version ${{ steps.get_basic_info.outputs.version }}"
87 |
88 | git push -u origin "$BRANCH_NAME" --force
89 |
90 | git branch -a
91 | echo "Waiting for branch to sync..."
92 | sleep 10 # Wait 10 seconds for branch sync
93 |
94 | - name: Create PR via GitHub API
95 | env:
96 | # How to config the token:
97 | # 1. Profile -> Settings -> Developer settings -> Personal access tokens -> Generate new token (with repo scope) -> Copy the token
98 | # 2. Go to the target repository -> Settings -> Secrets and variables -> Actions -> New repository secret -> Add the token as PLUGIN_ACTION
99 | GH_TOKEN: ${{ secrets.PLUGIN_ACTION }}
100 | run: |
101 | gh pr create \
102 | --repo langgenius/dify-plugins \
103 | --head "${{ steps.get_basic_info.outputs.author }}:${{ steps.get_basic_info.outputs.plugin_name }}-${{ steps.get_basic_info.outputs.version }}" \
104 | --base main \
105 | --title "bump ${{ steps.get_basic_info.outputs.plugin_name }} plugin to version ${{ steps.get_basic_info.outputs.version }}" \
106 | --body "bump ${{ steps.get_basic_info.outputs.plugin_name }} plugin package to version ${{ steps.get_basic_info.outputs.version }}
107 |
108 | Changes:
109 | - Updated plugin package file" || echo "PR already exists or creation skipped." # Handle cases where PR already exists
110 |
--------------------------------------------------------------------------------
/plugins/mockgpt/models/llm/llm.py:
--------------------------------------------------------------------------------
1 | import random
2 | import time
3 | import logging
4 | from collections.abc import Generator
5 | from typing import Optional, Union, List
6 |
7 | from dify_plugin import LargeLanguageModel
8 | from dify_plugin.entities import I18nObject
9 | from dify_plugin.errors.model import CredentialsValidateFailedError, InvokeError
10 | from dify_plugin.entities.model import AIModelEntity, FetchFrom, ModelType
11 | from dify_plugin.entities.model.llm import LLMResult, LLMResultChunk, LLMResultChunkDelta, LLMUsage
12 | from dify_plugin.entities.model.message import PromptMessage, PromptMessageTool, AssistantPromptMessage
13 |
14 | logger = logging.getLogger(__name__)
15 |
16 | class MockGptLargeLanguageModel(LargeLanguageModel):
17 | """
18 | MockGPT 实现
19 | """
20 |
21 | def _invoke(
22 | self,
23 | model: str,
24 | credentials: dict,
25 | prompt_messages: list[PromptMessage],
26 | model_parameters: dict,
27 | tools: Optional[list[PromptMessageTool]] = None,
28 | stop: Optional[list[str]] = None,
29 | stream: bool = True,
30 | user: Optional[str] = None,
31 | ) -> Union[LLMResult, Generator]:
32 | """
33 | 调用大语言模型
34 | """
35 |
36 | # 模拟响应内容
37 | demo_responses = [
38 | "这是一个演示模型的回复。我可以帮助您了解 Dify 插件的工作原理。",
39 | "作为演示模型,我会生成模拟的响应内容来展示插件功能。",
40 | "您好!这是 Demo AI 模型的模拟输出,用于演示插件开发流程。"
41 | ]
42 |
43 | response_text = random.choice(demo_responses)
44 |
45 | if stream:
46 | return self._handle_stream_response(model, prompt_messages, response_text)
47 | else:
48 | return self._handle_sync_response(model, prompt_messages, response_text)
49 |
50 | def _handle_stream_response(self, model: str, prompt_messages: List[PromptMessage],
51 | response_text: str) -> Generator:
52 | """
53 | 处理流式响应
54 | """
55 | # 模拟流式输出
56 | words = response_text.split()
57 | for i, word in enumerate(words):
58 | chunk_text = word + (" " if i < len(words) - 1 else "")
59 |
60 | delta = LLMResultChunkDelta(
61 | index=0,
62 | message=AssistantPromptMessage(content=chunk_text),
63 | finish_reason=None if i < len(words) - 1 else "stop",
64 | usage=self._calc_usage(response_text) if i == len(words) - 1 else None
65 | )
66 |
67 | yield LLMResultChunk(
68 | model=model,
69 | prompt_messages=prompt_messages,
70 | system_fingerprint=None,
71 | delta=delta
72 | )
73 |
74 | # 模拟网络延迟
75 | time.sleep(0.1)
76 |
77 | def _handle_sync_response(self, model: str, prompt_messages: List[PromptMessage],
78 | response_text: str) -> LLMResult:
79 | """
80 | 处理同步响应
81 | """
82 | return LLMResult(
83 | model=model,
84 | prompt_messages=prompt_messages,
85 | message=AssistantPromptMessage(content=response_text),
86 | usage=self._calc_usage(response_text),
87 | system_fingerprint=None
88 | )
89 |
90 | def _calc_usage(self, text: str) -> LLMUsage:
91 | """
92 | 计算使用量(模拟)
93 | """
94 | prompt_tokens = 50 # 模拟
95 | completion_tokens = len(text.split())
96 |
97 | return LLMUsage(
98 | prompt_tokens=prompt_tokens,
99 | prompt_unit_price=0.001,
100 | prompt_price_unit=1000,
101 | prompt_price=0.00005,
102 | completion_tokens=completion_tokens,
103 | completion_unit_price=0.002,
104 | completion_price_unit=1000,
105 | completion_price=completion_tokens * 0.000002,
106 | total_tokens=prompt_tokens + completion_tokens,
107 | total_price=0.00005 + completion_tokens * 0.000002,
108 | currency="USD",
109 | latency=1.5
110 | )
111 |
112 | def get_num_tokens(
113 | self,
114 | model: str,
115 | credentials: dict,
116 | prompt_messages: list[PromptMessage],
117 | tools: Optional[list[PromptMessageTool]] = None,
118 | ) -> int:
119 | """
120 | 计算 token 数量(模拟)
121 | """
122 | total_text = ""
123 | for message in prompt_messages:
124 | if isinstance(message.content, str):
125 | total_text += message.content
126 |
127 | # 简单估算:中文字符算1个token,英文单词算1个token
128 | return len(total_text.split()) + len([c for c in total_text if '\u4e00' <= c <= '\u9fff'])
129 |
130 | def validate_credentials(self, model: str, credentials: dict) -> None:
131 | """
132 | 验证模型凭据
133 | """
134 | try:
135 | pass
136 | except Exception as ex:
137 | raise CredentialsValidateFailedError(str(ex))
138 |
139 | def get_customizable_model_schema(
140 | self, model: str, credentials: dict
141 | ) -> AIModelEntity:
142 | """
143 | 返回模型 Schema
144 | """
145 | entity = AIModelEntity(
146 | model=model,
147 | label=I18nObject(zh_Hans=model, en_US=model),
148 | model_type=ModelType.LLM,
149 | features=[],
150 | fetch_from=FetchFrom.CUSTOMIZABLE_MODEL,
151 | model_properties={},
152 | parameter_rules=[],
153 | )
154 |
155 | return entity
156 |
157 | @property
158 | def _invoke_error_mapping(self) -> dict:
159 | """
160 | 错误映射
161 | """
162 | return {
163 | InvokeError: [Exception]
164 | }
--------------------------------------------------------------------------------