Study Notes Generator — 学习材料整理 Skill
将 PDF 课件 / 讲义 / 教材扫描件转化为结构化复习笔记,按章节独立输出。 通过"分段 → 逐段摘要 → 合成"的两遍策略,处理远超上下文窗口的大文件。
工作目录与调用约定
约定:本文所有命令统一写作 helper.sh <命令> <课程目录或PDF>。helper.sh 的子命令都把课程目录/PDF 作为参数,所以从哪个目录运行都行——无需 cd 到课程目录,也不会污染 skill 目录。
先把脚本放到 PATH(或用绝对路径):
# 二选一:
export PATH="$PATH:/path/to/ThisSkill" # 之后可直接 helper.sh ...
# 或每次用绝对路径:
/path/to/ThisSkill/helper.sh manifest /path/to/courses/MyCourse
# 目录结构示意:
# /path/to/courses/
# └── MyCourse/ ← 课程目录(作为参数传入)
# ├── tmp/ ← 中间文件目录(自动生成)
# ├── .study-notes-manifest.json ← 进度追踪文件(自动生成)
# ├── lecture1.pdf
# └── lecture2.pdf
helper.sh manifest /path/to/courses/MyCourse
❌ 错误用法:把 skill 目录或相对路径当课程目录传入——课程目录必须包含 PDF,否则 scan/manifest 扫不到任何文件。
helper.sh scan /path/to/LearningHelperSkill # 错误:传成了 skill 目录,里面没有课程 PDF
🎯 核心原则
原则1:基于Token数判断策略
现代模型的上下文能力:100K-200K tokens
判断标准:
| 提取文本大小 | Tokens | 策略 | 理由 |
|---|---|---|---|
| < 50K | ✅ 小于上下文一半 | 直接生成 | 保持内容连贯性,避免碎片化 |
| 50K-150K | ⚠️ 接近上下文上限 | 可选分段 | 可直接处理,或分为2-3段 |
| > 150K | ❌ 超出合理范围 | 必须分段 | 需要两遍策略 |
如何判断:
# 使用 estimate-tokens 命令
helper.sh estimate-tokens tmp/<stem>_full.txt
# 输出示例:
# Estimated tokens: 123,456
# Strategy: ⚠️ Optional segmentation (25-50K tokens per section)
常见误区:
- ❌ 不要机械地按固定行数切分(如200-400行)
- ❌ 不要将小文件(<50K tokens)强制分段
- ✅ 让LLM根据语义和结构智能分段
原则2:章节隔离(每章独立处理)
⚠️ 架构要求:每章必须独立处理,不得在一个会话中串行处理多章。
为什么必须隔离?
- 上下文清洁:每章从干净的状态开始,不受前章影响
- 质量稳定:第15章和第1章质量一致(不会"越到后面越着急")
- 可恢复:单章失败不影响其他章节
- 可并行:多章可以并行处理(如果资源允许)
实施方式:
方式1:用户主动隔离(推荐)
用户: "整理 Ch1 笔记"
Claude: 生成 Ch1.md
用户: "整理 Ch2 笔记" # 新会话或显式清理
Claude: 生成 Ch2.md
方式2:Agent 工具隔离(批量处理时)
用户: "批量整理所有章节"
Claude:
for chapter in chapters:
Agent(
subagent_type="general-purpose",
prompt=f"整理{chapter}笔记",
isolation="worktree" # 每章独立环境
)
⚠️ 并行安全:课程目录是外部目录,
isolation="worktree"只隔离 skill 仓库、隔离不到课程输出——所有 agent 会写同一个课程目录。因此并行模式下:
- 每个 agent 只允许
extract/ 写自己的Ch<N>.md,禁止运行manifest(否则多个 agent 同时重建.study-notes-manifest.json会互相覆盖损坏)。- 编排方(主会话)在所有 agent 全部完成之后,统一跑一次
helper.sh manifest <dir>。- 章节 PDF 拆分文件交给不同 agent(如
chapter07-1、chapter07-2合并到同一篇)时不要并行——会有写冲突;串行处理合并章节。
禁止行为:
- ❌ 在一个会话中生成 Ch1 → Ch2 → ... → Ch15
- ❌ 让上下文累积超过 50K tokens
- ❌ 期望"一次性处理所有章节"
原则3:两遍策略(仅在大文件时)
何时需要两遍策略?
不需要两遍(直接生成):
- 提取文本 < 50K tokens
- 读取全文 → 一步生成笔记
需要两遍(Map → Reduce):
- 提取文本 > 150K tokens
- 或者:提取文本 > 50K tokens 但内容复杂(多主题、长章节)
两遍策略流程:
第一遍(Map):
父模型读取全文 → 智能分段 → 每段生成摘要
目标:将 150K tokens 压缩为 30-50K tokens 的摘要集
第二遍(Reduce):
子模型读取所有摘要 → 合成连贯的笔记
目标:从摘要生成高质量笔记
Section 大小:
- 推荐:30-50K tokens/section
- 最小:不要低于 15K tokens(会碎片化)
- 最大:不要超过 80K tokens(失去意义)
示例:
CompArch Ch5 (123K tokens):
→ 分为3个section:45K + 40K + 38K tokens ✅
Psychotherapy Ch1 (28K tokens):
→ 直接生成,不分段 ✅
适用场景
- 课程课件(PDF 幻灯片)→ 按章复习笔记
- 教材章节扫描件 → 知识点梳理
- 讲义 / 提纲 → 展开为完整复习材料
- 从零搭建课程复习体系,或对已有笔记进行补充/重写
📋 工作流程
Phase 0: 初始化与评估
- 确认课程目录
- 运行
helper.sh manifest <dir>- 生成进度追踪文件 - 运行
helper.sh resume <dir>- 查看当前进度 - 确定本次要处理的章节范围
⚠️ 重要:如果批量处理多个章节,必须明确每章独立处理。
Phase 1: 文本提取与Token评估
对每个需要处理的 PDF:
运行
helper.sh extract <pdf>- 提取文本到
tmp/<stem>_full.txt - 自动优化:压缩空行、移除多余空格
- 提取文本到
评估提取文本大小:
helper.sh estimate-tokens tmp/<stem>_full.txt根据token数判断策略:
- < 50K → 直接进入 Phase 3(笔记生成)
- 50K-150K → 可选:直接生成或分段
150K → 必须进入 Phase 2(分段)
提取质量检查:
- 读前 20 行,确认文本质量
- 如果是乱码或图片型 PDF:用 Read 工具的 PDF 模式逐页阅读
Phase 2: 智能分段与摘要(仅大文件需要)
触发条件检查:
在开始此阶段之前,确认以下条件:
- ✅ 提取文本 > 150K tokens(或 50K-150K tokens 但内容复杂)
- ✅ 已运行
estimate-tokens确认需要分段 - ✅ 理解:分段是为了适应上下文,而非机械切分
如果检查失败:
- 如果文本 < 50K tokens → 跳过 Phase 2,直接 Phase 3
- 如果 50K-150K tokens 且内容简单 → 可直接处理
Step 2.1: 父模型智能分段
目标:将全文分段为 30-50K tokens 的 section
分段策略(由父模型执行):
识别自然边界(优先级从高到低):
- 编号标题:如 "5.1 Introduction", "5.2 Basic Concepts"
- 章节标题:如 "Overview", "Summary", "引言", "总结"
- 幻灯片边界:每个新幻灯片的标题
- 主题转换:内容从一个主题跳到另一个主题
- 段落边界:连续空行后出现新话题
调整section大小:
- 目标:30-50K tokens/section
- 如果某个section > 80K tokens → 在子标题处进一步切分
- 如果某个section < 15K tokens → 合并到相邻section
生成section文件:
- 创建
tmp/<stem>_sections/目录 - 写入
sec_001.txt,sec_002.txt, ... - 每个文件头部插入元数据:
## Section: <检测到的标题> | Source: <原文件名> | Lines: <起>-<止>
- 创建
更新manifest:
- 运行
helper.sh manifest <dir>更新进度 - manifest 应包含 sections 数组(id, title, file, estimated_tokens, summarized, summary_file)
- 运行
示例:
CompArch Ch5 (123K tokens):
→ sec_001.txt: "5.1 Overview" (45K tokens)
→ sec_002.txt: "5.2 Basic ILP" (40K tokens)
→ sec_003.txt: "5.3 Advanced" (38K tokens)
Step 2.2: 子模型逐段摘要
目标:每个section生成结构化摘要
工作流程:
- 读取manifest,找到第一个
summarized: false的section - 只读取该section文件(30-50K tokens,而非全文150K+)
- 生成摘要,写入
tmp/<stem>_sections/sec_NNN_summary.md - 更新manifest:标记该section为
summarized: true - 继续下一个section,直到所有section完成
摘要格式(信息密集但精炼):
## <本段主题/标题>
### 核心概念
- **概念A**:一句话定义
- ⭐ **重点概念B**:需要掌握的要点
- **概念C** vs **概念D**:两者区别
### 公式(如果有)
$$公式$$ — 变量含义:...
### 重要表格/对比
| 维度 | A | B |
|------|---|---|
### 关键结论
- 结论1
- 结论2
### 与其他部分的关联
→ 后文会用到此处的 X 概念
→ 前文的 Y 概念在此应用
摘要质量标准:
- ✅ 保留所有定义、公式、定理的精确表述
- ✅ 保留重要的数字和比例关系
- ✅ 保留对比关系的两边
- ❌ 去除重复阐述、过渡句、寒暄语
- ❌ 去除幻灯片中纯粹装饰性的内容
- ⭐ 标注考试高频考点
预期输出大小:
- 每个 section 摘要:2-5K tokens(约200-500行)
- 所有摘要合计:10-20K tokens(远小于原文)
Phase 3: 章节笔记生成(Reduce 或 直接)
情况A:未分段(直接生成)
适用:提取文本 < 50K tokens
流程:
- 读取
tmp/<stem>_full.txt(全文,< 50K tokens) - 按笔记模板生成完整章节笔记
- 写入
<dir>/Ch<N>-<名称>.md
情况B:已分段(从摘要合成)
适用:提取文本 > 150K tokens,已完成 Phase 2
流程:
一次性读入所有摘要文件
- 从
tmp/<stem>_sections/读取所有*_summary.md - 总量应在 10-20K tokens,完全在上下文内
- 从
合成为连贯的章节笔记
- 统一术语:确保同一概念全文用同一名称
- 建立衔接:在section之间添加过渡语
- 去重合并:多个section提到同一概念,合并为一处
- 添加速查表:从全文视角整理公式/概念速查表
- 添加关键概念清单:末尾的知识点checklist
写入笔记文件
- 按下方模板组织内容
- 写入
<dir>/Ch<N>-<名称>.md
更新manifest:
note_generated: true
章节笔记模板
# Ch<N> <章节标题>
> 课件:<文件名>.pdf (<页数> 页)
> 教材:*<教材名>* <版次>, Ch<N>
---
## N.0 本章概述
| 子主题 | 核心内容 | 重要程度 |
|--------|---------|---------|
| <主题1> | <简述> | ⭐⭐⭐ |
| <主题2> | <简述> | ⭐⭐ |
---
## N.1 <第一个子主题>
### 核心概念
- **概念A**:定义
- ⭐ **重点概念B**:要点
### 详细内容
- 知识点列表
- 关键概念用 **粗体** 标注
- 重要考点用 ⭐ 标注
- 公式用 $$ 行间 LaTeX 或 $ 行内 LaTeX
(表格/图示/代码块按需插入)
---
## N.2 <第二个子主题>
...
## N.X 公式速查表(可选 — 仅在有计算/公式内容时生成)
| 公式 | 含义 | 应用场景 |
|------|------|---------|
| $$...$$ | ... | ... |
## N.Y 概念/定理/定律速查表(可选 — 仅在以概念理论为主时生成)
| 名称 | 类型 | 核心内容 | 考点 |
|------|------|---------|------|
| XX定律 | 定理 | 一句话概括 | ⭐⭐⭐ |
## N.Z 本章关键概念清单
- [ ] 概念1:一句话说明
- [ ] 概念2:一句话说明
笔记撰写原则
- 全面性:覆盖课件/教材全部页面内容,不遗漏知识点
- 结构化:按课件原始章节组织,保持编号一致性
- 独立可读:每章笔记自成体系,可单独阅读复习
- 不可合并:每章必须单独一个文件,禁止合并为单文件
- 中英对照:核心术语首次出现时标注英文原文,如「流水线(Pipelining)」
与已有笔记的兼容
完成判定阈值:行数 ≥ 30 即视为"已完成"(与 helper.sh 的
NOTE_COMPLETE_LINES一致)。 合法的短章节(< 30 行但内容完整)可在笔记中加一行<!-- done -->标记覆盖行数判定。
- 若目标笔记文件不存在或为骨架文件(< 30 行且无
<!-- done -->),从摘要完整重写 - 若目标笔记文件已存在且内容充实,询问用户:保留现有笔记、还是用新摘要完整重写
Phase 4: 课程总览
文件:<课程目录>/00-总览.md
当大部分章节笔记完成后生成(或按需更新):
# <课程名> · 复习总览
> 学校/院系信息
> 教材信息
---
## 课程思路
(用 3-5 段自然语言讲清楚:)
- 这门课的核心问题是什么?要解决什么?
- 知识点按什么逻辑排列?为什么是这个顺序?
- 哪些是主线、哪些是支线?
- 学这门课需要什么前置知识?
---
## 课程结构
| 章节 | 课件 | 页数 | 核心主题 | 笔记 |
|------|------|------|---------|------|
| Ch1 绪论 | chapter01-intro.pdf | 125p | ... | [Ch1-绪论](Ch1-绪论.md) |
---
## 知识脉络图
```mermaid
graph TD
A[计算机系统概览] --> B[指令集架构]
A --> C[性能衡量]
B --> D[流水线]
B --> E[指令级并行]
D --> F[存储层次]
E --> F
F --> G[多线程]
分章节笔记
| 文件 | 内容 | 状态 |
|---|---|---|
| Ch1-绪论 | 计算机系统概览、性能、Amdahl定律 | ✅ |
知识脉络图使用 Mermaid `graph TD`(从上到下),用有向边表示依赖/前置关系。如果 Mermaid 不可用,退回 ASCII 树形图。
---
### Phase 5: 练习题框架
**文件**:`<课程目录>/练习题框架.md`(或按章节拆分)
从已有章节笔记中提取可考的知识点,按章节组织:
```markdown
## Ch<N> <章节名>
### 题型 1:<题型名称>
**公式**:(如果适用)
$$...$$
**解题步骤**:
1. ...
2. ...
**典型考法**:(如果适用)
**重点程度**:⭐⭐⭐ 高频考题 / ⭐⭐ 常见考题 / ⭐ 偶尔考
如果练习题内容过长(>300 行),按章节拆分为独立文件 练习题-Ch<N>-<名称>.md,主文件变为索引页。
子命令
整理单章笔记
用户指定一个 PDF → 为该 PDF 生成完整复习笔记。
用户: "整理 chapter03-pipeline.pdf 的笔记"
执行步骤:
helper.sh extract chapter03-pipeline.pdfhelper.sh estimate-tokens tmp/chapter03-pipeline_full.txt- 根据token数判断:
- < 50K → 直接读全文,生成笔记
150K → 执行 Phase 2(分段)→ Phase 3(合成)
- 将笔记写入 Ch3-流水线.md
- 更新 00-总览.md 中的链接(如有变化)
批量整理所有章节
用户: "把剩下的章节都整理了"
⚠️ 重要:必须每章独立处理,不得在一个会话中串行。
执行方式:
选项1:手动控制(推荐)
Claude: "检测到以下章节待处理:Ch4, Ch5, Ch6"
"建议逐章处理,每章在独立会话中完成"
"现在处理 Ch4,完成后请手动触发下一章"
用户: "开始 Ch4"
Claude: 生成 Ch4.md
用户: "开始 Ch5" # 新会话
Claude: 生成 Ch5.md
选项2:Agent 并行(如果用户同意)
Claude: 为每章启动独立 Agent,并行处理(agent 内只做 extract + 写 Ch<N>.md,不跑 manifest)
for chapter in chapters:
Agent(
subagent_type="general-purpose",
prompt=f"整理{chapter}笔记",
isolation="worktree"
)
# 所有 agent 完成后,主会话统一刷新一次进度:
helper.sh manifest <dir>
从断点继续
用户: "继续上次的工作"
helper.sh resume <dir>查看进度- 报告 PDF 级三态(未提取 / 已提取待笔记 / 笔记完成)
- 走了两遍策略的 PDF 会显示
N/M sections summarized的逐段摘要进度 - 末尾给出 "下一步:处理 X" 的建议(含第一个未摘要的 section)
- 找到第一个未完成的章节/section,从该断点继续
生成/更新练习题
用户: "生成练习题"
- 读取所有已有章节笔记
- 从每个章节中提取可考的知识点
- 按章节组织为练习题框架
- 如果内容过多,拆分为独立文件
仅提取大纲
用户: "先梳理一下课程大纲"
- 扫描目录中所有 PDF,对每个提取文本并快速浏览
- 识别各章核心主题
- 生成 00-总览.md 中的课程结构表格和知识脉络图
- 不生成详细笔记
📁 输出文件约定
| 文件 | 命名 | 说明 |
|---|---|---|
| 课程总览 | 00-总览.md |
课程思路、结构表格、知识脉络图、章节链接 |
| 章节笔记 | Ch<N>-<中文名>.md |
每章一个独立文件;行数 ≥30 或含 <!-- done --> 视为完成 |
| 练习题框架 | 练习题框架.md |
按章的题型与解题模板(可拆分) |
| 进度追踪 | .study-notes-manifest.json |
自动生成的进度文件,不要手动编辑(含 schema_version) |
| 中间文件 | tmp/ |
提取文本、段落摘要等,保留供调试/断点续传;helper.sh clean <dir> 可清理 |
helper.sh子命令速查:scan/extract/extract-all/skeleton/status/manifest/resume/estimate-tokens/clean,均接受课程目录(或 PDF)作为参数。
🔀 合并章节处理
有些课程的同一章节被拆成多个 PDF(如 chapter07-1-Coherence-I.pdf + chapter07-2-Coherence-II.pdf)。
处理方式:
- 两个 PDF 都执行 Phase 1 提取
- 两者的段落摘要连续编号(sec_001...sec_N, sec_N+1...sec_M)
- Phase 3 合成时,一次性读入两组摘要,合成为同一篇笔记
Ch7-缓存一致性.md
📝 文本提取注意事项
pdftotext -layout对扫描型 PDF 可能提取质量不佳,需要结合 PDF 直接阅读- 多栏排版可能错乱,需要根据上下文逻辑重新组织
- 表格、图示提取为文本后需要重建 Markdown 表格
- 公式可能提取为乱码,需要根据上下文推断并重写为 LaTeX
- 提取后会自动优化:压缩空行、移除多余空格
⚠️ 注意事项
- 所有路径使用相对于课程目录的相对路径
- Markdown 链接格式:
[显示文本](文件名.md),确保可点击跳转 - 每次处理一个 PDF 后告知用户完成,等待确认或下一章指令
- 不要删除用户已有的内容,除非用户明确要求重写
- 如果课件内容超出 PDF 文本提取能力(如大量手写批注、复杂公式图),需要在笔记中注明"该部分需对照原课件查看"
- 必须遵守章节隔离原则,不得在一个会话中处理多个章节