Dify Plugin 开发教程


发布于 2025-11-04 / 1 阅读 / 0 评论 /
# Dify Plugin 开发教程 本教程详细介绍如何开发一个完整的 Dify Plugin 工具。 ## 1. 工具类基本结构 每个工具都需要继承 Tool 基类,并实现 _invoke 方法: ```python from collections.abc import Generator fr

# Dify Plugin 开发教程

本教程详细介绍如何开发一个完整的 Dify Plugin 工具。

## 1. 工具类基本结构

每个工具都需要继承 Tool 基类,并实现 _invoke 方法:

```python

from collections.abc import Generator

from typing import Any

from dify_plugin import Tool

from dify_plugin.entities.tool import ToolInvokeMessage

class ExampleTool(Tool):

def invoke(self, toolparameters: dict[str, Any]) -> Generator[ToolInvokeMessage]:

# 工具逻辑实现

pass

```

## 2. 参数定义 (YAML 配置)

### 2.1 基本信息定义

```yaml

identity:

name: "example_tool" # 工具唯一标识

author: "your_name"

label:

en_US: "Example Tool"

zh_Hans: "示例工具"

description:

human:

en_US: "This is an example tool description."

zh_Hans: "这是一个示例工具描述。"

llm: "This tool is used for demonstration purposes."

```

### 2.2 参数字段定义

```yaml

parameters:

- name: required_param

type: string

required: true

label:

en_US: Required Parameter

zh_Hans: 必需参数

human_description:

en_US: "This is a required string parameter"

zh_Hans: "这是一个必需的字符串参数"

llm_description: "A required string parameter for the tool"

form: llm

- name: optional_param

type: string

required: false

label:

en_US: Optional Parameter

zh_Hans: 可选参数

human_description:

en_US: "This is an optional parameter"

zh_Hans: "这是一个可选参数"

llm_description: "An optional parameter with default value"

form: llm

- name: number_param

type: number

required: false

default: 100

label:

en_US: Number Parameter

zh_Hans: 数字参数

- name: boolean_param

type: boolean

required: false

default: false

label:

en_US: Boolean Switch

zh_Hans: 布尔开关

- name: select_param

type: select

required: true

options:

- value: "option1"

label:

en_US: "Option One"

zh_Hans: "选项一"

- value: "option2"

label:

en_US: "Option Two"

zh_Hans: "选项二"

label:

en_US: "Select Option"

zh_Hans: "选择选项"

```

参数类型说明:

- string: 字符串类型

- number: 数字类型

- boolean: 布尔类型

- select: 下拉选择,需要配合 options 字段

- file: 文件类型

## 3. 工具逻辑实现

### 3.1 参数获取和验证

```python

def invoke(self, toolparameters: dict[str, Any]) -> Generator[ToolInvokeMessage]:

try:

# 获取必需参数

required_param = tool_parameters.get('required_param')

optional_param = tool_parameters.get('optional_param', 'default_value')

number_param = tool_parameters.get('number_param', 100)

boolean_param = tool_parameters.get('boolean_param', False)

select_param = tool_parameters.get('select_param')

# 验证必要参数

if not required_param:

raise ValueError("required_param 是必需的参数")

# 参数类型转换和验证

try:

number_value = int(number_param)

except (TypeError, ValueError):

raise ValueError("number_param 必须是有效的数字")

# 继续业务逻辑...

```

### 3.2 返回成功结果

使用 self.create_json_message() 返回结构化数据:

```python

# 返回成功结果

result_data = {

"processed_items": 10,

"status": "completed",

"details": {"param1": required_param, "option": select_param}

}

yield self.create_json_message({

"success": True,

"message": "操作成功完成",

"data": result_data

})

```

返回格式建议:

- success: 操作是否成功 (boolean)

- message: 人类可读的消息 (string)

- data: 实际返回的数据 (any)

### 3.3 返回文本消息

如果需要返回纯文本:

```python

yield self.create_text_message("操作成功完成")

```

### 3.4 返回多条消息

可以多次使用 yield 返回多条消息:

```python

# 返回进度消息

yield self.create_text_message("开始处理数据...")

# 处理逻辑

processed_data = self.process_data(required_param)

# 返回最终结果

yield self.create_json_message({

"success": True,

"message": "数据处理完成",

"data": processed_data

})

```

## 4. 异常处理

### 4.1 参数验证异常

```python

# 验证必要参数

if not required_param:

raise ValueError("required_param 是必需的参数")

# 验证参数格式

if select_param not in ['option1', 'option2']:

raise ValueError("select_param 必须是有效的选项")

```

### 4.2 业务逻辑异常

```python

try:

# 业务逻辑

result = self._complex_operation(required_param, number_param)

except SpecificException as e:

# 处理特定异常

raise Exception(f"业务操作失败: {str(e)}")

except Exception as e:

# 处理其他异常

raise Exception(f"处理过程中发生错误: {str(e)}")

```

### 4.3 统一异常处理

```python

def invoke(self, toolparameters: dict[str, Any]) -> Generator[ToolInvokeMessage]:

try:

# 主要逻辑

# ...

except ValueError as e:

# 参数错误

raise Exception(f"参数错误: {str(e)}")

except Exception as e:

# 其他所有异常

raise Exception(f"工具执行失败: {str(e)}")

```

## 5. 完整示例

### 5.1 简单数据处理工具

```python

from collections.abc import Generator

from typing import Any

from dify_plugin import Tool

from dify_plugin.entities.tool import ToolInvokeMessage

class DataProcessorTool(Tool):

def invoke(self, toolparameters: dict[str, Any]) -> Generator[ToolInvokeMessage]:

try:

# 获取参数

input_data = tool_parameters.get('input_data')

operation = tool_parameters.get('operation', 'uppercase')

repeat_times = tool_parameters.get('repeat_times', 1)

# 参数验证

if not input_data:

raise ValueError("input_data 是必需的参数")

if operation not in ['uppercase', 'lowercase', 'reverse']:

raise ValueError("operation 必须是 uppercase、lowercase 或 reverse")

# 业务逻辑

result = self._process_data(input_data, operation, repeat_times)

# 返回结果

yield self.create_json_message({

"success": True,

"message": f"数据处理完成,操作类型: {operation}",

"data": {

"original": input_data,

"processed": result,

"operation": operation,

"length": len(result)

}

})

except Exception as e:

raise Exception(f"数据处理工具执行失败: {str(e)}")

def processdata(self, data: str, operation: str, repeat_times: int) -> str:

"""处理数据的内部方法"""

result = data

if operation == 'uppercase':

result = data.upper()

elif operation == 'lowercase':

result = data.lower()

elif operation == 'reverse':

result = data[::-1]

return result * repeat_times

```

对应的 YAML 配置:

```yaml

identity:

name: "data_processor"

author: "developer"

label:

en_US: "Data Processor"

zh_Hans: "数据处理器"

description:

human:

en_US: "Process text data with various operations."

zh_Hans: "使用多种操作处理文本数据。"

llm: "A tool for processing text data with operations like uppercase, lowercase, and reverse."

parameters:

- name: input_data

type: string

required: true

label:

en_US: Input Data

zh_Hans: 输入数据

human_description:

en_US: "The text data to process"

zh_Hans: "要处理的文本数据"

llm_description: "The input text data that will be processed"

form: llm

- name: operation

type: select

required: false

default: "uppercase"

options:

- value: "uppercase"

label:

en_US: "Uppercase"

zh_Hans: "大写"

- value: "lowercase"

label:

en_US: "Lowercase"

zh_Hans: "小写"

- value: "reverse"

label:

en_US: "Reverse"

zh_Hans: "反转"

label:

en_US: "Operation Type"

zh_Hans: "操作类型"

human_description:

en_US: "The operation to perform on the data"

zh_Hans: "对数据执行的操作类型"

llm_description: "The operation type: uppercase, lowercase, or reverse"

form: llm

- name: repeat_times

type: number

required: false

default: 1

label:

en_US: "Repeat Times"

zh_Hans: "重复次数"

human_description:

en_US: "Number of times to repeat the processed result"

zh_Hans: "重复处理结果的次数"

llm_description: "How many times to repeat the processed result"

form: llm

extra:

python:

source: tools/data_processor.py

```

### 5.2 API 调用工具示例

```python

import requests

from collections.abc import Generator

from typing import Any

from dify_plugin import Tool

from dify_plugin.entities.tool import ToolInvokeMessage

class APICallTool(Tool):

def invoke(self, toolparameters: dict[str, Any]) -> Generator[ToolInvokeMessage]:

try:

# 获取参数

url = tool_parameters.get('api_url')

method = tool_parameters.get('method', 'GET')

headers = tool_parameters.get('headers', {})

timeout = tool_parameters.get('timeout', 30)

# 参数验证

if not url:

raise ValueError("api_url 是必需的参数")

if method not in ['GET', 'POST', 'PUT', 'DELETE']:

raise ValueError("method 必须是 GET、POST、PUT 或 DELETE")

# 执行 API 调用

response = self._call_api(url, method, headers, timeout)

# 返回结果

yield self.create_json_message({

"success": True,

"message": f"API 调用成功,状态码: {response.status_code}",

"data": {

"status_code": response.status_code,

"headers": dict(response.headers),

"response": response.json() if response.content else None

}

})

except requests.exceptions.RequestException as e:

raise Exception(f"API 调用失败: {str(e)}")

except Exception as e:

raise Exception(f"API 工具执行失败: {str(e)}")

def callapi(self, url: str, method: str, headers: dict, timeout: int) -> requests.Response:

"""执行 API 调用的内部方法"""

response = requests.request(

method=method,

url=url,

headers=headers,

timeout=timeout

)

response.raise_for_status()

return response

```

## 6. 文件配置

extra 部分指定 Python 源文件位置:

```yaml

extra:

python:

source: tools/your_tool.py # 相对于插件根目录的路径

```

## 7. 开发最佳实践

1. 参数验证: 始终验证输入参数的有效性

2. 错误处理: 提供清晰具体的错误消息

3. 资源清理: 如果有资源需要清理,使用 try-finally 确保清理

4. 类型安全: 进行适当的类型检查和转换

5. 文档完整: 为所有参数提供完整的中英文文档

6. 性能考虑: 避免在工具中进行耗时操作,必要时提供进度反馈

## 8. 测试建议

- 测试正常流程和边界情况

- 测试参数缺失和无效的情况

- 测试异常处理流程

- 验证返回格式是否符合预期

通过以上教程,您可以快速掌握 Dify Plugin 的开发方法,创建自己的工具插件。



是否对你有帮助?

评论