重构方案 · 评审稿
一个以「构建世界」为终极目标的图文小说创作平台。本方案基于 22 项确认决策重写, 不沿用旧版实现方式,只借鉴其功能范围。
这不是「写一本小说」的工具,而是「构建一个世界」的底座——起步从一个故事开始, 结构上预留扩展成多本、跨代的宇宙。
| 维度 | 选择 | 理由 |
|---|---|---|
| 技术栈 | 沿用现有:Python + 原生 JS + SQLite | 最稳,改动集中在你已知的痛点上 |
| 部署形态 | 公网 · 单账号 | 随时随地上;只你一人用,不做多账号体系 |
| 开发环境 | Windows 10 开发 → Ubuntu / Docker 部署 | serv00 仅作备选,不为共享主机妥协架构 |
| 数据主存 | 数据库为唯一真相,文件仅作导出产物 | 根除「文件与库不同步」这一整类 bug |
功能参考源码,实现方式按本次讨论。 源码只用来回答「你以前做过哪些功能」以防遗漏;目录结构、命名、数据模型、 接口、UI 组织全部按本方案重做。旧版问题太多,不作为设计依据。
选择公网部署后,必须上 TLS。公网 + 单账号 + 明文密码是不可接受的组合。 此项不随分期推迟,属第 0 期地基的一部分。
本方案的全部输入。每一条都来自你的确认,不含我的臆测。
顶层是「世界」,不是「小说」。角色与场景挂在世界下而非单本下——这样同一个角色 才能在你的多本小说里出场。
World 世界(宇宙)
│
├─ 共享设定 (跨小说通用)
│ ├─ Character 角色 ────┐
│ ├─ Scene 场景 ────┼──→ 可被配图点引用(多对多)
│ └─ 世界观 / 力量体系 / 地理 │
│ │
│ 两者均带 阶段版本(随时间推进)
│
└─ Novel 小说 (世界中的一个故事)
└─ Volume 卷
└─ Chapter 章
└─ SceneSegment 场景段
└─ IllustrationPoint 配图点
└─ Image 图片 (可多版本,含候选)
Revision 修订 (所有正文变更留痕,可回滚)
起步兼容:初期 1 个世界 + 1 本小说,与单本创作体验无差别; 后续新增小说时自动继承共享设定。
四区是「试验→创作→定稿」的三段生命周期加一个隔离区;第五区是回收站—— 让删除变成可恢复的。
数据根目录/ │ ├── sandbox/ 测试区 AI 试写、生图试验、导入预览 ├── workspace/ 工作区 正在写的小说、草稿、未完成配图 ├── production/ 正式储存 已定稿内容,阅读页「正式」模式读这里 ├── backup/ 备份区 重大改动前的快照 └── trash/ 回收站 可恢复;1 个月后永久删除
| 动作 | 方向 | 确认方式 |
|---|---|---|
| 提升 | 测试区 → 工作区 | 手动点「采纳」 |
| 定稿 | 工作区 → 正式储存 | 手动点「定稿」,并自动触发备份 |
| 快照 | 任一区 → 备份区 | 重大改动前自动;只留最新 1 份 |
| 清理 | 备份区 → 回收站 | 超过 2 周自动转移 |
| 删除 | 任意 → 回收站 | 手动删除同样进回收站 |
| 永久删除 | 回收站 → 消失 | 满 1 个月未被动过 |
物理目录带来三个好处:备份可直接拷走、正式区与工作区物理隔离(误删不波及)、 测试脏数据进不了正式库。这直接根除旧版「测试小说混进正式列表」的问题。
这是本项目区别于其他写作工具的关键。要解决的问题只有一个:同一个人, 在不同章节的图里得长得像同一个人。
角色卡不是每张图都重新生成。读取剧情时生成一次、存档,之后复用。 当角色进入新形态,再手动(或自动)生成一张新阶段的卡,不满意可以反复重生, 满意才存。
角色「沈墨渊」 ├─ 阶段 1「筑基期」 第 1 章起 青年修士,黑发,深色袍 ├─ 阶段 2「机械飞升」 第 30 章起 一旦进入,后续全部延续此形态 └─ 阶段 3「……」 第 80 章起
给定「第 N 章」,系统应能唯一确定角色当时的形态——不靠你手选。
| 锚类型 | 机制 | 特点 |
|---|---|---|
| 文字锚 | 角色卡语义 → 编译器 → 提示词 | 通用,不依赖上游;已实测可行 |
| 图片锚 | 角色定妆图 / 三视图 → 参考图输入 | 视觉最准,需上游支持 |
不同上游的生图提示词格式不同——NovelAI 系用标签式,其他用自然语言,中英文支持 也不一致。所以加一层编译器:角色卡只存语义,不存死提示词, 由编译器按目标模型渲染成对应格式。换模型时角色卡不用改。
【语义层】模型无关、语言无关
角色:阿芷 / 阶段2 / 桃花眼、眼尾绯红
场景:荒山洞府 / 火光
│
▼ 按目标模型适配
【渲染层】模型专属
NAI 系 → 标签串 + 英文 + 权重语法
自然语言 → 中文描述句
其他 → 各连接自定义模板
每期以功能块为单位推进:做完、测完、记录完,才开下一块。 每期结束都是可用状态——不写完也能用。
| 功能块 | 内容 |
|---|---|
| 0.1 项目骨架 | 目录结构、配置、启动入口、依赖锁定 |
| 0.2 存储五区 | 五个物理目录自动创建与读写 |
| 0.3 数据模型 | 世界→小说→卷→章→场景段→配图点→图 |
| 0.4 鉴权 | 单账号登录、会话、CSRF、限流 |
| 0.5 部署脚本 | Ubuntu / Docker 一键部署 + TLS |
| 0.6 规范与总纲 | 命名/目录/接口/提交/测试规范;进度总纲模板 |
| 功能块 | 内容 |
|---|---|
| 1.1 卷章树 | 小说/卷/章 增删改、归档、软删除 |
| 1.2 正文编辑 | 编辑器 + 自动保存(自动保存 ≠ 正式稿) |
| 1.3 修订历史 | 版本列表、差异对比、回滚 |
| 1.4 阅读页 | 图文混排;预览 / 正式 双模式 |
| 1.5 四区流转 | 提升与定稿,均手动确认 |
| 1.6 备份与回收站 | 快照、超期转移、永久删除 |
| 功能块 | 内容 |
|---|---|
| 2.0 需求确认 | 11 项决定已定;复查发现 9 处结构缺口已补齐 |
| 2.1 补结构 | v2 迁移:新增 4 表 + 18 列;线上数据一条不丢 |
| 2.2 角色卡 / 场景卡 | 五字段 + 别名 + 自定义;默认归属不同(角色世界共享 / 场景本书专用) |
| 2.3 阶段状态系统 | 底 + 覆盖;只用章号;只填变化;重叠提示不拦 |
| 2.4 设定库界面 | 建卡 / 改卡 / 阶段时间轴 / 按章预览 |
| 2.5 引用索引 | 双向可查:看某章知涉及谁;改设定知影响哪些章 |
| 2.6 实体关系 | 角色↔角色 / 角色↔地点;含方向与时期 |
| 2.7 设定网界面 | 关系图 + 卡片关系 + 正文提及 + 本章涉及 |
| 执行顺序 | 内容 | 状态 |
|---|---|---|
| 地基 | v3 迁移(职位库 / 预设分条 / 流水线骨架 / 检测报告) | 已上线 |
| 后端 | 3.1 配图点 | 3.2 定妆图 | 3.3 提示词编译器 | 3.4 生图 | 已上线 |
| ① 流水线页 | 三个独立 tab:上游与模型 / 预设 / 职位与编排;范围切换(全局默认 / 本书覆盖) | 已上线 |
| ② 配图面板 | 生图 + 逐张确认(另提供自动确认出全章);候选审核(历史对比 / 采用 / 拒绝 / 回收站) | 已上线 |
| ③ 定妆图界面 | 上传本地图 或 从生成结果指定一张;卡面显示最新、可查历史 | 已上线 |
| ④ 参考图引导 | 双锚(文字锚 + 图片锚):任意图自动处理成 1024×1536 黑底 PNG(处理要告知),生图时定妆图当参考图 | 已上线 |
| 功能块 | 内容 |
|---|---|
| 4.1 连接管理 | 可扩展多上游;显式测试与具体失败原因 |
| 4.2 职责绑定 | 写作/提示词/生图;全局默认 + 单本覆盖 + 记忆上次 |
| 4.3 任务队列 | 持久化;失败落库;可重试;禁止静默回退 |
| 4.4 创意工作台 | 对话式创作,保留并打磨 |
| 4.5 导入导出 | Markdown 导入;完整包导出(含正文+配图) |
| 功能块 | 内容 |
|---|---|
| 5.1 安全加固 | TLS、密钥管理、日志脱敏 |
| 5.2 平台适配 | Linux / Docker 验证;serv00 备选适配 |
| 5.3 端到端验收 | 双小说完整走查 |
| 5.4 文档 | 用户手册、部署文档 |
实测旧版时发现的九个根因问题,逐条对应新系统中的处理方式。
对旧版「模型静默失败」的根因定位。此诊断仅用于理解旧问题,新系统按第 07 节对策实现。
提交生图任务后,任务状态一直是「排队中」——不报错、不推进、不提示。
连接健康状态显示为 failed。
worker 主循环捕获了执行器的异常,但只把任务 id 加进一个进程内存集合, 然后静默把状态改回排队——不写错误码、不记日志、不转失败状态。 该集合被用于排除认领,于是在本次进程生命周期内,这个任务永远不会再被处理。
# 简化示意
try:
self.executor(task, self)
except Exception:
self._failed_tasks.add(task["id"]) # 仅内存,重启即丢
self._safe_abandon(task) # 静默改回 queued
| 问题 | 表现 |
|---|---|
| 任务永久卡死 | 状态是「排队」,实际不再被认领 |
| 失败不可见 | 没有任何错误信息可查 |
| 不能重试 | 重试接口只接受失败态任务,而卡住的不算失败 |
| 重启后复发 | 内存集合清空 → 重新认领 → 再失败一次 |
失败必须落库(错误码 + 可读错误信息 + 状态转失败);失败任务可重试; 禁止静默回退——失败就是失败,不假装回队。这条写进了第 0 期地基与第 4 期任务队列的验收标准。