Skip to content

言語 / Language: 简体中文 · English · 日本語 · 繁體中文


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. 異常処理

1章の失敗が同バッチの他の章をブロックしない

场景: Batch 1中ch01写作失败

处理:
  1. ch01标记为失败,记入audit-log
  2. ch02, ch04继续正常执行
  3. Batch 1结束时,长记忆更新仅包含成功的章节
  4. ch01可以在后续批次中重试(不影响依赖图)
     注意: 如果ch03依赖ch01,ch03也需要延后

1章の失敗による下流のブロック

场景: 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 を参照してください。

Built with Meridian