DeepTutor 个性化辅导系统
456f9c2(版本 1.5.11)。
本专题共 45 篇。内容依据
官方仓库
的 README、AGENTS.md、pyproject.toml
与 deeptutor/ 下的源码整理。
参数与默认值随版本变动,请以仓库最新代码与 --help 的实际输出为准。
DeepTutor 是什么:把「终身个性化辅导」拆成能跑起来的模块
DeepTutor 的自述是 Lifelong Personalized Tutoring,但这句定位说不清它到底是个什么形态的软件。本文按仓库快照把它拆成可核查的几块:版本号写在哪一行、能力清单在哪个文件里列、它会在你本机执行哪些东西,以及容器注释自己写明的那条信任边界。
认识、安装与容器
四条安装路径各自适合什么场景、依赖为什么要分组、五个 compose 文件别拿错哪一份。还有一篇顺着 past_releases 把版本演进读了一遍——这类项目的能力边界,看版本记录往往比看 README 更清楚。
四条安装路径怎么选:从 pip 到 compose
DeepTutor 的 README 明写「ships four installation paths」,但四条路的前置条件、发布状态与运行形态差别很大。本文按 README 与 pyproject 的原文逐条拆开,并把 CLI-only 那条路上四处口径不一致的位置标出来,给出一条能自己核的选择路径。
Python 版本与依赖分组:`requirements/` 下每个文件管什么
DeepTutor 的 pyproject 把 Python 钉在 >=3.11,<3.14,定义了 15 个 optional-dependencies 分组,而 requirements/ 下只有 7 个文件。本文按行号读版本区间的理由、七个文件各自的条目数与引用关系,以及 8 个 extra 没有镜像文件。
五个 compose 文件各自干什么,别拿错那一份
DeepTutor 仓库根目录躺着五个 compose 文件,名字长得像但服务数、目标运行时和挂载策略都不一样。本文按行数与服务清单逐份读它们的分工,讲清两份主文件为什么要求用脚本启动,以及哪两份根本不能单独用,并给出五个文件的行数与服务数对照表,以及可自己复现的核对动作。
从早期版本到 1.5.11:`past_releases` 里的演进轨迹
DeepTutor 仓库里存着 65 份版本说明,其中 62 份在 assets/releases/past_releases 下。本文按文件名读这条演进线的形状,讲清版本号的单一来源与 CI 校验点,并指出 1.4.5 这个旧版本号至今还写在 pyproject 的依赖注释里、参与今天的 pip 解析。
`AGENTS.md` 与 `SKILL.md` 是写给谁看的
DeepTutor 仓库根目录同时放着 AGENTS.md 和 SKILL.md,名字都带 agent,受众却不是同一批。本文按行号读这两份文件的定位差异,并列出它们与代码对不上的六处可核查差异,以及每一处该怎么自己核:例如默认 skill hub 在文档与代码里是两个名字、可开关工具数一处写 4 一处是 7。
命令行:13 个命令组
init 向导每一步在问什么、配置最终写到哪个路径、provider 命令能配哪些字段,以及 skill 与 skill_login 这两个看着像一回事其实分工不同的命令。想快速判断这个项目能不能接进你的流程,先把命令树看完。
DeepTutor CLI 的命令树一次看完:命令组到底有几个,取决于你怎么数
DeepTutor 的命令行入口在 deeptutor_cli/ 下的 20 个文件里。本文按 main.py 的行号把命令组挂载表、四个顶层命令读一遍,并说清「命令有多少个」这个问题为什么会得出好几个不同的数字,以及 README 漏记了哪几组。
`init` 向导每一步在问什么,答错了会怎样
DeepTutor 的 deeptutor init 是一个交互式向导,代码里 cli_only 走四步、完整模式走五步。本文按 init_cmd.py 与 init_wizard.py 的行号拆开每一步问什么、默认值是多少,以及跳过、选 none、探测失败、不确认保存各自会落到什么结果上。
配置写到哪里去了:路径常量与读取优先级
DeepTutor 的配置落点由 get_runtime_home() 的三级优先级决定,最后一级兜底是当前工作目录。本文按行号读这条链,以及 data/user/settings 下各文件由谁创建、init --home 为什么要重置三个单例、容器里为什么又换了一套读取顺序。
`provider` 命令能配哪些字段:答案是一个都不配
DeepTutor CLI 有一个 provider 命令组,很多人以为 base_url、api_key、model 是在这里填的。按行号读完 provider_cmd.py 才会发现,这个组只有一个 login 命令、只认两个取值,真正的字段全部由 init 向导采集并落进 model_catalog.json。
`chat` 的交互模式:一次对话里发生了什么
DeepTutor CLI 的 chat 是一个 REPL。本文按行号读它的入口注册方式、输入怎么被读进来、斜杠命令里那处「替换」而非「追加」的语义、工具输出的截断与 /show 环形缓冲,以及 README 与代码对不上的两处命令表;所有结论均可按文中行号回仓库自行核对。
`kb` 知识库命令:建、灌、查、删
截至 2026-08-10 我们采集时,DeepTutor CLI 的 kb 组有七个子命令,都在 deeptutor_cli/kb.py 这 286 行里。本文按行号读 create 为什么不能建空库、add 的去重开关、search 的默认 mode,以及知识库落在哪个目录下。
`skill` 与 `skill_login` 不是一回事
DeepTutor CLI 目录里 skill.py 和 skill_login.py 并排放着,看名字像两个命令模块,实际上后者一个命令都没注册。本文按行号读清这两个文件的分工、loopback OAuth 的两个纯函数与一段带副作用的流程,以及那条把登录令牌排在最后的取值优先级。
`session` / `notebook` / `book` / `memory`:DeepTutor CLI 这四组命令各管什么
DeepTutor CLI 的这四个命令组加起来只有 382 行、16 个子命令,但完整度完全不在一个层级上。本文按文件行号读它们的子命令、默认值与落盘动作,重点讲 book 组那处「有命令组不等于能在 CLI 上做完」的反直觉设计,顺带说明为什么 README 里查不到 book 组。
agents 层:pipeline 与调度
BaseAgent 提供了什么、模型解析的优先级链怎么走、两个 LLM 入口分别用在哪。往下是 research、question、chat 三条 pipeline 各自的阶段流,以及提示词为什么被放进几十个 yaml 而不是写死在代码里。
agents 层的划分:三块主线与 8 个子包
DeepTutor 的 agents 目录 docstring 自述分成 research / question / chat 三块,磁盘上却有 8 个子包。本文按文件数与行数把这一层数一遍,说清哪些是主线、哪些是渲染与辅助,以及为什么 agent 循环引擎根本不在这一层。
`BaseAgent` 读一遍:模型解析优先级与两个 LLM 入口
DeepTutor 的 agents 目录顶层只有一个 769 行的 base_agent.py。本文按行号读它的四级模型解析优先级链、call_llm 与 stream_llm 两个入口,以及 response_format 那处会被静默跳过的能力检查。
2871 行的 research pipeline:阶段流怎么走
DeepTutor 的 research/pipeline.py 是 agents 目录里最大的一个文件,2871 行。本文按行号与常量读它的四阶段划分、八个标签词的两种用法、动态主题队列的三个默认上限、工具结果进报告前的两道削减,以及第三阶段为什么不是一趟走完的直线。
question pipeline:出题这条线的阶段与判分
DeepTutor 的出题走的是一个 2161 行的 QuestionPipeline,三阶段 Explore→Plan→Quiz。本文按行号读它的标签协议、预算常量、探索阶段那次额外的摘要调用,以及 ask_user 被挂载却在这条线上没有恢复通路的那处设计。
`chat` 的 agent loop:一轮里发生了什么,工具是怎么挂上去的
DeepTutor 的一次 chat 对话不是「先探索再作答」两段式,而是一个循环。本文按行号读 agent_loop.py 的轮次判定、exploration+4 的真实轮数上限、四步工具组合顺序,以及那条针对文本格式工具调用的回退路径。
提示词为什么放在几十个 yaml 里而不是写死在代码中
DeepTutor 的 agents 目录里有 38 个提示词 yaml、en 与 zh 各 19 份,路径靠目录约定解析,加载失败只把 prompts 置为 None 并打一条 warning、不抛异常。本文按行号读这套约定的解析路径、语言回退链、运行时分块拼装,以及那份定义了却没有第二处引用的模块名列表。
services 层:全仓最大的一块
六万多行的 services 分成二十多个子领域,这一组按行数从大到小往下拆:LLM 统一接入、rag 检索管线、三层记忆、文档解析引擎,以及那些你改不到的硬编码默认值与失败之后的重试超时常量。还有一篇讲它会去驱动你本机已装的 agent CLI。
65456 行的 services 层:26 个子领域怎么分工
DeepTutor 体量最大的一层是 services,占全包 Python 代码的四成多。本文按实读的行数分布、根目录七个文件、懒加载 __init__ 与跨层引用计数,讲清这 26 个子领域各管什么,以及它为什么不是依赖图最底下那一层。
LLM 接入层:统一调用口与代码里出现的 provider 名单
DeepTutor 把 provider 元数据收在一个文件里,36 个名字最后只落到 5 种后端实现。本文按行号读 provider_registry.py 的 ProviderSpec 字段与 provider_factory 的分发、实例池,以及能力表对不齐、两套 provider 抽象并存这两处可核查的差异。
硬编码默认值逐个看:DeepTutor 里哪些值你改不到
DeepTutor 的 services 层散着一批写在模块里的默认值。本文按行号分三类看:配置层能改的、只写在常量里的、以及你设了也会被按模型前缀改写的那一类——`gpt-5`、`o1`、`o3` 命中的强制温度 1.0 就属于最后这类。同时说明哪些常量自带环境变量开关,并给出可在自己 clone 上复跑的检索动作。
重试与超时常量:请求失败之后它会怎么退
DeepTutor 的重试逻辑不在一个地方。全局 settings 给了 max_retries=8、base_delay=5.0,provider 基类另有一组 (1, 2, 4),还有一个带熔断的子包在生产代码里没人引用。本文按文件行号把三层拆开,并把散在各模块的超时常量归到一张表里。
rag 检索管线:52 个文件拆成了几段
DeepTutor 的 services/rag 是 7539 行 52 个文件的一层。本文按 rag/factory.py 的行号读它的六个管线常量、按名字懒 import 的分发、(kb_base_dir, provider) 缓存键,以及那处「配错名字不报错、直接落回默认管线」的设计。
文档解析引擎支持哪些格式,各走哪条路
DeepTutor 的 parsing 层用一张注册表挂了五个解析引擎。本文按行号读这五个引擎名常量定义在哪一行、分别一一对应哪五个类、为什么注册表里有名字不等于这条路在你机器上能跑通,新装默认走的是哪一条,以及 MinerU 那条支路上的云端模式与模型权重下载枚举各自意味着什么。
三层记忆:`memory` 目录的分层与落盘
DeepTutor 的 L1/L2/L3 记忆不是三个抽象概念,而是两条 Literal 类型和一组固定目录。本文按文件与行号读它的分层边界、落盘位置、两个记忆工具截然不同的挂载规则、清理命令按源码只删哪几处目录,以及「memory」这个词在仓库里指的三种不同东西。
subagent 与 cli_apps:它会去驱动你本机的 agent CLI
DeepTutor 的 services 层里有两个目录不在服务端算东西,而是去启动你本机的外部程序:subagent 驱动已装的 agent CLI,cli_apps 安装并调用命令行工具。本文按行号读它们的后端注册表、探测规则、几组超时常量,以及那份写着"不要手改"的生成快照。
知识库与学习系统
这是它区别于普通 RAG 应用的地方:掌握度怎么算、复习时间按什么排、答错之后系统认为你错在哪,这些都有具体的模型与常量落在代码里。本组只讲这些参数写在哪一行、怎么运作,不评价其学习科学上的有效性。
知识库的类型模型与 `manifest` 清单:一个拒绝回答「索引了几篇」的模块
DeepTutor 的知识库分默认 indexed 与五种 connected 指针型,`kb_types.py` 用一个 frozenset 决定谁跳过索引流水线。本文按行号读这套类型模型,以及 manifest.py 里那个显式声明「故意不报告进索引文档数」的设计与它给出的三条理由。
知识库存到哪里,名字为什么会被拒
DeepTutor 建知识库时名字被拒,多半是撞上了 naming.py 里那三行常量。本文按行号读四条校验规则、KB 目录的固定布局与平铺的 version-N 版本目录,以及 resolve_kb_dir() 为什么规定谁都不许自己拼路径、遗留目录为什么把状态改写成 needs_reindex。
切块与检索参数:这些数字写在哪一行
DeepTutor 的 chunk_size、chunk_overlap、top_k 这几个数字并不散落在各处,而是集中写在 runtime_settings.py 的两段里。本文按行号读默认值与夹取范围,讲清哪个参数被故意不暴露、改了为什么不追溯,以及同名 top_k 三个引擎三个默认值、第四个干脆没有。
掌握度是怎么算出来的:`mastery.py` 与 `policy.py` 的闸门
DeepTutor 的 learning 层把「学没学会」压进了两个文件:40 行的 mastery.py 负责算分,295 行的 policy.py 负责判闸门。本文按行号读它的近因权重、置信封顶与 0.9 定量闸门,并把两者拼起来算给你看——为什么窗口里只要有一次答错就过不了闸。
间隔重复调度器:复习时间是按什么排的
DeepTutor 的 scheduler.py 只有 101 行,却决定了每个知识点下次什么时候再出现。本文按行号读它的四条间隔序列、答对答错时 interval_index 的不对称推进、复习队列的排序键,以及那个把一天变成一秒的调试开关。
判分与错误分类:答错之后系统认为你错在哪
DeepTutor 的判分只有 64 行代码,三种题型三条规则,错误分类只分两类。本文按行号读 grading.py 的判对边界、fail-closed 兜底、classify_error 的粗分类,以及答错之后 service 层那条固定流水线会牵动哪些状态。
capabilities 层:能力注册协议与五个能力的工具
DeepTutor 的 capabilities 目录里「能力」有两层不同含义,两个注册表一个 5 项一个 7 项。本文按行号读 LoopCapability 协议的六个成员、只加不减的工具面约定与它唯一的例外,以及五个能力各自拥有的工具。
book / co_writer / 内置 skill
把一个知识库变成一本书,中间要经过规划、合成、编译几层。这一组拆 book 的数据模型与函数链、SectionArchitect 与 SpineSynthesizer 怎么把目录规划出来,以及 co_writer 的协作写作机制与内置 skill 的注册方式。
book 模块怎么把一个知识库变成一本书:四段编译流水线读一遍
DeepTutor 的 book 目录有 58 个文件、7685 行 Python。本文按 engine.py 行号读它的四段生命周期、两道用户确认闸、单 worker 编译队列,以及那一页永远不走 LLM 的导览页;另说 24 个 API 路由与 3 条 CLI 子命令的落差,19 个块类型里 6 个未注册生成器。
book 的数据模型与章节结构:19 个 `BlockType` 与 13 个生成器
DeepTutor 的 book 模块把一本书拆成 Book / Spine / Chapter / Page / Block 五层对象。本文按 models.py 的行号读这套数据模型的字段、id 前缀与三个状态枚举,并讲清枚举里 19 个块类型对不上注册表里 13 个生成器这处差异。
`SectionArchitect` 与 `SpineSynthesizer`:目录是被规划出来的
DeepTutor 的 book 模块里,章节目录和每页的块序列不是模型一次吐出来就完事。本文按行号读 SpineSynthesizer 的 Draft-Critique-Revise 循环与三步确定性后处理、SectionArchitect 的 LLM 层与静态模板层,以及那处失败即回落静态模板的分支。
`co_writer` 的协作写作机制:623 行的包,与不在包里的那半套
我们 2026-08-10 采集的快照里,DeepTutor 的 co_writer 目录只有两个 Python 文件共 623 行,对应的 API 路由却有 618 行。本文按文件与行号读 EditAgent 的三种改写动作、gather_context 的静默降级、auto_mark 的标注配额,以及那半套实现在路由层而不在包里的选区 ReAct 编辑。
`skills/builtin`:内置技能的加载与注册
DeepTutor 内置技能只有五个目录、每个目录只有一份 SKILL.md。本文按行号读 skill/service.py 的 frontmatter 字段、user 遮蔽 builtin 的扫描顺序、一行清单与 always 整篇注入两条装载路径,以及 requires 那道会去查 PATH 与沙箱的可用性门。
渠道、多用户、API 与前端
partners 是一层 IM 渠道适配、multi_user 管用户隔离与授权、api 层负责对外,前端有两个目录。想把它当成一套可以给多人用的服务来部署,这一组是必读的部分。
多用户隔离与 `grant` 授权机制:四棵目录树和一个三态字段
DeepTutor 的 multi_user 包只有 14 个文件 2031 行,却把「谁能用什么」这件事拆成了目录隔离与 grant 授权两层。本文按行号读它的四棵数据树、grant v2 的字段清单、同一个 None 在不同资源上正好相反的语义,以及仓库自己写明的两处能力边界。
鉴权机制:谁能调、怎么校验
DeepTutor 的鉴权分成总开关、令牌校验、路由闸门三层,最反直觉的一处是 require_auth 必须写成 async def,否则身份 ContextVar 会在工作线程里丢掉。本文按行号读这条链,说明 WebSocket 侧为何要另起一套鉴权,并给出可自查的核对动作。
两个前端目录是什么关系,技术栈各是什么
DeepTutor 仓库里有 deeptutor_web/ 和 web/ 两个看起来都像前端的目录,源码检出下前者只有一个 __init__.py。本文按行号读 launcher 的目录解析逻辑、web/ 的 package.json 与 next.config.js,以及前端连后端的那层 middleware。
DeepTutor 的 api 层:一个 FastAPI 实例、装配顺序与全部路由挂载点
DeepTutor 的 api 包有 40 个 py 文件、15796 行,但装配全部收在 main.py 一处。本文按行号读它的 app 构造参数、启动期漂移校验、lifespan 启停序列与全部路由挂载点,并给出把 322 这个数字自己数一遍的核查动作。
partners 是一层 IM 渠道:它接到了哪些地方
截至 2026-08-10 快照,DeepTutor 的 deeptutor/partners 有 30 个 py 文件、12252 行,但包里并没有一个 partner 引擎。本文按行号读它的 16 个渠道模块、pkgutil 零导入的发现机制、allow_from 为空即全部拒绝的访问控制,以及 README 渠道清单与代码对不上的两处差异。
想让 Agent 真正接管一条完整工作流,而不只是回答问题?
从数字员工到 Agent 工程落地,站内有成体系的教程与课程。