dify1.11.1后端api源码编译及调试

1 环境准备

  • OS系统:Windows 10
  • vscode: 1.107.1(user setup)
  • uv:0.9.18

2 依赖安装

  • vscode打开api,调出终端,输入uv sync进行依赖安装

    cd api
    uv sync

3 虚拟环境选择

  • 依赖安装完成后,vscode右下角设置下当前目录下的虚拟环境

4 测试代码是否爆红

  • 此时,先随便打开一个py文件,如下面的redis插件扩展,不出意外报红如下:
  • 上述只是在静态编译期间爆红提示,并不是真正的错误,不影响运行,如果看着难受,可以降低pylance的严格级别,什么是pylance,看下面!
  • 在dify的api根目录下有一个文件是:pyrightconfig.json ,修改配置如下(pyrightconfig.json:python的类型检查文件,类似于typescript的tsconfig.json):

  • 再次打开之前的py文件,发现不报错了(强迫症治好了)

5 复制配置文件

  • 复制一份配置文件(不然直接启动app.py会报错,如右边)

    cp ..env.example .env

6 正常启动server

  • api入口文件是app.py,由于是启动文件,代码很简单(有点类似于SpringBoot的App.java中的main函数),如下:
  • 如果系统源码改动期间,可以热启动,可以增加配置如下


7 源码调试

  • 如果系统需要源码调试,则将api根目录下的.vscode/launch.json.example复制一份出来

  • 将其内容中的python一行全部注释掉,总过两处(不注释,启动会报错!!!)

  • 将"justMyCode"由之前的true修改为false,以支持进入第三方库调试,为什么之前设置为true,看下面👇

  • 改为结果如下:

  • 接下来就可以,F5启动调试了,效果如下

  • 继续F5,触发设置条件(数据库的扩展插件)

  • 这里的db是 SQLAlchemy 的实例

  • 因为之前设置过允许跳入到三方包中进行调试,所以按F11可以看到如下

  • 上面这个SQLAlchemy调用init_app函数时,会从当前app的config中读取一个名为"SQLALCHEMY_DATABASE_URI"的属性,这个属性的值默认如下:

  • 那这个值是怎么来的呢?答案Python的多重继承,直接看下面的图

    ../api/configs/app_config.py

  • 继续

    ../api/configs/middleware/init.py



8 Flask源码调试

  • 上面仅在Python普通代码里打断点是没问题的,如果想进入到Flask里面,比如路由api上的装饰器以及路由内的代码,需要将launch.json中的一个配置修改为false,如下:
  • 最终效果如下(下面是每一个请求前,都要验证下dify是否部署过,一旦部署过,表dify_setups会有一条记录,有记录就放行,否则会抛异常!):

9 总结

  • dify后端的代码写的很漂亮,模块化责职分明、代码高内聚、低耦合,利用插件的可插拔思想可以很容易扩展新的功能需求,等等。一开始调试代码时总感觉有点ioc的影子,flask框架中的app感觉就像ioc中的context,存储了整个web服务运行期间所需的各种数据,有配置、有实例(中间件如redis、db、obs这种的client)等,这些在任何代码可触及的地方都可以随拿随用。当然Flash是轻量级的,虽然比不上SpringBoot框架,但是上手是真的快。