首页 > 教程攻略 > ai资讯 >Dify + FastAPI 创建自定义工具

Dify + FastAPI 创建自定义工具

来源:互联网 时间:2026-07-18 13:31:09

Dify 的流程编排能力和内置工具确实丰富,但真到项目落地时,总有些个性化需求需要自己动手。最常见的一个场景,就是和我们私有的服务做集成。今天咱们就从头走一遍,看看怎么用 FastAPI 开发一个自定义工具,挂到 Dify 上用。

Dify + FastAPI 创建自定义工具

这篇文章会覆盖以下几个关键环节:

  • • 源码运行 Dify
  • • 容器挂载插件代码
  • • FastAPI 服务的搭建
  • • 自定义工具的创建与配置
  • • JSON 解析节点的使用
  • • 条件判断与汇总节点的组合

先直接看下最终效果,心里有个底。

容器运行中间件

其实用中间件和源码分离的方式来跑 Dify,并不是非做不可的一步。你也可以直接参考官方文档,用源码启动本地服务。

先克隆项目:

git clone https://github.com/langgenius/dify.git
cd dify

复制环境变量文件:

cp middleware.env.example middleware.env

如果本机已经部署了 Postgresql 之类的组件,记得改下端口,避免冲突。比如这样调一下:

EXPOSE_POSTGRES_PORT=5542
EXPOSE_REDIS_PORT=6389
EXPOSE_SANDBOX_PORT=8594
EXPOSE_SSRF_PROXY_PORT=3528
EXPOSE_WEA VIATE_PORT=8580

然后用 Compose 启动容器:

docker compose -f docker-compose.middleware.yaml up -d

检查了一下 compose 文件,里面确实引用了 middleware.env,但在我的环境中没生效。如果有同样踩坑的,可以试试下面这条命令,手动指定下 env 文件:

docker-compose --env-file middleware.env -f docker-compose.middleware.yaml up -d

正常运行的话,输出大致是这样:

> docker-compose --env-file middleware.env -f docker-compose.middleware.yaml up
[+] Building 0.0s (0/0)
[+] Running 6/6
 ✔ Network docker_default             Created                0.1s
 ✔ Network docker_ssrf_proxy_network  Created                0.0s
 ✔ Container docker-ssrf_proxy-1      Created                0.3s
 ✔ Container docker-sandbox-1         Created                0.2s
 ✔ Container docker-db-1              Created                0.2s
 ✔ Container docker-redis-1           Created                0.2s

源码启动应用

Dify 的应用代码在 api 目录下,进去启动就行。

cd api

先修改 .env 文件,设置 SECRET_KEY

MacOS 系统的操作:

openssl rand -base64 42
sed -i '' 's/SECRET_KEY=.*/SECRET_KEY=/g' .env

Linux 系统的操作:

openssl rand -base64 42
sed -i 's/SECRET_KEY=.*/SECRET_KEY=/' .env

不习惯命令的话,直接打开文件手动编辑也一样。

初始化Python环境

用 Conda 创建一个干净的新环境并激活:

conda env create -n dify python=3.10
conda activate dify

Dify 用 Poetry 管理依赖,安装它并拉取依赖包:

pip install poetry
poetry install

数据迁移和初始化:

# poetry shell
flask db upgrade

然后启动应用:

flask run --host 0.0.0.0 --port=5001 --debug

运行前端

前端的启动相对简单:

cd web
pnpm install
pnpm start

启动成功的输出类似:

> pnpm start

> dify-web@0.6.16 start dify/web
> cp -r .next/static .next/standalone/.next/static && cp -r public .next/standalone/public && cross-env PORT=$npm_config_port HOSTNAME=$npm_config_host node .next/standalone/server.js

  ▲ Next.js 14.2.4
  - Local:        http://localhost:3000
  - Network:      http://0.0.0.0:3000

 ✓ Starting...
 ✓ Ready in 144ms

浏览器访问 http://localhost:3000 就能看到界面了。如果是新数据库,需要先设置用户名和密码。

容器运行 Dify

自定义开发 Dify 组件通常只需要新增文件,所以不一定要用源码运行。通过文件挂载的方式添加代码,会更省事。

比如在 Compose 文件里加一个 volume,效果一样:

    volumes:
      # Mount the storage directory to the container, for storing user files.
      - ./volumes/app/storage:/app/api/storage
      - ./external_data_tool/weather_search:/app/api/core/external_data_tool/weather_search

IDE 运行

对 Dify 接口不熟悉的同学,肯定希望在开发过程中能调试。在喜欢的 IDE 里,用 Flask 程序的标准方式启动调试即可。

比如用 PyCharm,调试配置参考如下:

自定义工具

好,进入正题,看看怎么自定义工具。

FastAPI 服务

先实现一个 FastAPI 服务,让 Dify 来调用。

逻辑很简单:

  • • 实现一个简单的认证,密码设为 123456
  • • 接收并打印收到的消息
  • • 返回一个简单的 JSON

代码直接贴出来,不啰嗦了:

from fastapi import FastAPI, Body, HTTPException, Header
from fastapi.responses import FileResponse
from pydantic import BaseModel

app = FastAPI(servers=[
    {"url": "http://localhost:8000"}
])

class InputData(BaseModel):
    prompt: str
    params: dict

@app.post("/api/dify/receive")
async def dify_receive(data: InputData = Body(...), authorization: str = Header(None)):
    """
    Receive API query data from Dify.
    """
    expected_api_key = "123456" 
    auth_scheme, _, api_key = authorization.partition(' ')

    if auth_scheme.lower() != "bearer" or api_key != expected_api_key:
        raise HTTPException(status_code=401, detail="Unauthorized")
    return {
        "result": "ok"
    }

启动应用:

uvicorn main:app --reload --host 0.0.0.0

访问 http://127.0.0.1:8000/docs#/,就能看到 Swagger 文档。

再访问 http://127.0.0.1:8000/openapi.json,可以看到 OpenAPI 格式的 JSON 文件。把它整个拷贝下来,后面要用。

添加自定义工具

回到 Dify 界面,点击 工具 -> 自定义 -> 创建自定义工具

在弹出的窗口中填写工具名称,然后把刚才拷贝的 JSON 粘贴进去。

鉴权方式选择 API Key -> Bearer,然后保存。

接下来创建一个空白应用,选择 聊天助手工作流编排 类型。

右键点击画布,添加节点,选择我们刚刚创建的自定义节点。

节点配置如下:

当然,认证信息也可以在工具创建的时候直接配置好。

连接好节点,发个消息测试一下。可以看到,数据已经按照预期返回了。

返回信息默认按文本显示,而且支持 Markdown 格式。这意味着我们可以用它来展示更丰富的数据,比如超链接、文件下载、图片等。

细心看上面的截图,会发现回复信息不是那么干净,有引号之类的字符。

JSON解析节点

刚才提到,虽然返回内容支持 Markdown 展示,但内容要么是 JSON,要么字符串带着引号。如何干净地展示文件内容呢?这就轮到 JSON 解析节点出场了。

先把后端返回改成这样:

return {
    'success': True,
    'text': data.prompt,
    'image': ''
}

然后添加一个 JSON 解析节点。

流程和节点的具体配置如下:

再测试一下,聊天窗口就能干净地返回图片了。

条件判断

接下来看看怎么做分支逻辑,实现这样一个场景:

  • • 当请求 success 时,显示图片
  • • 否则,显示 text 的内容

增加一个条件分支节点。

把之前配置好的 JSON 解析 节点放在 IF 分支后面,再添加另一个 JSON 解析 节点放在 ELSE 分支后面。

然后增加一个 变量聚合器 节点,不需要额外配置,直接连线即可。

调整后端返回代码:

   return {
        'success': data.prompt=='hello',
        'prompt': data.prompt,
        'xlsx': '[Prompts.xlsx](http://localhost:3001/api/v1/openai/chat/completions)',
    'image': ''
        'text': """## 生成式 AI 应用创新引擎..."""

调试运行,在聊天窗口输入 world,就会得到文本回复;如果输入 hello,则会展示图片。

结语

通过自定义工具,再配合流程编排、JSON 解析这些节点,常见的业务逻辑处理基本都能覆盖了。

唯一美中不足的是,Dify 对消息的入参和出参定义还是比较克制,需要我们用 AI 时代的程序编排思维去使用它。另外,目前还不支持上传文件(只能上传图片),所以一些文件处理功能——比如之前做过的 Excel 问答填写——暂时还不太好集成。