Tutor:把书籍或文档变成课程的自托管 LLM 辅导工具
Show HN: Tutor, a self-hosted LLM tutor that teaches you your books or docs
作者发布自托管 LLM 辅导工具 Tutor,可把 EPUB、PDF、在线书籍或在线文档转成课程,先提取概念并检查你已掌握的部分,再逐个讲解并测试。工具在本地运行,使用 Anthropic、OpenAI 或 OpenRouter 的模型,需要 Node.js 22 及以上和对应 API key,通过 npm run ingest 导入书籍、npm start 在浏览器中学习。
另见我的另一个项目 Tapas Habit & Goal Tracker,一个功能齐全的 iPhone 和 Android 习惯追踪器。此外,我正在寻找一份全职工作,担任软件开发人员。请在 LinkedIn 上联系我。
一个私人导师,从你的书籍或在线文档中教你学习。你创建一个学习主题,例如“SQL”,并向其中添加书籍。一本书可以是 EPUB 文件、PDF 文件、在线书籍或在线文档。导师会在书中找到概念,并检查你已掌握哪些概念。然后它会一次一个地教授其余概念,并引用书中的内容,对每个概念进行测试。
导师在你的电脑上运行。它使用来自 Anthropic、OpenAI 或 OpenRouter 的一个大型语言模型(LLM)。由你选择模型。
| 概念图 | 课程 | 测试 |
|---|---|---|
![]() |
![]() |
![]() |
为什么不直接与你的书籍聊天?
与书籍聊天会回答你想到的问题。导师则将你的书籍变成一门课程:
- 结构。导师将某个主题的概念放入概念图中的模块里。它从学习队列中一次一个地教授它们。
- 所有概念。导入功能会找出每一章中的概念。然后它确保这些概念涵盖书中的粗体和斜体术语。
- 可见的进度。概念图和复习板显示每个概念的状态,例如已知、学习中或已掌握。
- 你的控制权。你选择要测试、学习和跳过的概念。你还设置学习队列的顺序。导师只提供建议。
快速开始
你需要 Node.js 22 或更高版本,以及 Anthropic、OpenAI 或 OpenRouter 的 API 密钥。我们在 macOS 上测试导师。
git clone https://github.com/demetrius-edelin/tutor.git cd tutor npm install cp .env.example .env # then set the provider, the model, and the API key npm run llm:check # optional: send 3 small test requests to the model npm run ingest -- SQL /path/to/book.epub # add a book to the subject "SQL" npm run fetch -- https://doc.rust-lang.org/book/ # optional: download an online book into an EPUB file npm start # then open http://localhost:3000
在 Windows 命令提示符中,使用 copy 而不是 cp。
ingest 命令会显示模型请求的数量,并在开始前询问。若只想从书中的某些章节开始,请参阅使用指南的第 3 步。
工作原理
你分四步使用导师。第 1 步到第 3 步是终端中的命令。第 4 步是浏览器中的应用。
flowchart LR
S1["1. Set up<br/>npm install<br/>.env"] --> S2["2. Check (optional)<br/>npm run llm:check<br/>npm run parse"]
S2 --> S3["3. Add a book<br/>or some chapters<br/>npm run ingest"]
S3 --> S4["4. Study<br/>npm start"]
S3 -->|"more chapters or books"| S3
style S2 stroke-dasharray: 5 5
加载中
- 设置导师。只需执行一次。
- 检查模型和书籍。此步骤是可选的。它不会保存任何数据。
- 向主题添加一本书。添加整本书,或只添加你现在想学习的章节。只有这一步会将书籍放入导师中。对于在线书籍,请先下载它。
- 在浏览器中学习。启动应用并开始学习。应用会在每个阶段显示下一步操作。
使用指南解释了每个步骤和每条命令。
在应用中
在应用中,你打开一个主题并经历以下阶段:
- 选择:在概念图上,对每个概念进行测试、学习或跳过。若要一次性对多个概念执行此操作,请选中它们的复选框,并使用页面底部的栏。
- 诊断:导师会针对你选择测试的每个概念提出 2 个问题。要开始,请点击概念旁边的“测试它”,或选择概念并点击“测试它们”。
- 学习队列:要学习的概念,其顺序你可以更改。
- 课程和测试:导师从你的书籍中教授一个概念,并附有引用。然后它用适合该概念的问题来测试它:简单概念一个问题,较大概念最多 5 个。要通过,需正确回答每个问题。通过后该概念即被掌握。
- 复习板:所有概念的列表,包含它们的状态和星级。
模型负责出题并批改开放题答案。如果你认为评分有误,请使用“对评分提出异议”。被提出异议的答案计为正确。
命令
| 命令 | 用途 | 使用模型 | 写入内容 |
|---|---|---|---|
npm run llm:check |
可选。在修改 .env 之后使用。 |
是,3 个小型请求。 | 无。 |
npm run parse -- <book> |
可选。用于检查一本书并查找 --chapters 的章节编号。 |
否。 | 一份 data/parse/<book>/ 格式的报告,供你阅读。 |
npm run fetch -- <url> |
用于学习在线书籍或在线文档。然后把 EPUB 文件当作书籍使用。 | 仅适用于没有 llms.txt 文件的网站:1 个小型请求。 |
一个 data/web/ 格式的 EPUB 文件。 |
npm run ingest -- <subject> <book> --chapters <list> --preview |
推荐。在保存某些章节之前检查其概念。 | 是。 | 预览书籍文件夹中的文件。数据库不会改变。 |
npm run ingest -- <subject> <book> --chapters <list> |
用于学习一本书的某些章节。 | 是。 | 书籍文件夹和数据库。 |
npm run ingest -- <subject> <book> |
用于学习一本书的所有章节。 | 是。 | 书籍文件夹和数据库。 |
npm start |
每次你想学习时。 | 是,用于诊断、课程和测试。 | 你在数据库中的进度。 |
npm run refresh -- <subject> <book> |
仅在导师更新且更改了解析器之后。 | 仅用于新图片。 | 书籍的章节文件。 |
书籍文件夹是 data/subjects/<subject>/books/<book>/。数据库是 data/tutor.db。
配置
导师从 .env 文件读取其配置。将 .env.example 复制为 .env。该文件解释了每个值。
| 变量 | 值 |
|---|---|
LLM_PROVIDER |
anthropic、openai 或 openrouter。 |
LLM_MODEL |
模型名称,与提供商所写的完全一致。对于 OpenRouter,使用 vendor/model 形式。 |
LLM_REASONING |
可选。none、minimal、low、medium、high、xhigh 或 max。留空表示使用模型的默认值。 |
OPENROUTER_PROVIDERS |
可选,仅适用于 OpenRouter。可以服务该模型的提供商,按顺序排列。 |
ANTHROPIC_API_KEY、OPENAI_API_KEY、OPENROUTER_API_KEY |
所选提供商的 API 密钥。 |
导师没有默认模型。在修改 .env 之后,运行 npm run llm:check。
使用哪个模型
我们用不同的模型测试了导师。OpenAI 的 GPT-6 Luna,在推理级别 high 下,给出了最好的结果。它也是我们测试中最便宜的模型,而且对于其价格区间的模型来说非常聪明。
更新,2026 年 10 月:Anthropic 的 Claude Haiku 5.5 现在与 GPT-6 Luna 价格相同,但给出的结果好得多!
LLM_PROVIDER=anthropic
LLM_MODEL=claude-haiku-5-5
LLM_REASONING=high
如果你使用 OpenAI,请使用这些值:
LLM_PROVIDER=openai
LLM_MODEL=gpt-6-luna
LLM_REASONING=high
费用
导师使用你的 API 密钥,因此你的提供商会为每个请求向你收费。
- Ingest 发出的请求最多,因为模型会读取书籍的每一章和每一张图片。该命令会显示请求数量,并在开始前询问。
- 导师将每一章和每一张图片的模型结果保存在缓存中。之后运行时不会为缓存中的章节再次付费。
- 在应用中,诊断、课程、关于课程的问题以及测试都会使用模型。
- 高推理级别会使每个请求变慢。
端口
应用使用端口 3000。要使用其他端口,请在 shell 中设置 PORT。导师不会从 .env 读取 PORT。
PORT=8080 npm start
书籍
- EPUB 文件效果最好。解析器会读取出版商的 CSS 以处理标题、粗体和斜体。
- PDF 文件必须带有标签。Word 和许多出版工具都能生成带标签的 PDF 文件。对于未加标签或扫描的 PDF,解析器会停止并给出明确消息。
- 有些书籍将代码或表格显示为图片。Ingest 使用模型来读取它们。如果模型不接受图片,图片将保留为占位符。
- 在线书籍和在线文档:
npm run fetch会将页面下载到一个 EPUB 文件中。该命令无法读取登录后的页面,或仅在 JavaScript 运行后才显示文本的页面。参见 添加在线书籍。
常见问题
- 我必须先运行
parse再运行ingest吗? 不需要。Ingest 会自行解析书籍。parse命令只是在终端打印一份报告,不产生任何费用。参见 检查一本书。 - 如何找到
--chapters所需的章节编号? 运行npm run parse并查看#列。这个编号可能与章节标题中的编号不同。 - 如何找到
--sections所需的节 id? 运行npm run parse并查看data/parse/<book>/sections/中的文件名。文件01-10-pointers.md就是节1.10。 - 我必须摄取整本书吗? 不需要。使用
--chapters或--sections,你可以一次学习书的一部分。之后,你可以添加更多部分。 ingest总是保存到数据库吗? 是的。只有--preview会保持数据库原样。使用--chapters时,应用会立即显示这些章节的概念。- 预览的章节我需要付费两次吗? 不需要。导师会保留每次运行的模型结果,因此之后的运行不会为这些章节再次付费。
- 之后如何添加更多章节? 再次运行
ingest,并附上新章节或节的列表。参见 之后添加更多章节。 - 摄取后我可以移动或删除书籍文件吗? 可以。Ingest 会在书籍的文件夹中保留一份书籍文件的副本。
- 导师可以从在线文档进行教学吗? 可以。使用文档的地址运行
npm run fetch。然后摄取 EPUB 文件。参见 添加一本在线书籍。 - 如何为一个主题添加第二本书? 使用相同的主题名称再次运行
npm run ingest。导师会将新书的概念添加到该主题的概念图中。 - 如何创建一个新主题? 使用新的主题名称运行
npm run ingest。第一本书会创建该主题。 - 如何删除一个主题? 在主题列表中,点击主题下方的“Delete”。然后点击打开的面板中的红色按钮。导师会删除书籍、概念、你的进度以及该主题的文件夹。此操作无法撤销。
- 我可以删除
data/parse/吗? 可以。没有其他东西使用它。
状态与路线图
导师目前是 0.1.0 版本。本 README 和使用指南中的所有命令和应用阶段均可正常工作。导师供一个人在单台电脑上使用。
计划中:
- 从应用中添加书籍,并显示摄取进度。目前你需要在终端中用命令添加书籍。
- 一个容器镜像,用于在你自己的服务器上运行导师。
开发
| 命令 | 作用 |
|---|---|
npm run dev:server 和 npm run dev:app |
以实时重载运行服务器和应用。使用两个终端。 |
npm test |
运行测试。测试使用假的模型客户端,因此不会调用模型。 |
npm run test:watch |
每次更改后再次运行测试。 |
npm run typecheck |
检查服务器和应用的 TypeScript 类型。 |
技术栈
| 部分 | 工具 |
|---|---|
| 语言 | TypeScript,运行于 Node.js 22。 |
| 服务器 | Fastify。 |
| 应用 | React 19 和 Vite。 |
| 数据库 | SQLite,配合 better-sqlite3。 |
| 书籍解析器 | 用于 EPUB 的 JSZip 和 cheerio,用于 PDF 的 pdf.js,以及用于 Markdown 的 Turndown。 |
| 在线书籍 | Node.js 的 fetch 函数、cheerio、用于 Markdown 页面的 marked,以及用于 EPUB 文件的 JSZip。 |
| 模型客户端 | Anthropic SDK 和 OpenAI SDK。OpenRouter 使用 OpenAI SDK。 |
| 测试 | Vitest。 |
项目结构
src/
cli/ command-line scripts
config.ts reads .env
db/ SQLite schema
ingest/
core/ blocks, sections, Markdown, checklist (all formats)
epub/ EPUB reader
pdf/ tagged PDF reader
stages/ extract, review, and merge (the model stages)
web/ online books: table of contents, pages, and the EPUB writer
llm/ model client for Anthropic, OpenAI, and OpenRouter
tutor/ diagnosis, lessons, questions, grader, and study queue
server/ HTTP API
app/ browser app (React)
docs/ usage guide
test/ tests, a fake model client, and a builder for test EPUB files
data/ your books, the results, and the database (not in git)
AI 辅助
我用 Claude Code 构建了 Tutor。所有产品和设计决策都由我做出,并且我用真实的书籍仔细测试了每个里程碑。Claude 编写了代码和大部分文档。
贡献
欢迎提交拉取请求。对于较大的更改,请先开一个 issue,以便我们就方案达成一致。
在发送拉取请求之前,请执行以下步骤:
- 运行
npm test。所有测试必须通过。 - 运行
npm run typecheck。它必须不显示任何错误。
隐私与版权
- 不要提交
data/或.env。Git 会忽略它们。 data/文件夹包含你购买的书籍以及你下载的在线书籍的文本。fetch命令遵循robots.txt,并在两次请求之间等待一秒。- 仓库中不包含任何书籍文本。测试会在代码中构建自己的小型 EPUB 文件。
- 当导师发送请求时,它会将书籍文本发送给你所选择的提供商。使用 OpenRouter 时,文本会发送给所选模型的供应商。
许可证
来源:Hacker News · github.com


