Dify(源码阅读)
从源码角度读 Dify 的三语言分工(React/Next.js + Python API + Go plugin daemon);是既有 [[dify|Dify 概览笔记]] 的「代码架构」补篇,聚焦服务边界与部署拓扑,而非产品用法。
[!info] related notes
Dify(源码阅读)
[!note] 与本仓库既有 Dify 笔记的关系
z/dify.md是产品概览(用法、节点类型、workflow 实践),属于dify-moc子系列。本篇是其代码架构补篇:只读服务边界与部署拓扑,不重复产品用法。
这是什么
AI 应用开发平台,实际分工是三语言:
React / Next.js → 交互与可视化(本仓库 web/)
Python API + AI workflow → 模型、Agent、RAG(本仓库 api/)
Go plugin daemon → 插件生命周期 / 进程 / 流式通信 / Redis 协调 / serverless runtime(兄弟仓库 dify-plugin-daemon)
它证明了「React 交互 + Go 运行时协调 + Python 模型与 Agent」这种三语言架构是合理的,前提是职责清晰:
React:交互和可视化
Go:稳定 API、并发、长连接、运行时协调
Python:模型、Agent、RAG、ML 生态
[!warning] 不适合当第一代码风格教材 仓库规模大、产品快速演进、Python API 与 Go daemon 分属不同仓库、插件与多租户引入大量当前不需要的复杂度。把它当「服务边界和部署拓扑」教材,不当逐文件模仿对象。
在你三层参考架构里的位置
用户定位:学习「React + Go + Python 三栈分工」的参考。恰好对应 BodySense 应坚持的分工。但只学服务边界与部署拓扑,不抄规模与目录。
版本快照
| 项 | 值 |
|---|---|
| 分支 | main |
| commit | 48451f5adf11(2026-08-11) |
| 抓取日期 | 2026-08-11 |
| 语言 | Python 3.12(api/pyproject.toml:dify-api 1.16.1,requires-python = "~=3.12.0") |
| 前端 | React 19 + Next.js(web/,依赖经 pnpm catalog 管理) |
| 包管理 | 后端 uv / 前端 pnpm |
仓库鸟瞰:顶层目录结构
dify/
├── api/ # Python 后端(FastAPI → app.py / app_factory.py)
├── web/ # React 19 + Next.js 前端
├── sdks/ # nodejs-client / php-client
├── packages/ # 内部共享包(dify-ui / contracts / tsconfig …)
├── dev/ docker/ scripts/ tests/ images/
├── pyproject.toml (api) package.json (web) pnpm-workspace.yaml
api/(Python 后端,depth 1,节选关键):
api/
├── app.py app_factory.py dify_app.py # 入口
├── controllers/ # FastAPI 路由分组(service_api / console / web / mcp / inner_api)
├── core/ # agent / rag / workflow / model_manager / provider_manager / tools
├── services/ # 业务服务(app / dataset / conversation / workflow / plugin …)
├── models/ # SQLAlchemy 模型
├── repositories/ # 数据访问
├── tasks/ # Celery 异步任务(索引 / 邮件 / 调度)
├── events/ # 领域事件
├── extensions/ # Flask/FastAPI 扩展装配
├── migrations/ # alembic
└── libs/ fields/ factories/ schedule/ commands/
web/(React 前端,depth 1,节选):
web/
├── app/ # Next.js App Router 页面(account / auth / signin / install …)
├── features/ # 功能域(account-profile / agent-v2 / home / deployments / tag-management)
├── service/ # API client(apps / datasets / workflow / use-*.ts)
├── context/ # 全局状态(app-context / provider-context / workspace-state)
├── components/ hooks/ models/ utils/ types/ i18n/ config/ themes/
└── next.config.ts package.json vite.config.ts
顶层边界职责
| 顶层目录 | 回答什么问题 | 备注 |
|---|---|---|
api/core/ | 模型/Agent/RAG/workflow 怎么实现 | 与 Python AI 生态对接处 |
api/services/ | 业务编排 | 跨域组合在 service 层 |
api/controllers/ | 路由怎么分组 | console / web / service_api 分离 |
web/features/ | 前端功能域 | 按功能而非按技术切 |
web/service/ | 前端如何调 API | 集中 client |
(兄弟仓库)dify-plugin-daemon | 插件运行时协调 | 见 dify-plugin-daemon |
分层与依赖方向
flowchart TB
WEB[web/ React] --> API[api/ FastAPI]
API --> CORE[core/ agent·rag·workflow]
API --> SVC[services/ 业务编排]
API --> TASK[tasks/ Celery]
PLUGIN[Go dify-plugin-daemon] --> API
PLUGIN --> PY[Python 插件 runtime]
PLUGIN --> REDIS[(Redis 协调)]
关键入口与调用链
| 入口 | 路径 | 说明 |
|---|---|---|
| 后端入口 | api/app_factory.py | FastAPI 应用装配 |
| 路由分组 | api/controllers/service_api/ | 对外 API |
| 核心能力 | api/core/workflow/ api/core/rag/ | 工作流与检索 |
| 前端入口 | web/app/layout.tsx web/app/(commonLayout)/ | Next.js 布局 |
| API client | web/service/ | 前端调用封装 |
阅读路线
- 先看
api/core/与web/features/的边界划分(服务边界教材) - 再看
web/service/如何封装 API 调用(前后端契约) - 最后读 dify-plugin-daemon 理解 Go 如何协调 Python 插件运行时
- 不逐文件读
controllers/、services/全量(规模过大)
深挖一条线:一次 chat 请求穿过三语言边界
选「用户在 web 发起一次对话,触发 Python workflow,必要时调到 Go 协调的插件」作为主线——它把 React / Next.js → Python API → Go daemon → Python 插件 的四段边界都走了一遍,是「服务边界与部署拓扑」教材的最佳样本。
web/(React 19 + Next.js)
→ web/app/(commonLayout)/… 页面
→ web/service/*.ts API client(集中封装)
│ HTTP
▼
api/(Python FastAPI)
→ api/app_factory.py 应用装配
→ api/controllers/service_api/ 路由分组(对外 API)
→ api/services/ 业务编排
→ api/core/workflow/ + core/rag/ 工作流 / 检索核心
│ 需要插件能力时
▼
dify-plugin-daemon(Go,兄弟仓库)
→ internal/server/ 对外通信(HTTP/TCP)
→ internal/core/ 插件生命周期与调度
→ 用 uv 拉起 Python 插件 runtime(stdin-stdout / TCP)
→ Python 插件执行 → 结果回传
│
▼ 响应原路返回 web/
跟读要点:
api/core/与web/features/的边界划分是「服务边界」教材本体,先读这两处web/service/看前端如何集中封装 API 调用(前后端契约)- 真正跨语言的手递手发生在
api→dify-plugin-daemon→ Python 插件 这一段;通道细节(HTTP/TCP/stdin-stdout)见兄弟仓库 README(待验证)
自检:Python 在哪把控制权交给 Go?Go 在哪把控制权交给 Python 插件 runtime?BodySense 的 Go consultation API 是否也需要这样一层「运行时协调层」?
值得偷师 / 不建议照抄
| 做法 | 评价 | 我的判断 |
|---|---|---|
| 三语言职责清晰切分 | 强 | BodySense 应坚持的同款分工 |
| console / web / service_api 路由分离 | 强 | 多端 API 边界参考 |
| 前端 feature 域切分 | 强 | 比按技术切更可维护 |
| 插件 + 多租户复杂度 | 弱 | 当前不需要,不抄 |
| 仓库规模与演进速度 | 弱 | 不当风格模板 |
我的疑问与待验证
- Dify Python API 与 Go daemon 之间通过 HTTP / TCP / stdin-stdout 的哪几种通道通信?兄弟仓库 dify-plugin-daemon 的 README 应能给答案。
- Go daemon 用
uv管理插件 Python 环境的具体机制,是否值得 BodySense 的 Go consultation API 借鉴?
沉淀出的笔记
相关链接 / 官方入口
| 入口 | 地址 |
|---|---|
| 仓库 | https://github.com/langgenius/dify |
| 插件守护进程(兄弟仓库) | https://github.com/langgenius/dify-plugin-daemon |