Python 版本与依赖分组:`requirements/` 下每个文件管什么
装一个 Python 项目之前,值得先花五分钟把它的依赖声明读一遍——尤其是当它同时存在 pyproject.toml 和 requirements/ 两套文件的时候。这两套东西一旦口径不一致,你按其中一份装出来的环境就和作者、CI、Docker 镜像里的不是同一个。
DeepTutor 正好是这种双轨结构。下面所有行号、条目数都对应我们采集的仓库快照:HEAD 456f9c2,采集日 2026-08-10,deeptutor/__version__.py 里的版本号是 1.5.11。你自己 clone 之后行号可能已经漂了,但文件名和 extra 的名字是稳的。
一、Python 版本区间:上限被写死在 3.14 之前
pyproject.toml:12-18 写的是 requires-python = ">=3.11,<3.14"。下限好理解,上限值得看一眼旁边那段注释:它给出的理由是 3.14 上 pip 找不到部分编译依赖(注释点名了 faiss-cpu)的 wheel,于是会退化成注定失败的源码构建,注释里引用了 issue #664。
同一个区间在 CLI-only 子包里也写了一遍:packaging/deeptutor-cli/pyproject.toml:9-12 同样是 >=3.11,<3.14。
但「能装」和「作者建议你用哪个」是两回事,仓库里至少有四层口径:
| 位置 | 写的是什么 |
|---|---|
pyproject.toml:12-18 | >=3.11,<3.14(硬约束) |
| README Option 1(PyPI 安装) | Python 3.11–3.13,且 PATH 上要有 Node.js 20+ |
| README Option 2(源码安装) | 建议 Python 3.11–3.13 + Node.js 22 LTS,理由是对齐 CI 与 Docker |
.github/workflows/tests.yml | 矩阵 3.11 / 3.12 / 3.13;另以 experimental: true(continue-on-error)额外跑 3.14,Node 侧用 22 |
Dockerfile | python-base 与 production 两个 stage 都是 python:3.11-slim |
这几层不冲突,但含义各不相同:pyproject 那一条是装不装得上的闸门,CI 矩阵那一条是「被测过的组合」,Docker 那一条是「官方镜像里实际跑的那个版本」。要复现作者的环境,看 Docker 那一行最直接;要判断自己的 3.13 会不会踩坑,看 CI 矩阵;至于 3.14,CI 里它是带 continue-on-error 的实验列,pyproject 的上限也把它排除在外——这是仓库当前状态,不是对未来版本的结论。
二、反直觉的那一处:requirements/ 不是依赖的来源
按大多数 Python 项目的习惯,requirements/ 下的文件就是依赖清单本体。这个仓库明确不是。
根目录 requirements.txt 共 22 行,头部注释(requirements.txt:6-8)自己声明:单一事实来源是 pyproject.toml,requirements/ 下的文件只是把那些 extra 镜像一份,供「还拿不到 pyproject.toml 与源码」的 Docker / CI 安装场景使用。requirements/ 下每个文件的文件头也都写着同一句话的变体:Mirrors pyproject.toml…… Keep in sync。
于是问题变成:镜像全了吗?
我们实读的数字是:pyproject.toml:80-240 里 [project.optional-dependencies] 实际定义了 15 个 key —— cli、server、partners、parse-markitdown、parse-docling、parse-pymupdf4llm、parse、tutorbot、matrix、matrix-e2e、math-animator、graphrag、rag-lightrag、dev、all。
而 requirements/ 下只有 7 个文件:cli.txt、server.txt、partners.txt、dev.txt、matrix.txt、matrix-e2e.txt、math-animator.txt。
两边做个差集,有 8 个 extra 没有对应的镜像文件:三个 parse-*、聚合的 parse、tutorbot、graphrag、rag-lightrag,以及 all。这条差集的实际后果很具体:如果你在一个只有 requirements/ 可用的环境里(比如某些只 COPY 了依赖文件的镜像构建阶段)想装文档解析或图谱检索这几块能力,pip install -r 是拿不到的,只能回到有 pyproject 的源码 checkout 用 pip install -e ".[parse]" 这类写法。
顺带一个同源的口径差:AGENTS.md:129-137 的 “Source extras” 只列了 8 个(cli / server / partners / matrix / matrix-e2e / math-animator / dev / all),README 的安装示例只给了 5 条(.[dev]、.[partners]、.[matrix]、.[matrix-e2e]、.[math-animator],README.md:265-269),而 pyproject 里是 15 个。三处列出的数量都不一样,以我们实读的 pyproject 为准。
三、七个文件各管什么
wc -l 数行数、grep -cvE '^\s*(#|$)' 数非注释条目,结果是这样:
| 文件 | 行数 | 非注释条目 |
|---|---|---|
requirements/cli.txt | 65 | 34 |
requirements/server.txt | 36 | 12(含 -r cli.txt) |
requirements/partners.txt | 41 | 19 |
requirements/dev.txt | 25 | 11(含 -r server.txt) |
requirements/matrix.txt | 18 | 4 |
requirements/matrix-e2e.txt | 19 | 2 |
requirements/math-animator.txt | 16 | 1 |
这张表要横着读,别竖着读。注意两件事:
其一,条目数里有一部分是 -r 引用,不是包。 事实卡里明确标注的两处是 server.txt 的 -r cli.txt 与 dev.txt 的 -r server.txt,其余文件是否也有引用行我们没有逐个核,所以下面这条 grep 值得你自己跑一遍。根 requirements.txt 那 22 行里唯一的实体内容也是一条引用——-r requirements/partners.txt,按头部注释,它对应的是完整 server 运行时(CLI + API + partners)那一档,而不是最小依赖;它与 dev / matrix / math-animator 各自覆盖什么,我们没有做逐包 diff。想搞清楚完整的引用图,最省事的动作是在仓库根目录跑一次 grep -n '^-r' requirements/*.txt,把每个文件头上的引用行捞出来自己连成一张图,比逐个文件翻要快——上面这张表里 partners.txt、matrix.txt、matrix-e2e.txt 的条目数同样可能含引用行,别当成纯包数看。
其二,条目少不等于装起来轻。 math-animator.txt 只有 1 条,就是 manim>=0.19.0(pyproject.toml:193-195)。但同一处注释写明了它的系统前置:LaTeX、pkg-config、cairo、cmake、ffmpeg——这些都要在 pip 之外自己装。一个条目的文件对应五个系统级依赖,是这批文件里最容易看走眼的一个。matrix-e2e.txt 只有 2 条,这 2 条具体是什么、有没有系统前置,我们没有核。
还有一个专门的标记要留意:tutorbot 这个 extra 在 pyproject.toml:176-177 被注明为 “Legacy alias kept for one release”。原样记录,不做延伸。
四、两个 marker 背后的坑
graphrag 与 rag-lightrag 这两个 extra 在 pyproject.toml:197-215 里都带了 python_version < '3.14' 的环境 marker。旁边注释写清了不加会怎样:pip 会静默把 deeptutor 回退到最后一个没有该 extra 的版本 1.4.5。
这个坑的形态值得单独记一下:它不报错。你以为装的是当前版本,实际解析器给了你一个旧版本,然后你在旧版本上找不到新功能,从头开始怀疑人生。判断动作很简单——装完之后先看一眼真正落地的版本号,跟 deeptutor/__version__.py 里那一行对一下(我们采集时是 1.5.11);对不上,就先回去看你的 Python 版本是不是落在了 marker 之外。
这一段只陈述注释写了什么与怎么核对,marker 生效后的实际解析结果我们没有验证。
五、cli.txt 文件头上那条口径差
写这篇的时候撞上一处必须说清的不一致,位置就在 requirements/cli.txt:7:这一行写的是 “Public install: pip install deeptutor-cli”。
同一件事在仓库里有四处表述:
README.md:372与README.md:755:CLI-only 包只能从源码 checkout 安装,“isn’t published to PyPI yet”AGENTS.md:78、AGENTS.md:126:把pip install deeptutor-cli # CLI-only写成安装方式requirements/cli.txt:7:Public install: pip install deeptutor-cliSKILL.md:20:pip install deeptutor-clifor CLI-only
而 .github/workflows/pypi-release.yml:139-153 的发布校验清单里只要求并发布 deeptutor-<version>-py3-none-any.whl 一个产物,不含 deeptutor-cli。
四处口径不一致,以我们实读的仓库状态为准。要不要按某一处去装,取决于你自己的核对结果,我们不推断哪一处是对的,也不据此评价这个项目。
六、还有第四张依赖面:Dockerfile.runner
如果你只盯着 pyproject 和 requirements/,会漏掉一张独立的依赖清单。
Dockerfile.runner 共 110 行,base 镜像同为 python:3.11-slim,单阶段,不 COPY 应用代码——它只 COPY 一个文件 deeptutor/services/sandbox/runner/server.py 到 /app/server.py(Dockerfile.runner:19、Dockerfile.runner:98)。注释写明了这么做的目的(Dockerfile.runner:14-16):它 “must not depend on the DeepTutor package or any heavy framework”,为的是把攻击面和镜像体积压到最小。
所以它的依赖是自己 pip 装的另一套 12 个包(Dockerfile.runner:63-75):numpy、pandas、python-docx、python-pptx、openpyxl、pypdf、pdfplumber、PyMuPDF、reportlab、lxml、defusedxml、Pillow。apt 侧装的是 git、curl、ca-certificates、ripgrep、jq、build-essential、nodejs、fonts-wqy-zenhei(Dockerfile.runner:26-35);注释解释了装 nodejs 却不装 npm 的原因——CLI apps 由主容器安装,runner 只读挂载执行。
这里有必要如实说明它的性质:这个容器是用来执行程序的,跑的是从主容器传过去的命令与脚本;DeepTutor 本身也会去驱动你本机已安装的 agent CLI。要不要开这条路径,请结合自己的环境判断,不要因为它叫 sandbox 就默认它等于安全隔离——docker-compose.yml:124 的注释自己就写着 “per-command isolation is a roadmap item”。
另一处值得记的取舍:LibreOffice(soffice)默认不装,理由写在 Dockerfile.runner:77-83,是体积 ~400MB+,相关 office 技能会先 command -v soffice 再优雅降级;文件里以注释形式给出了可选开启的命令。这意味着你如果需要 office 相关处理,得自己决定要不要把这段注释放开。
七、你可以照着核的五步
- 打开
pyproject.toml:12-18,确认requires-python的区间与上限那段注释的理由。 - 在
pyproject.toml:80-240里数一遍[project.optional-dependencies]的 key,再ls requirements数文件,把差集列出来——这决定了你能不能靠pip install -r装到某块能力。 - 跑一次
grep -n '^-r' requirements/*.txt,把文件之间的引用关系连成图,再决定你该-r哪一个。 - 打开
requirements/math-animator.txt与pyproject.toml:193-195,把 pip 之外的五个系统前置抄下来。 - 打开
pyproject.toml:197-215,确认那两个python_version < '3.14'marker 的存在;装完之后拿deeptutor/__version__.py的版本号对一遍,防止静默落到旧版本。
最后交代边界:本文只数了 requirements/*.txt 的行数与非注释条目数,没有把每个文件与 pyproject 对应 extra 做逐包 diff,所以「是不是真的逐条同步」我们没有验证;pyproject.toml:21-75 的核心 dependencies 我们只知道是 40 余项(含 openai / anthropic / dashscope / perplexityai / llama-index / faiss-cpu / fastapi / uvicorn / pocketbase / typer / rich 等),未逐行计数。以上出现的所有版本区间与默认配置都是仓库当前的声明,不是对安装结果的保证。
本文依据 DeepTutor 官方仓库(github.com/HKUDS/DeepTutor)的 README、AGENTS.md、
pyproject.toml 与 deeptutor/ 下的源码整理,核对日 2026-08-10,对应仓库快照 456f9c2(版本 1.5.11)。
本文内容为仓库源码与文档口径,我们没有安装、部署或运行过该项目,也没有调用过其中任何一个模型 API,
因此不涉及生成质量、响应速度与教学效果的任何描述。
参数与默认值随版本变动,请以仓库最新代码与 --help 的实际输出为准。
安全相关做法请结合自身环境评估,本文不构成安全方案建议。