你是否在使用 Dify 搭配 DeepSeek 大模型时,被多余的 think 标签困扰?本文以 Windows 环境为例,为你带来保姆级 Dify 插件开发教程。从环境准备、项目构建,到代码编写、调试打包,详细展示如何开发一个去除 think 标签的插件。无论你是新手还是有一定经验的开发者,都能从中获得实用的开发技巧和经验。快来一起开启 Dify 插件开发之旅吧!

一、背景简介

在使用 Dify 搭配 DeepSeek 大模型的过程中,许多用户常常觉得 DeepSeek 的 think 标签有些多余。借此契机,本文将详细演示 Dify 插件开发,以帮助大家解决这一困扰。本次 plugin_demo 项目的目标是实现对 DeepSeek 模型节点输出内容的清洗。需要注意的是,本次开发以 Windows 环境为例进行演示。

二、环境准备

开发 Dify 插件需要进行以下准备。

  • Dify 插件脚手架工具
  • Python 环境,版本号 ≥ 3.12

2.1 脚手架准备

访问 Dify Plugin CLI 项目地址,下载并安装最新版本号和对应操作系统的工具。

接下来以windows为例,展示如何开发dify插件。

windows 下载 dify-plugin-windows-amd64.exe

下面需要在windows自带的powershell中执行 。

脚手架检查

切换到 dify-plugin-windows-amd64.exe 所在目录,然后复制以下代码执行:

./dify-plugin-windows-amd64.exe version 

此时版本是0.0.6版本,dify更新比较块,不过大致是相似的。

三、构建项目

3.1 插件初始化

./dify-plugin-windows-amd64.exe plugin init 

3.2 基本信息填写

这里需要依次填写三个内容

  • plugin name 插件名称
  • author 作者信息
  • description 详细

按照提示依次输入,enter进入下一步。

3.3 开发语言选择

选择开发语言,这里使用Python为例

3.4 选择模板

本次演示的是tool开发

3.5 权限选择

上下移动,tab键选择。开发tools 必选tools、apps、endpoints权限,存储、大模型根据需求来选择。

完成选择后,项目框架就被自动创建完成。

四、插件代码编写

以pychram 打开plugin_demo工程。

4.1重点文件介绍

4.1.1 环境

.env 文件是用于调试的,拷贝 .env.example 文件并重命名为 .env,将获取的远程服务器地址和调试 Key 等信息填入其中。

INSTALL_METHOD=remote
REMOTE_INSTALL_HOST=YOUR_HOST
REMOTE_INSTALL_PORT=5003
REMOTE_INSTALL_KEY=****-****-****-****-****

port 与 key 可以在dify插件页面找到,如下:

4.1.2 provider

provider目录中有两个文件,.py.yaml

yaml文件 主要是tools的描述与作者。

py文件 是供应商的代码,如果你的插件用到其他供应商的api key,会做验证,如果验证不通过会抛出异常。若未用到则无需填写。

4.1.3 tools

以下是本次项目的.yaml文件

identity:
  name: plugin_demo
  author: fengjian
  label:
    en_US: plugin_demo
    zh_Hans: plugin_demo
    pt_BR: plugin_demo
description:
  human:
    en_US: plugin demo by fengjian 
    zh_Hans: plugin demo by fengjian 
    pt_BR: plugin demo by fengjian 
  llm: plugin demo by fengjian 
parameters:
  - name: deepseek_output
    type: string
    required: true
    label:
      en_US: deepseek output string
      zh_Hans: deepseek输出内容
      pt_BR: deepseek output string
    human_description:
      en_US: plugin demo by fengjian 
      zh_Hans: plugin demo by fengjian 
      pt_BR: plugin demo by fengjian 
    llm_description: plugin demo by fengjian 
    form: llm
extra:
  python:
    source: tools/plugin_demo.py
  • identity 包含了工具的基本信息,包括名称、作者、标签、描述等。
  • parameters 参数列表
    • name (必填)参数名称,唯一,不允许和其他参数重名。
    • type (必填)参数类型,目前支持stringnumberbooleanselectsecret-input 五种类型,分别对应字符串、数字、布尔值、下拉框、加密输入框,对于敏感信息,请使用secret-input类型。
    • label(必填)参数标签,用于前端展示。
    • form (必填)表单类型,目前支持llmform两种类型。
      • 在 Agent 应用中,llm 表示该参数 LLM 自行推理,form 表示要使用该工具可提前设定的参数。
      • 在 Workflow 应用中,llmform 均需要前端填写,但 llm 的参数会做为工具节点的输入变量。
    • required 是否必填
      • llm 模式下,如果参数为必填,则会要求 Agent 必须要推理出这个参数。
      • form 模式下,如果参数为必填,则会要求用户在对话开始前在前端填写这个参数。
    • options 参数选项
      • llm 模式下,Dify 会将所有选项传递给 LLM,LLM 可以根据这些选项进行推理。
      • form 模式下,typeselect 时,前端会展示这些选项。
    • default 默认值。
    • min 最小值,当参数类型为number时可以设定。
    • max 最大值,当参数类型为number时可以设定。
    • human_description 用于前端展示的介绍,支持多语言。
    • placeholder 字段输入框的提示文字,在表单类型为form,参数类型为stringnumbersecret-input时,可以设定,支持多语言。
    • llm_description 传递给 LLM 的介绍。为了使得 LLM 更好理解这个参数,请在这里写上关于这个参数尽可能详细的信息,以便 LLM 能够理解该参数。

.py文件是插件的核心代码 ,下面在具体开发中细说。

4.1.4 其他

requirements.txt 文件是用来规定python代码用到的包,如果用到了其他依赖,在这里添加。

icon.pvg 是插件图标,可以自己修改

4.2 具体开发

本次的目标是把think标签去掉,因此代码很简单,只需要split即可。这里是插件代码的主体,具体开发全在这里完成。

from collections.abc import Generator
from typing import Any

from dify_plugin import Tool
from dify_plugin.entities.tool import ToolInvokeMessage

class PluginDemoTool(Tool):
    def _invoke(self, tool_parameters: dict[str, Any]) -> Generator[ToolInvokeMessage]:
        context =  tool_parameters['deepseek_output']
        if '</think>' in context :
            result = context.split('</think>')[1]
        else:result = context
        yield self.create_text_message(result)

需要注意的是最后的返回值。下一节细说插件的输入输出。

4.3 插件input、output

很多人在使用tools或者其他结点时常见的问题就是搞不清楚结点的输入输出情况。

每个结点对入参都有要求,有的结点能输出多种内容,做好前一个节点的出参与下一节点的入参匹配,大部门使用上就不会出现问题。

4.3.1 插件开发input

插件开发时,需要规定插件的input,具体在 tools目录中的.yaml文件 。

parameters name 是参数名,本次案例是 deepseek_output ,因此在代码中使用 context = tool_parameters['deepseek_output'] 来获取入参。在dify tools中 支持五种入参:stringnumberbooleanselectsecret-input

4.3.2 插件开发output

Dify 支持文本 链接 图片 文件BLOB JSON 等多种消息类型,你可以通过以下不同的接口返回不同类型的消息。

在默认情况下,一个插件在 workflow 中的输出会包含 files text json 三个固定变量,且你可以通过下面的方法来返回这三个变量的数据。

例如使用 create_image_message 来返回图片,但是同时插件也支持自定义的输出变量,从而可以更方便地在 workflow 中引用这些变量。

以下是每种返回值的demo

  • 文本
  def create_text_message(self, text: str) -> ToolInvokeMessage:
        pass
  • 链接
 def create_link_message(self, link: str) -> ToolInvokeMessage:
        pass
  • 图片
def create_image_message(self, image: str) -> ToolInvokeMessage:
        pass
  • 文件BLOB

  • blob 文件的原始数据,bytes 类型。

  • meta 文件的元数据。如果开发者需要明确的文件类型,请指定mime_type,否则 Dify 将使用octet/stream作为默认类型。

    def create_blob_message(self, blob: bytes, meta: dict = None) -> ToolInvokeMessage:
        pass
  • JSON

如果你需要返回一个格式化的 JSON,可以使用以下接口。这通常用于 workflow 中的节点间的数据传递。在 agent 模式中,大部分大模型也都能够阅读和理解 JSON。

  • object 一个 Python 的字典对象,会被自动序列化为 JSON。
    def create_json_message(self, json: dict) -> ToolInvokeMessage:
        pass
  • 变量

对于非流式输出的变量,你可以使用以下接口返回,如创建多份,后者将覆盖前者。

    def create_variable_message(self, variable_name: str, variable_value: Any) -> ToolInvokeMessage:
        pass
  • 流式变量

如果你想以“打字机”效果输出一段文字,可以使用流式变量输出文本。如果你在 chatflow 应用中使用 answer 节点并引用了该变量,那么文本将以“打字机”的效果输出。但目前该方法仅支持字符串类型的数据。

    def create_stream_variable_message(
        self, variable_name: str, variable_value: str
    ) -> ToolInvokeMessage:

五、插件调试

至此插件开发已经完成,下面开始使用。先确保.env文件的信息按照上述需求填好。调试时,只要执行main.py文件即可。

如上图,插件就被提交到dify插件中。在插件列表中可以找到这个插件:

新建一个工作流进行测试

以下是整体工作流。

测试执行,观察plugin_demo的输入、输出确实把deepseek的标签解决了。

六、插件打包

打包时,依然使用powershell执行

 ./dify-plugin-windows-amd64.exe plugin package ./plugin_demo

出现一下说明打包成功

只需要把difypkg文件上传到dify的插件中即可。

如果你有兴趣,或者已经在用Dify了,欢迎添加作者微信,我们组织了一个Dify交流群,欢迎来提问或者分享你的经验。 关注公众号 dataspeed ,更能及时获取最近文章,更有作者联系方式

七、总结

插件开发有需要注意以下:

  • 使用脚手架做项目初始化

  • 做好入参与出参的设定

有插件开发的能力,可以让你的dify能力更上一层楼

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐