DeepTutor 是什么:把「终身个性化辅导」拆成能跑起来的模块
判断一个项目”是什么”,最不该依赖的就是它 README 第一行那句定位。DeepTutor 的第一行写的是 DeepTutor: Lifelong Personalized Tutoring(README.md:5)——“终身个性化辅导”,听起来像一个面向学生的产品。但你把仓库 clone 下来,会发现真正决定它形态的东西,散落在版本文件、AGENTS.md、Dockerfile 和几个 compose 文件里。本文就是把这句定位拆成可核查的几块。
先给锚点。以下所有数字与行号都对应我们采集的仓库快照:HEAD 456f9c2,采集日 2026-08-10,deeptutor/__version__.py:9 里的 __version__ = "1.5.11"。你自己 clone 之后行号可能已经漂了,文件名和字段名是稳的。
一、身份这一层,能钉死的几件事
截至 2026-08-10 我们从 GitHub API 取到的数据:HKUDS/DeepTutor,33426 star、4319 fork、90 个 open issue,建仓 2025-12-28,最后一次 push 2026-08-09,协议 Apache-2.0,主语言 Python。这几个数只是并列的事实,不能从中推出任何关于成熟度或适用性的结论——尤其别拿 star 数当质量指标。
版本号有唯一来源,而且带强制校验。deeptutor/__version__.py:1-7 的模块 docstring 把发布流程写死了:改这里的 __version__、提交、按 v<__version__> 打 tag;CI 会在发布到 PyPI 前核对 tag 与这个值是否一致。.github/workflows/pypi-release.yml:72-99 就是那一步,工作流步骤名叫 “Verify release tag matches deeptutor/__version__.py”,不一致就直接报 “Bump __version__ before tagging.”。同一个工作流还要求 tag 必须在 main 上,否则 “refusing to publish to PyPI”(:43-51)。发布只产 wheel 不产 sdist,注释给的理由是完整 wheel 里内含打包好的 Next.js 资源(:115-125)。
迭代密度也有可数的痕迹:assets/releases/ 下 3 份当前版说明,assets/releases/past_releases/ 下 62 份,加起来我们采集时仓库内共 65 份版本说明(版本演进的具体轨迹我们另有一篇专门讲,这里只取总量)。
维护面则比很多人预期的窄。CONTRIBUTING.md:26-28 把唯一维护者标注为 @pancacake,原文是 “Currently just me!”;README 则写项目由 HKUDS 组内的 Bingxi Zhao 主导,并且 “iterates in a fully open-source form”,同一处还有一句 “So far, we DO NOT have paid online products of any form.”(README.md:821)。贡献流程上,CONTRIBUTING.md:36-42 明确 “Please do not submit PRs directly to main”,两条目标分支是 dev 与 multi-user。
学术侧的出处在 CITATION.cff:title 是 “DeepTutor: Towards Agentic Personalized Tutoring”,7 位作者,preferred-citation 指向 “arXiv preprint arXiv:2604.26962”,year 2026。README 徽章里也标了同一个 arXiv 号,以及 Python 3.11+、Next.js 16、Apache-2.0(README.md:31-35)。许可这件事我们只指路不解读:LICENSE 首行是 Apache License Version 2.0、全文 202 行,商用边界与分发条件请以官方 LICENSE 原文为准。
顺带一个可以两分钟自己复现的小差异:README 有 11 个语言版本(根目录英文版加 assets/README/ 下 10 个),但那 10 个译版都不含根 README 的「📦 Releases」板块——用 grep -c '📦' assets/README/*.md 逐个数出来都是 0,译版从「新闻」段落开始。说完差异就停,不推断原因。
二、“辅导”在仓库里被拆成了什么
README 的「Key Features」列了 6 条(README.md:195-200):统一运行时(Chat / Quiz / Research / Visualize / Solve / Mastery Path 跑在同一个 agent loop 上)、连接式学习上下文、Subagents 与 Partners、多引擎知识(LlamaIndex / PageIndex / GraphRAG / LightRAG / Obsidian)、可扩展工具与技能、可检视记忆(L1/L2/L3)。README 另一处把自己描述为 “an agent-native learning workspace”(README.md:193),pyproject.toml:11 的包描述则是 “An agent-native intelligent learning companion with multi-agent collaboration and RAG”。
真正好用的清单在 AGENTS.md。我们采集时这份 138 行的文档,标题是 “DeepTutor — Agent-Native Architecture”,明确是写给读代码、改代码的人和 agent 看的。它给出两层插件模型(Tools / Capabilities)、三个入口(CLI、WebSocket、Python SDK),以及 AGENTS.md:58-66 那张 capability 表——7 个:chat、mastery_path、deep_solve、deep_question、deep_research、visualize、math_animator。
把这两处并排看,“终身个性化辅导”这句定位在代码里的落点就清楚了:它不是一个整块的辅导程序,而是一组注册进同一运行时的 capability,外加一层可扩展的 tools。
这里要先划一条线:mastery_path 这类能力背后必然有一套掌握度计算和复习安排的规则,那些规则是这个项目的实现选择,写在它自己的模块里,不是经过验证的教学结论。本文不展开那些参数,也不对它们的学习效果做任何评价或承诺——具体参数写在哪一行,我们另有专门的篇目去逐行核。
三、反直觉的那一处:它是个会在你本机执行程序的系统
名字里带 Tutoring,很容易让人默认这是”打开网页跟 AI 聊学习”。仓库里的证据指向另一种形态:它是一套装在你自己机器上、会去执行外部程序的本地服务。 这是本文最想讲透的一点。
第一层证据是它的运行形态。README 说四条安装路径共享同一套 workspace 布局,设置落在启动目录下的 data/user/settings/,或由 DEEPTUTOR_HOME / deeptutor start --home 指定(README.md:206);默认端口是后端 8001、前端 3782(README.md:220-222)。也就是说,这是个跑在你本机、带自己数据目录的服务,不是托管的 SaaS——README 那句”目前没有任何形式的付费在线产品”也和这一点对得上。
第二层证据是那个单独的沙箱镜像。仓库里有两个 Dockerfile:主 Dockerfile 503 行、四个 stage;另一个 Dockerfile.runner 只有 110 行,单阶段、不含任何 app 代码,全程只 COPY 一个文件——deeptutor/services/sandbox/runner/server.py 拷到 /app/server.py(Dockerfile.runner:19、:98)。它的注释把意图写得很直白:这个 runner “must not depend on the DeepTutor package or any heavy framework — keeping the attack surface and image size minimal”(Dockerfile.runner:14-16)。一个学习工具需要专门做一个最小攻击面的执行容器,本身就说明了它要执行东西。
第三层证据最直接。Dockerfile.runner:37-42 解释了为什么装 nodejs 却不装 npm:CLI apps 由主容器负责安装,runner 这边只读挂载执行。对应到 docker-compose.yml:119-144,sandbox-runner 服务挂了三样东西:./data/user/workspace、./data/users,以及 ./data/cli-apps:ro。换句话说,由主容器安装到 data/cli-apps 的那些命令行工具,会以只读方式挂进 runner 并在里面被执行——runner 执行的是真实的外部程序,不是模拟。同一个 runner 还 pip 装了 12 个文档处理库(numpy、pandas、python-docx、python-pptx、openpyxl、pypdf、pdfplumber、PyMuPDF、reportlab、lxml、defusedxml、Pillow,Dockerfile.runner:63-75),LibreOffice(soffice)默认不装,以注释形式给出可选开启命令,理由是体积 400MB 以上,且 office skills 会先 command -v soffice 再优雅降级(Dockerfile.runner:77-83)。
第四层是没有这个 sidecar 的时候会怎样。compose.yaml:38-42 明确说自己这份编排不含 sandbox-runner,会退化到 bwrap,或退化到由 sandbox_allow_subprocess 控制的受限子进程。也就是说,隔离强度取决于你用哪一份编排文件启动——这五个 compose 文件的分工另有一篇专讲,这里只强调”选哪份直接影响执行隔离”。CONTAINERIZATION.md:22-31 也把三种部署形态排了序:docker run(rootful、可写 rootfs)、docker compose(加 PocketBase 与 sandbox-runner 两个 sidecar)、podman compose -f compose.yaml(rootless、只读 rootfs、tmpfs);Security notes 里把带 sandbox-runner 的那种称为最强姿态(CONTAINERIZATION.md:443-467)。
带 sidecar 时的加固项是可以逐条核的(docker-compose.yml:149-161):no-new-privileges:true、cap_drop: ALL、read_only: true、/tmp 与 /home/runner 走 tmpfs、pids_limit: 256、mem_limit: 1g。仓库侧的约定还有 CONTRIBUTING.md:206-216:子进程一律 shell=False,一般文件上传上限 100 MB、PDF 上限 50 MB。
这些都是仓库里写着的配置,不是”你用起来一定安全”的保证。要不要在自己机器上跑一个会执行外部程序的服务,请结合你的环境自行评估。
四、仓库自己写明的那条信任边界
顺着上一节往下,有一处特别值得单独拎出来,因为它是项目自己写在注释里的,而不是我们推断的。
docker-compose.yml:119-144 那段注释坦承:这个容器里的每一条命令共享同一个文件系统视图,“per-command isolation is a roadmap item”(docker-compose.yml:124);并写明非 admin 账号之间通过 exec 可以互读对方的 settings、chat_history.db 与 knowledge_bases,原文是 “That cross-user visibility is accepted for the invite-only trust posture and enforced no further.”
我们只陈述这段文本的位置和内容,不评价、不推断。但它对”这个项目是什么”是有信息量的:它默认自己跑在一个小范围、互相信任的场景里,而不是给陌生人开账号的多租户服务。你要把它架起来给一群人用,这段注释是必须先读的。
五、几处「文档说的和代码不一样」
这类差异在这个仓库里不算少,我们只列与”这个项目对外暴露什么”直接相关的两条,位置都给全,读者可自查:
- 用户可开关的工具,
AGENTS.md说 4 个,代码里是 7 个。AGENTS.md:34-42写 “Four user-toggleable tools surface in/settings/tools”,只列了 brainstorm / web_search / paper_search / reason;而代码里的USER_TOGGLEABLE_TOOL_NAMES是 7 项,多出geogebra_analysis、imagegen、videogen(deeptutor/tools/builtin/__init__.py:1627-1635)。README 与SKILL.md的表述与代码一致(README.md:484、SKILL.md:57)。以我们实读的仓库状态为准。 geogebra_analysis算不算 “Coming soon”。AGENTS.md:51-52写它 “is parked underCOMING_SOON_TOOL_TYPES”;代码里COMING_SOON_TOOL_TYPES是个空元组,注释写 “No tools are parked right now.”(deeptutor/tools/builtin/__init__.py:1610-1614),而这个名字同时出现在上面那份可开关列表里。
另外原样记录几处项目自己标注的未完成状态,别当成已交付能力:README 关于 OpenAI Codex OAuth 的整节标题就写着 “OpenAI Codex OAuth (experimental).”(README.md:636),节末再次写 “This compatibility path is experimental: the upstream interface may change.”(:656);CLI-only 包 “It isn’t published to PyPI yet”(README.md:755);Docker 的 :pre 标签标注为 “pre-release, when available”(README.md:296)。
六、你可以照着核的六步
cat deeptutor/__version__.py,确认版本号和那段发布流程 docstring,再翻.github/workflows/pypi-release.yml:72-99看 CI 是怎么校验 tag 的。- 打开
AGENTS.md:58-66,把 7 个 capability 抄下来;这是比 README 形容词更实用的一张能力清单。 wc -l Dockerfile Dockerfile.runner,看 503 与 110 这两个数字的差距,再读Dockerfile.runner:14-16那三行注释。grep -n 'cli-apps' docker-compose.yml,看那个:ro挂载,并把:119-144的整段注释读完。grep -n 'sandbox_allow_subprocess' compose.yaml,确认不带 sidecar 时的降级路径。- 把
AGENTS.md:34-42和deeptutor/tools/builtin/__init__.py:1627-1635并排放,数一下 4 与 7 的差。
最后说边界。本文只读了 README、AGENTS.md、CONTRIBUTING.md、CITATION.cff、pyproject.toml、两个 Dockerfile、几个 compose 文件与 CONTAINERIZATION.md,deeptutor/ 下绝大部分实现代码没有读,web/ 前端源码完全没读——凡是涉及”跑起来之后会怎样”的部分,本文一律不下结论。文中所有阈值与默认值都是源码里的默认配置,不是运行结果的保证。
本文依据 DeepTutor 官方仓库(github.com/HKUDS/DeepTutor)的 README、AGENTS.md、
pyproject.toml 与 deeptutor/ 下的源码整理,核对日 2026-08-10,对应仓库快照 456f9c2(版本 1.5.11)。
本文内容为仓库源码与文档口径,我们没有安装、部署或运行过该项目,也没有调用过其中任何一个模型 API,
因此不涉及生成质量、响应速度与教学效果的任何描述。
参数与默认值随版本变动,请以仓库最新代码与 --help 的实际输出为准。
许可条款请以官方 LICENSE 原文为准,本文不构成法律意见。
安全相关做法请结合自身环境评估,本文不构成安全方案建议。