├── README.md ├── simple-jina ├── requirements.txt ├── PRIVACY.md ├── README.md ├── .env.example ├── main.py ├── _assets │ └── icon.svg ├── provider │ ├── simple-jina.py │ └── simple-jina.yaml ├── tools │ ├── simple-jina.py │ └── simple-jina.yaml ├── manifest.yaml ├── .gitignore ├── .difyignore └── GUIDE.md ├── replicate-flux ├── PRIVACY.md ├── requirements.txt ├── .env.example ├── main.py ├── _assets │ └── icon.svg ├── provider │ ├── replicate.py │ └── replicate.yaml ├── tools │ ├── flux_schnell.yaml │ └── flux_schnell.py ├── manifest.yaml ├── README.md ├── docs │ ├── work_plan.md │ └── dify_plugin_development.md ├── .gitignore ├── .difyignore └── GUIDE.md └── .gitignore /README.md: -------------------------------------------------------------------------------- 1 | # dify-plugins -------------------------------------------------------------------------------- /simple-jina/requirements.txt: -------------------------------------------------------------------------------- 1 | dify_plugin~=0.0.1b67 2 | requests==2.32.3 3 | -------------------------------------------------------------------------------- /replicate-flux/PRIVACY.md: -------------------------------------------------------------------------------- 1 | ## Privacy 2 | 3 | !!! Please fill in the privacy policy of the plugin. -------------------------------------------------------------------------------- /simple-jina/PRIVACY.md: -------------------------------------------------------------------------------- 1 | ## Privacy 2 | 3 | !!! Please fill in the privacy policy of the plugin. -------------------------------------------------------------------------------- /replicate-flux/requirements.txt: -------------------------------------------------------------------------------- 1 | dify_plugin~=0.0.1b67 2 | replicate==0.22.0 3 | requests~=2.32.3 4 | -------------------------------------------------------------------------------- /simple-jina/README.md: -------------------------------------------------------------------------------- 1 | ## simple-jina 2 | 3 | **Author:** verysmallwoods 4 | **Version:** 0.0.1 5 | **Type:** tool 6 | 7 | ### Description 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /simple-jina/.env.example: -------------------------------------------------------------------------------- 1 | INSTALL_METHOD=remote 2 | REMOTE_INSTALL_HOST=debug.dify.ai 3 | REMOTE_INSTALL_PORT=5003 4 | REMOTE_INSTALL_KEY=********-****-****-****-************ 5 | -------------------------------------------------------------------------------- /replicate-flux/.env.example: -------------------------------------------------------------------------------- 1 | INSTALL_METHOD=remote 2 | REMOTE_INSTALL_HOST=debug.dify.ai 3 | REMOTE_INSTALL_PORT=5003 4 | REMOTE_INSTALL_KEY=********-****-****-****-************ 5 | -------------------------------------------------------------------------------- /simple-jina/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 | -------------------------------------------------------------------------------- /replicate-flux/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 | -------------------------------------------------------------------------------- /simple-jina/_assets/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 6 | -------------------------------------------------------------------------------- /simple-jina/provider/simple-jina.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 SimpleJinaProvider(ToolProvider): 8 | def _validate_credentials(self, credentials: dict[str, Any]) -> None: 9 | try: 10 | """ 11 | IMPLEMENT YOUR VALIDATION HERE 12 | """ 13 | except Exception as e: 14 | raise ToolProviderCredentialValidationError(str(e)) 15 | -------------------------------------------------------------------------------- /simple-jina/provider/simple-jina.yaml: -------------------------------------------------------------------------------- 1 | identity: 2 | author: verysmallwoods 3 | name: simple-jina 4 | label: 5 | en_US: simple-jina 6 | zh_Hans: simple-jina 7 | pt_BR: simple-jina 8 | description: 9 | en_US: Convert a web page into well structured Markdown 10 | zh_Hans: Convert a web page into well structured Markdown 11 | pt_BR: Convert a web page into well structured Markdown 12 | icon: icon.svg 13 | tools: 14 | - tools/simple-jina.yaml 15 | extra: 16 | python: 17 | source: provider/simple-jina.py 18 | -------------------------------------------------------------------------------- /simple-jina/tools/simple-jina.py: -------------------------------------------------------------------------------- 1 | from collections.abc import Generator 2 | from typing import Any 3 | import requests 4 | 5 | from dify_plugin import Tool 6 | from dify_plugin.entities.tool import ToolInvokeMessage 7 | 8 | class SimpleJinaTool(Tool): 9 | def _invoke(self, tool_parameters: dict[str, Any]) -> Generator[ToolInvokeMessage]: 10 | url = tool_parameters["url"] 11 | try: 12 | response = requests.get(f"https://r.jina.ai/{url}") 13 | response.raise_for_status() 14 | yield self.create_json_message({ 15 | "result": response.text 16 | }) 17 | except requests.RequestException as e: 18 | yield self.create_json_message({ 19 | "error": f"Failed to fetch URL: {str(e)}" 20 | }) 21 | -------------------------------------------------------------------------------- /replicate-flux/_assets/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | FLUX 19 | -------------------------------------------------------------------------------- /replicate-flux/provider/replicate.py: -------------------------------------------------------------------------------- 1 | from typing import Any 2 | 3 | import replicate 4 | from dify_plugin import ToolProvider 5 | from dify_plugin.errors.tool import ToolProviderCredentialValidationError 6 | 7 | class ReplicateProvider(ToolProvider): 8 | def _validate_credentials(self, credentials: dict[str, Any]) -> None: 9 | """Validate the Replicate API token.""" 10 | try: 11 | # Set the API token 12 | client = replicate.Client(api_token=credentials["replicate_api_token"]) 13 | 14 | # Try to list models to verify the token 15 | # This will raise an error if the token is invalid 16 | client.models.get("black-forest-labs/flux-schnell") 17 | except Exception as e: 18 | raise ToolProviderCredentialValidationError(str(e)) -------------------------------------------------------------------------------- /simple-jina/tools/simple-jina.yaml: -------------------------------------------------------------------------------- 1 | identity: 2 | name: simple-jina 3 | author: verysmallwoods 4 | label: 5 | en_US: simple-jina 6 | zh_Hans: simple-jina 7 | pt_BR: simple-jina 8 | description: 9 | human: 10 | en_US: Convert a web page into well structured Markdown 11 | zh_Hans: Convert a web page into well structured Markdown 12 | pt_BR: Convert a web page into well structured Markdown 13 | llm: Convert a web page into well structured Markdown 14 | parameters: 15 | - name: url 16 | type: string 17 | required: true 18 | label: 19 | en_US: URL 20 | zh_Hans: URL 21 | pt_BR: URL 22 | human_description: 23 | en_US: The URL of a web page to convert 24 | zh_Hans: The URL of a web page to convert 25 | pt_BR: The URL of a web page to convert 26 | llm_description: The URL of a web page to convert 27 | form: llm 28 | extra: 29 | python: 30 | source: tools/simple-jina.py 31 | -------------------------------------------------------------------------------- /replicate-flux/provider/replicate.yaml: -------------------------------------------------------------------------------- 1 | identity: 2 | author: VerySmallWoods 3 | name: replicate 4 | label: 5 | en_US: Replicate 6 | zh_Hans: Replicate 7 | description: 8 | en_US: Use Replicate's AI models to generate images 9 | zh_Hans: 使用 Replicate 的 AI 模型生成图像 10 | icon: icon.svg 11 | tags: 12 | - image 13 | 14 | credentials_for_provider: 15 | replicate_api_token: 16 | type: secret-input 17 | required: true 18 | label: 19 | en_US: Replicate API Token 20 | zh_Hans: Replicate API Token 21 | placeholder: 22 | en_US: Enter your Replicate API Token 23 | zh_Hans: 输入你的 Replicate API Token 24 | help: 25 | en_US: Get your API token from https://replicate.com/account 26 | zh_Hans: 从 https://replicate.com/account 获取你的 API Token 27 | url: https://replicate.com/account 28 | 29 | tools: 30 | - tools/flux_schnell.yaml 31 | 32 | extra: 33 | python: 34 | source: provider/replicate.py -------------------------------------------------------------------------------- /replicate-flux/tools/flux_schnell.yaml: -------------------------------------------------------------------------------- 1 | description: 2 | human: 3 | en_US: Generate images using the Flux Schnell model 4 | zh_Hans: 使用 Flux Schnell 模型生成图像 5 | llm: A tool for generating images. Input should be a prompt describing the image you want to generate, such as "black forest gateau cake spelling out the words FLUX SCHNELL, tasty, food photography, dynamic shot" 6 | 7 | identity: 8 | name: flux_schnell 9 | author: VerySmallWoods 10 | label: 11 | en_US: Flux Schnell 12 | zh_Hans: Flux Schnell 13 | 14 | parameters: 15 | - name: prompt 16 | type: string 17 | required: true 18 | label: 19 | en_US: Image Prompt 20 | zh_Hans: 图像提示词 21 | human_description: 22 | en_US: Describe the image you want to generate 23 | zh_Hans: 描述你想要生成的图像 24 | llm_description: A detailed description of the image you want to generate. 25 | form: llm 26 | 27 | extra: 28 | python: 29 | source: tools/flux_schnell.py -------------------------------------------------------------------------------- /simple-jina/manifest.yaml: -------------------------------------------------------------------------------- 1 | version: 0.0.1 2 | type: plugin 3 | author: verysmallwoods 4 | name: simple-jina 5 | label: 6 | en_US: simple-jina 7 | ja_JP: simple-jina 8 | zh_Hans: simple-jina 9 | pt_BR: simple-jina 10 | description: 11 | en_US: Convert a web page into well structured Markdown 12 | ja_JP: Convert a web page into well structured Markdown 13 | zh_Hans: Convert a web page into well structured Markdown 14 | pt_BR: Convert a web page into well structured Markdown 15 | icon: icon.svg 16 | resource: 17 | memory: 268435456 18 | permission: 19 | tool: 20 | enabled: true 21 | endpoint: 22 | enabled: true 23 | app: 24 | enabled: true 25 | plugins: 26 | tools: 27 | - provider/simple-jina.yaml 28 | meta: 29 | version: 0.0.1 30 | arch: 31 | - amd64 32 | - arm64 33 | runner: 34 | language: python 35 | version: "3.12" 36 | entrypoint: main 37 | created_at: 2025-03-01T17:22:27.898452Z 38 | privacy: PRIVACY.md 39 | verified: false 40 | -------------------------------------------------------------------------------- /replicate-flux/manifest.yaml: -------------------------------------------------------------------------------- 1 | version: 0.0.1 2 | type: plugin 3 | author: verysmallwoods 4 | name: replicate-flux 5 | label: 6 | en_US: replicate-flux 7 | ja_JP: replicate-flux 8 | zh_Hans: replicate-flux 9 | pt_BR: replicate-flux 10 | description: 11 | en_US: Image generation by Flux model on Replicate 12 | ja_JP: Image generation by Flux model on Replicate 13 | zh_Hans: Image generation by Flux model on Replicate 14 | pt_BR: Image generation by Flux model on Replicate 15 | icon: icon.svg 16 | resource: 17 | memory: 268435456 18 | permission: 19 | tool: 20 | enabled: true 21 | endpoint: 22 | enabled: true 23 | app: 24 | enabled: true 25 | storage: 26 | enabled: true 27 | size: 1048576 28 | plugins: 29 | tools: 30 | - provider/replicate.yaml 31 | meta: 32 | version: 0.0.1 33 | arch: 34 | - amd64 35 | - arm64 36 | runner: 37 | language: python 38 | version: "3.12" 39 | entrypoint: main 40 | created_at: 2025-02-28T23:20:59.110761Z 41 | privacy: PRIVACY.md 42 | verified: false 43 | -------------------------------------------------------------------------------- /replicate-flux/tools/flux_schnell.py: -------------------------------------------------------------------------------- 1 | from collections.abc import Generator 2 | from typing import Any 3 | 4 | import replicate 5 | from dify_plugin import Tool 6 | from dify_plugin.entities.tool import ToolInvokeMessage 7 | 8 | class FluxSchnellTool(Tool): 9 | def _invoke(self, tool_parameters: dict[str, Any]) -> Generator[ToolInvokeMessage, None, None]: 10 | """Generate an image using the Flux Schnell model.""" 11 | try: 12 | # Initialize the Replicate client 13 | client = replicate.Client(api_token=self.runtime.credentials["replicate_api_token"]) 14 | 15 | # Run the model 16 | output = client.run( 17 | "black-forest-labs/flux-schnell", 18 | input={"prompt": tool_parameters["prompt"]} 19 | ) 20 | 21 | # The output is a list with one image URL 22 | if isinstance(output, list) and len(output) > 0: 23 | image_url = output[0] 24 | 25 | # Return the image URL in a format Dify can handle 26 | yield self.create_image_message(image_url=image_url) 27 | else: 28 | yield self.create_text_message("Failed to generate image: No output received from the model") 29 | 30 | except Exception as e: 31 | yield self.create_text_message(f"Failed to generate image: {str(e)}") -------------------------------------------------------------------------------- /replicate-flux/README.md: -------------------------------------------------------------------------------- 1 | # Replicate Flux Plugin for Dify 2 | 3 | A Dify plugin that integrates the Flux Schnell model from Replicate to generate dynamic food photography images. 4 | 5 | ## Features 6 | 7 | - Generate high-quality food photography images 8 | - Simple prompt-based interface 9 | - Secure API token management 10 | - Support for both English and Chinese interfaces 11 | 12 | ## Prerequisites 13 | 14 | - Python 3.11 or higher 15 | - A Replicate account and API token 16 | - Dify platform access 17 | 18 | ## Installation 19 | 20 | 1. Clone this repository or download the plugin package 21 | 2. Install dependencies: 22 | ```bash 23 | python -m venv venv 24 | source venv/bin/activate # On Windows: .\venv\Scripts\activate 25 | pip install -r requirements.txt 26 | ``` 27 | 28 | ## Configuration 29 | 30 | 1. Get your Replicate API token from [https://replicate.com/account](https://replicate.com/account) 31 | 2. When installing the plugin in Dify, you'll be prompted to enter your API token 32 | 33 | ## Usage 34 | 35 | ### In Dify Platform 36 | 37 | 1. Install the plugin through Dify's plugin management interface 38 | 2. Enter your Replicate API token when prompted 39 | 3. The plugin will be available in your workflows and applications 40 | 41 | ### Example Prompts 42 | 43 | - Basic food photo: 44 | ``` 45 | A delicious chocolate cake with strawberries on top, food photography style 46 | ``` 47 | - Dynamic shot (like the model demo): 48 | ``` 49 | black forest gateau cake spelling out the words FLUX SCHNELL, tasty, food photography, dynamic shot 50 | ``` 51 | 52 | ## Development 53 | 54 | To run the plugin in development mode: 55 | 56 | 1. Copy `.env.example` to `.env` 57 | 2. Set your Dify debug key and server details in `.env` 58 | 3. Run: 59 | ```bash 60 | python -m main 61 | ``` 62 | 63 | ## Author 64 | 65 | VerySmallWoods 66 | 67 | ## License 68 | 69 | MIT 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /replicate-flux/docs/work_plan.md: -------------------------------------------------------------------------------- 1 | # Replicate Flux Plugin Development Work Plan 2 | 3 | ## 1. Configuration Files 4 | 5 | ### 1.1 Provider Configuration (`/provider/replicate.yaml`) 6 | - Define provider identity (name, author, description) 7 | - Set up credentials configuration for Replicate API Token 8 | - Configure icon path 9 | - Set appropriate tags (image) 10 | - Link to tool configuration and Python source 11 | 12 | ### 1.2 Tool Configuration (`/tools/flux_schnell.yaml`) 13 | - Define tool identity 14 | - Configure parameters: 15 | - prompt (string, required) - The image generation prompt 16 | - Set up proper descriptions for both human and LLM 17 | - Link to tool implementation file 18 | 19 | ## 2. Python Code Implementation 20 | 21 | ### 2.1 Provider Implementation (`/provider/replicate.py`) 22 | - Implement ReplicateProvider class 23 | - Add credentials validation logic 24 | - Test Replicate API token validation 25 | 26 | ### 2.2 Tool Implementation (`/tools/flux_schnell.py`) 27 | - Implement FluxSchnellTool class 28 | - Add Replicate API integration 29 | - Implement image generation logic 30 | - Handle response and error cases 31 | - Return appropriate output format 32 | 33 | ## 3. Dependencies 34 | 35 | ### 3.1 Required Packages 36 | - replicate (Python client for Replicate API) 37 | - requests (for API calls) 38 | - dify-plugin (Dify plugin SDK) 39 | 40 | ### 3.2 Requirements File (`requirements.txt`) 41 | ``` 42 | replicate==0.22.0 43 | requests==2.31.0 44 | dify-plugin==0.3.8 45 | ``` 46 | 47 | ## 4. Environment Configuration 48 | 49 | ### 4.1 Development Environment (`.env`) 50 | ``` 51 | INSTALL_METHOD=remote 52 | REMOTE_INSTALL_HOST=localhost 53 | REMOTE_INSTALL_PORT=5003 54 | REMOTE_INSTALL_KEY= 55 | ``` 56 | 57 | ### 4.2 Runtime Environment Variables 58 | - REPLICATE_API_TOKEN (to be provided by end users) 59 | 60 | ## 5. Assets 61 | 62 | ### 5.1 Icon 63 | - Create an SVG icon representing image generation 64 | - Place in `_assets` folder 65 | - Suggested name: `icon.svg` 66 | 67 | ## 6. Testing Plan 68 | 69 | ### 6.1 Local Testing 70 | - Test credential validation 71 | - Test image generation with sample prompts 72 | - Verify error handling 73 | - Check output format 74 | 75 | ### 6.2 Integration Testing 76 | - Test plugin installation in Dify 77 | - Verify credential input workflow 78 | - Test image generation in Dify interface 79 | 80 | ## 7. Documentation 81 | 82 | ### 7.1 README.md 83 | - Installation instructions 84 | - Usage guide 85 | - API token acquisition steps 86 | - Example prompts 87 | 88 | ## Implementation Order 89 | 1. Set up dependencies 90 | 2. Create configuration files 91 | 3. Implement provider code 92 | 4. Implement tool code 93 | 5. Create icon and assets 94 | 6. Test locally 95 | 7. Test integration 96 | 8. Prepare documentation 97 | 98 | ## Notes 99 | - The plugin will use the black-forest-labs/flux-schnell model from Replicate 100 | - API Token must be handled securely 101 | - Image generation results will be in WebP format 102 | - Error handling should be user-friendly -------------------------------------------------------------------------------- /simple-jina/.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 | -------------------------------------------------------------------------------- /.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 | # PyPI configuration file 171 | .pypirc 172 | -------------------------------------------------------------------------------- /replicate-flux/.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 | -------------------------------------------------------------------------------- /simple-jina/.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 | 174 | # Mac 175 | .DS_Store 176 | 177 | # Windows 178 | Thumbs.db 179 | -------------------------------------------------------------------------------- /replicate-flux/.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 | 174 | # Mac 175 | .DS_Store 176 | 177 | # Windows 178 | Thumbs.db 179 | -------------------------------------------------------------------------------- /simple-jina/GUIDE.md: -------------------------------------------------------------------------------- 1 | ## User Guide of how to develop a Dify Plugin 2 | 3 | Hi there, looks like you have already created a Plugin, now let's get you started with the development! 4 | 5 | ### Choose a Plugin type you want to develop 6 | 7 | Before start, you need some basic knowledge about the Plugin types, Plugin supports to extend the following abilities in Dify: 8 | - **Tool**: Tool Providers like Google Search, Stable Diffusion, etc. it can be used to perform a specific task. 9 | - **Model**: Model Providers like OpenAI, Anthropic, etc. you can use their models to enhance the AI capabilities. 10 | - **Endpoint**: Like Service API in Dify and Ingress in Kubernetes, you can extend a http service as an endpoint and control its logics using your own code. 11 | 12 | Based on the ability you want to extend, we have divided the Plugin into three types: **Tool**, **Model**, and **Extension**. 13 | 14 | - **Tool**: It's a tool provider, but not only limited to tools, you can implement an endpoint there, for example, you need both `Sending Message` and `Receiving Message` if you are building a Discord Bot, **Tool** and **Endpoint** are both required. 15 | - **Model**: Just a model provider, extending others is not allowed. 16 | - **Extension**: Other times, you may only need a simple http service to extend the functionalities, **Extension** is the right choice for you. 17 | 18 | I believe you have chosen the right type for your Plugin while creating it, if not, you can change it later by modifying the `manifest.yaml` file. 19 | 20 | ### Manifest 21 | 22 | Now you can edit the `manifest.yaml` file to describe your Plugin, here is the basic structure of it: 23 | 24 | - version(version, required):Plugin's version 25 | - type(type, required):Plugin's type, currently only supports `plugin`, future support `bundle` 26 | - author(string, required):Author, it's the organization name in Marketplace and should also equals to the owner of the repository 27 | - label(label, required):Multi-language name 28 | - created_at(RFC3339, required):Creation time, Marketplace requires that the creation time must be less than the current time 29 | - icon(asset, required):Icon path 30 | - resource (object):Resources to be applied 31 | - memory (int64):Maximum memory usage, mainly related to resource application on SaaS for serverless, unit bytes 32 | - permission(object):Permission application 33 | - tool(object):Reverse call tool permission 34 | - enabled (bool) 35 | - model(object):Reverse call model permission 36 | - enabled(bool) 37 | - llm(bool) 38 | - text_embedding(bool) 39 | - rerank(bool) 40 | - tts(bool) 41 | - speech2text(bool) 42 | - moderation(bool) 43 | - node(object):Reverse call node permission 44 | - enabled(bool) 45 | - endpoint(object):Allow to register endpoint permission 46 | - enabled(bool) 47 | - app(object):Reverse call app permission 48 | - enabled(bool) 49 | - storage(object):Apply for persistent storage permission 50 | - enabled(bool) 51 | - size(int64):Maximum allowed persistent memory, unit bytes 52 | - plugins(object, required):Plugin extension specific ability yaml file list, absolute path in the plugin package, if you need to extend the model, you need to define a file like openai.yaml, and fill in the path here, and the file on the path must exist, otherwise the packaging will fail. 53 | - Format 54 | - tools(list[string]): Extended tool suppliers, as for the detailed format, please refer to [Tool Guide](https://docs.dify.ai/docs/plugins/standard/tool_provider) 55 | - models(list[string]):Extended model suppliers, as for the detailed format, please refer to [Model Guide](https://docs.dify.ai/docs/plugins/standard/model_provider) 56 | - endpoints(list[string]):Extended Endpoints suppliers, as for the detailed format, please refer to [Endpoint Guide](https://docs.dify.ai/docs/plugins/standard/endpoint_group) 57 | - Restrictions 58 | - Not allowed to extend both tools and models 59 | - Not allowed to have no extension 60 | - Not allowed to extend both models and endpoints 61 | - Currently only supports up to one supplier of each type of extension 62 | - meta(object) 63 | - version(version, required):manifest format version, initial version 0.0.1 64 | - arch(list[string], required):Supported architectures, currently only supports amd64 arm64 65 | - runner(object, required):Runtime configuration 66 | - language(string):Currently only supports python 67 | - version(string):Language version, currently only supports 3.12 68 | - entrypoint(string):Program entry, in python it should be main 69 | 70 | ### Install Dependencies 71 | 72 | - First of all, you need a Python 3.11+ environment, as our SDK requires that. 73 | - Then, install the dependencies: 74 | ```bash 75 | pip install -r requirements.txt 76 | ``` 77 | - If you want to add more dependencies, you can add them to the `requirements.txt` file, once you have set the runner to python in the `manifest.yaml` file, `requirements.txt` will be automatically generated and used for packaging and deployment. 78 | 79 | ### Implement the Plugin 80 | 81 | Now you can start to implement your Plugin, by following these examples, you can quickly understand how to implement your own Plugin: 82 | 83 | - [OpenAI](https://github.com/langgenius/dify-plugin-sdks/tree/main/python/examples/openai): best practice for model provider 84 | - [Google Search](https://github.com/langgenius/dify-plugin-sdks/tree/main/python/examples/google): a simple example for tool provider 85 | - [Neko](https://github.com/langgenius/dify-plugin-sdks/tree/main/python/examples/neko): a funny example for endpoint group 86 | 87 | ### Test and Debug the Plugin 88 | 89 | You may already noticed that a `.env.example` file in the root directory of your Plugin, just copy it to `.env` and fill in the corresponding values, there are some environment variables you need to set if you want to debug your Plugin locally. 90 | 91 | - `INSTALL_METHOD`: Set this to `remote`, your plugin will connect to a Dify instance through the network. 92 | - `REMOTE_INSTALL_HOST`: The host of your Dify instance, you can use our SaaS instance `https://debug.dify.ai`, or self-hosted Dify instance. 93 | - `REMOTE_INSTALL_PORT`: The port of your Dify instance, default is 5003 94 | - `REMOTE_INSTALL_KEY`: You should get your debugging key from the Dify instance you used, at the right top of the plugin management page, you can see a button with a `debug` icon, click it and you will get the key. 95 | 96 | Run the following command to start your Plugin: 97 | 98 | ```bash 99 | python -m main 100 | ``` 101 | 102 | Refresh the page of your Dify instance, you should be able to see your Plugin in the list now, but it will be marked as `debugging`, you can use it normally, but not recommended for production. 103 | 104 | ### Package the Plugin 105 | 106 | After all, just package your Plugin by running the following command: 107 | 108 | ```bash 109 | dify-plugin plugin package ./ROOT_DIRECTORY_OF_YOUR_PLUGIN 110 | ``` 111 | 112 | you will get a `plugin.difypkg` file, that's all, you can submit it to the Marketplace now, look forward to your Plugin being listed! 113 | 114 | 115 | ## User Privacy Policy 116 | 117 | Please fill in the privacy policy of the plugin if you want to make it published on the Marketplace, refer to [PRIVACY.md](PRIVACY.md) for more details. -------------------------------------------------------------------------------- /replicate-flux/GUIDE.md: -------------------------------------------------------------------------------- 1 | ## User Guide of how to develop a Dify Plugin 2 | 3 | Hi there, looks like you have already created a Plugin, now let's get you started with the development! 4 | 5 | ### Choose a Plugin type you want to develop 6 | 7 | Before start, you need some basic knowledge about the Plugin types, Plugin supports to extend the following abilities in Dify: 8 | - **Tool**: Tool Providers like Google Search, Stable Diffusion, etc. it can be used to perform a specific task. 9 | - **Model**: Model Providers like OpenAI, Anthropic, etc. you can use their models to enhance the AI capabilities. 10 | - **Endpoint**: Like Service API in Dify and Ingress in Kubernetes, you can extend a http service as an endpoint and control its logics using your own code. 11 | 12 | Based on the ability you want to extend, we have divided the Plugin into three types: **Tool**, **Model**, and **Extension**. 13 | 14 | - **Tool**: It's a tool provider, but not only limited to tools, you can implement an endpoint there, for example, you need both `Sending Message` and `Receiving Message` if you are building a Discord Bot, **Tool** and **Endpoint** are both required. 15 | - **Model**: Just a model provider, extending others is not allowed. 16 | - **Extension**: Other times, you may only need a simple http service to extend the functionalities, **Extension** is the right choice for you. 17 | 18 | I believe you have chosen the right type for your Plugin while creating it, if not, you can change it later by modifying the `manifest.yaml` file. 19 | 20 | ### Manifest 21 | 22 | Now you can edit the `manifest.yaml` file to describe your Plugin, here is the basic structure of it: 23 | 24 | - version(version, required):Plugin's version 25 | - type(type, required):Plugin's type, currently only supports `plugin`, future support `bundle` 26 | - author(string, required):Author, it's the organization name in Marketplace and should also equals to the owner of the repository 27 | - label(label, required):Multi-language name 28 | - created_at(RFC3339, required):Creation time, Marketplace requires that the creation time must be less than the current time 29 | - icon(asset, required):Icon path 30 | - resource (object):Resources to be applied 31 | - memory (int64):Maximum memory usage, mainly related to resource application on SaaS for serverless, unit bytes 32 | - permission(object):Permission application 33 | - tool(object):Reverse call tool permission 34 | - enabled (bool) 35 | - model(object):Reverse call model permission 36 | - enabled(bool) 37 | - llm(bool) 38 | - text_embedding(bool) 39 | - rerank(bool) 40 | - tts(bool) 41 | - speech2text(bool) 42 | - moderation(bool) 43 | - node(object):Reverse call node permission 44 | - enabled(bool) 45 | - endpoint(object):Allow to register endpoint permission 46 | - enabled(bool) 47 | - app(object):Reverse call app permission 48 | - enabled(bool) 49 | - storage(object):Apply for persistent storage permission 50 | - enabled(bool) 51 | - size(int64):Maximum allowed persistent memory, unit bytes 52 | - plugins(object, required):Plugin extension specific ability yaml file list, absolute path in the plugin package, if you need to extend the model, you need to define a file like openai.yaml, and fill in the path here, and the file on the path must exist, otherwise the packaging will fail. 53 | - Format 54 | - tools(list[string]): Extended tool suppliers, as for the detailed format, please refer to [Tool Guide](https://docs.dify.ai/docs/plugins/standard/tool_provider) 55 | - models(list[string]):Extended model suppliers, as for the detailed format, please refer to [Model Guide](https://docs.dify.ai/docs/plugins/standard/model_provider) 56 | - endpoints(list[string]):Extended Endpoints suppliers, as for the detailed format, please refer to [Endpoint Guide](https://docs.dify.ai/docs/plugins/standard/endpoint_group) 57 | - Restrictions 58 | - Not allowed to extend both tools and models 59 | - Not allowed to have no extension 60 | - Not allowed to extend both models and endpoints 61 | - Currently only supports up to one supplier of each type of extension 62 | - meta(object) 63 | - version(version, required):manifest format version, initial version 0.0.1 64 | - arch(list[string], required):Supported architectures, currently only supports amd64 arm64 65 | - runner(object, required):Runtime configuration 66 | - language(string):Currently only supports python 67 | - version(string):Language version, currently only supports 3.12 68 | - entrypoint(string):Program entry, in python it should be main 69 | 70 | ### Install Dependencies 71 | 72 | - First of all, you need a Python 3.11+ environment, as our SDK requires that. 73 | - Then, install the dependencies: 74 | ```bash 75 | pip install -r requirements.txt 76 | ``` 77 | - If you want to add more dependencies, you can add them to the `requirements.txt` file, once you have set the runner to python in the `manifest.yaml` file, `requirements.txt` will be automatically generated and used for packaging and deployment. 78 | 79 | ### Implement the Plugin 80 | 81 | Now you can start to implement your Plugin, by following these examples, you can quickly understand how to implement your own Plugin: 82 | 83 | - [OpenAI](https://github.com/langgenius/dify-plugin-sdks/tree/main/python/examples/openai): best practice for model provider 84 | - [Google Search](https://github.com/langgenius/dify-plugin-sdks/tree/main/python/examples/google): a simple example for tool provider 85 | - [Neko](https://github.com/langgenius/dify-plugin-sdks/tree/main/python/examples/neko): a funny example for endpoint group 86 | 87 | ### Test and Debug the Plugin 88 | 89 | You may already noticed that a `.env.example` file in the root directory of your Plugin, just copy it to `.env` and fill in the corresponding values, there are some environment variables you need to set if you want to debug your Plugin locally. 90 | 91 | - `INSTALL_METHOD`: Set this to `remote`, your plugin will connect to a Dify instance through the network. 92 | - `REMOTE_INSTALL_HOST`: The host of your Dify instance, you can use our SaaS instance `https://debug.dify.ai`, or self-hosted Dify instance. 93 | - `REMOTE_INSTALL_PORT`: The port of your Dify instance, default is 5003 94 | - `REMOTE_INSTALL_KEY`: You should get your debugging key from the Dify instance you used, at the right top of the plugin management page, you can see a button with a `debug` icon, click it and you will get the key. 95 | 96 | Run the following command to start your Plugin: 97 | 98 | ```bash 99 | python -m main 100 | ``` 101 | 102 | Refresh the page of your Dify instance, you should be able to see your Plugin in the list now, but it will be marked as `debugging`, you can use it normally, but not recommended for production. 103 | 104 | ### Package the Plugin 105 | 106 | After all, just package your Plugin by running the following command: 107 | 108 | ```bash 109 | dify-plugin plugin package ./ROOT_DIRECTORY_OF_YOUR_PLUGIN 110 | ``` 111 | 112 | you will get a `plugin.difypkg` file, that's all, you can submit it to the Marketplace now, look forward to your Plugin being listed! 113 | 114 | 115 | ## User Privacy Policy 116 | 117 | Please fill in the privacy policy of the plugin if you want to make it published on the Marketplace, refer to [PRIVACY.md](PRIVACY.md) for more details. -------------------------------------------------------------------------------- /replicate-flux/docs/dify_plugin_development.md: -------------------------------------------------------------------------------- 1 | Title: Tool Plugin | Dify 2 | 3 | URL Source: https://docs.dify.ai/plugins/quick-start/develop-plugins/tool-plugin 4 | 5 | Markdown Content: 6 | * * * 7 | 8 | Tool type plugins are external tools that can be referenced by Chatflow / Workflow / Agent application types to enhance the capabilities of Dify applications. For example, adding online search capabilities, image generation capabilities, etc. to an application. Tool Type Plugins provide a complete set of tools and API implementations. 9 | 10 | In this article, a "Tool Plugin" refers to a complete project that includes the tool provider file, functional code, and other related components. A tool provider may encompass multiple Tools (which can be understood as additional functionalities offered by a single tool), structured as follows: 11 | 12 | ``` 13 | - Tool provider 14 | - Tool A 15 | - Tool B 16 | ``` 17 | 18 | This article uses `GoogleSearch` as an example of how to quickly develop a tool type of plugin. 19 | 20 | * Dify plugin scaffolding tool 21 | 22 | 23 | For detailed instructions on how to prepare scaffolding tools for plugin development, see [Initializing Development Tools](https://docs.dify.ai/plugins/quick-start/develop-plugins/initialize-development-tools). 24 | 25 | Run the CLI tool to create a new dify plugin project: 26 | 27 | ``` 28 | ./dify-plugin-darwin-arm64 plugin init 29 | ``` 30 | 31 | If you have renamed the binary file to `dify` and copied it to the `/usr/local/bin` path, you can run the following command to create a new plugin project: 32 | 33 | > In the following, the command-line tool `dify` is used. If issues occur, please replace the `dify` command with the appropriate path to your command-line tool. 34 | 35 | ### 36 | 37 | Select plugin type and template 38 | 39 | There are three types of plugins: tool, model and extension. All templates within SDK are provided with full code projects. The following part will use the **Tool plugin** template as an example. 40 | 41 | > If you are already familiar in plugin development, please refer to the [Schema Definition](https://docs.dify.ai/plugins/schema-definition) to implement various types of plugins. 42 | 43 | #### 44 | 45 | Configuring Plugin Permissions 46 | 47 | The plugin also needs to read permissions from the Dify platform to connect properly. The following permissions need to be granted for the example tool plugin: 48 | 49 | * Enable persistent storage Storage, allocate default size storage 50 | 51 | * Allow registration of Endpoint 52 | 53 | 54 | > Use the arrow keys to select permissions within the terminal and the "Tab" button to grant permissions. 55 | 56 | After checking all the permission items, tap Enter to complete the creation of the plug-in. The system will automatically generate the plug-in project code. 57 | 58 | #### 59 | 60 | 1\. Create the tool vendor yaml file 61 | 62 | The tool vendor file can be understood as the base configuration entry point for a tool type plugin, and is used to provide the necessary authorization information to the tool. This section demonstrates how to fill out that yaml file. 63 | 64 | Go to the `/provider` path and rename the yaml file in it to `google.yaml`. The `yaml` file will contain information about the tool vendor, including the provider name, icon, author, and other details. This information will be displayed when the plugin is installed. 65 | 66 | Example: 67 | 68 | ``` 69 | identity: 70 | author: Your-name 71 | name: google 72 | label: 73 | en_US: Google 74 | zh_Hans: Google 75 | description: 76 | en_US: Google 77 | zh_Hans: Google 78 | icon: icon.svg 79 | tags: 80 | - search 81 | ``` 82 | 83 | * `identity` contains basic information about the tool provider, including author, name, label, description, icon, and more. 84 | 85 | * The icon needs to be an attachment resource, which needs to be placed in the `_assets` folder in the project root directory. 86 | 87 | * Tags help users quickly find plugins by category, here are all the tags currently supported. 88 | 89 | * ``` 90 | class ToolLabelEnum(Enum): 91 | SEARCH = 'search' 92 | IMAGE = 'image' 93 | VIDEOS = 'videos' 94 | WEATHER = 'weather' 95 | FINANCE = 'finance' 96 | DESIGN = 'design' 97 | TRAVEL = 'travel' 98 | SOCIAL = 'social' 99 | NEWS = 'news' 100 | MEDICAL = 'medical' 101 | PRODUCTIVITY = 'productivity' 102 | EDUCATION = 'education' 103 | BUSINESS = 'business' 104 | ENTERTAINMENT = 'entertainment' 105 | UTILITIES = 'utilities' 106 | OTHER = 'other' 107 | ``` 108 | 109 | 110 | 111 | Make sure that the path to the file is in the `/tools` directory, the full path is below: 112 | 113 | ``` 114 | plugins: 115 | tools: 116 | - "google.yaml" 117 | ``` 118 | 119 | Where the `google.yaml` file needs to use its absolute path in the plugin project. 120 | 121 | * **Completion of third-party service credentials** 122 | 123 | 124 | For ease of development, we have chosen to use the Google Search API provided by a third-party service, SerpApi. SerpApi requires an API Key in order to use it, so you need to add the `credentials_for_provider` field to the `yaml` file. 125 | 126 | The full code is below: 127 | 128 | ``` 129 | identity: 130 | author: Dify 131 | name: google 132 | label: 133 | en_US: Google 134 | zh_Hans: Google 135 | pt_BR: Google 136 | description: 137 | en_US: Google 138 | zh_Hans: GoogleSearch 139 | pt_BR: Google 140 | icon: icon.svg 141 | tags: 142 | - search 143 | credentials_for_provider: #Add credentials_for_provider field 144 | serpapi_api_key: 145 | type: secret-input 146 | required: true 147 | label: 148 | en_US: SerpApi API key 149 | zh_Hans: SerpApi API key 150 | placeholder: 151 | en_US: Please input your SerpApi API key 152 | zh_Hans: 请输入你的 SerpApi API key 153 | help: 154 | en_US: Get your SerpApi API key from SerpApi 155 | zh_Hans: 从 SerpApi 获取您的 SerpApi API key 156 | url: https://serpapi.com/manage-api-key 157 | tools: 158 | - tools/google_search.yaml 159 | extra: 160 | python: 161 | source: google.py 162 | ``` 163 | 164 | * where the `credentials_for_provider` sub-level structure needs to satisfy the [ProviderConfig](https://github.com/langgenius/dify-docs/blob/main/en/plugins/quick-start/schema-definition/general-specifications.md#providerconfig) specification. 165 | 166 | * It is necessary to specify which tools are included in this provider. This example only includes a `tools/google_search.yaml` file. 167 | 168 | * For the provider, in addition to defining its basic information, you also need to implement some of its code logic, so you need to specify its implementation logic. In this example, the code file for the function is placed in `google.py`, but instead of implementing it for the time being, you write the code for `google_search` first. 169 | 170 | 171 | #### 172 | 173 | 2\. Fill out the tool yaml file 174 | 175 | There can be multiple tools under a tool vendor, and each tool needs to be described by a `yaml` file, which contains basic information about the tool, its parameters, its output, and so on. 176 | 177 | Still using the `GoogleSearch` tool as an example, you can create a new `google_search.yaml` file in the `/tools` folder. 178 | 179 | ``` 180 | identity: 181 | name: google_search 182 | author: Dify 183 | label: 184 | en_US: GoogleSearch 185 | zh_Hans: Google Search 186 | pt_BR: GoogleSearch 187 | description: 188 | human: 189 | en_US: A tool for performing a Google SERP search and extracting snippets and webpages.Input should be a search query. 190 | zh_Hans: A tool for performing Google SERP search and extracting snippets and webpages. Input should be a search query. 191 | pt_BR: A tool for performing a Google SERP search and extracting snippets and webpages.Input should be a search query. 192 | llm: A tool for performing a Google SERP search and extracting snippets and webpages.Input should be a search query. 193 | parameters: 194 | - name: query 195 | type: string 196 | required: true 197 | label: 198 | en_US: Query string 199 | zh_Hans: Query string 200 | pt_BR: Query string 201 | human_description: 202 | en_US: used for searching 203 | zh_Hans: used for searching webpage content 204 | pt_BR: used for searching 205 | llm_description: key words for searching 206 | form: llm 207 | extra: 208 | python: 209 | source: tools/google_search.py 210 | ``` 211 | 212 | * `identity` contains the tool's basic information, including name, author, labels, description, etc. 213 | 214 | * `parameters` parameter list 215 | 216 | * `name` (required) parameter name, must be unique, cannot duplicate other parameter names 217 | 218 | * `type` (required) parameter type, currently supports five types: `string`, `number`, `boolean`, `select`, `secret-input`, corresponding to string, number, boolean, dropdown menu, and encrypted input field. For sensitive information, please use `secret-input` type 219 | 220 | * `label` (required) parameter label, used for frontend display 221 | 222 | * `form` (required) form type, currently supports two types: `llm` and `form` 223 | 224 | * In Agent applications, `llm` means the parameter is inferred by LLM, `form` means parameters that can be preset to use the tool 225 | 226 | * In workflow applications, both `llm` and `form` need to be filled in the frontend, but `llm` parameters will serve as input variables for tool nodes 227 | 228 | 229 | * `required` whether the field is required 230 | 231 | * In `llm` mode, if a parameter is required, the Agent must infer this parameter 232 | 233 | * In `form` mode, if a parameter is required, users must fill in this parameter in the frontend before starting the conversation 234 | 235 | 236 | * `options` parameter options 237 | 238 | * In `llm` mode, Dify will pass all options to LLM, which can make inferences based on these options 239 | 240 | * In `form` mode, when `type` is `select`, the frontend will display these options 241 | 242 | 243 | 244 | * `min` minimum value, can be set when parameter type is `number` 245 | 246 | * `max` maximum value, can be set when parameter type is `number` 247 | 248 | * `human_description` introduction displayed in frontend, supports multiple languages 249 | 250 | * `placeholder` prompt text for input fields, can be set when form type is `form` and parameter type is `string`, `number`, or `secret-input`, supports multiple languages 251 | 252 | * `llm_description` introduction passed to LLM. To help LLM better understand this parameter, please write as detailed information as possible about this parameter here so that LLM can understand it 253 | 254 | 255 | 256 | #### 257 | 258 | 3\. Preparation of tool codes 259 | 260 | After filling in the configuration information of the tool, you can start writing the functional code of the tool to realize the logical purpose of the tool. Create `google_search.py` in the `/tools` directory with the following contents. 261 | 262 | ``` 263 | from collections.abc import Generator 264 | from typing import Any 265 | 266 | import requests 267 | 268 | from dify_plugin import Tool 269 | from dify_plugin.entities.tool import ToolInvokeMessage 270 | 271 | SERP_API_URL = "https://serpapi.com/search" 272 | 273 | class GoogleSearchTool(Tool): 274 | def _parse_response(self, response: dict) -> dict: 275 | result = {} 276 | if "knowledge_graph" in response: 277 | result["title"] = response["knowledge_graph"].get("title", "") 278 | result["description"] = response["knowledge_graph"].get("description", "") 279 | if "organic_results" in response: 280 | result["organic_results"] = [ 281 | { 282 | "title": item.get("title", ""), 283 | "link": item.get("link", ""), 284 | "snippet": item.get("snippet", ""), 285 | } 286 | for item in response["organic_results"] 287 | ] 288 | return result 289 | 290 | def _invoke(self, tool_parameters: dict[str, Any]) -> Generator[ToolInvokeMessage]: 291 | params = { 292 | "api_key": self.runtime.credentials["serpapi_api_key"], 293 | "q": tool_parameters["query"], 294 | "engine": "google", 295 | "google_domain": "google.com", 296 | "gl": "us", 297 | "hl": "en", 298 | } 299 | 300 | response = requests.get(url=SERP_API_URL, params=params, timeout=5) 301 | response.raise_for_status() 302 | valuable_res = self._parse_response(response.json()) 303 | 304 | yield self.create_json_message(valuable_res) 305 | ``` 306 | 307 | In this example, we simply request the `serpapi` and use `self.create_json_message` to return a string of `json` formatted data. For more information on the types of data returned, you can refer to the [tool](https://github.com/langgenius/dify-docs/blob/main/en/plugins/quick-start/schema-definition/tool.md) documentation. 308 | 309 | #### 310 | 311 | 4\. Completion of tool vendor codes 312 | 313 | Finally, you need to create a vendor code implementation code that will be used to implement the vendor's credential validation logic. If the credential validation fails, the `ToolProviderCredentialValidationError` exception will be thrown. After successful validation, the `google_search` tool service will be requested correctly. 314 | 315 | Create a `google.py` file in the `/provider` directory with the following code: 316 | 317 | ``` 318 | from typing import Any 319 | 320 | from dify_plugin import ToolProvider 321 | from dify_plugin.errors.tool import ToolProviderCredentialValidationError 322 | from tools.google_search import GoogleSearchTool 323 | 324 | class GoogleProvider(ToolProvider): 325 | def _validate_credentials(self, credentials: dict[str, Any]) -> None: 326 | try: 327 | for _ in GoogleSearchTool.from_credentials(credentials).invoke( 328 | tool_parameters={"query": "test", "result_type": "link"}, 329 | ): 330 | pass 331 | except Exception as e: 332 | raise ToolProviderCredentialValidationError(str(e)) 333 | ``` 334 | 335 | Dify provides remote debugging method, go to "Plugin Management" page to get the debugging key and remote server address. 336 | 337 | Go back to the plugin project, copy the `.env.example` file and rename it to .env. Fill it with the remote server address and debugging key. 338 | 339 | The `.env` file: 340 | 341 | ``` 342 | INSTALL_METHOD=remote 343 | REMOTE_INSTALL_HOST=localhost 344 | REMOTE_INSTALL_PORT=5003 345 | REMOTE_INSTALL_KEY=****-****-****-****-**** 346 | ``` 347 | 348 | Run the `python -m main` command to launch the plugin. You can see on the plugin page that the plugin has been installed into Workspace. Other team members can also access the plugin. 349 | 350 | After confirming that the plugin works properly, you can package and name the plugin with the following command line tool. After running it you can find the `google.difypkg` file in the current folder, which is the final plugin package. 351 | 352 | ``` 353 | dify plugin package ./google 354 | ``` 355 | 356 | Congratulations, you have completed the complete development, debugging and packaging process of a tool type plugin! 357 | 358 | You can now publish your plugin by uploading it to the [Dify Plugins code repository](https://github.com/langgenius/dify-plugins)! Before uploading, make sure your plugin follows the [plugin release guide](https://github.com/langgenius/dify-docs/blob/main/en/plugins/quick-start/publish-plugins/publish-to-dify-marketplace.md). Once approved, the code will be merged into the master branch and automatically live in the [Dify Marketplace](https://marketplace.dify.ai/). 359 | 360 | **Quick Start:** 361 | 362 | **Plugins Specification Definition Documentaiton:** 363 | 364 | ![Image 1](https://docs.dify.ai/~gitbook/image?url=https%3A%2F%2Fassets-docs.dify.ai%2F2024%2F12%2F053415ef127f1f4d6dd85dd3ae79626a.png&width=768&dpr=4&quality=100&sign=1c835148&sv=2) 365 | 366 | ![Image 2](https://docs.dify.ai/~gitbook/image?url=https%3A%2F%2Fassets-docs.dify.ai%2F2024%2F12%2F9cf92c2e74dce55e6e9e331d031e5a9f.png&width=768&dpr=4&quality=100&sign=afb20492&sv=2) 367 | 368 | ![Image 3](https://docs.dify.ai/~gitbook/image?url=https%3A%2F%2Fassets-docs.dify.ai%2F2025%2F02%2F60c4c86a317d865133aa460592eac079.png&width=768&dpr=4&quality=100&sign=ff2afaee&sv=2) 369 | 370 | ![Image 4](https://docs.dify.ai/~gitbook/image?url=https%3A%2F%2Fassets-docs.dify.ai%2F2024%2F11%2F0fe19a8386b1234755395018bc2e0e35.png&width=768&dpr=4&quality=100&sign=745f0f3f&sv=2) 371 | 372 | ![Image 5](https://docs.dify.ai/~gitbook/image?url=https%3A%2F%2Fassets-docs.dify.ai%2F2024%2F12%2Fdd3c0f9a66454e15868eabced7b74fd6.png&width=768&dpr=4&quality=100&sign=b052c795&sv=2) 373 | 374 | ![Image 6](https://docs.dify.ai/~gitbook/image?url=https%3A%2F%2Fassets-docs.dify.ai%2F2024%2F12%2F7e7bcf1f9e3acf72c6917ea9de4e4613.png&width=768&dpr=4&quality=100&sign=485a1707&sv=2) --------------------------------------------------------------------------------