dify插件简述
插件逻辑
在 dify
的插件管理中,整个体系逻辑比较混乱,这里使用该文本记录一下 dify
的插件管理逻辑。
插件概述
一个插件以及插件对应的工具的组成部分如下图所示:
--- title: 插件 --- flowchart LR plugin_id("plugin_id"):::green organization1("organization"):::animate plugin_name1("plugin_name"):::animate slash1("/"):::error plugin_id --> organization1 --> slash1 --> plugin_name1 plugin_unique_identifier("plugin_unique_identifier"):::green organization2("organization"):::animate slash2("/"):::error symbol2(":"):::error at2("@"):::error plugin_name2("plugin_name"):::animate version1("version"):::animate checksum1("checksum"):::animate plugin_unique_identifier --> organization2 --> slash2 --> plugin_name2 --> symbol2 --> version1 --> at2 --> checksum1 provider("full_provider"):::green organization3("organization"):::animate slash3_1("/"):::error plugin_name3("plugin_name"):::animate slash3_2("/"):::error provider_name3("provider"):::animate provider --> organization3 --> slash3_1 --> plugin_name3 --> slash3_2 --> provider_name3 classDef pink 1,fill:#FFCCCC,stroke:#333, color: #fff, font-weight:bold; classDef green fill: #696,color: #fff,font-weight: bold; classDef purple fill:#969,stroke:#333, font-weight: bold; classDef error fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5 classDef coral fill:#f9f,stroke:#333,stroke-width:4px; classDef animate stroke-dasharray: 9,5,stroke-dashoffset: 900,animation: dash 25s linear infinite;
插件在数据库中的管理逻辑
插件在数据库中,会涉及到以下几个重要的表:
plugin_declarations/plugins
在 plugin_declarations
表和 plugins
中,声明了插件的相关信息,其中最主要的字段有三个:
plugin_unique_identifier
插件的唯一ID,这个ID存在唯一索引不能重复;plugin_id
是标志插件的类型,但是他只是标志了插件的类型,实际上可以同时存在多个不同的版本;declaration
声明了插件的元数据信息。例如,他是一个model
还是tools
等。
1 | CREATE TABLE public.plugin_declarations ( |
例如,对于 langgenius/dingtalk
这个插件的 0.0.4
版本,他的数据如下:
1 | SELECT * |
1 | -[ RECORD 1 ]------------------------- |
在这里,我们需要仔细的查看一下 declaration
的内容,我保留了主干内容后如下:
由于这是一个工具类型的插件,所以从声明中我们可以看得出来,他在配置文件中声明了他在这个工具中所包含的 action
,并且指明了每个 action
的输入和输出。
1 | { |
整体的结构如下:
--- title: 插件配置 --- flowchart LR declaration("declaration"):::purple tool("tool"):::purple tools("tools"):::purple subgraph tool_array tool_01("tool_1"):::pink tool_02("tool_2"):::pink tool_03("..."):::pink tool_04("tool_n"):::pink end subgraph tool_info direction LR identity("identity"):::green description("description"):::green parameters("parameters"):::pink output_schema("output_schema"):::green has_runtime_parameters("has_runtime_parameters"):::green end subgraph parameter_info_list direction LR param_01("param_1"):::green param_02("param_2"):::green param_03("..."):::green param_04("param_N"):::green end subgraph parameter_info direction LR name("name"):::pink required("required"):::pink human_description("human_description"):::pink default("default"):::pink end declaration --> tool --> tools --> tool_array tool_01 --> tool_info tool_02 --> tool_info tool_03 --> tool_info tool_04 --> tool_info parameters --> parameter_info_list param_01 --> parameter_info param_02 --> parameter_info param_03 --> parameter_info param_04 --> parameter_info classDef pink 1,fill:#FFCCCC,stroke:#333, color: #fff, font-weight:bold; classDef green fill: #696,color: #fff,font-weight: bold; classDef purple fill:#969,stroke:#333, font-weight: bold; classDef error fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5 classDef coral fill:#f9f,stroke:#333,stroke-width:4px; classDef animate stroke-dasharray: 9,5,stroke-dashoffset: 900,animation: dash 25s linear infinite;
插件安装
在 dify
执行安装之后,会根据对应的类型,在对应的表中写入一行数据,这个比较直观,直接从表名就可以看出来具体类型,这里就不展开说了:唯一需要注意的是,有的插件可能不能提供工具调用,就不会在 tool_installations
插入数据。
--- title: 插件 --- flowchart LR classDef pink 1,fill:#FFCCCC,stroke:#333, color: #fff, font-weight:bold; classDef green fill: #696,color: #fff,font-weight: bold; classDef purple fill:#969,stroke:#333, font-weight: bold; classDef error fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5 classDef coral fill:#f9f,stroke:#333,stroke-width:4px; classDef animate stroke-dasharray: 9,5,stroke-dashoffset: 900,animation: dash 25s linear infinite; plugin_declarations("plugin_id"):::green agent_strategy_installations("agent_strategy_installations"):::animate ai_model_installations("ai_model_installations"):::animate plugin_installations("plugin_installations"):::animate tool_installations("tool_installations"):::animate plugin_declarations --> agent_strategy_installations plugin_declarations --> ai_model_installations plugin_declarations --> plugin_installations plugin_declarations --> tool_installations
插件和工具有什么区别?
先说结论:工具是插件的一个子集,看我们前面的
json
我们可以看到,一个插件的declaration
中可能包含了一个tools
数组,其实这个数组我个人倾向于是dify在实现的过程中实现了错误的逻辑。因为这个
tools
在前端展示时显示的名称为action
,代表了一个函数调用,我认为这里命名为actions
是更合理的。
在我们安装插件的过程中,如果该插件声明了 tools
,那么会向 tool_installations
表写入一行数据:
1 | CREATE TABLE public.tool_installations ( |
可以看到,在这里除了 plugin_id
和 plugin_unique_identifier
这两个关键字段之外,我们还多出来了一个额外的 provider
字段。
再回到我们前面的描述,我们会发现 dify
提供了一个接口用于查询 tool
:
1 | curl 'https://test-aiflow.woa.com/backend-api/console/api/workspaces/current/tool-provider/builtin/aiflow/google_api/google_api/tools' |
可以看到在这个 curl 中我们的参数是 /aiflow/google_api/google_api
而不是单纯的 ``/aiflow/google_api`