HKUDS/DeepTutor 拆解:一个 agent-native 的终身个性化辅导工作台是怎么搭起来的
posts posts 2026-07-17T02:58:33+08:00DeepTutor 是港大 HKUDS 开源的 agent-native 学习工作台,把 9 个能力面统一到同一 agent loop,配套 5 套 RAG 引擎与三层可审计 Memory。技术笔记DeepTutor, AI Agent, RAG, Memory一句话判断
DeepTutor(HKUDS/DeepTutor)是港大数据智能实验室(HKUDS)维护的 agent-native 终身个性化辅导工作台,截至 2026-07 在 GitHub 上 26.7k stars / 3.6k forks,Apache-2.0。 它不是又一款 RAG chatbot,而是把"辅导"这件事拆成 9 个共享同一 agent loop 的能力面(Chat / Quiz / Research / Visualize / Solve / Mastery Path / Co-Writer / Book / Partners),并把这 9 个面下需要的知识库、技能、人格、记忆、IM 渠道、子代理全部接进了同一套状态机。读它的关键不是 feature list,而是"为什么 Chat、Partners、Co-Writer、Book、Knowledge Center 之间能共享上下文,以及这套上下文用三层 Memory + 5 套 RAG 引擎是如何被组织起来的"。
如果你正在评估"自己造一个 AI 辅导产品 / 内部知识助手",或者在选 RAG 引擎和 agent loop 编排方式,这篇文章值得完整读完。
系统地图
DeepTutor 的真实架构不是 README 顶部那张"能力面截图",而是 v1.4 重写之后沉淀出来的 Tools + Capabilities 插件模型。下面这张图把"用户感知的入口"、“能力面”、“共享工具层”、“可插拔底座"四层拆开:
┌──────────────────────────────────────────────────────────────────────┐
│ 入口层 (User-facing surfaces) │
│ Web / CLI (deeptutor) / IM 渠道 (15+) / REST + WebSocket API │
└─────────────────────────────────┬────────────────────────────────────┘
│
┌─────────────────────────────────▼────────────────────────────────────┐
│ 能力面层 (Capabilities, all share one agent loop) │
│ Chat · Quiz · Research · Visualize · Solve · Mastery Path · │
│ Co-Writer · Book · Partner (per-channel long-running companion) │
└─────────────────────────────────┬────────────────────────────────────┘
│
┌─────────────────────────────────▼────────────────────────────────────┐
│ 共享工具层 (Capability-scoped Tools, mount automatically) │
│ brainstorm · web_search · paper_search · rag · read_source · │
│ read_memory · write_memory · read_skill · load_tools · exec · │
│ web_fetch · ask_user · list_notebook · write_note · github · │
│ consult_subagent · imagegen · videogen · geogebra_analysis · … │
└─────────────────────────────────┬────────────────────────────────────┘
│
┌─────────────────────────────────▼────────────────────────────────────┐
│ 底座层 (Pluggable substrate) │
│ ┌─────────────────────┐ ┌─────────────────────┐ ┌──────────────┐ │
│ │ Knowledge Center │ │ Learning Space │ │ My Agents │ │
│ │ 5 retrieval engines│ │ notebook / skills │ │ Claude Code │ │
│ │ + 5 parser engines │ │ / persona / qbank │ │ Codex · 等 │ │
│ └─────────────────────┘ └─────────────────────┘ └──────────────┘ │
│ ┌─────────────────────┐ ┌──────────────────────────────────────┐ │
│ │ Memory (L1/L2/L3) │ │ Channel Adapter (Feishu/Telegram/ │ │
│ │ trace + cur + synth│ │ Slack/Discord/DingTalk/QQ/WeCom/ │ │
│ │ file-backed │ │ WhatsApp/Zulip/Mattermost/Matrix/ │ │
│ │ │ │ Mochat/Teams) │ │
│ └─────────────────────┘ └──────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────────┘
│
┌─────────────────────────────────▼────────────────────────────────────┐
│ LLM Provider + Embedding Provider (configurable, multi-provider) │
└──────────────────────────────────────────────────────────────────────┘这张图最重要的一条路径:“入口 → 能力面 → 自动挂载的工具 → 可插拔底座”,每一层都可以单独替换或扩展;这就是 README 自己反复强调的"agent-native”——把 agent loop 作为内核,而不是把每个能力面写成独立的微服务。
边界与角色划分
把 DeepTutor 拆成 4 组"不变项",可以一次性回答"它和别的 RAG 工具到底差在哪":
| 维度 | 不变项 | 工程含义 |
|---|---|---|
| 能力组织 | 9 个能力面共享同一个 agent loop | 切换目标不切换引擎;上下文随学习者流转 |
| 知识接入 | 5 套 RAG 引擎 + 5 套文档解析引擎,可单库绑定 | LlamaIndex(默认,向量+BM25)/ PageIndex / GraphRAG / LightRAG / LightRAG Server / linked Obsidian;Text-only / MinerU / Docling / markitdown / PyMuPDF4LLM |
| 上下文 | 三层文件可审计 Memory + 可选子代理 | L1 trace / L2 表面事实 / L3 跨面综合,每一条都能回溯证据 |
| 部署形态 | 4 路安装路径共享同一 workspace | PyPI / Docker / 源码 / remote-Docker;所有配置都落在 data/user/settings/ 或 $DEEPTUTOR_HOME |
要注意的几个边界:DeepTutor 不是一个 LMS(学习管理系统)——它没有课程编排、没有班级、没有成绩册;它的定位是"个人学习工作台 + 可挂载子代理的辅导引擎"。它也不是一个 RAG 框架——LlamaIndex / PageIndex / GraphRAG / LightRAG / LightRAG Server 都只是 Knowledge Center 下的可选后端,你换掉它不会影响上层能力面。
关键机制
1. 同一个 agent loop,9 个能力面
DeepTutor v1.4 的核心抽象是 “agent loop as the single engine"。Chat、Quiz、Research、Visualize、Solve、Mastery Path 全部跑在 ChatOrchestrator 这一个回路上;能力面的差异不是引擎差异,而是:
- 不同的 system prompt + 不同的工具挂载集合
- 不同的入口 UI / 输出卡片(quiz 题卡 / 引用报告 / 图表 / 动画)
- 不同的会话上下文(Mastery Path 会自动记录每题的对错并累积到 Question Bank)
这条回路有个值得专门记下的机制:ask_user 是一个"挂起而非猜"的工具——模型不是盲目继续推理,而是在不确定时主动暂停一个 turn,向用户发一个结构化澄清问题,等用户回答后从中断点恢复。这把"agent 的不确定性"显式化了,而不是把它藏在重试里。
工具挂载分两类:
- 用户可切换:
brainstorm、web_search、paper_search、reason、geogebra_analysis,外加配置了生成模型后的imagegen/videogen - 上下文自动挂载:
rag、read_source、read_memory、write_memory、read_skill、load_tools、exec、web_fetch、ask_user、list_notebook、write_note、github、consult_subagent
“自动挂载"这一类决定了 DeepTutor 的"工作台"气质——你把一个知识库钉在 composer 工具栏,工具链就会自动接上,不需要在每次提问里手动选。
2. 5 套 RAG 引擎,单库单绑
Knowledge Center 是 DeepTutor 最容易被低估的一部分。表面上它就是一个"上传文档 → 问 → 答"的工作流,但它的设计里有几个少见的工程决定:
- 每个 KB 只能绑一个 retrieval 引擎。一个 KB 要么是 LlamaIndex,要么是 PageIndex,要么是 GraphRAG/LightRAG,要么是一个链接到本地 Obsidian vault 的"linked KB”。这避免了"同一库多套索引一致性"的灾难,但代价是切换引擎必须重建索引。
- Document parsing 与 retrieval 解耦。你可以选 LlamaIndex 引擎,但解析时换 MinerU;这让"重解析"和"重检索"变成两个独立操作。
- Re-index 不会毁掉工作索引。每次重建都会写一个新的
version-N目录,旧版本保留;这样中途失败可以立即回退,而不是把 KB 留在一半状态。 - 单文档级删除(v1.5.1)。即便是处在
error状态的单文档,也可以从 KB 中移除而不用删整个 KB——这是对"用户上传了一张坏 PDF 不能用怎么办"的具体回应。 - LightRAG Server 把检索外置。如果团队已经有一个 LightRAG 实例,可以让 DeepTutor 用 HTTP 调它而不是本地跑,知识库的所有权留在外部系统。
3. 三层 Memory:可审计的个性化
DeepTutor 的 Memory 不是 vector DB,是一个文件化、可读、可改的三层系统:
L1 trace/<surface>/<date>.jsonl 追加式事件流(每次 tool call / 每回合输出)
L2 L2/<surface>.md 每个表面的精选事实(curated facts)
L3 L3/<profile|recent|scope|preferences>.md 跨表面综合关键不变量:L2 必须能引用到 L1 的事件,L3 必须能引用到 L2 的事实。这意味着模型声称"记得你上周写过一篇笔记"这件事,你能从 L3 追到 L2 再追到 L1 的原始 trace,整条链是 openable 的。这和"黑盒向量记忆"最大的差别在于:你可以编辑、删除、修正自己的画像,而不是被动等系统"学会”。
注意这条不对称的访问控制:Partner 读主人的 memory,但只写自己的 memory。这是 Partner 的"它记得我,但它不会把对我的印象写进我的 L3"。
4. Partner:复用 ChatOrchestrator 的"长连接人格"
Partner 是一个看起来独立、实际上没有自己引擎的子系统。每一条来自 IM 渠道的消息,最终都变成一个普通的 ChatOrchestrator turn,跑在 partner-scoped workspace 里。
这意味着:
- Partner 不是一个新的 agent runtime,它和 Chat 共用同一条回路、同样的 RAG、同样的 Memory API
- Partner 的"个性"由
SOUL.md、model policy、channels、tool policy、assigned library 这五个文件决定 - 同一个 Partner 可以同时挂在 Feishu、Telegram、Slack 等 15+ 渠道上,对话上下文共享
- Knowledge bases、skills、notebooks 会被复制到
data/partners/<id>/workspace/,所以 Partner 用的工具不需要特殊实现
这种设计的代价是:Partner 不能跑 Chat 没有的能力(比如它跑不了 Visualize 的图表生成),但收益是把"多渠道一致性"几乎免费拿到——只要一个 Chat 能回答,挂了 IM 的 Partner 也能回答。
5. My Agents:把外部 agent 当成上下文
“Subagent"在 DeepTutor 里不是另一种 worker,而是一种上下文类型。consult_subagent 工具让 Chat 在一个 turn 内真正运行你本地的 Claude Code / Codex CLI,或者运行你自己定义的 Partner,并把它的输出以流式方式呈现在 Activity 面板。
特别值得注意的是"导入历史对话"的能力——/agents 面板可以把你过去和 Claude Code / Codex 的历史对话作为第三方对话导入进来,而不是当作 DeepTutor 自己的回合:这些对话保持原来的语气、格式、工具调用痕迹,DeepTutor 只是在 Chat 里把它们当成可引用的 transcript。
6. CLI = Agent-native Interface
deeptutor CLI 不是"暴露 API 给脚本”,而是被设计成"CLI 也是 agent loop 的入口":
deeptutor init # 工作区初始化(端口/provider/key)
deeptutor start # 启动后端 + Next.js 前端
deeptutor skill install <name> # 从 EduHub 安装 skill(带安全门)
deeptutor kb list/info/create/add/search # KB 全生命周期 CLI 镜像
deeptutor book health / book refresh-fingerprints # 检测 source 与 compiled page 是否漂移deeptutor 的 session 可以保留 id 跨多轮复用——这让"在脚本里驱动 DeepTutor 多轮对话"成为常态,而不是把 CLI 当作一次性 prompt 工具。
一个请求如何流过系统
下面以一个具体的"读论文 + 出 quiz + 加进 Mastery Path"任务走一遍:
用户在 Chat 里粘贴论文 PDF
│
▼
Composer 工具栏: 选中 Knowledge Base = "papers-llm" (LlamaIndex 引擎)
│ 自动挂载: rag / read_source / write_memory / write_note /
│ list_notebook / consult_subagent / ask_user / reason
▼
ChatOrchestrator 起一个 turn:
Round 1: rag → 论文前 6 段摘要
Round 2: ask_user → "你想出 5 题还是 10 题?偏推理还是偏概念?"
(用户答: 5 题 + 偏推理)
Round 3: reason + read_skill "quiz-gen" → 5 道 quiz + 答案解释
Round 4: 写一条 L2 fact "用户偏好: 概念题多于推理题" → Memory
Round 5: write_note "LLM 论文 5 题" → Notebook
▼
用户: "把这 5 题加到我的 Mastery Path 里"
│
▼
Mastery Path 能力面复用同一 ChatOrchestrator,但挂载额外工具:
- mastery_track_progress (记录每题对错)
- qbank_add (把题存进 Question Bank)
│
▼
Partner "研究助理" 在 Feishu 收到推送:
因为 Partner 复用 ChatOrchestrator,message 进来变成 partner-scoped turn,
同样的 RAG 同样 memory 同样 model policy,但 read 主人的 L3、写自己的 L3。这个例子刻意覆盖了 4 个面(Chat / Mastery Path / Memory / Partner)+ 1 个外部 partner,目的是让你看到它们不是 4 套系统,而是同一个 agent loop 在不同入口的不同投影。
采用顺序与适用边界
推荐采用顺序
- 从 Chat + 一个 LlamaIndex KB 开始——这是 80% 场景的最小可用单元,验证"个人知识助手"是否值得继续投入。
- 加 Memory(L2 精选事实)——这一步是把"工具"升级成"个性化助手"的关键跳转,且 L2 文件可读,调试成本几乎为零。
- 引入 Partner 把 Chat 挂到 IM 渠道——如果你已经在用 Feishu/Slack,这一步把"打开 Web"变成"在群里 @ 机器人"。
- 再考虑 Book / Co-Writer / Mastery Path——它们价值大但场景窄,等基础回路用熟之后再启用。
- 多用户部署(v1.3.8+)——只在确认要服务超过一个用户时再做,每个用户的 workspace 隔离 + admin grants + 范围化 runtime 访问需要单独运维。
适用边界
| 适合 | 不适合 |
|---|---|
| 个人/小团队的私人学习与研究助手 | 学校/企业的 LMS / 课程编排 / 班级管理 |
| 多源知识库(论文/笔记/笔记软件/对话历史)需要统一检索 | 单文档偶尔查询(直接用 IDE Copilot 就够) |
| 需要把 agent 接到飞书/Slack/微信等已有 IM 渠道 | 纯离线、纯本地、零 LLM 依赖的场景 |
| 想用一套代码既跑 Web 也跑 CLI、还能被脚本驱动 | 想要商业 LMS 的合规、审计、学情报告能力 |
| 愿意承担"agent-native"心智模型(理解 Tools + Capabilities 模型) | 只想找一个开箱即用的 ChatPDF |
风险与未知项
- 大依赖面:README 标注 Python 3.11+ 与 Node.js 20+,部署前需要确认目标机器的依赖;rootless Podman 在 v1.4.13 起支持,但仍要单独验证。
- 第三方过期材料:OSSU 之类的关联项目会随时间漂移,仓库本身已警示——选第三方扩展时建议直接看仓库的 latest release。
- arXiv 论文 ID 与日期:README 提到 arXiv:2604.26962 的 preprint,文章写作时该编号按仓库当时引用为准,建议读者在引用前自行验证。
- 许可证:Apache-2.0,对二次分发相对友好,但 v1.4+ 的 Partner / IM 渠道抽象下,私有部署仍需逐项评估依赖子项目的许可证。
一处延伸阅读
如果想继续深入:
- HKUDS/DeepTutor 仓库——主仓库,README 中"Explore DeepTutor"是按能力面组织的最佳目录。
- DeepTutor 文档站 deeptutor.info——按能力面 + 安装路径组织的官方文档,2026-05 上线。
- arXiv 预印本 2604.26962——论文侧重设计与思路而非工程实现,适合和本文互为补充。
- Roadmap Issue #498——仓库自维护的路线图 issue,贡献前可在此投票/提案。