每次生成小说的一章,调度器要做三个决策:注入哪些世界设定、哪些前文摘要、哪些结构约束。这不是一个简单的"贪心召回"问题,而是要在有限的上下文窗口内,权衡相关性、预算和一致性的三角形约束。
调度问题的三个维度
相关性:召回真正需要的设定与前文
生成第 10 章时,模型需要知道的背景信息远超过上下文容量。世界观有多条规则线,前文有 9 章的事件积累,人物有 10 多个角色的状态变化,每一项都可能与当前章节相关。
相关性检索的核心是"这些东西与当前章节生成任务有多大的影响"。这不只是 Qdrant 的向量相似度匹配。一条"主角接到任务时必须穿过北城门"的世界规则,与其他几条规则的组合方式,决定了它对第 10 章是否真正有约束力。
系统里的做法是把世界观资源分层:
- 硬约束层:世界核心规则、人物基础设定、已确定的事实
- 软约束层:前文原文、场景描写、对话
- 可选层:已排除的假设、备选方向
向量检索时,应该先检索硬约束层,再按优先级检索软约束层,最后考虑可选层。这个顺序的反转会导致"生成偏离世界规则但文采很好"的常见问题。
预算:在窗口限额内排序
假设模型上下文窗口是 8K tokens,去掉系统 prompt、生成目标、章节大纲,实际可用空间约 6K。这 6K 要装下:
- 世界观摘要(500-800 tokens)
- 相关人物设定(300-500 tokens)
- 前 N 章摘要(1000-2000 tokens)
- 本章拆细(200-300 tokens)
- 写法约束(200-300 tokens)
就算每项都精简,也很容易超出。这时候需要动态预算:系统估算本章的生成复杂度(新人物出现?大事件转折?),动态调整各部分的分配。
简单的做法是按字数均分,结果通常是浪费。好的做法是:
- 把硬约束固定分配(不能省)
- 把相关性最高的前文摘要(不是原文)作为主体
- 其余空间留给可选背景
前文不用原文,用摘要。这是关键优化。一章正文 2000 字,用 200 字的摘要(关键事件 + 角色状态变化 + 留下的悬念)可以承载 80% 的必要信息,剩下 20% 的细节(某个对话的原词、场景的视觉细节)在绝大多数情况下不影响后续章节的生成一致性。
一致性:跨章节事实的映射
第 10 章里模型可能生成"某交易的金额是 5000 元",第 11 章的调度器需要知道这个信息。但如果第 10 章生成了两个版本(一个 5000 元,一个 6000 元),调度器用了不同的版本,第 11 章可能会自相矛盾。
这是故事"越写越散"的根本原因。传统做法是写完全文后回头检查一致性,那时候改得很贵。好的做法是在每章生成后,立即抽取"硬事实"(人物位置、已完成交易、确定的时间戳、确认过的背景细节),写入一个"事实账本",下一章生成时优先查这个账本。
这不是自然语言的摘要,而是结构化的事实提取:交易金额、时间点、位置坐标、角色关系状态。第 11 章的模型看到的前文摘要里,这些数字必须与事实账本对齐。
LangGraph 的角色:流程与状态
LangGraph 的工作是管理整个调度流程和状态转移。它不生成小说,而是组织生成的前置条件。
一个最小的调度 DAG 是这样的:
检索相关世界规则 → 检索前文摘要 → 检索事实账本
↓
动态预算分配
↓
确定最终上下文
↓
调用生成模型
↓
检测一致性问题
↓
是否需要修复 → 是 → 重新调度 + 重新生成
↓ 否
提取并记录新事实
↓
状态转移到下一章
LangGraph 在这个流程中的价值是:
- 可观察性:每一步的输入输出都记录,可以回放整个调度决策过程
- 可恢复性:如果中间某一步失败(比如生成模型超时),可以从失败点恢复,不用重新调度前面所有步骤
- 条件分支:一致性检测失败时,可以触发自动修复流程,而不是简单地重试整个生成
- 状态机:跨多章的生成是有顺序的,章 N 的状态会影响章 N+1 的调度。LangGraph 管理这个状态链
代码层面,这意味着每个节点是一个独立的可调用单元,节点间通过状态对象通信。比如"动态预算分配"这个节点,它的输入是"已检索的资源列表 + 本章复杂度评分",输出是"每个资源的分配 token 数",这个输出成为下一个节点的输入。
Qdrant 的角色:相关性与召回
Qdrant 存储两类向量:
- 世界观资源的向量化(规则、势力、地点、角色设定)
- 历史章节的向量化(章节摘要、关键事件、角色状态快照)
调度时,系统用当前章节的"生成任务"(比如"主角在封闭病区内发现病历记录不一致")作为查询向量,去 Qdrant 检索。
检索策略分两层:
第一层:硬约束检索
用专有字段(not 向量相似度)精确匹配。比如"这章涉及的人物有:角色 A、角色 B",那么系统直接从数据库里取这两个角色的设定,不走向量检索。硬约束必须 100% 准确。
第二层:软上下文检索
用向量相似度检索前文摘要、相关规则、可用场景要素。设置相似度阈值(比如 0.7),只返回真正相关的资源。
一个常见的优化是使用混合检索:用关键词和向量相似度结合。比如检索"与角色 A 相关的前文事件",既用 BM25 匹配"角色 A"这个关键词,又用向量相似度找相似的事件类型。这能减少"语义相关但实际无关"的召回。
优先级策略:硬约束优先
一个实际的优先级排序是这样的:
第一梯队(固定,必须纳入)
- 当前章节涉及的所有人物的最新设定
- 上一章的事实账本
- 本章任务单里的硬约束("主角必须提到过的某个承诺")
- 世界核心规则中与本章有直接冲突关系的部分
第二梯队(按相关性,逐个加入直到预算用尽)
- 历史章节中提到过的相关地点描写
- 相关势力或人物的行动线
- 前 3 章的事件时间线
- 可能在本章触发的伏笔提示
第三梯队(可选,仅在预算充足时加入)
- 其他角色的背景故事
- 世界观的附加说明
- 参考范本
这个优先级的核心原则是:生成一致性 > 生成创意。第二梯队和第三梯队是为了提升文章质量,但如果加入它们会导致硬约束无法完整表达,就必须删掉。
一致性检测与修复流程
生成完成后,系统会用一个检测模块检查:
- 本章提到的人物位置与上章是否矛盾
- 本章提到的时间戳是否与事实账本对齐
- 本章是否违反了硬约束规则
- 本章是否引入了未设定过的背景信息
如果检测到矛盾,调度器不是简单地重新生成,而是定向修复:
- 位置矛盾:部分改写那个段落,保持其他内容
- 时间矛盾:调整时间戳,保持事件顺序
- 规则违反:提示模型重新考虑那个场景
- 未设定背景:或纳入世界设定,或要求模型移除
这需要生成模块支持"部分修复"而不是"全盘重试"。全盘重试成本高且容易导致连锁问题(修好了位置矛盾,却引入了新的对话矛盾)。
现有系统的实现参考
项目里已经实现了的相关部分:
"本书世界、角色、拆书、知识库联动"模块说明系统已经在做这些事:世界观能生成世界骨架和世界手册,角色准备会结合势力倾向和世界规则,知识库文档能回灌到规划和正文生成。这是调度器的底层数据来源。
"章节定稿时自动抽取正文中的关键硬事实并写入事实账本,下一章生成时即可读到真实前文"这一项正是上面说的事实账本机制,系统已经开始做了。
"修复懒规划(JIT)模式下结构化大纲步骤被误报"未产出"的问题"说明系统在处理的一个具体问题是:生成任务和实际输出的不对齐。调度器需要理解"这一步预期输出什么"和"实际输出了什么"之间的差异。
一致性和失败处理这两个难点,已经不是理论讨论,而是项目里正在打磨的工程问题。调度器的价值体现在能多快地从这些失败中恢复。
■