收官:把 20 天连成一张地图
恭喜你走到了最后一天!过去 19 天我们像拆一台精密机器,一个零件一个零件地看。今天不再拆新零件,而是退后一步,把所有零件拼回一台完整的机器:一张全景知识地图、一条贯穿始终的请求血脉、5 个反复出现的设计思想、一眼前端全貌,最后是"学完之后往哪走"的建议和一段收官寄语。这一天读完,Dify 在你脑子里就该是"一整块"而不是"二十块碎片"了。
20 天,我们到底学了什么
先把 20 天按"阶段"归拢一下,你会发现它其实只有六大块:
| 阶段 | 覆盖天数 | 核心目录 | 解决的问题 |
|---|---|---|---|
| ① 入门与请求旅程 | D01-04 | core/app/ | 一条消息进来怎么被一层层处理成回答 |
| ② 模型运行时 | D05-07 | core/model_manager.py、core/provider_manager.py | 几十家模型怎么统一调、多 key 轮询 |
| ③ 工作流引擎 | D08-12 | core/workflow/ | 可视化编排:节点、图、变量怎么跑起来 |
| ④ RAG 知识库 | D13-15 | core/rag/、core/indexing_runner.py | 文档怎么切片、检索、喂给模型 |
| ⑤ 工具与 Agent | D16-18 | core/tools/、core/agent/、core/plugin/、core/mcp/ | 让模型会用工具、能自主规划、能被扩展 |
| ⑥ 运维与收官 | D19-20 | api/tasks/、core/ops/ | 慢活异步化、全链路可观测 |
全景知识地图
把六大块画到一张图上,箭头表示"谁调用谁"。这就是 Dify 后端 api/core/ 的骨架(目录属实,见文末动手区 ls api/core/):
一条请求走完全图(把地图"跑"一遍)
光看静态图不够,我们让一条真实请求"跑"过全图。假设用户在一个"带知识库 + 带工具"的 Agent 应用里问:"根据我们的产品手册,帮我算一下 A 套餐买 3 年省多少钱,并把结论发到我邮箱。"
① 请求进来前端把消息发到 Controller API → 进 core/app/ 的 AgentChat 流程,建 AgentRunner(Day04/17)。④ 先查知识库Agent 判断需要产品手册信息 → 走 RAG(Day13-15)检索"A 套餐价格"相关片段,作为上下文。② 调模型思考Agent 把"问题 + 检索到的手册 + 工具菜单"发给模型(经 Day05 的 ModelInstance,可能还多 key 轮询)→ 模型决定:先调计算器工具。⑤ 调工具Agent 循环(Day17)→ 经 ToolEngine(Day16)调计算器算出"省 1800 元" → 观察结果回喂 → 模型再决定调发邮件工具(可能是个 MCP/插件工具,Day18)→ 邮件发出。⑥ 全程被追踪这一路每次模型调用、工具调用都产生 TraceTask(Day19),塞进内存队列、攒批异步上报 Langfuse。① 流式返回模型最终答案以 SSE 流(Day04)一段段推回前端;发邮件这类若要异步还会走 Celery 队列。用户看到"已为您计算并发送邮件"。贯穿全书的 5 个设计思想
比记住某个类更值钱的,是记住这些"反复出现的招式"——它们在任何大型系统里都通用:
| 设计思想 | 它长什么样 | 在哪见过 |
|---|---|---|
| 门面 / 统一抽象 | 不管底下多复杂,对外只给一个简单入口 | ModelInstance(D05)、Tool 基类(D16)、PluginService(D18) |
| 常见情况走快路径 | 不为"不常见"给"常见"添开销 | 单 key 直调(D05)、无负载均衡跳过 Redis(D05)、没配追踪就跳过(D19) |
| 流式而非大块 | 边产生边消费,省内存、体验好 | 模型流式(D05)、工具 Generator(D16)、SSE(D04) |
| 异步解耦 / 旁路 | 慢活/观测不阻塞主流程 | Celery 队列(D19)、追踪两级异步(D19) |
| 隔离与协议化 | 用进程隔离保安全,用协议保扩展 | 插件独立进程(D18)、MCP 协议(D18)、多租户(全书) |
get_provider_model_bundle 的确切签名,但只要你带走了上面这 5 招,换任何一个大型 AI 项目,你都能快速猜到"它大概会怎么设计"——因为好的工程实践是相通的。Dify 只是这些思想的一个优秀载体。web/ 前端一瞥
20 天我们几乎只看后端 api/。但 Dify 还有一整个前端 web/,用 Next.js + React 写(web/package.json 里 name 是 dify-web,依赖 next/react)。目录结构(属实,见动手区 ls web/):
web/app/Next.js App Router 的页面。里面按布局分组:(commonLayout)、(shareLayout)(分享出去的应用)、account、auth 等。你在浏览器里点的每个页面都在这。web/service/ · web/models/前端调后端 API 的封装、以及 TypeScript 数据类型。前后端在这里"对暗号"——后端返回的 SSE 流就在这被解析成聊天气泡。web/i18n/多语言。Dify 支持多国语言,文案都在这——这也是它能全球流行的原因之一。web/hooks/ · web/context/React 的状态与逻辑复用。比如"当前工作区""当前应用配置"这类全局状态。api/)是"大脑和内脏",前端(web/)是"脸和手"。你这 20 天练的是"看懂内脏怎么运转"——这是最难也最值钱的部分。前端如果你熟 React,照着 web/service/ 摸一遍 API 调用就能上手;如果不熟前端,也完全不影响你已经掌握的后端功力。学完之后,怎么继续深入
看懂 ≠ 会用。想把这 20 天变成真本事,推荐三条路,按投入从小到大:
路线 A:本地跑起来用 docker compose 把 Dify 跑起来,对照教程在界面上建一个"带知识库 + Agent + 工具"的应用。把你在源码里看到的概念,在 UI 上一一对应——这一步的收获超乎想象。路线 B:加断点读一次真实请求在 core/app/ 的 AppRunner、model_manager.invoke_llm、ToolEngine.agent_invoke 打断点,发一条消息,单步跟一次。亲眼看着 Day04→05→16→17 的调用栈真的串起来,比读十遍都牢。路线 C:动手改一点挑个小切口:写一个自己的内置工具、加一个 MCP server、或给某个流程加一条日志。能改动并跑通,才算真的懂了。也是给开源社区贡献的起点。收官寄语
core/app/ 的 Runner;Runner 经 model_manager 调模型、按需用 core/rag 检索知识、用 core/workflow 编排流程;如果是 Agent,就在 core/agent 里循环决策、经 core/tools 执行工具(工具可来自 plugin 独立进程或 mcp 外部协议);答案以 SSE 流回前端;慢活甩给 api/tasks 的 Celery,全程被 core/ops 追踪上报。"——如果这句话你读着毫不费力,那这 20 天就没白花。👶 小白:读完源码,我最该带走的到底是什么?
👨🏫 老师:不是背下多少函数名,而是三样东西——①一张能自己画出来的架构地图(L02);②一套可迁移的设计直觉(L04 的 5 招);③一种"再大的系统也敢拆开看"的底气。第三样最珍贵。你已经拆完了一个 star 数十万的顶级开源项目——下一个复杂系统摆在你面前时,你不会再怕了。这,就是读源码真正的礼物。
🧠 20 天全景自检(都能答就毕业了)
- 一条消息进 Dify,完整走哪几大块?(① 请求→②模型/③工作流/④RAG→⑤工具/Agent→⑥后勤)
- 模型体系怎么统一几十家供应商?(ModelInstance 门面 + ProviderManager 配置中心,D05-07)
- 工作流/RAG 各解决什么?(可视化编排 / 让模型用上外部知识,D08-15)
- Agent 和工具是什么关系?(Agent 决策循环,ToolEngine 执行,D16-17)
- 能力怎么扩展、怎么隔离?(插件独立进程 + MCP 协议,D18)
- 生产系统怎么"不卡"和"看得见"?(Celery 异步 + 攒批可观测,D19)
- 贯穿全书的 5 个设计思想是哪些?(门面/快路径/流式/异步解耦/隔离协议化,L04)
✋ 最后 10 分钟:亲手确认这张地图
cd /Users/bitmart/work/codes/github/AI_WORK/dify
# 后端六大块,全在这一个 core/ 目录下
ls api/core/ # app / model_manager.py / provider_manager.py / workflow /
# rag / tools / agent / plugin / mcp / ops ...
# 异步任务底座
ls api/tasks/ | wc -l # 50+ 个后台任务
# 前端全貌
cat web/package.json | grep '"name"' # dify-web (Next.js + React)
ls web/app/ # 页面路由