📖 把一本长篇小说拆成分集候选:六个阶段与三条硬闸
手上有几十万字的小说原文,要判断它能不能改竖屏短剧、能切几集。
第一反应是”扔给模型让它读一遍,给个结论”。
这条路走不通。长文本进不了上下文,分段丢进去又会导致第 47 章按一种边界分析、
按另一种边界聚合,而且没有人会发现。更麻烦的是,AI 读长篇特别擅长写一份
“读起来很完整”的总结——它会自作主张地补齐缺章,让缺失在结果里不留痕迹。
下面这套流程的核心不是”读得更全”,而是让每一步都可追溯、可证伪。
一、索引是唯一切片真源
第一步不是读小说,是建章节索引。而且整个流程只建一次。
1 | python3 novel_index.py index 输入/{原文} --out _work/_index.next.json |
如果每个阶段各跑一次正则去切章节,就会切出互相对不上的章节。所以索引一旦发布,
后续所有阶段都只引用它——引用的是行号 span,不是章节内容。
脚本的识别规则很朴素,但每条都对应一个真实问题:
- 识别阿拉伯数字与中文数字章号(含 千 / 两,覆盖千章以上连载)
- 只认一种编号单位:一本用
第N章分章、用第N节分小节的书,
应当看到chapter_unit: 章且节被记入ignored_heading_units。
反过来说明分章单位判断错了 - 只把短的独立行当标题:以章号开头的正文段落记进
long_heading_lines_skipped,
不误判成章节 - 剔除开头的目录块:否则目录会被当成 100 个”章”
它不做任何编辑判断——哪章重要、讲了什么,是后面阶段的事。
problems 非空就停下
常见的四种:
| 问题 | 说明 |
|---|---|
| 章号跳号 | 缺章,或抓错了标题 |
| 同卷内重号 | 多卷书原文章号会重复,靠 sequence 区分 |
| 正文极少的章 | 多半抓到了目录残留或卷首页 |
| 无法解析的章号 | 手写边界 |
不要带着错表进下一阶段。带着错表继续跑,后面每一层的产出都继承这个错,
而且错得越来越隐蔽。
原文改了必须重建索引
verify 核对编号、顺序与行号覆盖,所以插行删行会被报出来。
但同行数的原地改写不会——那一步靠改原文的人自己重建,脚本不比对字节。
二、S1 快评:先回答”值不值得”
全量拆解一本几十万字的小说成本很高,所以先抽样判断。
1 | python3 novel_index.py sample _index.json --count 12 |
抽样的三条性质:确定、可复现、首尾必取。跑第二次引用的是同一批章,
不会每次给出不同的快评。
快评覆盖六件事:故事框架、三类判定比例(screen_ready / 待改造 / prose_only)、
开篇替换点、制作负担量级、最大的三处改编风险、分集候选量级。
第一行必须写覆盖率(脚本返回的 coverage_ratio),所有结论限于抽样范围。
不能让抽样结论冒充全量分析——这是这套流程里最容易被破坏的一条。
这里会停下问创作者:给出快评与全量拆解的预计耗时,问是否继续。
创作者一开始就明确说”一次跑完”时才不停下,但 triage.md 照样要写——
它是最后一步要回填对照的第一版假设。
三、S2 逐章提取:覆盖率是硬闸
按索引逐章走,能并发就分批并发(每批 5–8 章,等一批落盘再发下一批)。
每章落到 chapters/ch-<N>-extract.md,**<N> 是索引里的 sequence,不是原文章号**
(多卷书的原文章号会重复,sequence 不会)。
全部落盘后跑覆盖率:
1 | python3 novel_index.py coverage _index.json chapters |
这里有两个字段必须分清:
missing非空 → 补跑缺的章unmatched_files非空 → 文件名写歪了,它既不算覆盖也不会被当成缺章,必须改名而不是重跑
不要在覆盖率不足时进入下一阶段。聚合阶段会照样产出一份读起来完整的结果,
而缺掉的章不会在任何地方留下痕迹。
单章连续失败两次就标记跳过,写进 _progress.md 的失败记录,
并在后续每一份聚合产物里注明该章缺失。
失败可以接受,失败被藏起来不行。
四、S3 聚合:不回头重读原文
从逐章提取聚合,不回头重读原文。
原因很实际:原文在 S2 已经被读过一次,再读一次只会得到第二份互相矛盾的事实。
第 47 章的提取说主角在城外,聚合时再读一遍又觉得在城里——两份材料摆在一起,
谁都不知道该信哪个。
产出两份:
story-units.md:把情节点归成有始有终的单元,每个单元记录进入状态、冲突、代价、出去状态rhythm-and-emotion.md:关键信息如何逐章推进、情绪触动点的铺垫→释放→余波、跨章伏笔与兑现
聚合完跑三条阈值自检(归属置信、覆盖率、重叠率)。
关键理解:阈值不是评分,是边界模糊的信号。重叠率过高说明两个单元其实是一个单元,
不是”这段写得不好”。
五、S4 人物归并:候选,不是资产
跨章去重、别名归一、分级。别名合并的规则很严:
- 专名 + 有同指证据的绰号 → 可以合并
- 描述性称谓与头衔 → 永远不触发合并
“那个穿黑衣的男人”不能和”张三”合并,因为可能是路人。
这里的人物条目带 unresolved 与来源引用,它是候选,不是资产。
真正的资产身份是后面从”已被接受的剧本”里建立的。
绕过这条链直接建资产,等于让原著的人物表冒充剧本的出现证据。
六、S5 改编价值:这一步是分水岭
通用拆书做到”人物表 + 情节线”就结束了。这个阶段多做的两件事:
1. adaptation-value.md:哪些在画面上兑现不了
- 哪些单元在竖屏短剧里能直接成立
- 哪些要换载体(内心戏改成动作、叙述性诡计改成视听线索)
- 哪些是纯文字快感——长铺垫、心理描写、旁白式幽默——在画面上无法兑现
2. episode-candidates.jsonl:按戏剧结果切,不按章号切
每条候选集带来源 span、承担的功能、以及未决项。
不按章号或字数平均切——平均切出来的集,每集的戏剧强度参差,
而且切点常常落在一段戏的中间。
同时回填 S1 的快评:哪几条抽样判断被全量结果推翻了,写在开头。
一个抽样结论被证伪,比它被悄悄忘掉有用得多——下一本书的快评会因此更准。
七、规则分级:什么能阻断,什么不能
四条级别决定了哪些是机器能拦的、哪些只能人来判断:
| 级别 | 含义 | 谁能阻断 |
|---|---|---|
structural_invariant | 索引与 span 的可证明性、引用完整性、覆盖率 | 脚本可以阻断 |
reviewed_invariant | 功能提取是否忠于原文、归并是否保住戏剧作用 | 需要审查 |
craft_default | 通常有帮助的做法 | 创作者说明理由后可覆盖 |
taste_option | 从哪里开篇、保留哪条线 | 不得单独阻断 |
最后一条是本流程的立场:不要用固定的章数配方、情节点数量或篇幅比例替代因果判断。
“每集 60 秒””三集一个转折”这类规矩是参考,不是约束。
八、几条贯穿全程的原则
1. 省略要写下来
不拍某一场时,在正文开头写 - 未拍场次:<场景 ID>(理由:……)。
省略和漏拍在成稿文档里长得一模一样,理由必须落到文档里,不能留在对话中。
2. 不把原文成段复制进分析
只记录 locator、span 与去引用的功能摘要,需要证据时引用最短的必要片段。
分析是只读的转化性工作。
3. 个别片段处理不了就跳过并记录
不要因此中止整章或整本——中止会让后续所有阶段拿到一份有洞却看不出洞在哪的分析。
4. 没有字节就没有 span
只有书名没有原文时,请创作者提供文件或粘贴正文,不要凭书名回忆情节。
凭记忆写的分析无法被引用,也无法被反驳。
九、小结
这套流程的产出不是”一份小说总结”,而是一份能被引用、能被反驳、能被接着用的分析层:
- 每个结论都能追到原文的行号
- 每个缺失都在文档里留下记录
- 每个抽样判断最后都会被全量结果检验
它慢,但它不会让你在第三十集才发现第二集的伏笔其实没接上。

