从零开始之Dify二次开发篇



前言

Dify是一个对接大模型的脚手架,Dify对应的文档地址为:Dify传送门。基于Docker Compose的Dify部署: Dify Docker Compose部署篇传送门。基于源码的Dify部署:Dify 源码部署篇传送门。本文将详细描述基于Dify的二次开发流程,适合小白食用。


一、工具列表

基于Dify二次开发需要准备的工具列表有:

  • windows11
  • vmware
  • centos
  • docker
  • docker-compose
  • dify
  • vscode
  • python 3.10.x
  • node.js 18.x
  • final shell

二、开发流程

1. 基础环境部署

vmware、centos、docker、docker-compose 部署可参考从零开始之Dify部署篇 搭建流程1-5步骤即可。finalshell是方便远程连接管理linux服务器的工具,Finalshell官方下载传送门

2. 部署Dify中间件

2.1. 下载Dify

将Dify代码从github下载至服务器,或者通过http的方式下载Dify的代码的zip文件后,上传至服务器解压缩。

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

也可以通过历史TAG进行拉取对应版本的代码。
dify的TAG版本

2.2. 将dify组件镜像转移到阿里云(可选)

因为国内docker限制的原因,如果不能直接通过docker将官方的镜像拉取下来,则可利用github action 同步到阿里云或国内其他云使用。

2.2.1. 阿里云容器镜像服务开通

开通阿里云容器镜像服务:阿里云容器镜像服务传送门
阿里云容器镜像仓库配置:阿里云容器镜像仓库配置传送门

2.2.2. 设置docker访问信息

在个人版中设置 docker 访问密码,账户就是阿里云的登录账号。
docker访问信息

2.2.3. 创建命名空间

创建命名空间

2.2.4. fork转储的github项目

转储docker镜像的github项目地址为:github项目传送门

2.2.5. 信息配置

进入对应的自己的github项目,进入Settings标签页面
Setting标签页
在Settings页面的左导航栏中找到【Security】-【Secrets and variables】-【Actions】,然后在右侧页面部分找到【New repository secret】按钮后进行添加。
仓库密钥配置
需要添加的信息如下所示:

  • ALIYUN_REGISTRY_USER:阿里云用户
  • ALIYUN_REGISTRY_PASSWORD:阿里云容器服务设置的密码
2.2.6. 开启action

开启Action

2.2.7. 修改镜像同步文件

修改 trigger.txt 内容,内容分为两部分,中间使用 空格隔开,目前每次代码提交都会 触发镜像同步,需要注意

  • 前面是需要同步的镜像

  • 后面是上传到阿里云地址的镜像

    • 第一部分是阿里云容器镜像仓库地址
    • 第二部分是我们自己的命名空间地址
    • 最后就是镜像名称和版本

trigger配置原图
trigger配置解释图
docker.yaml 中也存在阿里云容器镜像仓库地址,需要和 trigger.txt 保持一致。
docker配置位置
docker配置内容

2.2.8. 转存dify相关镜像

本文使用的是dify 0.6.11版本,部署完整版的dify组件镜像如下所示:

  • langgenius/dify-api:0.6.11
  • langgenius/dify-web:0.6.11
  • postgres:15-alpine
  • redis:6-alpine
  • semitechnologies/weaviate:1.19.0
  • langgenius/dify-sandbox:0.2.1
  • ubuntu/squid:latest
  • nginx:latest

部署二次开发的dify镜像组件可参考docker-compose.middleware.yaml 需要的镜像如下所示。

  • postgres:15-alpine
  • redis:6-alpine
  • semitechnologies/weaviate:1.19.0
  • langgenius/dify-sandbox:0.2.1
  • ubuntu/squid:latest

对应的 trigger.txt 参见如下所示,仓库地址命名空间 需要改为 自己 的地址和空间,并且需要一条一条执行。

langgenius/dify-api:0.6.11 registry.cn-hangzhou.aliyuncs.com/gkzx2024/dify-api:0.6.11

langgenius/dify-web:0.6.11 registry.cn-hangzhou.aliyuncs.com/gkzx2024/dify-web:0.6.11

postgres:15-alpine registry.cn-hangzhou.aliyuncs.com/gkzx2024/postgres:15-alpine

redis:6-alpine registry.cn-hangzhou.aliyuncs.com/gkzx2024/redis:6-alpine

semitechnologies/weaviate:1.19.0 registry.cn-hangzhou.aliyuncs.com/gkzx2024/weaviate:1.19.0

langgenius/dify-sandbox:0.2.1 registry.cn-hangzhou.aliyuncs.com/gkzx2024/dify-sandbox:0.2.1

ubuntu/squid:latest registry.cn-hangzhou.aliyuncs.com/gkzx2024/squid:latest

nginx:latest registry.cn-hangzhou.aliyuncs.com/gkzx2024/nginx:latest
2.2.9. 检查转存是否成功

检查github上的action是否状态为成功,并到阿里镜像仓库中查看对应的镜像是否成功转存。
Actions成功图
仓库镜像成功图

2.3. 拉取dify镜像

使用 finalshell 连接上 linux 服务器后,可先进入阿里云仓库中查看对应的镜像下载步骤。
镜像拉取步骤
需要先登录自己的阿里的docker仓库,然后拉取对应的镜像。拉取到自己服务器后,通过如下命令可以查看镜像的简要信息。

docker images

docker images
可以看到从阿里云拉取下来的镜像对应的 REPOSITORY 带有 registry.cn-hangzhou.aliyuncs.com/ 内容,需要使用如下命令进行更改名称为标准名称。

docker tag 【原镜像的IMAGE ID】 【新镜像的名称:版本号】

在这里插入图片描述
例如:registry.cn-hangzhou.aliyuncs.com/gkzx2024/dify-web 的 IMAGE ID 为 882c7d6ccdb8,新镜像的名称为langgenius/dify-web,版本号为0.6.11,其命令如下所示。

docker tag 882c7d6ccdb8 langgenius/dify-web:0.6.11

其他同理,需要拉取的组件可参考文件 docker-compose.middleware.yaml 进行拉取,从0.6.11版本中可获得,docker-compose.middleware.yaml 需要的镜像如下所示。

  • postgres:15-alpine
  • redis:6-alpine
  • semitechnologies/weaviate:1.19.0
  • langgenius/dify-sandbox:0.2.1
  • ubuntu/squid:latest

2.4. 修改compose文件

根据开发需要修改 docker-compose.middleware.yaml 文件,本文中因为需要访问dify组件的服务,所以将所有dify组件的服务的端口都暴露出来。
dify compose文件修改

2.5. 启动dify中间件

进入 docker-compose.middleware.yaml 的同级目录,通过使用如下命令可启动docker中间件组件的所有服务。

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

命令执行后的结果
可通过如下命令查看docker服务的运行健康情况。

docker ps -a

镜像运行状态检查

3. 部署Dify源码

3.1. Python安装

本文选择的Python的版本为 3.10.11(最好选3.10.x的版本,不然后续会有其他很多问题)
Python安装流程传送门

3.2. VSCode安装

VSCode安装流程传送门

3.3. VSCode安装Python插件

需要安装Python的插件如下图
Python插件

3.4. Python虚拟环境建立

首先进入dify源码的api目录
api目录
基于此目录进入命令终端窗口,输入如下命令即可进入VSCode

code .

vscode进入方式
进入VSCode命令输入栏
VSCode命令输入栏
选择后选择Python Create Environment,然后使用venv建立Python虚拟环境。
venv虚拟环境建立
venv命令
点击后会在程序主目录下生成一个.venv目录。

3.5. openssl安装

OpenSSL安装流程传送门

3.6. 修改配置文件

进入dify程序的api目录下,复制一份.env.example 文件,并重命名为.env,生成随机密钥,并替换.env中的SECRET_KEY的值。

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

celery配置、redis配置、PostgreSQL数据库、Weaviate向量数据库配置,更改为中间件所在服务器的地址。本文IP为192.168.200.130

# celery configuration
CELERY_BROKER_URL=redis://:difyai123456@192.168.200.130:6379/1
# redis configuration
REDIS_HOST=192.168.200.130
# PostgreSQL database configuration
DB_HOST=192.168.200.130
# Weaviate configuration
WEAVIATE_ENDPOINT=http://192.168.200.130:8080
# CODE EXECUTION CONFIGURATION
CODE_EXECUTION_ENDPOINT=http://192.168.200.130:8194

3.7. 安装依赖包

在dify程序的api目录下执行如下命令,即可安装api程序需要的依赖包。Python镜像源推荐

.venv\Scripts\pip3 install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
3.7.1. 安装异常解决方案:

如果出现如下提示

no module named distutils....but distutils installed?

可通过安装setuptools解决

pip install setuptools

问题详细描述解决方案传送门

如果出现如下提示

distutils.errors.DistutilsPlatformError: Microsoft Visual C++ 14.0 or greater is required

可通过安装Microsoft c++对应的插件解决
问题详细描述解决方案传送门

如果出现如下提示

AttributeError: module 'pkgutil' has no attribute 'ImpImporter'. Did you mean: 'zipimporter'?

可通过降级至Python3.10.x解决问题
问题详细描述解决方案传送门

3.8. 执行数据库迁移

在【dify主程序目录/api】目录下执行如下命令,将数据库结构迁移至最新版本

..\.venv\Scripts\flask db upgrade

启动API服务

..\.venv\Scripts\flask run --host 0.0.0.0 --port=5001 --debug

正确输出

* Debug mode: on
INFO:werkzeug:WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on all addresses (0.0.0.0)
 * Running on http://127.0.0.1:5001
INFO:werkzeug:Press CTRL+C to quit
INFO:werkzeug: * Restarting with stat
WARNING:werkzeug: * Debugger is active!
INFO:werkzeug: * Debugger PIN: 695-801-919

3.9 启动api服务(基础功能)

因为项目中已经存在 .vscode 目录,里面的 launch.json 文件定义了调试需要的配置参数,所以我们可以直接用vscode进行调试。

3.9.1. 选择调试启动方式

点击调试按钮后,选择Python Debugger: debug using launch.json 的方式。
调试按钮
选择Flask的调试方式即可。
Flask调试按钮

3.10. 启动Worker服务(如果需要开发知识库功能)

如果需要开发调试知识库功能,则需要启动这个服务。否则可以不用启动这个服务。

3.10.1. 选择调试启动方式

调试按钮
选择Celery的调试方式即可。
Celery调试按钮
如果遇到如下提示

zoneinfo._common.ZoneInfoNotFoundError: 'No time zone found with key UTC'

则通过升级pytz、tzdata可解决。
问题详细描述解决方案传送门

3.11. 前端页面部署

3.11.1. NVM安装

NVM详细安装传送门

如果遇到nvm使用use命令失效的问题,可参考NVM的use命令失效解决方案传送门

如果npm安装各种依赖包的时候,下载速度慢,可通过更换npm源的方式解决。npm源切换详解

如果出现npm install 一直sill idealTree buildDeps问题。可参考解决方案 npm install一直sill idealTree buildDeps

npm cache clear --force

npm config set registry http://registry.npmjs.org/
3.11.2. 配置前端

进入【dify主程序目录\web】目录下,用如下命令安装依赖包。

npm install

配置环境变量。在当前目录下创建文件 .env.local,并复制.env.example中的内容。根据需求修改这些环境变量的值:

# For production release, change this to PRODUCTION
NEXT_PUBLIC_DEPLOY_ENV=DEVELOPMENT
# The deployment edition, SELF_HOSTED or CLOUD
NEXT_PUBLIC_EDITION=SELF_HOSTED
# The base URL of console application, refers to the Console base URL of WEB service if console domain is
# different from api or web app domain.
# example: http://cloud.dify.ai/console/api
NEXT_PUBLIC_API_PREFIX=http://localhost:5001/console/api
# The URL for Web APP, refers to the Web App base URL of WEB service if web app domain is different from
# console or api domain.
# example: http://udify.app/api
NEXT_PUBLIC_PUBLIC_API_PREFIX=http://localhost:5001/api

# SENTRY
NEXT_PUBLIC_SENTRY_DSN=
NEXT_PUBLIC_SENTRY_ORG=
NEXT_PUBLIC_SENTRY_PROJECT=

构建代码

npm run build

启动 web 服务

npm run start
# or
yarn start
# or
pnpm start

如果npm run build时遇到cp不是内部命令错误
可用git bash来解决。问题详细描述解决方案传送门

4. 提交代码、镜像打包

4.1 配置dockerhub

因为需要通过github的actions将打包好的docker镜像存储到dockerhub上,因此需要对dockerhub进行配置,并获得dockerhub相关的信息。dockerhub官方传送门

4.1.1 创建dockerhub仓库

登录dockerhub仓库后,进入【Repositories】后点击【Create repository】按钮
创建dockerhub仓库
在创建仓库的界面填写仓库名称即【Repository Name】即可,个人有一个私有仓库的限额。
配置dockerhub仓库

4.1.2. 配置actions访问的信息

进入Account settings 后进入Security,然后创建一个Access Tokens,需要记住这个Access Tokens,后面配置github的actions时需要使用。
Account settings

4.2.配置github中的Actions

dify项目中包含github的workflow的相关配置路径,fork后自己提交代码只需关注build-push.yml工作流即可,此工作流的作用是将源码打包成docker镜像提交到dockerhub。
workflow文件地址
build-push.yml文件中需要关注的地方有3个。

  • 工作流触发条件,本文为每当push main主线的时候触发

  • dockerhub相关配置

    • DOCKERHUB_USER:dockerhub的用户名
    • DOCKERHUB_TOKEN:dockerhub的access token
    • DIFY_WEB_IMAGE_NAME:dify-web的镜像名称
    • DIFY_API_IMAGE_NAME:dify-api的镜像名称
  • github仓库名称,这个为自己fork的dify代码所在仓库

由于dockerhub的相关配置是通过配置github的Settings实现的,所以这个文件只需要修改github仓库名称为自己的即可。
在这里插入图片描述

4.3.配置github中的Settings

进入github的Settings标签页进行配置Secrets,创建两个secrets。

  • DOCKERHUB_USER:dockerhub的用户名
  • DOCKERHUB_TOKEN:dockerhub的access token

github的Settings配置
切换到Variables标签页配置两个Variables。

  • DIFY_API_IMAGE_NAME:这个为dify-api的dockerhub的命名空间/仓库名称
  • DIFY_WEB_IMAGE_NAME:这个为dify-web的dockerhub的命名空间/仓库名称

github的Variables配置
工作流的相关配置完成配置后,就可以进入github的Actions中开启即可。后面每次提交主线代码则会自动进行打包到docker的操作。如果不需要每次提交都打包,可查看Actions文档进行修改。github Actions工作流语法文档传送门github Actions工作流变量文档传送门

开启Action

4.4. 从dockerhub转存到阿里云

可参考 【2.2. 将dify组件镜像转移到阿里云(可选)】点击跳转到 - 2.2. 将dify组件镜像转移到阿里云(可选) 将dockerhub中的二次开发的docker镜像转存到阿里云镜像仓库中。然后可参考【2.3. 拉取dify镜像】点击跳转到 - 2.3. 拉取dify镜像 将阿里云镜像仓库中的镜像拉取下来部署即可。

4.5. 提交代码时的问题

因为dify提交代码时设置了代码规范检测,采用的是ruff模块。如果遇到缺失ruff模块的问题,需要按照如下命令进行安装ruff模块。

.venv\Scripts\pip3 install ruff -i https://pypi.tuna.tsinghua.edu.cn/simple

如果遇到了需要使用dev/reformat进行代码优化处理的问题。因为dify主目录下有dev/reformat命令,因此需要在dify主目录下,运行git bash命令界面,在git bash命令行界面里运行如下命令即可。

dev/reformat

参考

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐