核心原则一句话:文学创作判断交给 LLM,状态流转、任务调度、数据持久化全部交给确定性代码。LLM 只负责产出文学内容,无权直接修改底层存储,所有读写必须走工具协议;任务下一步由 Engine 基于 Store 里持久化的事实做无模型路由,而不是由 LLM 自己决定下一步要干什么。

项目描述

  • 全自动 AI 长篇小说创作 CLI 引擎,核心思想:事实层确定,语义层自主。控制流用确定性代码;创作、判断交给 LLM;全部状态落地文件系统,支持 step 级断点恢复,面向 500 + 章长篇网文。
  • 这套系统的核心不是「一个大模型自己编排整本书」,而是确定性引擎按事实调度、三个创作代理自主干活、裁定函数按需出场。一句话:事实层确定,语义层自主。

事实在文件
创作进度、大纲、章节、摘要、审阅结果,都落在磁盘上(如 progress.json、章节正文、checkpoint),不是只活在聊天记录里。
Agent 读到的是「书现在长什么样」;重启后真相仍在文件里。

调度在代码
「下一步该派 Architect / Writer / Editor」不是靠模型自己说,也不是靠提示词里写死流程。
是 Go 里的 Route:读 Store 里的事实 → 查决策表 → 派下一个 Worker。
不消耗 LLM,行为可测、可穷举。

核心架构总览

核心架构总览

完整架构精炼总结

核心思想:事实层确定,语义层自主

不是大模型全权编排全书;确定性调度引擎基于磁盘事实做流程控制,创作代理自主完成语义内容,仅在关键岔路口调用 Arbiter 裁定,所有状态全部持久化到文件 Store。

层级 模块 是否调用 LLM 职责
Host 层 Host + TUI/Headless 外壳 程序生命周期、用户交互入口、预算哨兵、干预处理、闸门控制;不参与业务调度逻辑
调度层 Engine + Route 主循环,每次LoadState读取 Store 完整状态;Route 纯函数查表输出下一步派谁;零 LLM,不做文学判断
裁定层 Arbiter**(利用大模型来辅助)** ✅(单次函数调用) 规划师选型、用户干预分诊、失败僵局处理;输入事实,输出结构化 JSON;裁定全部写入decisions.jsonl可审计
创作层 Workers(Architect/Writer/Editor)+Tools+Store ✅(Agent 循环) 三个创作代理,通过工具读写 Store;模型自主生成内容,但工具调用顺序、产物契约被强制约束

协作本质:

  1. 所有可信状态全部保存在 Store(文件系统),内存只是临时镜像;
  2. Engine 只读取 Store 事实,Route 查表得到下一步;
  3. Arbiter 只输出结构化决策,决策结果写入 Store 才生效
  4. Workers 只允许通过 Tools 读写 Store,Agent 之间不直接互相调用通信,靠磁盘工件协作。

完整故事链路总览

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
用户 / TUI


Host ── 生命周期、用户干预、Gate闸门、事件输出


Engine ── 循环:读Store → Route(纯函数无LLM) → 启动Worker


Writer(LLM循环) ── 只能调用Tools,不能直接读写文件
│ ├─ novel_context
│ ├─ read_chapter
│ ├─ plan_chapter
│ ├─ draft_chapter
│ ├─ read_chapter(draft)
│ ├─ check_consistency
│ └─ commit_chapter

Tools ── 前置校验|原子IO|checkpoint|返回事实JSON


Store(文件事实层:大纲/plan/draft/final/meta/checkpoints)

└── Engine下一轮循环读取Store状态,重新路由任务
  • Route 管「事实已知时下一步是谁」;Arbiter 管「用户这句话在语义上要哪几种控制动作」。意图理解 + 授权范围判断(改什么、改多大、要不要停),不是状态机能稳定覆盖的。

一、Host(运行时外壳):对外入口 + 生命周期与策略层

Host不参与章节内容决策、不决定下一章写什么,是整个系统的外层容器,负责和用户 / 终端交互,管理全局资源与权限闸门。

核心职责

  1. 任务生命周期管理:启动、暂停、恢复、终止、完本,处理异常中断。
  2. 用户干预通道(Steer):接收用户修改设定、剧情干预指令;把干预事实送入 Arbiter 做裁定,再将裁定结果下发给 Engine。
  3. 事件与视图输出:把系统内部状态投影到 TUI / 前端界面;提供模型切换、参数切换入口。
  4. 预算与限流哨兵:token 消耗统计、调用配额控制,防止超支。
  5. 推进闸门 Gate:类似 /review on 的人工审核开关,章节推进需要满足 Gate 许可才能往下走。**Gate 说「用户政策允不允许现在往前走」。**默认全自动几乎感觉不到它;/review on 或干预要求「改完停」时,它就是人手动控速的闸。
  6. 资源持有:实例持有 Store 存储、Worker 任务执行器 Runner、状态观测器 Observer 等底层资源。

二、Engine(调度核心,确定性循环):任务分发器,单 goroutine 串行

Engine 是整个系统的任务调度内核,主循环完全确定性,Route 路由逻辑是纯函数,默认不调用 LLM

主循环流程

读取 Store 持久化事实 → Route 路由决策表 → 前置校验 + Gate 放行 → 启动一个 Worker 执行任务 → 校验本次任务是否完成推进 → 回到循环。

Route 路由(零 LLM 决策)

输入:当前 State(阶段 phase、工作流 flow、待重写队列、剧情弧缺口等)
输出:下一步启动哪个 Worker、做哪一章任务(Writer / Editor / Architect)

路由逻辑不调用大模型,只读取已经落盘的事实来判断任务优先级。优先级示例:返工队列 > 剧情弧末尾评审 / 摘要更新 > 拓展新剧情弧 / 新卷 > 安排 Writer 写下一章。

Engine 的 LLM 使用边界

只有少数场景才按需唤起 Arbiter(LLM):规划方案选择、用户干预分诊、任务陷入僵局 / 失败兜底。正常章节流转完全不用模型做调度判断。

崩溃恢复特性

不依赖 LLM 会话上下文记忆。服务重启后,直接读取 Store 与 checkpoint,从上次持久化的状态继续跑,会话不会丢失。

类比:Engine = 流水线调度 PLC,读取当前工位状态,按固定规则派工人干活;只有卡住、需要人工仲裁时才请示模型。

Worker + Tools:LLM 不能裸写文件,必须通过工具访问 Store

Worker 就是带 LLM 能力的执行单元:Writer、Editor、Architect 都属于 Worker。
硬性约束:Worker/LLM 没有直接读写文件的权限,所有增删改查都必须调用 Tools 原子工具集。

失败策略要做阶梯式分层处理

  • 核心根源:不同失败的代价、可恢复性完全不一样,一刀切处理会两个极端:要么浪费大量 token 烧钱,要么不该停的时候直接误杀业务流程

系统拆成两条互相独立的阶梯,不能混为一张表

  1. Worker 执行失败(handleWorkerError):调用模型、网络、接口报错,属于运行异常
  2. 僵局死锁 trackDeadlock:没有报错,但反复派同一个任务,没有业务进展(空转)

Store:文件系统事实层

存储全部持久化状态,以文件形式落地:

  • 进度文件:progress.json
  • 大纲、章节计划、草稿、终稿
  • 摘要、角色状态、伏笔账本、checkpoint 记录
  • 世界设定、人物关系、时间线

存储设计特点:

  • 子存储独立加锁;
  • 跨多个文件的变更,依靠操作顺序约定 + 幂等重放保证一致性,不引入重型分布式事务;
  • checkpoint 记录在 meta/checkpoints.jsonl,记录每一步工具执行的阶段(plan / draft / check / commit)。

Tools 原子工具的统一能力

每一个写入类工具都内置一套标准化流程:

  1. 前置校验:校验当前阶段合法、章节状态符合预期,是否允许本次修改;
  2. 原子 IO 写入:先写临时文件,成功后 rename 覆盖正式文件,杜绝半截损坏文件;
  3. 追加 checkpoint 记录:标记当前执行到哪一步;
  4. 返回结构化事实 JSON,附带next_step字段驱动 LLM 进入下一个工具调用;不返回文学提示词

工具带来四层边界保障:

  1. 协议边界:限制 LLM 修改范围,终稿只能由commit_chapter生成,禁止 Worker 随意篡改正式章节;
  2. 一致性边界:正文、伏笔、角色状态、进度数据同步更新,保证小说世界事实统一;
  3. 恢复边界:工具调用成功即落盘 checkpoint;程序崩溃,可以在 step 粒度恢复执行;
  4. 幂等边界:相同 Scope+Step+Digest 的 checkpoint 会被识别,自动跳过重复执行,防止重复生成内容。

commit_chapter 特殊增强:持久化 Saga 事务

提交终稿时,创建PendingCommit快照,冻结当前正文、角色、伏笔等全部参数。

作用:如果提交中途崩溃,重启后重放这个冻结快照完成提交,不会让新的 Writer 重新生成一套不一致的世界状态。

三、核心设计价值总结

  1. 关注点分离:LLM 只负责文学内容创作、文学判断;调度、状态流转、持久化、任务分支全部交给确定性代码,减少模型幻觉带来的调度失控。
  2. 可恢复:所有关键节点都落盘 checkpoint,任何阶段崩溃,重启后从 step 级恢复,不需要重跑全部对话。
  3. 可审计可回溯:plan、draft、check、commit 每个阶段都有持久化文件,完整保留创作中间产物,支持复盘、人工介入修改。
  4. 可控的记忆加载:novel_context 提供结构化元信息,read_chapter 按需加载正文,控制上下文长度,抑制 token 膨胀。【所有真实状态持久化到 Store,对话上下文只是临时视图。
  5. 幂等安全:工具层做原子写入与幂等判断,防止重复生成、文件损坏、数据不一致。

阶梯 A:Worker 执行失败(网络、接口报错、审核拦截)

阶梯:免费本地重试 → Arbiter 语义仲裁 → 最终人工暂停

  1. 第 1 次失败:直接原地重试,不调用 Arbiter
    网络抖动、服务商 503、瞬时限流这类偶发故障,重试很大概率直接恢复。
    如果一出错就调用 Arbiter,平白消耗一次 LLM token,属于不必要开销。
  2. 第 2 次仍然失败:交给 Arbiter 做结构化裁定
    可选动作:retry再试、reroute换别的任务、abort中止当前任务。

    内容审核拦截也走这套阶梯:实测直接重派更换上下文有概率自愈,不能直接粗暴熔断。

  3. Arbiter 自己调用也失败:直接暂停,交给人处理
    Arbiter 本身也是大模型调用,它也会网络失败、被审核拦截,不能无限递归。

阶梯 B:僵局死锁 trackDeadlock(没有报错,但原地空转)

现象:不停派发完全一样的 Agent+Task,有 checkpoint 日志产出,但业务后置条件始终不满足

典型场景:Writer 反复 plan/draft,但永远不执行commit_chapter提交章节;Architect 反复跑但设定始终不全。

一句话总结整套哲学

廉价瞬时故障优先用代码本地自愈,不去消耗大模型;需要语义判断才交给 Arbiter;哪怕交给模型仲裁,也必须设置硬熔断上限,防止系统无限空转烧钱。

**很多项目都是两层状态:**Phase 是整本书走到哪一站,Flow 是写作站里正在干哪件事。

  • Phase:大阶段,只许前进
  • Flow:写作期内的当前工作流

使用长篇小说生成

如何实现不一次性生成全部章节,初始产出指南针 + 前 2 卷骨架 + 第一弧详细章节;后续弧只保留目标与预估章数,写到边界再滚动展开;

这个是如何实现的?

  • LLM脑子里 / 输出文本里可以产出完整全书大纲,管不住。
  • 但是落地写到 Store 磁盘这一步被工具门禁卡死,没有工具接口可以一次性整体替换全部大纲。

可复用的设计口诀

  1. 能查表的绝不问模型
  2. 模型只产出工件,不产出调度
  3. 磁盘是真相,会话可丢
  4. 控制动作发生在循环边界
  5. 失败先重试,再裁定,最后熔断
  6. 同任务重复 = 无进展,必须有硬上限
  7. 对模型的约束写在工具和闸门里,不写在请求它「请遵守」

如果只记一条:这是把 Agent 系统做成状态机 + 工具副作用 + 少量 LLM 函数,而不是做成一个会聊天的超级编排器。前者可测、可恢复、可停;后者通常不能。

设计示意