DAG批次執行策略
框架文檔 — 如何安全地並行化章節寫作,最大化生產效率 適用於任何存在章節間依賴關係的技術書籍項目
1. 問題: 爲什麼不能全部並行
樸素想法
"{{章節數}}章完全獨立,全部並行寫作,一次搞定。"
爲什麼行不通
技術書籍的章節不是完全獨立的:
第5章: "如前文第3章所述的消息队列机制..."
第8章: "这里复用了第2章介绍的配置加载模式..."
第12章: "结合第4章的核心数据结构和第7章的执行引擎..."如果第5章和第3章同時寫作:
- 第5章的作家讀取
chapter-summaries.md時,第3章的摘要還不存在 - 作家只能憑空想象第3章的內容 → 不一致、錯誤引用
- 術語表(glossary)中還沒有第3章引入的新術語 → 命名不一致
核心約束
File Pointers機制要求: 後續章節的Agent必須能讀取到前序章節的長記憶更新。因此,有依賴關係的章節必須按順序執行。
2. 依賴分析: 構建章節DAG
什麼是章節依賴
章節A依賴章節B,當且僅當:
- A引用了B中首次引入的概念
- A使用了B中定義的術語
- A的代碼示例建立在B的代碼示例之上
- A的"知識階梯"假設讀者已經讀過B
從大綱提取依賴
在Phase 1(大綱定稿)完成後,從 outline-final.md 中提取依賴關係:
方法1: 显式声明
在大纲中为每章标注"前置章节":
## 第5章: {{章节标题}}
前置依赖: ch03, ch04
方法2: 自动推断
分析大纲中每章的"学习目标"和"前置知识"
如果A章的前置知识包含B章的学习目标 → A依赖B
方法3: 人工标注
在大纲定稿时由用户直接标注依赖关系DAG表示
用有向無環圖(DAG)表示章節依賴:
示例: 一本{{章节数}}章的技术书
ch01 ─────┐
├───▶ ch03 ──────┐
ch02 ─────┘ ├───▶ ch06 ──────┐
│ ├───▶ ch08
ch04 ──────────────────────┘ │
│
ch05 ──────────────────────────────────────┘
ch07 (独立章节,无前置依赖)
依赖关系:
ch03 depends on [ch01, ch02]
ch06 depends on [ch03, ch04]
ch08 depends on [ch05, ch06]
ch07 depends on [] ← 完全独立依賴關係配置格式
在項目配置中使用如下格式聲明依賴:
yaml
# chapter-dependencies.yaml
chapters:
ch01: [] # 无依赖,基础章节
ch02: [] # 无依赖,基础章节
ch03: [ch01, ch02] # 依赖前两章的基础概念
ch04: [] # 独立主题
ch05: [ch01] # 仅依赖第1章
ch06: [ch03, ch04] # 依赖第3、4章
ch07: [] # 独立章节
ch08: [ch05, ch06] # 依赖第5、6章
# ...3. 批次劃分算法
拓撲排序分層
將DAG進行拓撲排序,劃分爲多個批次(Batch):
算法:
1. 找出所有入度为0的节点 → 这些节点构成 Batch 1
2. 移除Batch 1的节点和所有出边
3. 再次找出入度为0的节点 → 构成 Batch 2
4. 重复直到所有节点分配完毕
结果:
Batch 1: [ch01, ch02, ch04, ch05, ch07] — 所有无依赖的章节
Batch 2: [ch03] — 依赖Batch 1中的章节
Batch 3: [ch06] — 依赖Batch 2中的章节
Batch 4: [ch08] — 依赖Batch 3中的章节批次執行模型
时间 ──────────────────────────────────────────────────────────▶
Batch 1: ┌─ch01─┐ ┌─ch02─┐ ┌─ch04─┐ ┌─ch05─┐ ┌─ch07─┐
└──────┘ └──────┘ └──────┘ └──────┘ └──────┘
▼ 更新长记忆
Batch 2: ┌─ch03─┐
└──────┘
▼ 更新长记忆
Batch 3: ┌─ch06─┐
└──────┘
▼ 更新长记忆
Batch 4: ┌─ch08─┐
└──────┘
─── 同一批次内并行 ───── 批次间串行 ───4. 並行安全規則
規則1: 批次內並行,批次間串行
✅ 允许: Batch 1中的ch01和ch02同时执行研究→写作→审查→评审
✅ 允许: Batch 1中的ch04和ch07同时执行
❌ 禁止: Batch 1的ch01和Batch 2的ch03同时执行
(ch03依赖ch01的长记忆更新)規則2: 同一章節內的4步嚴格串行
对于每一章:
Step 1 研究 → Step 2 写作 → Step 3 审查 → Step 4 评审
❌ 禁止: 同一章节的研究和写作并行
(写作需要研究报告作为输入)
❌ 禁止: 同一章节的写作和审查并行
(审查需要初稿作为输入)規則3: 審查步驟內部可並行
在Step 3内部:
✅ R1, R2, R3 可以同时审查同一份draft
(三个reviewer读同一份draft但写不同的输出文件)
在Step 4内部:
✅ RS, RE, RH 可以同时评审規則4: 長記憶文件在批次邊界更新
批次执行流程:
1. 并行执行批次内所有章节的完整流水线
2. 所有章节完成后,统一更新长记忆文件:
- chapter-summaries.md ← 追加所有章节的摘要
- glossary.md ← 追加所有新术语
- metaphor-registry.md ← 追加所有新比喻
3. 开始下一批次
为什么不在每章完成后立即更新?
- 同一批次内的章节是并行的
- 如果ch01完成后立即更新summaries,ch02可能正在读取summaries
- 批次边界统一更新避免了读写竞争規則5: 批次內的章節不互相引用
既然同一批次内的章节并行写作,它们之间不应存在互相引用。
如果发现同一批次内两章需要互相引用:
→ 说明依赖分析有遗漏
→ 需要将其中一章移到下一批次
→ 重新划分批次5. 資源約束與批次大小
API併發限制
实际并发数 = min(批次内章节数, {{最大并发数}})
每章的4步流水线中,Step 3和Step 4各自内部也有并行:
- Step 3: 3个reviewer并行 → 3个API调用
- Step 4: 3个读者并行 → 3个API调用
单章的最大同时API调用: 3
N章并行时的最大同时API调用: N × 3(当多章同时进入Step 3/4时)上下文質量約束
并行章节越多,批次完成后需要一次性更新的长记忆越多。
权衡:
过少并行: 效率低,项目周期长
过多并行:
- 同一批次内章节无法互相参考
- 术语可能在多章中被不同定义(批次结束后统一纠正)
- 批次边界的长记忆更新量大
推荐: 每批次不超过{{最大批次大小,默认3-5}}章批次大小調整策略
策略1: 固定大小
每批次固定N章,简单但可能不是最优
策略2: 按依赖图自然分层
直接使用拓扑排序的自然分层结果
有些层可能只有1章,有些可能有5章
策略3: 分裂大批次
如果某一层有太多章节(>{{最大批次大小}}),拆分为子批次
子批次之间虽然无依赖,但可以让后续子批次利用前一子批次的长记忆
示例:
原Batch 1有8章无依赖 → 拆为:
Batch 1a: [ch01, ch02, ch04] → 更新长记忆
Batch 1b: [ch05, ch07, ch09] → 更新长记忆(可利用1a的成果)
Batch 1c: [ch10, ch11] → 更新长记忆6. 與流式工具執行器的類比
本框架的並行策略與現代AI Agent框架中的**流式工具執行器(Streaming Tool Executor)**如出一轍。
概念映射
AI Agent框架概念 → 书籍生产概念
─────────────────────────────────────────────────
流式工具执行器 → 主编排(#0)
Tool call → Agent调度
有限并发池 → 每批次最大并行数
依赖等待 → 批次间串行
独立tool call同时执行 → 同批次内章节并行
tool结果汇聚后继续 → 批次完成后更新长记忆執行模式對比
AI Agent框架:
const results = await Promise.all([
tool1(), // 独立任务1
tool2(), // 独立任务2
tool3(), // 独立任务3
]);
// 所有完成后,使用results继续
书籍生产:
// Batch 1: 并行
const batch1Results = await Promise.all([
writeChapter(ch01),
writeChapter(ch02),
writeChapter(ch04),
]);
updateLongTermMemory(batch1Results);
// Batch 2: 依赖Batch 1的长记忆
const batch2Results = await Promise.all([
writeChapter(ch03), // 读取更新后的long-term memory
]);
updateLongTermMemory(batch2Results);7. 實施步驟
Step 1: 定義依賴關係
在Phase 1(大綱定稿)完成後,創建依賴配置:
markdown
## 章节依赖关系
| 章节 | 依赖 | 说明 |
|------|------|------|
| ch01 | — | {{章节1标题}},基础章节 |
| ch02 | — | {{章节2标题}},基础章节 |
| ch03 | ch01, ch02 | {{章节3标题}},需要前两章的概念 |
| ... | ... | ... |Step 2: 生成批次計劃
markdown
## 批次执行计划
### Batch 1(并行)
- ch01: {{章节1标题}}
- ch02: {{章节2标题}}
预计时间: {{单章时间}} (并行执行)
### Batch 2(等待Batch 1完成)
- ch03: {{章节3标题}}
预计时间: {{单章时间}}
### 总计
- 批次数: {{批次数}}
- 如果串行: {{章节数}} × {{单章时间}} = {{总串行时间}}
- 使用批次并行: {{实际预计时间}}
- 效率提升: {{提升百分比}}Step 3: 執行與監控
每个批次执行时:
1. 并行启动批次内所有章节的Step 1(研究)
2. 各章研究完成后,各自启动Step 2(写作)
3. 各章写作完成后,各自启动Step 3(三审并行)
4. 各章审查完成后,各自启动Step 4(读者评审)
5. 批次内所有章节全部完成
6. 统一更新长记忆文件
7. 更新checkpoint.md
8. 开始下一批次8. 異常處理
單章失敗不阻塞同批次其他章節
场景: Batch 1中ch01写作失败
处理:
1. ch01标记为失败,记入audit-log
2. ch02, ch04继续正常执行
3. Batch 1结束时,长记忆更新仅包含成功的章节
4. ch01可以在后续批次中重试(不影响依赖图)
注意: 如果ch03依赖ch01,ch03也需要延后單章失敗導致下游阻塞
场景: ch03依赖ch01,但ch01持续失败
处理:
1. ch03的批次开始前检查依赖是否全部完成
2. 如果ch01未完成 → ch03标记为BLOCKED
3. 跳过ch03,继续执行本批次中不依赖ch01的章节
4. 最终汇总所有BLOCKED章节,等人工干预批次邊界的長記憶衝突
场景: Batch 1中ch01和ch02都定义了类似的术语,但表述不同
处理:
1. 在批次完成后的长记忆更新中检测冲突
2. 优先使用最先完成的章节的术语定义
3. 在后续章节的写作中自然统一
4. Phase 4(统稿)中做最终统一9. 監控與可視化
批次進度矩陣
Batch 1:
ch01: [✅研究] [✅写作] [✅R1] [✅R2] [✅R3] [✅合并] [✅评审]
ch02: [✅研究] [✅写作] [✅R1] [⏳R2] [✅R3] [ 合并] [ 评审]
ch04: [✅研究] [⏳写作] [ R1] [ R2] [ R3] [ 合并] [ 评审]
Batch 2: (等待Batch 1)
ch03: [ 研究] [ 写作] [ R1] [ R2] [ R3] [ 合并] [ 评审]
图例: ✅完成 ⏳进行中 ❌失败 空=未开始此矩陣記錄在 checkpoint.md 中,詳見 recovery.md。