手上有几十万字的小说原文,要判断它能不能改竖屏短剧、能切几集。
第一反应是”扔给模型让它读一遍,给个结论”。

这条路走不通。长文本进不了上下文,分段丢进去又会导致第 47 章按一种边界分析、
按另一种边界聚合,而且没有人会发现
。更麻烦的是,AI 读长篇特别擅长写一份
“读起来很完整”的总结——它会自作主张地补齐缺章,让缺失在结果里不留痕迹。

下面这套流程的核心不是”读得更全”,而是让每一步都可追溯、可证伪。

一、索引是唯一切片真源

第一步不是读小说,是建章节索引。而且整个流程只建一次。

1
2
python3 novel_index.py index 输入/{原文} --out _work/_index.next.json
python3 novel_index.py verify _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
只有书名没有原文时,请创作者提供文件或粘贴正文,不要凭书名回忆情节。
凭记忆写的分析无法被引用,也无法被反驳。

九、小结

这套流程的产出不是”一份小说总结”,而是一份能被引用、能被反驳、能被接着用的分析层:

  • 每个结论都能追到原文的行号
  • 每个缺失都在文档里留下记录
  • 每个抽样判断最后都会被全量结果检验

它慢,但它不会让你在第三十集才发现第二集的伏笔其实没接上。

下一篇讲这套分析怎么变成改编契约与前几集剧本,
属于短剧创作体系里的一环;
机械核对的脚本思路与文档解析那篇同源。