Article

炼云小说工厂 v0.1:我想把 AI 写作做成一个生产系统

记录炼云小说工厂 v0.1 的开源过程,以及我对 AI 长篇写作、agent 工作流和可观察生产系统的一些想法。

3 min read

最近把之前折腾的一个网文创作平台整理了一下,改名叫 炼云小说工厂,然后开源了。

项目地址是:https://github.com/larry-xue/lianyun-novel-factory

这个项目现在还很早期,说 v0.1 都有点勉强,但我还是想先把它放出来。原因也很简单,我最近一直在想一个问题:如果 AI 真的要参与长篇内容创作,它到底应该是一个更强的聊天框,还是应该是一个可以被观察、被调度、被修改的生产系统?

我现在更倾向于后者。

所以炼云并不是一个“输入一句话,然后生成一本书”的工具。它更像一个工作台,里面有立项、agent、prompt、活文档、伏笔、章节、批量任务、运行记录。听上去有点重,但这也是我想做它的原因。长篇小说不是一次 prompt 就能解决的问题,它本质上是一个持续维护状态的过程。

起因

之前我也试过很多很直接的 AI 写作方式,比如写一个很长的 prompt,把题材、主角、爽点、节奏、字数都塞进去,然后让模型生成大纲或者章节。

短内容这样其实还可以,写个小故事、写个广告文案、写一章试读,有时候效果还不错。但是一旦想写长篇,问题就开始变得很明显。

角色会成长,关系会变化,世界观规则不能前后打架,伏笔不能埋了就忘,大纲也不可能从第一章开始就一成不变。更麻烦的是,模型每次都像是重新开始工作,哪怕你给它塞了很多上下文,它也不一定真的理解当前这本书写到哪里了,哪些东西已经成为事实,哪些只是草稿,哪些应该被废弃。

这时候继续加长 prompt 只能缓解一部分问题,不能从根上解决问题。上下文越长,调用越贵,模型也越容易抓不住重点。更重要的是,人其实也看不清这个系统为什么这样写。

所以后来我的想法就变成了:不要把 AI 写作理解成“一次生成”,而是把它理解成一个流水线。每个 agent 负责一小段工作,中间产物全部落库,人可以随时打开看、手动改,系统也能知道后续应该基于哪个版本继续。

我不太相信一键成书

说实话,我现在不太相信“一键生成一本长篇小说”这个产品形态。

不是因为模型写不了字。恰恰相反,现在模型很会写字,很多时候它甚至太会写了,几千字很快就能出来。但长篇小说真正难的地方不只是写出一章,而是持续维持一整本书的方向、节奏和一致性。

如果产品只给一个输入框和一个生成按钮,最后拿到一大段正文,看起来很爽,但很快会遇到一堆问题。

这一章为什么这样推进?它参考了哪些设定?前面埋的坑还有没有记住?我刚刚手动改了一个角色设定,后面的章节会不会知道?如果某一章写崩了,我到底是 prompt 有问题、模型有问题,还是上游的大纲就不对?

这些问题不解决,AI 写作就会一直停留在“生成一些看起来不错的文本”这个阶段。它可以帮你起草,但很难真的参与一个长篇项目。

炼云想做的事情,就是把这些隐藏的问题暴露出来。

v0.1 现在有什么

当前版本已经包含了一条从想法到章节的基础闭环。

用户可以先在书架里输入一个 idea,然后进入立项 chat。这个 chat 不是闲聊,而是用来讨论选题方向,生成候选卡,确认之后再进入生产流程。

后面的流程大概是这样:

  1. 立项和故事设计。
  2. 生成分层大纲。
  3. 创建角色、世界观和活文档。
  4. 进入 gate,让人确认是否继续。
  5. 按章节循环执行写作、检查、维护和追踪。

UI 上现在能看到书架、立项 chat、书籍详情、文件树、伏笔看板、Prompt 仓库、Runs、Batches 和设置页。这里面我比较在意的其实是几个“看起来不那么像写作功能”的东西。

比如 Runs 页面。每一次 agent 调用、每一次 LLM 请求,都会有记录。以后章节写坏了,不需要靠猜,可以回头看当时输入了什么,模型返回了什么,schema 校验有没有失败,token 和延迟是多少。

再比如 Prompt 仓库。prompt 不再只是代码里的一个字符串,而是可以在 UI 里编辑、回滚、跟运行记录对应起来的产品资产。

还有伏笔看板。长篇小说里最难的不是“埋一个坑”,而是记得这个坑什么时候该收、有没有被暗示过、最后是不是已经废弃了。所以它不应该只是 markdown 里的一句话,而应该有状态。

这些东西做起来都不酷,但我觉得它们比“再调一个更强的 prompt”重要得多。

人类主编 + AI 工人

我对炼云的定位不是全自动写作系统,更不是自动发布系统。

我更想要的是一种“人类主编 + AI 工人”的模式。人类负责方向、品味、取舍,AI 负责生成候选、补全文档、写初稿、做检查,系统负责把这些工作串起来,并且把每一步留下痕迹。

这也是为什么里面有 gate 机制。

现在 gate-1 已经接进去了。立项和初始大纲完成之后,系统会暂停,让用户确认要不要继续。后面可以继续加 gate-2、gate-3,比如卷规划确认、关键章节确认、质量审核确认。

之前我做很多 AI 产品的时候,都会不自觉地想把流程做得更自动。但现在回头看,越是复杂的东西,越需要在关键节点停下来。全自动看起来很智能,但如果中间状态不可见,出了问题就很难修。

PG 是 source of truth

很多 AI 写作工具会把状态存在 prompt 里,或者存在一堆 markdown 文件里。

炼云现在选择 PostgreSQL 作为 source of truth。这个选择不花哨,但是很实际。长篇生产里有大量需要查询、筛选、聚合和追踪的状态,这些东西如果都塞进 markdown,后面一定会很痛苦。

比如伏笔不能只是一句 markdown:

主角小时候收到过一封神秘信。

它应该能回答更多问题:

  • 什么时候引入?
  • 权重是小伏笔、弧伏笔,还是整本书级别?
  • 当前状态是 open、hinted、paying,还是 paid_off?
  • 预期在哪个章节范围内回收?
  • 关联哪些角色和规则?

只有结构化以后,系统才能在写下一章前查出“现在最该处理什么”,也才能在写完之后更新状态。

所以炼云里有两类数据。

一种是 markdown 长文档,比如人物档案、世界观描述、风格说明。这些东西适合人读,也适合 agent 作为背景材料。

另一种是结构化表,比如伏笔状态、大纲节点、运行记录、审批状态、章节索引。这些东西适合查询、过滤、统计和自动判断。

我现在越来越觉得,做 agent 产品不要把所有东西都塞进 prompt。prompt 是很重要,但它不是数据库,也不是任务队列,更不是观测系统。

prompt 也是产品资产

还有一个我比较想保留下来的设计,是 Prompt 仓库。

在很多项目里,prompt 都是写死在代码里的一个常量。这样早期很方便,但一旦 agent 多起来,prompt 就会变成产品行为的一部分。它应该有版本,应该能回滚,应该能和某一次模型调用对应起来。

炼云现在的做法是,部分 agent 的 system prompt 会 seed 到数据库里。UI 可以看,也可以改。agent 执行时会动态加载最新版本,如果数据库里没有,就回退到代码里的 fallback。

这不是什么复杂设计,但我觉得很重要。否则每次调 prompt 都像是在空气里改配置,今天改了哪里,明天为什么变差,最后谁也说不清。

架构设计

当前 v0.1 的架构可以粗略分成几层。

flowchart TD
  UI[Web 工作台<br/>TanStack Start + React]
  API[Server Functions]
  Orchestrator[生产编排层<br/>book-producer / pg-boss]
  Agents[Agent / Harness 层<br/>topic-scout / planner / writer / guard]
  DB[(PostgreSQL<br/>books / chapters / docs / threads / runs)]
  LLM[OpenAI-compatible LLM Endpoint]

  UI --> API
  API --> Orchestrator
  Orchestrator --> Agents
  Agents --> LLM
  Agents --> DB
  Orchestrator --> DB
  API --> DB

Web 工作台

前端使用 TanStack Start 和 React。

这里我没有做成一个很炫的 landing page,也没有做成纯聊天产品,而是做成一个偏后台系统的工作台。书架、章节、文件树、伏笔、Runs、Batches、Prompt 仓库都直接暴露出来。

说实话现在 UI 还比较工程化,离真正好用的创作软件还差得远,但这个方向我觉得是对的。对这种工具来说,能不能看清状态比好不好看更重要。

数据层

数据层用 Drizzle ORM + PostgreSQL。

比较核心的表包括:

  • books:书籍主信息和生产状态。
  • chapters / chapter_revisions:章节正文和不同阶段的修订。
  • outline_nodes:卷、弧、章节拍的分层大纲。
  • plot_threads / plot_thread_events:结构化伏笔和事件流。
  • book_docs:角色、世界观、关系、时间线等活文档。
  • prompts / prompt_revisions:提示词仓库。
  • runs / llm_calls:运行追踪和模型调用记录。
  • batches / batch_jobs:批量生产任务。

这些表的核心目的不是“把数据存起来”这么简单,而是让后续 agent 可以基于当前状态继续工作,让人也能随时接管。

Agent 层

当前项目里有多个不同职责的 agent 或 harness:

  • topic-scout:选题侦察。
  • story-designer:故事设计。
  • chapter-planner:章节规划。
  • chapter-writer:章节写作。
  • consistency-guard:一致性检查。
  • quality-linter:质量检查。
  • living-doc-updater:活文档维护。
  • element-curator:元素词典维护。

我尽量避免让一个超级 agent 什么都做。因为一个 agent 什么都做,最后就会变成一个更长、更难调的 prompt。长篇生产更适合拆成多个职责明确的小 worker,每个 worker 只负责一个产物或者一个判断。

编排层

book-producer 是当前最核心的编排服务。

它负责把“写一本书”拆成多个阶段:

sequenceDiagram
  participant User as 用户
  participant UI as Web UI
  participant Producer as book-producer
  participant Agent as agents
  participant DB as PostgreSQL

  User->>UI: 输入 idea
  UI->>Producer: 创建/确认立项
  Producer->>Agent: story design / outline / docs
  Agent->>DB: 写入大纲、角色、活文档
  Producer->>DB: 创建 gate-1
  User->>UI: approve
  UI->>Producer: resumeAfterGate1
  loop 每一章
    Producer->>Agent: planner / writer / guard
    Agent->>DB: 写入章节、状态、伏笔事件
    Producer->>Agent: living doc update / summary
  end

批量任务则通过 pg-boss 入队,适合一次性跑多个选题或多个实验方向。

观测层

runChildAgent 会把每次 agent 调用包装成一棵 run 树:

  • 先写入 runs,状态为 running。
  • 调用模型。
  • 写入 llm_calls,记录 prompt、response、token、延迟和错误。
  • 校验输出 schema。
  • 更新 run 状态为 success 或 failure。

这让 /runs/$id 可以看到完整调用链。

对 agent 产品来说,观测不是锦上添花,而是基础设施。没有 trace,就很难判断到底是 prompt 问题、模型问题、输入问题,还是编排逻辑问题。

为什么开源

我觉得 AI 写作还远没有定型。

现在很多产品都在做更强的一键生成,这当然也有价值。但我更感兴趣的是另一条路:把创作过程拆开,让每个环节都可以被看见、被替换、被二次开发。

开源炼云主要是想做几个事情。

  1. 给想研究 AI 长篇创作的人一个可运行的参考实现。
  2. 让更多人看到 agent 产品不只是聊天框,也可以是生产系统。
  3. 把 prompt、数据结构、运行追踪和 UI 工作台放在一起讨论。
  4. 为后续更换 runtime kernel 做准备。

当前版本使用的是 Mastra 风格的 agent 和本地 harness services。下一步我想尝试把内核换成 Pi Agent。

不过我不太想直接推倒重写。更合理的方式应该是先抽出 runtime adapter:

Web 工作台 / 数据库 / Runs UI


runtime adapter

          ├── 当前 Mastra/harness kernel
          └── 未来 Pi Agent kernel

这样一来,炼云的 Web 工作台和数据库结构就不依赖某个具体 agent 框架。真正有价值的部分是“长篇生产系统”的抽象,而不是某个 SDK 的调用方式。

现在还不完美

v0.1 只是第一版开源,问题也很多。

比如 UI 还偏工程化,普通作者应该很难直接上手。agent kernel 也没有完全模块化,沙箱执行、权限控制、插件系统都还没有成型。prompt 和数据结构也需要更多真实长篇项目验证。

但我现在对这个项目的期待也不是马上变成一个完整产品。先把一个能跑、能看、能改的系统放出来,再慢慢围绕真实使用去迭代。

相比把它包装成一个“神奇 AI 写书神器”,我更愿意承认它现在就是一个早期的生产系统骨架。

最后

写这个项目的时候,我经常会想,这是不是又是一个做着很爽、但不知道有没有人用的东西?

可能是。

但它至少把我最近对 agent 产品的一些想法落实到了代码里:状态要显性化,prompt 要版本化,调用要可追踪,人类要能介入,runtime 要能替换。

如果 AI 真的要参与复杂创作,它不应该只是一个聊天框。它更应该是一个可以被观察、被调度、被审阅的生产系统。

炼云 v0.1 先把这个方向开源出来。后面我会继续往 runtime adapter、沙箱执行、插件化 prompt/agent packs,以及 Pi Agent kernel 的方向推进。