Files

512 lines
9.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
如果这样,那章节越多,后续要传递给api的参数就越多?
是的,**如果你每次都把前面所有章节正文传给 API,章节越多,参数一定越来越大,成本会爆,速度也会慢。**
但真正的长篇小说系统**不能这么做**。
正确做法是:
> **不是把全部正文传给模型,
> 而是把“压缩后的关键记忆 + 当前章节相关内容”传给模型。**
也就是说,后面写第 100 章,不需要把前 99 章全文都传进去,只需要传:
```text
小说圣经摘要
当前卷纲
最近 3-5 章摘要
本章相关人物状态
本章相关伏笔
本章章节卡
禁止改动规则
文风规则
```
这样 API 输入会长期保持稳定,不会随着章节无限增长。
---
# 一、错误做法:全文堆上下文
比如写第 80 章时,你把第 1–79 章全部塞进去:
```text
第1章全文
第2章全文
第3章全文
...
第79章全文
请写第80章
```
这个做法有几个问题:
1. token 成本越来越高;
2. 请求越来越慢;
3. 模型容易被大量旧内容干扰;
4. 真正重要的信息反而被淹没;
5. 超过上下文长度后直接无法调用;
6. 多模型协作时更难稳定。
所以长篇流水线绝对不能靠“全文传递”。
---
# 二、正确做法:三层记忆压缩
你要做的是**分层记忆**。
## 第一层:永久核心记忆
每次都传,但内容要很短。
包括:
```text
小说一句话核心
世界观规则
主角核心人设
主要角色不可改动项
文风规则
禁用桥段
短剧改编规则
```
控制在 **10002000 字**
这部分相当于小说宪法。
---
## 第二层:近期记忆
每次只传最近 35 章摘要。
比如写第 80 章,只传:
```text
第75章摘要
第76章摘要
第77章摘要
第78章摘要
第79章摘要
```
不传全文。
每章摘要控制在 150300 字。
总共大概 **10001500 字**
---
## 第三层:检索记忆
这部分不是每次都传全部,而是按本章需要查。
比如第 80 章出场人物是:
```text
岑青
陈淑蘅
姚知知
```
那就只查这几个人的状态:
```text
岑青当前知道了什么
陈淑蘅隐瞒了什么
姚知知上次出现在哪里
她们之间的关系变化
```
如果本章涉及某个伏笔,就只查相关伏笔。
比如:
```text
F012:被撕掉的签到簿缺页
F018:姚知知画本里的第五只手
```
不相关的伏笔不传。
---
# 三、写第 100 章时,真正传给 API 的应该是这样
不是:
```text
前99章全文 + 请写第100章
```
而是:
```json
{
"bible_summary": "小说核心设定摘要,约1500字",
"style_rules": [
"克制",
"电影感",
"不狗血",
"不打脸复仇",
"对白短而有张力"
],
"current_volume_outline": "当前第3卷卷纲摘要,约800字",
"recent_chapter_summaries": [
"第95章摘要",
"第96章摘要",
"第97章摘要",
"第98章摘要",
"第99章摘要"
],
"active_character_states": [
{
"name": "岑青",
"current_state": "已经确认林照不是一个人,但还缺最后证据"
},
{
"name": "陈淑蘅",
"current_state": "知道周榕真名,但仍不愿公开其他女工身份"
}
],
"active_foreshadows": [
{
"code": "F012",
"title": "签到簿缺页",
"status": "developing",
"expected_reveal": "第102章"
}
],
"chapter_card": {
"chapter_no": 100,
"title": "缺页",
"goal": "岑青找到签到簿缺失页的线索",
"must_happen": [
"姚知知交出画本",
"岑青发现画本夹层里有一页旧纸",
"陈淑蘅第一次失控"
],
"ending_hook": "纸页上不是一个名字,而是五个名字"
}
}
```
这个上下文即使写到第 500 章,也可以控制在 **40008000 字**以内。
---
# 四、上下文不是越多越好,而是越准越好
很多人误以为:
> 传越多,AI 越不会乱。
其实不一定。
真正有效的是:
```text
重要信息完整
无关信息少
当前任务明确
禁止事项清楚
```
你给模型塞 30 万字前文,它不一定抓得住重点。
但你给它一份高质量上下文:
```text
当前主线
当前人物状态
当前伏笔
上一章结尾
本章目标
不能写什么
```
它反而更稳。
---
# 五、你系统里要做“记忆压缩器”
每写完一章,就让 AI 或程序生成一份压缩记忆。
比如第 20 章正文有 3000 字,压缩成:
```json
{
"chapter_no": 20,
"summary": "岑青在旧仓库找到签到簿,发现林照名下有五种笔迹。",
"character_updates": [
{
"name": "岑青",
"update": "开始怀疑林照不是单一人物"
},
{
"name": "陈淑蘅",
"update": "看到签到簿后明显紧张,但拒绝解释"
}
],
"new_foreshadows": [
{
"code": "F020",
"title": "被撕掉的一页",
"surface": "签到簿中间缺了一页",
"hidden_truth": "缺页记录了火灾当晚真实值班名单"
}
],
"next_chapter_must_continue": [
"岑青需要追查缺页",
"陈淑蘅不能立刻说出全部真相"
]
}
```
以后第 50 章、第 100 章需要这个信息时,系统从数据库查这条摘要,不用查完整正文。
---
# 六、上下文传递应该有 4 个等级
## L1:每次必传
```text
小说圣经摘要
文风规则
禁用规则
本章章节卡
```
---
## L2:经常传
```text
最近 3-5 章摘要
当前卷纲
当前主线进度
```
---
## L3:按需传
```text
本章出场人物状态
本章相关伏笔
本章相关场景
本章相关道具
```
---
## L4:特殊情况才传
```text
某一章原文片段
某个角色上次出场完整段落
某个伏笔首次出现原文
某段重要对白
```
只有当模型需要复刻细节时,才传原文片段。
比如本章要回收第 12 章的一句台词,那就检索第 12 章相关原文片段传进去。
---
# 七、成本大概怎么控制?
假设一章 3000 字。
错误做法:
```text
写第100章时传前99章全文
≈ 30万字上下文
```
这非常贵,也不稳定。
正确做法:
```text
固定核心上下文:1500字
最近5章摘要:1500字
人物状态:800字
伏笔:800字
章节卡:800字
风格规则:500字
```
总共大概:
```text
5900字上下文
```
后续写到第 300 章,也还是差不多 5000–8000 字上下文。
成本是可控的。
---
# 八、你要加一个 Context Budget 机制
系统里要给每次调用设置上下文预算。
比如:
```json
{
"max_context_tokens": 12000,
"budget": {
"bible_summary": 2000,
"recent_summaries": 2000,
"character_states": 2000,
"foreshadows": 1500,
"chapter_card": 1500,
"style_rules": 1000,
"retrieved_original_snippets": 2000
}
}
```
如果超过预算,系统自动压缩。
优先级:
```text
本章章节卡 > 人物当前状态 > 最近章节摘要 > 相关伏笔 > 小说圣经摘要 > 原文片段
```
不是所有东西都平等。
---
# 九、你现有系统可以这样落地
你当前项目已经有 `MemoriesModule`,也有小说章节管理、故事圣经、角色、分集、脚本、分镜这些模块。文档里也提到后续需要把小说、故事圣经、角色抽取、分集、脚本、分镜等文本步骤统一成更严格的 schema、重试、验证和 Prompt 版本管理。
所以你现在应该补:
```text
NovelContextBuilderService
NovelMemoryCompressorService
NovelRetrievalService
NovelContextBudgetService
```
职责如下:
```text
NovelMemoryCompressorService
每章写完后,把正文压缩成摘要、人物变化、伏笔变化。
NovelRetrievalService
写新章前,从数据库检索相关人物、伏笔、场景、章节片段。
NovelContextBudgetService
控制本次 API 输入不要超预算。
NovelContextBuilderService
把所有信息拼成最终 Prompt。
```
---
# 十、一个稳定的 Context Builder 流程
```text
准备写第 N 章
读取小说圣经摘要
读取当前卷纲
读取最近 5 章摘要
读取章节卡
根据章节卡识别出场人物
读取这些人物当前状态
根据章节卡识别相关伏笔
读取这些伏笔状态
如有需要,检索原文片段
按 token 预算压缩
拼成最终 API prompt
调用模型写作
```
这样章节再多,也不会爆。
---
# 十一、最重要的数据库设计
你至少需要这几个表:
```text
NovelContextMemory
NovelCharacterState
NovelForeshadow
NovelChapterSummary
NovelAgentRunContext
```
如果你不想多建表,也可以先把它们合并进一个 `NovelContextMemory`,用 `memory_type` 区分。
例如:
```text
memory_type = bible_summary
memory_type = chapter_summary
memory_type = character_state
memory_type = foreshadow
memory_type = style_rule
memory_type = timeline
```
第一版这样就够。
---
# 十二、最终答案
你的担心是对的:
> **如果每次都传全部章节,章节越多,API 参数一定越来越多。**
但专业系统不会这么做。
专业系统是:
```text
全文入库
摘要常用
相关内容检索
上下文预算控制
每章写完更新记忆
每次调用只传必要信息
```
一句话:
> **小说全文存在数据库里,不存在 Prompt 里。
> Prompt 里只放当前模型完成任务必须知道的内容。**
这样写 30 章、300 章、1000 章,API 输入都可以保持稳定。