2026年7月2日 周四晚上19:30,报名腾讯会议了解“如何构建自进化的动态知识库(Brain)”(限30人)
免费POC, 零成本试错
FDE知识库

FDE知识库

学习大模型的前沿技术与行业落地应用


收藏

扩展 Dify 内置工具集,打造自己独有的 AI Agent 工作站

发布日期:2024-08-08 17:03:46 浏览次数: 6965
作者:数翼

微信搜一搜,关注“数翼”

Dify 提供了很多的内置工具,让我们在创建 Agent 的时候可以做更多的事情。 看着琳琅满目的工具,我们是不是也想接入自己独特的工具呢?

今天演示下如何构建自己的工具并添加到 Dify 内置工具集里面。

运行 Dify

如何运行 Dify(源码和容器运行)我这里就不赘述了,大家可以参考前面这两篇文章:

  • • Dify + FastAPI 创建自定义工具

  • • Dify+谷歌翻译 使用中文提示词实现本地文生图

扩展工具

厂商(供应商)和工具

首先我们了解下 Dify 内置工具的两个概念:厂商 和 工具

你要扩展工具的话,首先要注册一个厂商,一个厂商下面可以有多个工具,在你选择工具的时候,工具会按照厂商分组。

扩展方式

扩展 Dify 工具和厂商分了两部分:

  • • 使用 yaml 文件描述其参数的功能

  • • 使用 python 文件编写厂商注册函数和工具实现

不如定义了两个工具,最终的目录结构大概是这样:

├── _assets
│   └── icon.svg
├── shuyi.py
├── shuyi.yaml
└── tools
    ├── shuyi_excel.py
    ├── shuyi_excel.yaml
    ├── shuyi_test.py
    └── shuyi_test.yaml

定义厂商

厂商定义 yaml

这个 yaml 将包含工具供应商的信息,包括供应商名称、图标、作者等详细信息,以帮助前端灵活展示。

在 core/tools/provider/builtin 目录下创建一个文件夹,比如 shuyi,然后软件 shuyi.yaml

在文件里面增加关于工具的描述、以及展示的图标。

identity:
  author: Shuyi
  name: shuyi
  label:
    en_US: Shuyi
    zh_Hans: 数翼
    pt_BR: Shuyi
  description:
    en_US: Shuyi tools
    zh_Hans: 数翼自定义工具集
    pt_BR: Shuyi tools
  icon: icon.svg
  tags:
    - search
    - productivity

授权定义

如果工具需要授权,那么我们还需要定义授权参数

授权一般都是填写这个工具的密钥(API Key),比如谷歌搜索、DALL-E 绘画,通过授权可以完成工具的安全调用。

如果配置了授权在工具详情就会出现一个授权按钮:

点击可以看到授权参数的填写:

我们自定义工具增加两个授权参数:

  • • 服务器地址:我们自己部署服务的地址

  • • API Key:用于验证调用的合法性

定义授权参数 shuyi_api_key 和 shuyi_api_url,表单类型分别是secret-inputtext-input。Yaml 增加如下内容:

credentials_for_provider:
  shuyi_api_key:
    type: secret-input
    required: true
    default: "123456"
    label:
      en_US: Shuyi API key
      zh_Hans: Shuyi API key
      pt_BR: Shuyi API key
    placeholder:
      en_US: Please input your Shuyi API key
      zh_Hans: 请输入你的 Shuyi API key
      pt_BR: Please input your Shuyi API key
    help:
      en_US: Get your Shuyi API key from Shuyi
      zh_Hans:  Shuyi 获取您的 Shuyi API key
      pt_BR: Get your Shuyi API key from Shuyi
    url: https://blog.tupu.work/

  shuyi_api_url:
    type: text-input
    required: true
    default: http://localhost:8000
    label:
      en_US: Shuyi API url
      zh_Hans: Shuyi API 地址
      pt_BR: Shuyi API url
    placeholder:
      en_US: Please input your Shuyi API url
      zh_Hans: 请输入你的 Shuyi API 服务地址
      pt_BR: Please input your Shuyi API url
    help:
      en_US: Get your Shuyi API url from Shuyi
      zh_Hans:  Shuyi 获取您的 Shuyi API url
      pt_BR: Get your Shuyi API url from Shuyi
    url: https://blog.tupu.work/

这时候我们就可以看到工具的授权参数了:

点击可以看到授权表单:

是否必须授权和调用外部服务

自定义工具当然不是必须需要授权或者调用服务的。

你可以把所有逻辑都在你的工具代码里面实现,这样比较简单,但是也有一些弊端:

  • • 工具代码过于复杂,耦合性过高,也不利于测试

  • • 插件依赖等问题可能和 Dify 冲突,升级安装也不好保证

  • • 在 Dify 中计算不方便分布式扩容

如果我们的工具功能比较简单,可以不用认证这些的,就比如 JSON 相关的工具:

如果要实现的工具功能复杂,还是建议单独写一个服务,让 Dify 来调用。

工具实现

工具实现也是分为定义文件 Yaml 和功能实现类两部分。

我们再 shuyi/tools 目录下创建 shuyi_test.yaml 文件如下,内容主要就是工具描述、以及参数两部分。

identity:
  name: shuyi_test
  author: Shuyi
  label:
    en_US: ShuyiTest
    zh_Hans: 数翼工具测试
    pt_BR: ShuyiTest
description:
  human:
    en_US: A tool for testing Dify message type and input parameters.Input should be a search query.
    zh_Hans: 用于测试Dify消息类型和输入参数的工具。
    pt_BR: A tool for testing Dify message type and input parameters.Input should be a search query.
  llm: A tool for testing Dify message type and input parameters.Input should be a search query.
parameters:
  - name: query
    type: string
    required: true
    label:
      en_US: Query string
      zh_Hans: 查询语句
      pt_BR: Query string
    human_description:
      en_US: used for searching
      zh_Hans: 用于搜索内容
      pt_BR: used for searching
    llm_description: key words for searching
    form: llm

Dify 支持的参数有四种类型:

  • • string

  • • number

  • • boolean

  • • select

这块儿我们不在赘述,需要的话可以参考官方文档[2]

值得注意的是 form 这个参数, form 表示表单类型,目前支持llmform两种类型,分别对应 Agent 自行推理和前端填写。

Agent 自行推理的意思就是有 LLM 确定字段的值。

工具的实现类 shuyi_test.py 最简单的莫过于直接返回一个固定的消息。

from typing import AnyUnion

from core.tools.entities.tool_entities import ToolInvokeMessage
from core.tools.tool.builtin_tool import BuiltinTool

class ShuyiTestTool(BuiltinTool):
    def _invoke(self,
                user_id: str,
                tool_parameters: dict[strAny],
                
) -> Union[ToolInvokeMessage, list[ToolInvokeMessage]]:
        return self.create_link_message('hello')

当然现实中肯定不会这么简单,我们一般要获取插件认证的参数:

api_url = self.runtime.credentials['shuyi_api_url'],
params = {
    "api_key": self.runtime.credentials['shuyi_api_key'],
    "type": tool_parameters['type'],
    "query": tool_parameters['query'],
}

调用外部服务:

response = requests.get(url=api_url, params=params)

解析调用结果的服务返回一般逻辑比较复杂,我们可以使用一个单独的函数实现:

def _parse_response(self, response: dict) -> dict:
    result = {}
    # logics
    return result

然后返回:

response.raise_for_status()
valuable_res = self._parse_response(response.json())
return self.create_json_message(valuable_res)

我写了这样一个模板,大家可以基于这个模板来创建自己的工具

from typing import AnyUnion

import requests

from core.tools.entities.tool_entities import ToolInvokeMessage
from core.tools.tool.builtin_tool import BuiltinTool

class ShuyiTestTool(BuiltinTool):

    def _parse_response(self, response: dict) -> dict:
        result = {}
        # logics
        return result

    def _invoke(self,
                user_id: str,
                tool_parameters: dict[strAny],
                
) -> Union[ToolInvokeMessage, list[ToolInvokeMessage]]:
        api_url = self.runtime.credentials['shuyi_api_url'],
        params = {
            "api_key": self.runtime.credentials['shuyi_api_key'],
            "type": tool_parameters['type'],
            "query": tool_parameters['query'],
        }
        response = requests.get(url=api_url, params=params)
        response.raise_for_status()
        valuable_res = self._parse_response(response.json())
        return self.create_json_message(valuable_res)

消息类型

Dify 提供了几种消息类型[3], 在我看来都是文本(Markdown)类型的封装,下面是对应的封装方法:

  • • 图片:create_image_message(self, image: str, save_as: str = '')

  • • 链接:create_link_message(self, link: str, save_as: str = '')

  • • 文本:create_text_message(self, text: str, save_as: str = '')

  • • Blob: create_blob_message(self, blob: bytes, meta: dict = None, save_as: str = '')

  • • JSON: create_json_message(self, object: dict)

当然,也支持返回多个消息,用数组表示即可。

文本

文本类型其实是 Markdown 。

我们创建一个包含图片、列表、标题的 Markdown 消息:

return self.create_text_message(
                """### User message
%s
### 生成式 AI 应用创新引擎
开源的 LLM 应用开发平台,轻松构建和运营生成式 AI 原生应用。
- 生成式 AI
- 应用开发框架



#### RAG Pipeline
"""
 % params['query'])

效果如下:

图片消息

图片消息需要传递一个 地址:

image_path = 'https://buffer.com/cdn-cgi/image/w=1000,fit=contain,q=90,f=auto/library/content/images/size/w1200/2023/10/free-images.jpg'
return self.create_image_message(image_path)

效果如下:

Blob 消息

文档上说 Blob 消息可以返回文件的原始数据,如图片、音频、视频、PPT、Word、Excel 等。

但是实际测试下来效果不太对。

with open(file_path, 'rb'as mp4:
    byte_arr = mp4.read()

return self.create_blob_message(
    blob=byte_arr,
    meta={
        # 'mime_type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
        'mime_type''video/mp4',
        'file_name''xxx.mp4',},
    save_as=self.VARIABLE_KEY.IMAGE.value
)

效果并没有显示出文件内容,或者下载链接:

经过尝试,如果想要返回文档,发现只有使用 Markdown 来实现一个下载超链接。

[something.xlsx](https://yourhost/xxx.xlsx

链接消息

连接类型的消息只需要出入一个地址,

return self.create_link_message(link)

返回的内容就是:Link: 后面跟上你的链接:

多条消息

Dify 还支持多条消息的返回,使用数组即可:

messages = [
    self.create_text_message("""### User message ...""" % params['query']),
    self.create_json_message({'result''success''text''This is a message'}),
    self.create_image_message(image_path),
    self.create_link_message(link),
    ...
]

效果也是多条消息的拼接:

使用工具

当我们编写好工具类,重启服务就可以使用刚刚创建的工具类了。

添加节点的时候找到并选择自己的工具:

就可以和 Dify 提供的默认工具一样用了。

总结

相比于在 UI 上创建基于 OpenAPI 的自定义工具,通过代码来扩展供应商和工具集更使能方便我们完成 工具的积累和传播,在使用上也有更大的可能性。

通过扩展工具,基于 Dify 打造自己独特的 AI 工作站,同时还可以复用自己之前的工具积累,而不仅仅是通用的 AI Agent 工作站。

53AI,企业落地大模型首选服务商

产品:场景落地咨询+大模型应用平台+行业解决方案

承诺:免费POC验证,效果达标后再合作。零风险落地应用大模型,已交付160+中大型企业

联系我们

售前咨询
186 6662 7370
预约演示
185 8882 0121

微信扫码

添加专属顾问

回到顶部

加载中...

扫码咨询

扫码登录
登录即表示您同意《53AI网站服务协议》
服务协议

欢迎您使用【53AI 官方网站】(以下简称“本网站”或“我们”)。本《会员服务协议》(以下简称“本协议”)是您(以下简称“会员”或“用户”)与【深圳市博思协创网络科技有限公司】之间关于注册、登录及使用本网站会员服务所订立的法律协议。

在您注册或登录前,请务必审慎阅读、充分理解各条款内容,特别是免除或限制责任的条款、知识产权条款、争议解决条款等。此类条款将以加粗形式提示您注意。 当您通过微信公众号授权、手机验证码验证或其他方式成功登录本网站时,即视为您已完全理解并同意接受本协议的全部内容。

一、 定义

本网站:指由【深圳市博思协创网络科技有限公司】运营的,域名为【53ai.com】的网站及相关移动端页面。

会员服务:指本网站向注册会员提供的知识库文章查阅、内容检索及其他相关增值服务。

知识库内容:指本网站发布的包括但不限于文字、图表、数据、研究报告、行业分析等数字化内容资源。

二、 账号注册与登录

登录方式:本网站支持以下登录方式,您可根据实际情况选择:

微信公众号授权登录:您同意将您的微信OpenID信息授权给本网站,用于创建或关联会员账号。

手机验证码登录:您需提供真实有效的手机号码,并通过短信验证码完成身份验证与登录/注册。

账号安全:您的账号仅限您本人使用,禁止赠与、借用、租用、转让或售卖。因您保管不善导致的账号被盗、密码泄露等损失,由您自行承担。

实名认证:根据相关法律法规要求,我们可能要求您在特定功能下完成实名认证。如您拒绝提供,可能无法使用部分或全部服务。

未成年人保护:若您未满18周岁,请在法定监护人的陪同下阅读本协议,并在征得监护人同意后使用本服务。

三、 服务内容与规范

知识库查阅权限:会员登录后,有权按照其会员等级对应的权限范围,在线浏览、检索本网站知识库中的相关文章及内容。

服务变更:我们有权根据业务发展需要,调整、变更或终止部分服务内容,并将以网站公告、公众号消息等方式提前通知。

禁止行为:您在使用服务时不得实施以下行为:

利用技术手段批量爬取、下载、转存知识库内容;

将知识库内容用于商业目的或未经授权地向第三方传播;

干扰本网站正常运行或侵犯其他用户合法权益;

发布违法违规信息或从事违反公序良俗的活动。

四、 知识产权声明

权利归属:本网站知识库中的排版设计、软件代码等内容的知识产权均归【公司全称】或原权利人所有,受《中华人民共和国著作权法》等法律保护。

有限许可:本网站授予会员一项非独占、不可转让、不可转授权的普通许可,仅限于个人学习、研究之目的在线查阅知识库内容。

侵权追责:未经书面许可,任何单位或个人不得以任何形式复制、转载、摘编、镜像、汇编或以其他方式使用上述内容。一经发现,我们保留追究其法律责任的权利。

五、 个人信息保护

我们重视对您个人信息的保护。关于我们如何收集、使用、存储和保护您的个人信息,请单独阅读 《隐私政策》。

您通过微信公众号授权或手机号验证所提供的信息,我们将严格按照《个人信息保护法》的规定处理,仅用于身份识别、服务提供及安全验证等必要用途。

您可以随时通过网站设置或联系客服行使查阅、更正、删除个人信息及撤回授权同意的权利。

六、 免责声明

内容准确性:知识库内容仅供参考,不构成专业建议。我们不对其完整性、准确性、时效性作任何明示或暗示的保证,您应自行判断并承担使用风险。

不可抗力:因自然灾害、政策法规变化、网络故障、第三方平台接口异常(如微信接口维护、运营商短信通道故障)等不可抗力导致的服务中断或延迟,我们不承担违约责任。

第三方链接:本网站可能包含指向第三方网站的链接,该等网站的内容和服务不受我们控制,请您自行甄别风险。

七、 违约责任

如您违反本协议约定,我们有权视情节采取警告、限制功能、暂停服务、注销账号等措施,并保留要求赔偿损失的权利。

如因您的违约行为导致我们遭受行政处罚、第三方索赔或商誉损失,您应承担全部赔偿责任(包括但不限于罚款、赔偿金、律师费、公证费等)。

八、 法律适用与争议解决

本协议的订立、执行和解释均适用中华人民共和国大陆地区法律。

因本协议产生的或与本协议有关的任何争议,双方应友好协商解决;协商不成的,任何一方均可向【公司所在地】有管辖权的人民法院提起诉讼。

九、 其他

本协议构成双方就本服务达成的完整协议,取代此前任何口头或书面约定。

本协议任一条款被认定为无效或不可执行的,不影响其他条款的效力。

我们对本协议享有最终解释权,并在法律允许的范围内保留随时修改的权利。修改后的协议一经公布即生效,继续使用服务即视为同意修订内容。


已查阅