从0开始把PDF教材喂给AI:一条交互式教程生成管线的实战指南

张开发
2026/4/18 19:06:13 15 分钟阅读

分享文章

从0开始把PDF教材喂给AI:一条交互式教程生成管线的实战指南
从0开始把PDF教材喂给AI一条交互式教程生成管线的实战指南笔者手边有一本 700 多页的英文教材——Real-Time Rendering 第四版业界简称 RTR4。这本书写得很扎实图形学的方方面面几乎都覆盖了但说实话每次翻到第三章就犯困。不是书写得不好是那种学术教材特有的密度和语调——每一句都在传递信息每一句也都像在催眠。如果你跟我一样硬盘里躺着几本永远在计划中的技术 PDF你会理解这种感觉这些书的内容本身没问题但阅读体验像是盯着混凝土墙看。而手动把笔记整理成博客教程工程量大到让人望而却步——一本 27 章的书光排版就要耗掉几个周末。后来我想了一件事如果我能把 PDF 直接丢给 AI让它用我喜欢的那种风格——带吐槽、带踩坑预警、带我们而不是读者应当的语气——重写成一篇篇能让人读下去的教程呢这件事如果做成了不只是我一个人的阅读问题被解决了——任何一个有技术 PDF 或者 Wolai 笔记文档的人都可以用同样的方式把看得懂但读不下去的资料变成想继续读下去的交互式教程网站。这个想法最后变成了一个叫 Grimoire 的开源项目GitHubhttps://github.com/charliechen114514/grimoire整条管线从解析到生成到打包成网站全部自动化中间还夹了一套质量审查机制来盯住 AI 的手。接下来笔者想把这个项目拆开来讲——不只是展示它能做什么更想聊清楚它为什么必须被设计成这个样子。先别急着丢给 ChatGPT这件事最直觉的做法是把每一章的内容粘贴到 ChatGPT说帮我重写成教程风格。笔者最开始也是这么干的。然后发现这条路走不通原因不止一个。第一道墙是 token 截断。一本正经的技术教材一章动辄几万字LLM 的 8K token 输出上限根本兜不住。你让 AI 重写一章内容它写到一半就停了后半截直接消失连个未完待续都没给你留。第二道墙更隐蔽——跨章的概念连续性。第一章提到渲染管线的时候给出了一种解释到第四章再提的时候 AI 已经忘了自己之前怎么说的了直接换了一套说法。术语不统一这件事在教程里是致命的读者会在第四章突然怀疑自己是不是看的同一本书。第三道墙是质量控制。AI 写出来的东西你总得检查吧27 章的内容你不可能一章一章手动审。但如果你不审鬼知道它会在哪一章突然开始用论文腔写东西。这三道墙拼在一起指向一个核心认知教程生成不是一个 Prompt 问题而是一个工程问题。它实际上是五个子问题的组合——概念提取、教程正文生成、练习题创建、要点总结外加一层质量审查和自动修复。每个子问题需要的上下文不同、策略不同、质量标准也不同。所以我们需要的不是一个更大的 Prompt而是一条结构化的管线。拆解一条教材变教程的管线长什么样Grimoire 的管线分四个阶段每个阶段干一件明确的事像一条工厂流水线一样首尾衔接。第一阶段是解析Parse。输入可以是 PDF 文件也可以是网页 URL。PDF 走PDFParser提取文本和图片网页走引擎系统——Wolai、静态 HTML、Playwright SPA 渲染三选一也可以自动检测。解析的产物是一份chapters_raw.json把整本书按章节拆好后续所有阶段都围着这份结构化数据转。第二阶段是批量生成Batch Generate这是管线的核心。每一章会经历四个 Agent 的接力ConceptAgent先跑从原文中提取 10 到 25 个核心概念同时维护一份跨章节的全局术语表。概念提取完之后WritingAgent和ExerciseAgent同时启动——一个写教程正文一个出分级练习题互不依赖所以并行跑。两者都完成后TLDRAgent收尾把全章提炼成最多 5 个要点。多个章节之间也可以并行处理用--workers N控制并发数术语表通过快照策略保证并发安全。第三阶段是质量审查Review。独立的ReviewAgent从风格一致性、难度曲线、概念密度三个维度给每章打分低于 7 分的不及格章节会被送进FixAgent做最小化的定向修复修完重新送审循环迭代直到通过或达到最大重试轮次。第四阶段是打包Package把所有生成的教程 Markdown 打包成一个可以直接部署的 MkDocs 静态网站。这条管线的架构不是拍脑袋决定的。有几个地方的设计决策值得展开说因为它们直接决定了输出质量。先看 Phase 2 里 Agent 之间的依赖关系。ConceptAgent必须先跑——它负责从原文中提取 10 到 25 个核心概念还要区分哪些是本章新出现的、哪些是前面章节已经定义过的。这些概念信息会被后续的WritingAgent和ExerciseAgent消费所以它是一个前置依赖。但概念提取完成之后教程正文和练习题之间就没有依赖了——它们各自消费同一份概念列表互不干扰所以管线把它们做成并行的用asyncio.gather同时跑。这一步直接把每章的耗时砍掉了大约 25% 到 30%。跨章节的术语表glossary是一个更微妙的设计。当多个章节并行跑的时候--workers 4意味着最多 4 章同时处理每章都能读到术语表但它们不能同时往术语表里写新概念——否则就会出现竞争条件A 章和 B 章可能对同一个术语给出不同的定义。Grimoire 的解法是快照策略所有并行章节拿到的是同一份术语表快照各自处理完之后新概念在锁的保护下延迟合并回全局术语表。这意味着并行章节之间不会互相干扰代价是后跑的章节可能看不到前面章节刚刚提取的新概念——但实践中这个代价很小因为术语通常在多个章节里重复出现不会只在一个章节里被首次定义。Phase 3 的审查环节也是被故意独立出来的。如果生成和审查是同一个 Agent 自己干的那相当于让学生给自己判卷——你永远不知道它会不会自我感觉良好。独立的ReviewAgent用一套完全不同的评分维度来审视输出而FixAgent只做最小化的定向修改不会把整章推翻重写。这个审查与修复分离的设计是保证批量输出质量一致性的关键。从零开始5 分钟跑通你的第一个教程环境搭建很快。笔者的开发环境是 WSL2 上的 UbuntuPython 3.12整个过程不超过三分钟。先把项目 clone 下来创建虚拟环境gitclone https://github.com/charliechen114514/grimoire.gitcdgrimoire python-mvenv .venvsource.venv/bin/activate pipinstall-e.这里pip install -e .会以开发模式安装所有核心依赖。如果你还需要 OCR 增强的 PDF 解析或者 Playwright 的 SPA 渲染可以换成pip install -e .[all]一步到位。接下来是 API 密钥。项目根目录有一个.env.template模板文件复制成.env然后填入你的 Anthropic API Key 就行cp.env.template .env# 编辑 .env填入 ANTHROPIC_API_KEY你的密钥如果你用的是第三方代理比如智谱、DeepSeek 的兼容接口也可以在.env里设置ANTHROPIC_BASE_URL指向代理地址Grimoire 会自动走代理。好了所有准备工作到这里就结束了。下面这一行命令会把整个管线从头跑到尾——解析、生成、审查含自动修复、打包成网站python-mcli all books/your-textbook.pdf--slugMYBOOK如果是 Wolai 上的教程网页把 PDF 路径换成 URL 就行管线会自动检测域名并选择对应的解析引擎python-mcli allhttps://www.wolai.com/xxxxx--slugRTR4--workers4这里的--workers 4开启 4 章并行处理。实测 RTR4 这本 27 章的教材用 4 个 worker 跑完全部章节只花了大约 15 分钟——包含概念提取、教程正文生成、练习题创建和要点总结。管线跑完之后输出在output/MYBOOK/目录下。进到这个目录用 MkDocs 起一个本地服务器就能预览成品了cdoutput/MYBOOKmkdocs serve# 打开 http://127.0.0.1:8000 预览到这里你的第一个 AI 生成的教程网站就跑起来了。灵魂所在让 AI 用你的风格写教程如果说管线架构是骨架那写作风格系统就是 Grimoire 的灵魂。一般的 AI 写作工具给你一个文本框你输入用技术博客风格重写AI 就按它理解的那个风格给你输出。问题是AI 理解的技术博客风格和你理解的不是同一个东西——它可能给你整出一堆好了接下来让我们看看这种一眼就能识别的模板过渡句或者用学术论文腔把原本有趣的机制讲得比原文还无聊。Grimoire 不走这条路。它用一份 600 多行的纯 Markdown 配置文件config/writing_style.md来精确控制生成风格的每一个维度——从人格定位、语气规则、叙事节奏到过渡句模板全部可配。举一个具体的例子。这份风格文件定义了三种叙事节奏模式针对不同类型的内容自动切换。第一种叫SICP 紧绷模式用在章节引子和核心概念首次亮相的场景——句子短留白多一句话只讲一件事讲完就停强迫读者停下来思考。第二种叫侯捷紧密模式用在机制拆解和代码逐段讲解——每句话都有信息量没有废话读者像在跑步机上连续走节奏紧凑但不留悬念。第三种叫费曼流动模式用在类比引入和踩坑故事——思路外放像在跟朋友聊天允许绕路和重复。这套节奏机制解决的是 AI 生成文本最常见的病征——“起伏太平”。每个段落读起来密度一样、节奏一样像心电图上画了一条直线。而一个好的技术教程段落之间需要有张力的起伏建立期待 → 推进展开 → 反直觉的转折点 → 释放和喘息。Grimoire 的风格配置里甚至有一节专门讲段落张力曲线的设计要求每个超过 400 字的大段内建一条完整的张力弧线。还有一个笔者特别满意的机制——类比回收规则。风格文件强制要求每个类比必须出现三次第一次建立映射第二次在讲完真实机制后揭示类比开始失效的边界第三次在小节末尾用同一个类比检验读者的理解。这解决的是技术写作里最常见的类比用完就丢问题——读者看完类比觉得懂了但一回到真实机制就又懵了因为类比和现实之间的距离从来没被说清楚。最终效果长什么样这里是 RTR4 第二章的生成片段实时渲染这件事本质上是一个残酷的数学游戏。这听起来有点夸张但让我们把这个画面拆解开来你的显示器每秒钟需要刷新几十次通常是 60 次甚至更多每一次刷新计算机都必须在不到 16.7 毫秒的时间里完成从「这里有辆车」到「屏幕上这辆车该有的颜色和光影」的全部计算。这不仅仅是算得快的问题。这是一场关于「感知」的战斗。这不是原文的语气——原文是标准的英文学术教材体。Grimoire 把它重写成了一个带着叙事张力的开场而风格文件同时控制了这种重写不会跑偏——它不会在第四章突然开始用本节将介绍这种官方文档腔。如果你不喜欢默认的 SICP 叙事风项目里还提供了第二套模板writing_style2.template.md是更接近工程师博客实战风的风格——更强调手把手推进、踩坑预警和上号式的段落标题。复制过来覆盖默认配置就行一行命令搞定。不止 PDF插件式引擎怎么吃掉一整个网站Grimoire 最早只能吃 PDF但笔者后来发现很多好的技术教程不是写在 PDF 里的——它们在 Wolai、Notion、各种静态网站上。于是 Web 解析引擎系统被设计成了插件式架构。核心是一个叫BaseWebEngine的抽象基类每个引擎只需要实现一个parse()方法——输入 URL输出标准化的章节数据。引擎的选择逻辑也很直觉如果命令行里显式指定了引擎名--engine wolai就用指定的如果没有指定就根据 URL 域名自动匹配比如wolai.com自动走 Wolai 引擎如果域名也没匹配上就回退到静态 HTML 引擎用 httpx BeautifulSoup 抓取。内置的三个引擎各有各的绝活。Wolai 引擎是最快的——它不走浏览器渲染而是直接调 Wolai 的公开 API 拿页面结构27 章的内容大概 7 秒钟就全部解析完毕。Static 引擎适用于传统的服务端渲染网站用 httpx 抓页面再用 BeautifulSoup 提取正文。Playwright 引擎最重但最通用它启动一个无头 Chromium 浏览器来渲染 SPA 页面——React/Vue 那种内容全靠 JS 动态加载的网站不用浏览器根本拿不到完整内容。说实话Playwright 引擎在开发过程中坑了笔者半天。标准的asyncio.sleep()和 Playwright 自带的page.wait_for_timeout()在某些 SPA 网站上会把主线程卡死——页面在那里等着你的代码也在那里等着两边互相等最后一起超时。解决方案是绕开 Python 侧的 sleep改用page.evaluate()注入一个浏览器内的Promise setTimeout组合让等待动作跑在浏览器的事件循环里而不是 Python 的事件循环里。这个坑真的很隐蔽笔者在这里血压拉满。如果你需要解析的网站不在内置引擎的覆盖范围内自己写一个引擎也不难。20 行 Python 代码就够——继承BaseWebEngine设置NAME和DOMAINS实现parse()方法把文件丢到src/parsers/engines/目录下引擎就会被自动发现和注册不需要手动配置任何东西。或者你也可以用--engine /path/to/my_engine.py直接指定一个外部文件。27 章并行跑断点续跑与并发加速RTR4 有 27 章如果串行处理——一章一章排着队跑——整个生成过程会非常漫长。Grimoire 提供了--workers N参数来开启章节级并行处理。并行的核心挑战不是怎么同时做多件事而是怎么同时做多件事且不出错。术语表的并发竞争问题前面讲过了——快照策略配合延迟合并解决的。另一个需要处理的是全局 API 并发控制。4 个 worker 意味着最多 4 章同时处理每章内部WritingAgent和ExerciseAgent又是并行的所以实际的并发 API 请求数可能是 worker 数的两倍。Grimoire 用一个全局信号量MAX_CONCURRENT_CHAPTERS * 2来限制并发请求数的上限配合指数退避做双重保护避免被 API 限流直接打回来。还有一个在工程上很重要的机制——断点续跑。每一章完成后进度会被原子性地写入progress.json。这意味着你随时可以CtrlC中断处理——去吃饭、合上电脑、甚至断网——下次重新运行同一个命令时管线会自动跳过所有已经完成的章节从断点继续。对于一本几十章的大书来说这个机制基本是必须的因为你不可能保证一次性跑完几个小时的管线而不被打断。审查 Agent谁来看住 AI 的手AI 生成的教程质量不稳定是常态不是例外。同一套风格配置第一章可能写得行云流水到了第五章突然开始堆砌列表、用本文将介绍这种论文腔。如果没有审查机制你需要一章一章手动检查那自动化管线的意义就打了对折。Grimoire 的审查系统由两个 Agent 配合完成。ReviewAgent从三个维度给每章打分风格一致性style、难度曲线difficulty和概念密度density每个维度 1 到 10 分三项都 7 才算通过。它不只是给个分数——还会给出具体的问题定位指出哪一段出了什么问题、严重程度如何、建议怎么改。比如 RTR4 第一章的实际审查报告里ReviewAgent发现了这样一个问题练习题的参考答案部分用了1.xxx 2.xxx的编号列表体出现了根据图形渲染管线的定义……这种教科书腔调。它给出的修复建议是把解析改写成连贯的叙述体——如果你把整个流程看作数据在管道里流动那么裁剪肯定是第一道关卡……这种风格。审查不通过的章节会被送给FixAgent它做的事不是推翻重写而是最小化的定向修改——只动有问题的段落保留其余部分。修改完后重新送审如果通过了就放行没通过就再修一轮。默认最多修两轮可通过--max-retries调整。这个最小化修复的设计是故意的。如果你让 FixAgent 推翻重写它可能在修好原有问题的同时引入新的问题——相当于用一个新的未知数替换一个已知的问题。定向修改把变动范围控制在最小每一轮修复的可预测性更高。在all命令里审查加自动修复是默认开启的。如果你只想要审查报告不想自动改东西加一个--no-fix就行。大章节的暴力拆解Verbose 模式与自适应分节标准模式下Grimoire 对每章做一次压缩重写输出大约是原文 20% 的篇幅。这个比例对于大多数想要快速掌握要点的场景已经够了但如果你想要的是一份基本保留所有技术细节的忠实改写——比如你想用它替代原文来做学习参考——20% 显然不够。这就是 Verbose 模式存在的理由。开启后--verbose-mode管线会用 PDF 的 TOC 层级结构来自适应分节先按 L2 标题切分如果某一节超过 30K 字符就展开到 L3 甚至 L4 子标题。切完之后每一节独立调用 LLM 进行忠实改写输出 token 上限也提到了 16K。最终结果是一章被拆成多个文件ch05_1.md、ch05_2.md、ch05_3.md……外加一个索引页把它们串起来。内容保留率从 20% 跳到大约 75%API 成本也相应地涨了 3 到 5 倍。这是预料之中的权衡——你想保留更多细节就得花更多的 API 调用。值得注意的是即使不开启 Verbose 模式管线也会自动检测大章节并做分节处理。对于从 Wolai 等网页来源获取的章节如果原文里包含 Markdown 标题比如### 12.1 图像处理管线会按标题切分后逐节处理防止单次 LLM 调用的输出 token 不够导致内容截断。这个机制对 PDF 来源同样安全——pymupdf 提取的 TOC 通常已经包含多级条目会优先使用 TOC 数据来分节。说点现实的API 成本和耗时笔者知道大家最关心的一个问题是这玩意烧多少钱以 RTR4 为例27 章标准模式使用sonnet模型--workers 4并行处理。从progress.json记录的时间戳来看整个生成阶段从08:44:16到08:59:13大约 15 分钟。API 成本方面标准模式下每章大约一次 WritingAgent 调用加一次 ExerciseAgent 调用并行加一次 TLDRAgent 调用总计大约 3-4 次 LLM 调用。27 章加起来大概 80-100 次调用。Verbose 模式的成本会涨到 3-5 倍因为每章被拆成多节每节独立调用。如果你用的是opus模型追求最高质量价格还会再上一个台阶。笔者的实用建议是这样的先用--model haiku快速跑一遍看看整体效果和风格是否符合预期——haiku 的成本大约只有 sonnet 的十分之一速度快很多。确认风格满意之后再用 sonnet 正式生成。opus 可以留着给审查环节用python -m cli review MYBOOK --fix -m opus让最强的模型来负责质量把关但不需要让它跑全部的生成任务。另外Grimoire 支持通过ANTHROPIC_BASE_URL接入第三方代理所以如果你用的是智谱、DeepSeek 等提供 Anthropic 兼容接口的服务直接配置 base URL 和对应的模型映射就行不需要改任何代码。魔改指南插件、Prompt、模型全可换Grimoire 的设计思路是分层定制——你可以不动一行代码就调整大部分行为也可以深入到 Python 层做任意扩展。最简单的定制是换写作风格。编辑config/writing_style.md这是一个纯 Markdown 文件你写的每一条规则都会被 Agent 当作风格指令来遵循。文件写得越详细生成的教程风格就越一致。项目自带两套模板一套是默认的 SICP 叙事风一套是工程师博客实战风复制过来改一改就能用。再深一层是调整 Agent 的 Prompt。所有 Agent 的系统提示词和用户提示词都在prompts/system/和prompts/user/目录下全部是纯 Markdown 文件——不涉及任何 Python 代码。这意味着你不需要理解项目的代码结构就能调整 Agent 的行为。想让练习题出得更难改prompts/user/exercise_user.md。想让 TLDR 更精炼改prompts/user/tldr_user.md。最深的一层是代码扩展。Web 解析引擎前面已经展示过了——继承BaseWebEngine20 行代码搞定一个新引擎。如果你想做更激进的事情比如添加一个新的 Agent 类型或者修改编排逻辑项目结构很清晰每个 Agent 一个文件编排逻辑在orchestrator.py批处理在batch.py都有充分的注释。Prompt 与代码分离是整个定制系统里最重要的设计决策。它意味着一个不懂 Python 的人——比如一位专注于教学法的内容创作者——也可以通过编辑 Markdown 文件来精确控制 AI 的输出风格而不需要碰任何代码。还没完——接下来想做什么Grimoire 目前还有一些局限笔者不打算藏着掖着。PDF 解析依赖正则匹配Chapter N格式的章节标题如果你的 PDF 没有这种格式比如中文教材用第 N 章需要改一下正则。所有的 Prompt 和风格配置目前是中文的英文支持需要翻译 Prompt 文件。Playwright 引擎需要安装 Chromium 的系统依赖。项目在 GitHub 上开源MIT 协议欢迎提交 Issue 和 PR。如果你有好的写作风格配置或者新的 Web 引擎实现笔者非常乐意把它们集成进项目。回到开头那个 700 页的 PDF还记得开头说的那本 RTR4 吗笔者现在已经能用大约 15 分钟把它从一本 700 页的学术教材变成一个 27 章的交互式教程网站——每章带着概念梳理、练习题和要点总结写法是那种笔者自己愿意读下去的叙事风格不是催眠的学术腔。教程正文生成之后还有一轮自动质量审查兜底不达标的章节会被自动修复。Grimoire 做的事情不是让 AI 写东西——市面上做这件事的工具已经太多了。它做的是把 AI 生成当作一个严肃的工程问题来对待用多 Agent 管线分工协作、用独立的审查机制质量控制、用可配置的风格系统保证输出一致性、用断点续跑和并行加速处理工程实用性。这些设计决策没有一个是为了炫技——每一个都是为了解决你拿到的那份 AI 输出到底靠不靠谱这个核心问题。如果你手边也有几本一直想啃但啃不下去的技术 PDF或者有一堆 Wolai 笔记想变成更系统的教程可以试试 Grimoire。毕竟AI 时代了我们不应该还在用最原始的方式啃教材。GitHubhttps://github.com/charliechen114514/grimoire — Star、Issue、PR 都欢迎。

更多文章