零LLM开销调度:ainovel-cli的Route决策表与12万组合穷举测试怎么做 零LLM开销调度ainovel-cli的Route决策表与12万组合穷举测试怎么做【免费下载链接】ainovel-cli✨多agent实现全自动AI小说生成项目地址: https://gitcode.com/gh_mirrors/ai/ainovel-cliainovel-cli 是一个多 Agent 全自动 AI 小说生成 CLI 工具确定性 Engine 按事实决策表调度 Architect / Writer / Editor 三个创作代理主循环零 LLM 开销行为由 12 万组合穷举测试钉死。这篇文章拆解它的 Route 决策表是怎么设计的、穷举测试又是怎么写出来的。为什么下一步派谁不再问 LLM多 Agent 工作流里最常见的烧钱点就是协调者写完一章之后由一个 coordinator LLM 决定接下来该调谁。它的成本结构是这样的每章要多跑 1~2 个 LLM 轮次每轮吃掉 3500~7000 tokens 的 system prompt 与上下文一本 200 章的长篇就是 200~400 次调用其中约 90% 是纯路由——LLM 只是在复述规则层已经算好的答案更糟的是 LLM 会路由错漏掉弧末评审、跳过重写队列、崩溃恢复后分支遗漏……ainovel-cli 的解法一句话概括可枚举的状态迁移归代码边界清晰的语义判断归 LLM 函数Arbiter开放式创作归 LLM 循环Worker。写完一章后派谁属于第一类——读事实、查表错误率应该趋近 0而 LLM 在这里没有任何红利。完整的三分法与四铁律见 docs/architecture.md早期调研每章 3500-7000 tokens、90% 是冗余路由的账目见 docs/refactor-flow-driven.md。Route 决策表是怎么工作的整张表就在三个文件里internal/flow/router.go决策表本体、internal/flow/state.go事实加载、internal/flow/router_test.go单分支用例。1. State路由的唯一输入Route不读数据库、不碰文件系统它只看一个显式声明的State结构体当前阶段Phase、活跃流程Flow、待重写队列、弧边界、弧评审/弧摘要/卷摘要是否完成、基础设定缺项、规划级别、全局审阅事实……设计注释写得很直白所有事实必须在此显式声明禁止 Route 内部读 Store。所有读盘集中在LoadState唯一的IO 边界一次性把路由需要的事实读齐。任何读取失败都直接返回错误——损坏的工件和尚未生成是两种不同事实Router 不得在不完整快照上继续派单。2. Route11 分支优先级查表Route(s State) *Instruction是一个纯函数自上而下匹配第一个命中的分支优先级事实条件派给谁1PhaseComplete完本nilHost 确定性输出总结2规划期设定缺项且规划师可判定同一规划师补齐缺项3重写/打磨队列非空writer 按队列头重写/打磨4FlowReviewing / Steeringnil让位于 LLM / 用户干预5外部修订导致聚合工件失效editor 重建弧/卷摘要6外部修订影响后续规划architect 消费修订反馈7分层书到达弧末评审→弧摘要→卷摘要→扩弧→续卷5 步流水8非分层书全局审阅到期editorscopeglobal9非分层大纲已耗尽architect 决定完结或续接10兜底writer 写下一章两个关键设计返回 nil 是合法的。它表示当前没有可由确定性事实推出的指令交由 Engine 处理终态、启动补裁或等待用户干预——查表查不出来的才轮到 LLMArbiter上场每条指令都带 Reason。路由理由直接进事件流和日志失败裁定时 Arbiter 也能看到排查为什么派了这个活一目了然。3. Instruction一张类型化工单输出不是自然语言而是结构体Agent派谁、Task干什么、Reason为什么、Chapter涉及哪章。Engine 拿到后直接程序化运行 Worker没有任何 LLM 工具转发层——指令到执行之间没有复述环节这是零 LLM 开销的最后一块拼图。12 万组合穷举测试怎么写这才是整篇文章的重点。测试文件是 internal/flow/router_exhaustive_test.go核心思路可以拆成四件事。1. 先给决策表写一个独立镜像测试里有一个expectedInstruction函数它按架构规格独立计算某个 State 应该得到什么裁定。关键纪律故意不复用实现的任何代码。这意味着实现重构后行为若有偏移这里立刻红灯要改变行为必须同时改动规格并留下 diff——规格与实现互为参照谁先动一目了然。2. 维度枚举 × 交叉相乘把 State 拆成 10 个正交维度每个维度只取有代表性的枚举点维度枚举点数Phase阶段5init / premise / outline / writing / completeFlow流程5writing / reviewing / rewriting / polishing / steering重写队列2空 / {7,9}分层模式2已完成章节集3含正好命中全局审阅间隔的点基础设定缺项2规划级别 tier3空 / short / long全局审阅事实2外部修订条数2聚合工件2再乘以50 个弧边界形态无边界、弧中以及 弧末 × 评审有无 × 摘要有无 × 卷末 3 态 × 后续动作 4 态 的 2×2×3×4 矩阵十层嵌套循环把全部交叉组合喂给Route。项目文档将这一交叉空间记为12 万组合穷举docs/architecture.md 控制面规格表。还有一个防缩水护栏if total 5000 { t.Fatalf(枚举空间意外缩水%d 组合检查维度枚举, total) }将来有人改维度、误删枚举点组合数悄悄掉下去测试直接失败——覆盖不能无声缩小。3. 守恒性质与具体分支无关的断言每个组合除了规格期望 vs 实现实际比对外还检查一组与分支无关的性质assertConservation终态或无进度时不得产生任何指令writer 指令必须带章节号重写队列非空时必须派队列头、动词随 Flow 变重写/打磨editor / architect 指令不得带章节号Task 与 Reason 均不得为空无法归类的指令组合直接判失败。这些性质不依赖某条具体规则是无论怎么重构都不许违反的底线。4. 纯函数 确定性断言每个组合还额外验证两件事纯函数调用前后深拷贝快照reflect.DeepEqual必须一致——Route 不得改写输入 State确定性同一输入连续调用两次结果必须完全相同。查表的正确性不该靠跑一遍看看而要靠全空间逐点核对。5. 规格先行的纪律项目铁律写明控制面改动必须先改穷举规格再改实现。两个测试文件分工明确router_test.go的单分支用例负责可读的意图文档每个用例就是一个场景故事穷举文件负责全组合空间下的优先级与守恒性质。想加一条路由规则先在穷举规格里写出新分支在哪些组合下命中什么再动router.go——这是防止决策表随功能增长腐化的核心机制。Engine 拿到工单之后internal/host/engine.go 的执行循环是LoadState → Route → 前置校验 → 直接运行 Worker → 哨兵边界检查然后下一轮。值得注意的三个细节nil 的出路Route 返回 nil 时Engine 先试启动补裁首次规划师选型等窗口否则自然停机等待用户 Continue——查表管不到的地方停机是默认姿态而不是瞎派单僵局有显式限界上一轮执行后 Route 仍产生同一AgentTask说明路由后置条件没被满足。连续 3 次咨询 Arbiter连续 5 次硬熔断暂停并通知人工介入——确定性引擎不允许无限空转失败重试只给一次同一指令首败重试一次再败就把错误类型和当前事实打包给 Arbiter 做失败裁定每次裁定都落盘decisions.jsonl可离线重放审计。小结这套模式可以抄走吗 先给决策做性质分类可枚举 → 代码查表边界清晰 → 单次 LLM 函数开放创作 → LLM 循环。把每章都要做的下一步派谁放进第一类就能砍掉 90% 的调度 token查表函数保持纯输入一个显式 State 结构体输出类型化工单读盘集中在唯一的 IO 边界穷举测试 独立规格镜像 维度枚举交叉 守恒性质 纯函数/确定性断言再加空间缩水即失败的护栏和先改规格再改实现的纪律。当调度路径是封闭的确定性代码就是最便宜的 LLM。而它省下来的每一分开销都变成了给 Writer 多写一字的预算。更多入口说明见 README.md引擎与仲裁器的设计演进记录见 docs/engine-arbiter.md。【免费下载链接】ainovel-cli✨多agent实现全自动AI小说生成项目地址: https://gitcode.com/gh_mirrors/ai/ainovel-cli创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考