# Study Notes

> Process learning materials (PDFs, slides, lecture notes) into structured study notes. Generates per-chapter study notes, course overview with dependency graphs, exam-point summaries, and practice problems. Uses a two-pass "segment-summarize-synthesize" pipeline to handle large files that exceed context. Make sure to use this skill whenever the user mentions: 整理笔记, 生成复习笔记, study notes, process slides, 整理课件, 生成练习题, 提取考点, 复习大纲, 或者要处理 PDF 学习材料。

- Skill: `luohaomin/study-notes` (Agent Skill, multi-file: 5 files)
- Install (CLI): `npx skillmds@latest add luohaomin/study-notes`
- Raw SKILL.md: https://api.skillmd.com/api/skills/luohaomin/study-notes/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- Author: LuoHaomin (https://skillmd.com/u/luohaomin)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/luohaomin/study-notes

---


# Study Notes Generator — 学习材料整理 Skill

> 将 PDF 课件 / 讲义 / 教材扫描件转化为结构化复习笔记，按章节独立输出。
> 通过"分段 → 逐段摘要 → 合成"的两遍策略，处理远超上下文窗口的大文件。

---

### 工作目录与调用约定

**约定**：本文所有命令统一写作 `helper.sh <命令> <课程目录或PDF>`。`helper.sh` 的子命令都把课程目录/PDF 作为参数，所以**从哪个目录运行都行**——无需 cd 到课程目录，也不会污染 skill 目录。

先把脚本放到 PATH（或用绝对路径）：
```bash
# 二选一：
export PATH="$PATH:/path/to/ThisSkill"   # 之后可直接 helper.sh ...
# 或每次用绝对路径：
/path/to/ThisSkill/helper.sh manifest /path/to/courses/MyCourse
```

```bash
# 目录结构示意：
# /path/to/courses/
#   └── MyCourse/                            ← 课程目录（作为参数传入）
#       ├── tmp/                             ← 中间文件目录（自动生成）
#       ├── .study-notes-manifest.json       ← 进度追踪文件（自动生成）
#       ├── lecture1.pdf
#       └── lecture2.pdf

helper.sh manifest /path/to/courses/MyCourse
```

**❌ 错误用法**：把 skill 目录或相对路径当课程目录传入——课程目录必须包含 PDF，否则 `scan`/`manifest` 扫不到任何文件。
```bash
helper.sh scan /path/to/LearningHelperSkill   # 错误：传成了 skill 目录，里面没有课程 PDF
```

---

## 🎯 核心原则

### 原则1：基于Token数判断策略

**现代模型的上下文能力**：100K-200K tokens

**判断标准**：

| 提取文本大小 | Tokens | 策略 | 理由 |
|------------|--------|------|------|
| < 50K | ✅ 小于上下文一半 | **直接生成** | 保持内容连贯性，避免碎片化 |
| 50K-150K | ⚠️ 接近上下文上限 | **可选分段** | 可直接处理，或分为2-3段 |
| > 150K | ❌ 超出合理范围 | **必须分段** | 需要两遍策略 |

**如何判断**：
```bash
# 使用 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：章节隔离（每章独立处理）

**⚠️ 架构要求**：每章必须独立处理，不得在一个会话中串行处理多章。

**为什么必须隔离？**

1. **上下文清洁**：每章从干净的状态开始，不受前章影响
2. **质量稳定**：第15章和第1章质量一致（不会"越到后面越着急"）
3. **可恢复**：单章失败不影响其他章节
4. **可并行**：多章可以并行处理（如果资源允许）

**实施方式**：

**方式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: 初始化与评估

1. **确认课程目录**
2. **运行 `helper.sh manifest <dir>`** - 生成进度追踪文件
3. **运行 `helper.sh resume <dir>`** - 查看当前进度
4. **确定本次要处理的章节范围**

**⚠️ 重要**：如果批量处理多个章节，必须明确每章独立处理。

---

### Phase 1: 文本提取与Token评估

对每个需要处理的 PDF：

1. **运行 `helper.sh extract <pdf>`**
   - 提取文本到 `tmp/<stem>_full.txt`
   - 自动优化：压缩空行、移除多余空格

2. **评估提取文本大小**：
   ```bash
   helper.sh estimate-tokens tmp/<stem>_full.txt
   ```

3. **根据token数判断策略**：
   - < 50K → 直接进入 Phase 3（笔记生成）
   - 50K-150K → 可选：直接生成或分段
   - > 150K → 必须进入 Phase 2（分段）

4. **提取质量检查**：
   - 读前 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

**分段策略**（由父模型执行）：

1. **识别自然边界**（优先级从高到低）：
   - **编号标题**：如 "5.1 Introduction", "5.2 Basic Concepts"
   - **章节标题**：如 "Overview", "Summary", "引言", "总结"
   - **幻灯片边界**：每个新幻灯片的标题
   - **主题转换**：内容从一个主题跳到另一个主题
   - **段落边界**：连续空行后出现新话题

2. **调整section大小**：
   - 目标：30-50K tokens/section
   - 如果某个section > 80K tokens → 在子标题处进一步切分
   - 如果某个section < 15K tokens → 合并到相邻section

3. **生成section文件**：
   - 创建 `tmp/<stem>_sections/` 目录
   - 写入 `sec_001.txt`, `sec_002.txt`, ...
   - 每个文件头部插入元数据：
     ```markdown
     ## Section: <检测到的标题> | Source: <原文件名> | Lines: <起>-<止>
     ```

4. **更新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生成结构化摘要

**工作流程**：

1. **读取manifest**，找到第一个 `summarized: false` 的section
2. **只读取该section文件**（30-50K tokens，而非全文150K+）
3. **生成摘要**，写入 `tmp/<stem>_sections/sec_NNN_summary.md`
4. **更新manifest**：标记该section为 `summarized: true`
5. **继续下一个section**，直到所有section完成

**摘要格式**（信息密集但精炼）：

```markdown
## <本段主题/标题>

### 核心概念
- **概念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

**流程**：
1. 读取 `tmp/<stem>_full.txt`（全文，< 50K tokens）
2. 按笔记模板生成完整章节笔记
3. 写入 `<dir>/Ch<N>-<名称>.md`

#### 情况B：已分段（从摘要合成）

**适用**：提取文本 > 150K tokens，已完成 Phase 2

**流程**：
1. **一次性读入所有摘要文件**
   - 从 `tmp/<stem>_sections/` 读取所有 `*_summary.md`
   - 总量应在 10-20K tokens，完全在上下文内

2. **合成为连贯的章节笔记**
   - **统一术语**：确保同一概念全文用同一名称
   - **建立衔接**：在section之间添加过渡语
   - **去重合并**：多个section提到同一概念，合并为一处
   - **添加速查表**：从全文视角整理公式/概念速查表
   - **添加关键概念清单**：末尾的知识点checklist

3. **写入笔记文件**
   - 按下方模板组织内容
   - 写入 `<dir>/Ch<N>-<名称>.md`

4. **更新manifest**：`note_generated: true`

---

#### 章节笔记模板

```markdown
# 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：一句话说明
```

---

#### 笔记撰写原则

1. **全面性**：覆盖课件/教材全部页面内容，不遗漏知识点
2. **结构化**：按课件原始章节组织，保持编号一致性
3. **独立可读**：每章笔记自成体系，可单独阅读复习
4. **不可合并**：每章必须单独一个文件，禁止合并为单文件
5. **中英对照**：核心术语首次出现时标注英文原文，如「流水线（Pipelining）」

---

#### 与已有笔记的兼容

> 完成判定阈值：**行数 ≥ 30** 即视为"已完成"（与 helper.sh 的 `NOTE_COMPLETE_LINES` 一致）。
> 合法的短章节（< 30 行但内容完整）可在笔记中加一行 `<!-- done -->` 标记覆盖行数判定。

- 若目标笔记文件不存在或为骨架文件（< 30 行且无 `<!-- done -->`），从摘要完整重写
- 若目标笔记文件已存在且内容充实，**询问用户**：保留现有笔记、还是用新摘要完整重写

---

### Phase 4: 课程总览

**文件**：`<课程目录>/00-总览.md`

当大部分章节笔记完成后生成（或按需更新）：

```markdown
# <课程名> · 复习总览

> 学校/院系信息
> 教材信息

---

## 课程思路

（用 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-绪论](Ch1-绪论.md) | 计算机系统概览、性能、Amdahl定律 | ✅ |
```

知识脉络图使用 Mermaid `graph TD`（从上到下），用有向边表示依赖/前置关系。如果 Mermaid 不可用，退回 ASCII 树形图。

---

### Phase 5: 练习题框架

**文件**：`<课程目录>/练习题框架.md`（或按章节拆分）

从已有章节笔记中提取可考的知识点，按章节组织：

```markdown
## Ch<N> <章节名>

### 题型 1：<题型名称>

**公式**：（如果适用）
$$...$$

**解题步骤**：
1. ...
2. ...

**典型考法**：（如果适用）

**重点程度**：⭐⭐⭐ 高频考题 / ⭐⭐ 常见考题 / ⭐ 偶尔考
```

如果练习题内容过长（>300 行），按章节拆分为独立文件 `练习题-Ch<N>-<名称>.md`，主文件变为索引页。

---

## 子命令

### 整理单章笔记

用户指定一个 PDF → 为该 PDF 生成完整复习笔记。

```
用户: "整理 chapter03-pipeline.pdf 的笔记"
```

执行步骤：
1. `helper.sh extract chapter03-pipeline.pdf`
2. `helper.sh estimate-tokens tmp/chapter03-pipeline_full.txt`
3. **根据token数判断**：
   - < 50K → 直接读全文，生成笔记
   - > 150K → 执行 Phase 2（分段）→ Phase 3（合成）
4. 将笔记写入 Ch3-流水线.md
5. 更新 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>
```

---

### 从断点继续

```
用户: "继续上次的工作"
```

1. `helper.sh resume <dir>` 查看进度
   - 报告 PDF 级三态（未提取 / 已提取待笔记 / 笔记完成）
   - 走了两遍策略的 PDF 会显示 **`N/M sections summarized`** 的逐段摘要进度
   - 末尾给出 **"下一步：处理 X"** 的建议（含第一个未摘要的 section）
2. 找到第一个未完成的章节/section，从该断点继续

---

### 生成/更新练习题

```
用户: "生成练习题"
```

1. 读取所有已有章节笔记
2. 从每个章节中提取可考的知识点
3. 按章节组织为练习题框架
4. 如果内容过多，拆分为独立文件

---

### 仅提取大纲

```
用户: "先梳理一下课程大纲"
```

1. 扫描目录中所有 PDF，对每个提取文本并快速浏览
2. 识别各章核心主题
3. 生成 00-总览.md 中的课程结构表格和知识脉络图
4. 不生成详细笔记

---

## 📁 输出文件约定

| 文件 | 命名 | 说明 |
|------|------|------|
| 课程总览 | `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`）。

处理方式：
1. 两个 PDF 都执行 Phase 1 提取
2. 两者的段落摘要连续编号（sec_001...sec_N, sec_N+1...sec_M）
3. Phase 3 合成时，一次性读入两组摘要，合成为同一篇笔记 `Ch7-缓存一致性.md`

---

## 📝 文本提取注意事项

- `pdftotext -layout` 对扫描型 PDF 可能提取质量不佳，需要结合 PDF 直接阅读
- 多栏排版可能错乱，需要根据上下文逻辑重新组织
- 表格、图示提取为文本后需要重建 Markdown 表格
- 公式可能提取为乱码，需要根据上下文推断并重写为 LaTeX
- 提取后会自动优化：压缩空行、移除多余空格

---

## ⚠️ 注意事项

- 所有路径使用相对于课程目录的相对路径
- Markdown 链接格式：`[显示文本](文件名.md)`，确保可点击跳转
- 每次处理一个 PDF 后告知用户完成，等待确认或下一章指令
- 不要删除用户已有的内容，除非用户明确要求重写
- 如果课件内容超出 PDF 文本提取能力（如大量手写批注、复杂公式图），需要在笔记中注明"该部分需对照原课件查看"
- **必须遵守章节隔离原则**，不得在一个会话中处理多个章节


