voocel/ainovel-cli
GitHub: voocel/ainovel-cli
基于多智能体协作的全自动AI长篇小说创作引擎,通过LLM驱动长循环从一句话需求自动生成500章以上的完整小说。
Stars: 665 | Forks: 132
# ainovel-cli
全自动 AI 长篇小说创作引擎。Coordinator 在一次 Prompt 里驱动 Architect / Writer / Editor 三个子代理完成整本书的创作,Host 只做启动、恢复和观察。从一句话需求到完整小说,全程无需人工干预。
.models` 为可选字段,用于声明该 provider 下允许在 TUI `/model` 面板中切换的模型列表;如果未配置,系统会回退为当前配置文件里已经出现过的该 provider 模型。
## 诊断报告
在 TUI 中输入 `/diag` 可对当前小说的 output 产物进行诊断分析,产出可执行的发现和改进建议。
诊断覆盖四个维度:
- **流程** — 改写循环卡顿、未消费的转向指令、阶段/流程状态异常、章节跳号
- **质量** — 评审维度持续低分、合同履约率、改写率、章节字数异常
- **规划** — 伏笔停滞、指南针过时、大纲耗尽、摘要缺失
- **上下文** — 角色消失、时间线缺口、关系数据停滞
每条发现包含:问题描述、数据证据、改进建议(指向具体的 prompt/flow/config)。
`/diag` 同时会写出一份**已脱敏**的 `meta/diag-export.md`(移除小说正文,仅保留工具调用、错误串、重复次数等行为骨架)。遇到死循环 / 中断类问题,把它贴到 GitHub issue 即可,方便维护者在拿不到本地数据的情况下定位。
## 仿写画像
把参考文章放到当前启动目录的 `simulate/` 文件夹中,然后在 TUI 输入 `/simulate`。系统会递归读取 `.txt`、`.md`、`.markdown` 文件,用 architect 模型分析语料,并写入:
output/novel/meta/simulation_profile.json
再次运行 `/simulate` 时,会按 `relative_path + sha256` 跳过未变化文件;如果没有新增或变更内容,会提示“画像已是最新”并且不会调用 LLM。若已有画像且 `simulate/` 中出现新增或修改文章,系统会在原画像基础上继续合成。
也可以导入之前生成的画像,避免重复分析同一批文章:
/simulate
/importsim ./profile.json
`/importsim` 只接受本功能生成的 `simulation_profile.v1` JSON,并按语料指纹合并,重复来源会跳过。只导入可信来源的画像文件;导入内容会成为后续 Agent 的上下文参考。画像会以 compact 形式注入 `novel_context`,Coordinator、Architect、Writer、Editor 都能读取;各 Agent 只借鉴结构、节奏、钩子和吸引读者手法,不复制原文表达或专有设定。
## 导入
在 TUI 中输入 `/import <文件路径>` 可把一本已有的小说反推导入:先按章切分,再用 LLM 反推出前提 / 角色 / 世界观 / 分层大纲 / 指南针,逐章落盘。原文作为第一卷落成可续写的连载,导入完成后会**自动接力续写**——Coordinator 在第一卷末做评审/摘要、追加新卷,从下一章继续。
/import ~/我的小说.txt # 从头导入并反推 foundation
/import ~/我的小说.txt from=50 # 从第 50 章接着导入(跳过反推)
**章节切分规则**:自动识别这些标题格式(行首,可带 `#`/`##` Markdown 前缀、`【】`/`〖〗` 包裹、全角空格,兼容 GBK/BOM 编码):
- 中文编号:`第一章` `第3回` `第十话` `第二卷` `第五节` `第二幕`、独立 `卷一`,数字支持大写(`第壹章`),可带副标题(`第三章:决战`)
- 中文特殊单元:`序章` `楔子` `引子` `前言` `尾声` `终章` `后记` `番外` `外传`
- 英文:`Chapter 1` `Chapter II`、`Prologue` `Epilogue`,可带副标题(`Chapter 1: The Beginning`)
若提示**"未识别到任何章节"**,请确认文件确为分章小说文本(章节标题独占一行、位于行首)。
## 导出
在 TUI 中输入 `/export` 可把已完成的章节合并导出,默认 TXT,写到 `{novelDir}/{NovelName}.txt`。导出是只读操作,写作中途也可以随时拿"现阶段成品",不影响 Coordinator 运行。
格式由**输出路径后缀**决定(`.txt` / `.epub`):
/export # 默认 TXT,{novelDir}/{NovelName}.txt
/export ~/光斑.txt # 后缀 .txt → TXT
/export ~/光斑.epub # 后缀 .epub → EPUB(Apple Books / 微信读书 / Kindle 转换器可读)
/export from=10 to=30 --overwrite # 章节区间 + 覆盖
/export from=10 ~/x.epub --overwrite
- **TXT** — `《书名》` → 卷分隔 → 章节正文(长篇分层模式自动加卷分隔)。两类内部数据**不进导出**:premise(创作蓝图,含目标读者 / 写作禁区等后台信息,写给作者与引擎看的)、弧分隔(读者视角下弧是过细的内部结构)。导出器统一生成"第 N 章 标题",正文里 writer 自带的重复标题(`# 第N章…` 或 `# 章节名`)会被剥掉。
- **EPUB** — EPUB 3 标准容器,含封面页、目录、按章拆分的 XHTML,标识符基于内容稳定派生(重导出同一本书阅读器识别为更新版本)。不带封面图。
范围内未完成的章节会跳过并显示在结果里,不算错误。
#### 按角色使用不同模型
通过 `roles` 字段为不同智能体分配不同的模型,未配置的角色使用默认模型:
{
"provider": "openrouter",
"model": "google/gemini-2.5-flash",
"providers": {
"openrouter": { "api_key": "sk-or-v1-xxx", "base_url": "https://openrouter.ai/api/v1" },
"anthropic": { "api_key": "sk-ant-xxx" }
},
"roles": {
"writer": { "provider": "anthropic", "model": "claude-sonnet-4" },
"architect": { "provider": "openrouter", "model": "google/gemini-2.5-pro" }
}
}
可配置的角色:`coordinator` / `architect` / `writer` / `editor`
#### 自定义代理
选择任意 Provider 后填写代理地址即可,或使用 Custom Proxy 并指定 API 协议类型。自定义代理的 `api_key` 可选;如果你的代理不需要认证,可以省略:
{
"provider": "my-proxy",
"model": "gpt-4o",
"providers": {
"my-proxy": {
"type": "openai",
"base_url": "https://proxy.example.com/v1"
}
}
}
支持的 Provider:`openrouter` / `anthropic` / `gemini` / `openai` / `deepseek` / `qwen` / `glm` / `grok` / `ollama` / `bedrock` 及任意自定义代理。
关于 `api_key`:
- `openrouter` / `anthropic` / `gemini` / `openai` / `deepseek` / `qwen` / `glm` / `grok` 这类托管接口通常需要填写 `api_key`
- `ollama` 和 `bedrock` 允许不填 `api_key`
- 显式指定了 `type` 的自定义代理允许不填 `api_key`
例如本地 `ollama` 配置:
{
"provider": "ollama",
"model": "qwen3:latest",
"providers": {
"ollama": {
"base_url": "http://localhost:11434/v1"
}
}
}
### 写作风格
通过配置文件的 `style` 字段切换:
- `default` — 通用风格
- `suspense` — 悬疑推理
- `fantasy` — 奇幻仙侠
- `romance` — 言情
### 去 AI 味与自定义规则
内置一份去 AI 味基线(`assets/` 下,出厂默认):机械黑名单 `rules/default.md`(套句 / 疲劳词,commit 时确定性检查)+ 语义判据 `references/anti-ai-tone.md`(注入 writer / editor 规避与举证)。
想叠加自己的偏好**无需改源码**:在 `~/.ainovel/rules/` 目录(全局,放任意 `.md`,按文件名字典序合并)或项目根 `./rules.md`(本书)里,**用大白话写偏好即可**(如「主角别写成圣母」「多用身体感知」),editor 会按语义审阅——零格式、零 YAML。想要「字数 / 禁词」这类硬性确定检查,再**可选地**在文件顶部加一段 front matter。就近覆盖、与内置基线叠加生效;完整字段见 [`rules.md.example`](rules.md.example)。
## 输出结构
所有创作数据(章节、大纲、角色、进度等)保存在output目录中。中断后重新运行会自动从上次进度续写。删除output目录将重新开始创作。
output/{novel_name}/
├── chapters/ # 终稿(Markdown)
│ ├── 01.md
│ └── ...
├── summaries/ # 章节摘要(JSON)
├── drafts/ # 章节草稿
├── reviews/ # 评审报告
├── meta/
│ ├── premise.md # 故事前提
│ ├── outline.json # 扁平章节大纲(仅含已展开的章节)
│ ├── layered_outline.json # 分层大纲(当前卷 + 预览卷,长篇模式)
│ ├── compass.json # 终局方向指南针(长篇模式)
│ ├── characters.json # 角色档案
│ ├── world_rules.json# 世界规则
│ ├── progress.json # 进度状态
│ ├── timeline.json # 时间线
│ ├── foreshadow.json # 伏笔台账
│ ├── state_changes.json # 角色状态变化记录
│ ├── style_rules.json# 写作风格规则(弧边界时提炼)
│ ├── snapshots/ # 角色状态快照(长篇)
│ ├── checkpoints.jsonl # Step 级 checkpoint(每个工具成功后追加)
│ ├── characters.md # 角色档案(可读版)
│ └── world_rules.md # 世界规则(可读版)
## 断点恢复
写一部长篇小说可能需要数小时甚至数天,中途崩溃、断网、Ctrl+C 都是常见情况。系统在**同一目录再次运行时自动恢复**,无需手动操作。
### 恢复场景
| 中断时机 | 恢复行为 |
|---|---|
| 规划阶段(正在构建世界观/大纲) | 检查已保存的设定,自动补全缺失项 |
| 某章正在写作(有草稿未提交) | 从该章续写,读取已有草稿继续 |
| 审阅进行中 | 重新触发 Editor 评审 |
| 重写/打磨队列未清空 | 继续处理待重写的章节 |
| 弧/卷展开中断(评审完但下一弧未展开) | 自动检测骨架弧/卷,触发 Architect 展开 |
| 用户干预未完成 | 重新注入上次的干预指令 |
| 正常写作中断 | 从下一章继续 |
### 工作原理
所有创作产物持久化在 `output/` 目录。每个工具执行成功后写入 checkpoint (`meta/checkpoints.jsonl`)。重启时:
1. 读取 `progress.json` + 最近 checkpoint + 待处理信号
2. 精确到 step 级生成恢复指令(如"第 7 章 draft 已落盘,请继续 check_consistency")
3. 一次 `Prompt` 启动 Coordinator,进入长循环继续创作
## 实时干预(Steer)
创作过程中可以随时通过输入框注入修改意见,**不需要暂停或重启**。
### TUI 模式
创作启动后,底部输入框自动切换为干预模式:
❯ 把感情线提前到第4章,增加男女主的对手戏
输入后按 Enter,系统自动:
1. 记录干预指令到 `run.json`(崩溃恢复用)
2. 注入到正在运行的 Coordinator
3. Coordinator 评估影响范围,决定是修改设定、重写已有章节,还是在后续章节调整
### 干预示例
| 干预指令 | 系统可能的响应 |
|---|---|
| "主角改成女性" | 修改角色设定,评估已写章节是否需要重写 |
| "把感情线提前到第4章" | 调整大纲,可能重写第4章及后续 |
| "加入一个反派角色" | 更新角色档案和世界规则,在后续章节引入 |
| "节奏太慢了,加快推进" | 调整后续章节的大纲密度 |
## 设计理念
### LLM 驱动,越简单越稳定
- **决策权归 LLM** — 流程决策全部由 Coordinator 自主判断,Host 不介入。工具失败时返回结构化错误,由 LLM 自行决定重试或调整策略
- **工具只返事实** — 原子 IO + checkpoint 写入,返回值是 JSON 事实字段(`final_verdict` / `pending_rewrites` / `arc_end_reached`),不夹带任何指令字符串
- **Reminder 驱动每轮** — Host 在每轮 LLM 调用前读事实层,运行纯函数 generator 生成 `` 注入,指令不进持久历史、每轮从事实重算
- **StopGuard 物理守门** — `Phase ≠ Complete` 时 Coordinator 物理上不可 `end_turn`,连续阻拦超限才升级终止
- **拒绝复杂编排** — 没有 task queue、没有 scheduler、没有 policy engine。Coordinator 的一次 Run 就是唯一的控制流
- **模型越强收益越大** — 架构把决策权留在 prompt 和工具语义里,模型升级后直接吃到收益,Host 一行不用改
### 全自动闭环
一句话输入,完整小说输出:
“写一部悬疑小说” → 构建世界观 → 设计角色 → 规划大纲
→ 逐章写作 → 质量评审 → 自动重写
→ 弧级摘要 → 角色快照 → 完整成书
- **Coordinator 自主调度** — 在一次长循环里读事实层 + Reminder 决定下一步,无需 Host 干预
- **Writer 自主创作** — 每章独立完成 plan → draft → check → commit 的完整闭环
- **Editor 自主评审** — 跨章节分析结构问题,输出裁定及影响范围
- **Architect 自主构建** — 从一句话需求推导出完整设定,弧/卷边界时自主展开后续规划
- **自动伏笔管理** — 埋设、推进、回收全程由 Agent 自行追踪
- **自动节奏调控** — 追踪叙事线和钩子类型历史,避免连续章节结构雷同
### 事实与指令解耦
工具只返事实,指令由 Reminder 每轮从事实层重算:
- `commit_chapter` / `save_review` 返回结构化事实(`final_verdict` / `pending_rewrites` / `arc_end_reached` / `next_chapter`),不夹带任何 `[系统]` 字符串
- `internal/host/reminder/` 下的纯函数 generator 读 `Progress` + `Outline`,每轮 pre-turn 生成 ``:`flow`(当前该做什么 / 弧末刹车)/ `queue_guard`(队列未清禁止新章)/ `book_complete`(全书完成才放行)。物理兜底由 `StopGuard` 在 `phase≠Complete` 时拒绝 `end_turn` 承担
- Reminder 只存活一轮,不进历史、不参与压缩;规则有单元测试,退化可被回归捕获
这样指令不会被链式调用吞掉,也不会在工具产物里漂移。改 bug 只需加一个 generator + 一个测试。
## 技术栈
- **Go 1.25** — 主语言
- **[agentcore](https://github.com/voocel/agentcore)** — 极简 Agent 内核(tool-calling + streaming)
- **[litellm](https://github.com/voocel/litellm)** — 统一 LLM 接口适配
- **[Bubble Tea](https://github.com/charmbracelet/bubbletea)** — 终端 TUI 框架
## License
MIT
本项目积极参与并认可 [linux.do 社区](https://linux.do/)。
标签:AI小说生成, C2, DLL 劫持, EVTX分析, TUI, 多智能体协作, 大语言模型, 日志审计, 自动化写作