news 2026/5/1 19:23:25

AI辅助网文创作理论研究笔记(十一):文档库——生成产出的版本管理与组织

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
AI辅助网文创作理论研究笔记(十一):文档库——生成产出的版本管理与组织

笔记11:文档库——生成产出的版本管理与组织

一、问题的发现

当前系统的覆盖式存储

审视现有代码,L1~L4 各层 API 的存储逻辑如下:

l1.py: outputs/l1_vision.json ← POST generate 覆盖 l2.py: outputs/l2_outline.json ← SSE stream 完成后覆盖 l3.py: outputs/l3_chapter_plan.json ← POST generate 覆盖 l4.py: outputs/l4_text.json + .txt ← SSE stream 完成后覆盖

每次重新生成,旧文档直接消失。用户对第一次产出不满意想再试一次,却发现前一次的版本已经不可恢复。这在网文创作中尤其致命——很多时候"第一版的某个点子"反而值得保留,或者需要对比三个版本挑最好的一个。

需要的功能

  1. 每份产出都存档:不论 L1 愿景、L2 大纲、L3 章纲、L4 正文,每次生成都新增一份,旧版本不删除
  2. 可浏览的文档栏:像 VS Code 文件浏览器一样,一个可折叠的侧边栏,展示文档树
  3. 用户可自由整理:创建目录,移动、重命名、删除文档
  4. 外部文件导入:用户可以塞自己的 .md/.json 文件进去,后续可从文档库里导入
  5. 随机编号或 AI 命名:不必用户每次手动起名,系统自动生成可辨识的标题

二、概念命名

暂定名称:文档库 (Document Library)

在 ACENTS.md 目录结构中的位置:

data/projects/{id}/ ├── project.json ├── worldbook.json ├── outputs/ ← 当前固定文件名存储(废弃) ├── library/ ← 新增:文档库 │ ├── manifest.json ← 元数据索引 │ └── files/ ← 实际文件(uid 命名) │ ├── a1b2c3d4.json ← L1 愿景 v1 │ ├── e5f6g7h8.json ← L1 愿景 v2 │ ├── i9j0k1l2.json ← L2 大纲 │ └── ... └── logs/

三、数据模型

3.1 文档条目 (DocEntry)

每份文档在 manifest.json 中存一条记录:

{ "uid": "a1b2c3d4", "name": "废土倒爷 v1 — 双界贸易 + 丧尸末世", "layer": "l1", "format": "json", "source": "generate", // generate | import | manual "parent_uid": null, // 从哪份文档衍生(如 L2 大纲衍生自 L1 愿景) "directory": "/", // 用户创建的目录路径,/ 表示根 "tags": ["末世", "双界贸易"], "created_at": "2026-04-30T10:30:00", "word_count": 2500, "status": "active" // active | archived }

字段说明

字段类型说明
uidstr(8)8位随机 hex,作为文件名
namestr显示名称,系统自动生成,用户可改
layerstrl1/l2/l3/l4/imported,标识来源层
formatstrjson/md/txt
sourcestrgenerate(系统生成) / import(用户导入) / manual(手动创建)
parent_uidstr?链路追溯:这份 L2 大纲是从哪个 L1 愿景生成的
directorystr用户创建的目录路径
tagslist用户或 AI 打的标签
created_atstrISO 时间戳
word_countint字数统计
statusstractive / archived(归档后不在主视图中显示)

3.2 文档库清单 (LibraryManifest)

{ "project_id": "abc12345", "directories": ["/", "/备份", "/L1草稿", "/L2方案/剧情流", "/L2方案/人物流"], "documents": [ ...DocEntry... ], "updated_at": "2026-04-30T10:30:00" }

3.3 自动命名策略

系统生成文档时,自动按规则命名。命名不要纯随机(用户看到的是一堆乱码),也不应该全靠用户手动输入(增加摩擦)。

命名公式{层级前缀} — {AI 摘要短语}

前缀示例
L1 愿景L1 愿景 — 废土双界倒爷 + 修真物资流
L2 大纲L2 大纲 — 拍卖会打脸 + 势力初探
L3 章纲L3 章纲 — 第12章 拍卖场风波
L4 正文L4 正文 — 第12章 拍卖场风波 (3200字)
导入导入 — 原文件名

AI 摘要由 LLM 在生成内容时同步产生。以 L1 为例,VisionDocument增加一个可选字段summary_phrase: str = "",生成时让 LLM 用 10-15 字概括这份愿景。摘要短语放在name字段,完整内容放library/files/{uid}.json

如果不想每次都调 LLM 生成摘要,可以退化为:L1 愿景 — 2026-04-30 10:30(时间戳命名)。用户在界面里可以随时重命名。


四、文档溯源链 (Provenance)

这是文档库区别于普通文件夹管理器的关键特性。

L1 愿景 (uid=aaa) ←── L1 愿景 (uid=bbb) [两个并行的 L1 尝试] │ ├── L2 大纲 (uid=ccc, parent_uid=aaa) ← 基于 aaa 生成 │ │ │ ├── L3 章纲 (uid=ddd, parent_uid=ccc) │ │ │ │ │ └── L4 正文 (uid=eee, parent_uid=ddd) │ │ │ └── L3 章纲 (uid=fff, parent_uid=ccc) [同一个大纲,两种章纲方案] │ └── L2 大纲 (uid=ggg, parent_uid=aaa) [同一个愿景,不同大纲方案]

parent_uid记录的是"生成此项时,使用的是哪个文档作为输入"。这个链路有两个作用:

  1. 追溯:L4 正文有问题,顺着链找到 L3 章纲是哪份,再找到 L2 大纲是哪份,找到决策节点
  2. 回退选择:L2 讨论完毕、L3 已经开始做了,发现不如之前的方案,可以沿着链回到 L2 的分叉点重新走

实现方式

每次生成 API(L2/L3/L4)接受一个可选参数source_doc_uid: str,指定"以哪份文档为输入源"。如果不传,默认取该层最新的一份(兼容当前的单文件覆盖行为)。生成后新文档的parent_uid自动设为source_doc_uid

# L2 生成时 POST /api/projects/{id}/l2/stream?source_doc_uid=aaa # 新文档 uid=ccc, parent_uid=aaa

五、与现有生成 API 的集成

5.1 改造点

当前 API 的存储模式:

l1/generate ──→ 覆盖 outputs/l1_vision.json l2/stream ──→ 完成后覆盖 outputs/l2_outline.json l3/generate ──→ 覆盖 outputs/l3_chapter_plan.json l4/stream ──→ 完成后覆盖 outputs/l4_text.json + .txt

改造后每个 API 在产出时调用library.add_document(entry, content)存入文档库。同时保留一份"当前活动文档"的指针(兼容前端各处按固定路径读取的逻辑)。

活动文档指针outputs/current_l1.json,current_l2.json等,内容为{"uid": "a1b2c3d4"},指向当前选中的文档。前端页面默认加载当前活动文档。

前端增加一个文档选择器(dropdown 或从文档栏点击)来切换当前活动文档。

5.2 API 新增端点

文档库管理(CRUD) GET /api/projects/{id}/library 列出文档树 GET /api/projects/{id}/library/{uid} 获取文档内容 POST /api/projects/{id}/library 新增文档(导入/手动) PUT /api/projects/{id}/library/{uid} 更新文档元数据(重命名/移动/标签) DELETE /api/projects/{id}/library/{uid} 删除文档 PUT /api/projects/{id}/library/{uid}/archive 归档/取消归档 活跃文档 GET /api/projects/{id}/library/active/{layer} 获取某层当前活跃文档 PUT /api/projects/{id}/library/active/{layer} 设置某层活跃文档 (body: {uid})

六、前端 UI 设计

6.1 文档栏布局

参考 VS Code 的侧边栏设计:

┌──────────────────────────────────────────────────────────────┐ │ [📁] [🔍] [📊] 页面内容区 │ │ ┌──────────┐ ┌──────────────────────────────────────────────┐ │ │ 文档库 │ │ │ │ │ │ │ │ │ │ 📂 / │ │ 当前页面主内容区域 │ │ │ 📄 L1 — │ │ │ │ │ 📂 L1草稿 │ │ (L1/L2/L3/L4/世界书/设置) │ │ │ 📄 L1 — │ │ │ │ │ 📄 L1 — │ │ │ │ │ 📂 L2方案│ │ │ │ │ 📂 剧情流│ │ │ │ │ 📄 L2 —│ │ │ │ │ 📄 L2 —│ │ │ │ │ 📂 人物流│ │ │ │ │ 📂 备份 │ │ │ │ │ 📄 导入 —│ │ │ │ │ │ │ │ │ │ [+新建目录]│ │ │ │ │ [+导入文件]│ │ │ │ └──────────┘ └──────────────────────────────────────────────┘ │ ▲ 可拖拽边缘调整宽度 △ 点击标签折叠/展开侧边栏 │ └──────────────────────────────────────────────────────────────┘

6.2 侧边栏状态

侧边栏有三种状态:

  • 折叠状态:只显示一个竖条图标(类似 IDE 的 Activity Bar),鼠标悬停或点击展开
  • 展开状态:显示完整目录树,宽度可拖拽调整(默认 280px)
  • 弹窗状态:在小屏幕上以浮层形式出现

默认状态:折叠。用户需要时点击展开。

6.3 目录树交互

  • 展开/折叠:点击目录名展开或折叠子节点
  • 选中文档:点击文档高亮,右侧显示预览(标题、元数据、前 500 字内容、溯源链)
  • 右键菜单:重命名、移动到目录、复制 UID、导出、归档、删除
  • 拖拽:文档可拖拽到不同目录下
  • 双击文档:如果是对应层的文档,在当前页面加载该文档作为输入(跳转到对应层的页面并将该文档设为活跃文档)

6.4 文档详情预览

点击文档后在右侧区域展示:

┌─────────────────────────────────────────────┐ │ 📄 L2 大纲 — 拍卖会打脸 + 势力初探 │ │ │ │ 层级: L2 格式: JSON 字数: 3500 │ │ 创建: 2026-04-30 10:30 │ │ 标签: [末世] [打脸] [拍卖会] │ │ 源文档: ← L1 愿景 — 废土双界倒爷 (uid=aaa) │ │ 衍生文档: → L3 章纲 — 第12章 (uid=ddd) │ │ → L3 章纲 — 第12章 备选 (uid=fff) │ │ │ │ 内容预览: │ │ ┌─────────────────────────────────────────┐ │ │ │ { "sequences": [{ "name": "拍卖会进场", │ │ │ │ "functions": ["铺垫", "阻碍"], ... │ │ │ └─────────────────────────────────────────┘ │ │ │ │ [在L2页面打开] [设为活跃] [导出] [归档] │ └─────────────────────────────────────────────┘

6.5 文档图标

不同类型文档用不同图标区分:

图标类型
💡L1 愿景文档
🏗️L2 精修大纲
📝L3 章纲细纲
📖L4 正文文本
📥用户导入文档
📂目录

七、外部文件导入

7.1 导入场景

  • 用户有一份自己写的设定 .md,想纳入文档库统一管理
  • 用户从别处拿了一份大纲草稿,想导入后作为 L2 的参考或起点
  • 用户在别处写了片段,想拖进来供 L4 参考

7.2 导入方式

  1. 拖拽导入:将 .md/.json/.txt 文件拖入文档栏区域
  2. 按钮导入:点击文档栏底部的[+ 导入文件],弹出文件选择对话框
  3. 剪贴板导入:粘贴文本内容,输入文档名,存入文档库

7.3 导入后的处理

  • 自动识别格式(.md/.json/.txt)
  • source = "import",layer = "imported"
  • 文件名为导入文件名
  • 自动提取 word_count
  • 自动放在当前浏览的目录下(默认根目录)

八、归档机制

文档越积越多后会混乱。提供归档功能:

  • 归档 = 文档status改为archived,不出现在目录树的默认视图中
  • 归档的文档不删除,可随时恢复
  • 目录树下增加一个📦 已归档节点,点击可展开查看已归档文档

九、实现路径

9.1 后端:backend/services/library_manager.py

一个LibraryManager类,封装 manifest 的读写和文件操作:

class LibraryManager: def __init__(self, project_path: Path): self.library_path = project_path / "library" self.manifest_path = self.library_path / "manifest.json" self.files_path = self.library_path / "files" self.manifest: LibraryManifest def add_document(self, entry: DocEntry, content: str | dict) -> str: """添加文档,返回 uid""" def get_document(self, uid: str) -> tuple[DocEntry, dict]: """获取文档元数据和内容""" def update_entry(self, uid: str, **kwargs) -> None: """更新元数据(重命名、移动、标签等)""" def delete_document(self, uid: str) -> None: """删除文档及其文件""" def get_tree(self, include_archived=False) -> dict: """返回文档树结构(供前端渲染目录树)""" def set_active(self, layer: str, uid: str) -> None: """设置某层的活跃文档""" def get_active(self, layer: str) -> str | None: """获取某层的活跃文档 uid""" def list_by_layer(self, layer: str) -> list[DocEntry]: """按层级列出文档"""

9.2 改造现有 API

L1~L4 的 generate 方法在产出时改为调用library.add_document()

# l1.py 改造后 vision = generator.generate(input_data) summary = generator.summarize(vision) # 调用 LLM 生成 10-15 字摘要 entry = DocEntry( uid=generate_uid(), name=f"L1 愿景 — {summary}", layer="l1", source="generate", ... ) library = LibraryManager(project.project_path) uid = library.add_document(entry, vision.model_dump()) library.set_active("l1", uid)

9.3 前端改动

  1. 新增DocumentSidebar.vue组件:目录树渲染、展开/折叠、右键菜单、拖拽
  2. App.vue增加侧边栏插槽:左侧增加可折叠面板
  3. 各页面增加"当前文档"指示器:显示当前活跃文档名,点击可打开文档选择下拉菜单或跳转文档库
  4. Dashboard 增加文档库入口:项目卡片增加"文档"链接

9.4 迁移策略

旧数据(outputs/l1_vision.json等)在第一次加载文档库时自动导入:

  • 如果library/目录不存在且outputs/下有文件,自动迁移
  • 为每个旧文件生成 DocEntry 并复制到library/files/
  • 迁移完成后在原outputs/文件旁写一个.migrated标记文件

十、双轨存储:章节管理器与文档库的分工

10.1 理论基础:工业流水线中的两类数据

回顾笔记5中提出的"数据海"概念——原始小说库作为输入,经过三道过滤最终进入向量数据库。这是一个从数据到知识的萃取流程

文档库与章节管理器的分工,本质上也是同一个逻辑在系统内部的复现:

外部数据海 (笔记5) 400G 网文 txt → 三道过滤 → 向量数据库 ↓ 供 Agent 检索 系统内部数据流 (本章) Agent 产出的正文 │ ├──→ 章节管理器(结构化、可查询、Agent 所见) │ ↓ │ 供 RAG-历史回顾检索 │ 供世界书管理员提取状态变化 │ └──→ 文档库(自由组织、用户所见) ↓ 用户浏览、对比、导出的工作空间

两条线在"结构化程度"和"使用者面向"上互补,不存在谁取代谁的问题。

10.2 章节管理器:为 Agent 设计

章节管理器关心的问题是:

  • "第 12 章写到哪了?下章开头需要衔接什么?"
  • "主角在 12-45 章之间的修为变化轨迹是什么?"
  • "第 45 章埋的伏笔在第 78 章回收了吗?"

这些都是结构化查询。章节管理器必须维护:

  • 章节编号的严格顺序
  • 每章的状态标记(草稿/定稿/需修改)
  • 与 RAG 向量索引的同步(每完成一章即增量索引)
  • 与世界书的联动(章节完成后世界书管理员自动提取状态变化)

数据格式天然是结构化的:

chapters/ ├── manifest.json ← 章节索引:编号、标题、状态、字数、关联人物 ├── ch001.json ← 正文 + 元数据(视角、节奏标注、关联伏笔) ├── ch002.json └── ...

10.3 文档库:为用户设计

文档库关心的问题是:

  • "这三个版本的 L2 大纲哪个最好?放一起对比看看。"
  • "上面写废了四个版本,我把它们归档到废稿文件夹。"
  • "朋友发了我一份他写的人设,我拖进来参考。"

这些都是自由浏览型操作。文档库不关心顺序、不关心章节间的因果链——它就是一个文件管理器,只是加了溯源链和自动入库的便利。

10.4 两者如何交互

两者不是嵌套关系,而是平行关系,有点对点传递

章节管理器 ──(用户触发"导出到文档库")──→ 文档库 ↑ 用户手动导入 ←──

用户在章节管理器中看到 L4 生成的正文,觉得"这一章写得好",点一下"导出到文档库",这章的副本就出现在文档库里。文档库里的这份副本从此和章节管理器断开联系——它是一个不可变的快照(除非用户手动编辑)。

反过来,用户也可以从文档库把一份导入的大纲"设为 L2 活跃文档",流水线会用这份大纲来生成——这时候文档库的角色是"输入端的选择器"。


十一、已决问题

11.1 AI 摘要命名:可选轻量 LLM


10.2 AI 摘要命名:可选轻量 LLM

决策:不强制要求 LLM。提供三种命名方式,用户可选择。

方式效果成本适用场景
时间戳L1 愿景 — 20260430_1030默认,不需要 LLM
轻量 LLML1 愿景 — 废土双界倒爷一次小模型调用用户配置了 LLM 且开启
手动命名用户输入任意名称零(人力)用户双击即改,或生成时弹输入框

轻量 LLM 策略

  • 使用一个极短 prompt(~50 token)调 LLM,只做摘要不生成其他内容
  • 如果用户配置了 embedding 模型也可考虑用向量聚类关键词,不调 LLM
  • 前端提供一个开关:"自动命名 (需 LLM)"

11.2 草稿机制

决策:支持存草稿。未完成的产出也入库。

DocEntry 增加两个字段:

{ "status": "draft", // draft | completed "checkpoint": { // 断点续传信息 "layer": "l2", "current_round": 2, "last_expert": "editor", "meeting_history": [...] } }

草稿的生命周期

用户启动 L2 会议 │ ├── 第一轮发言完成 → 自动存草稿 ├── 用户关闭页面 → 草稿保留 ├── 下次打开 → 检测到有草稿,提示用户: │ "检测到未完成的 L2 会议(进度:第2轮/3轮,最后发言:网络编辑)。 │ [继续上次] [重新开始] [查看草稿]" │ └── 会议完成 → status 变为 completed, checkpoint 清空

各层存草稿的时机

何时存草稿断点信息
L1每个聊天气泡发送后(已有的 auto-save)消息历史
L2每轮专家发言完成后当前轮次、最后发言人、会议历史
L3用户每次修改场景标签后已选择的标签组合、已填写的字段
L4每生成一个场景后(SSE 流已产出部分场景)已生成的场景索引、已生成文本

草稿与已完成文档的区分

  • 草稿在目录树中显示为灰色/虚线图标 📝
  • 草稿不参与"活跃文档"指针(只有completed的文档才能设为活跃)
  • 用户可以手动将草稿标记为完成

十二、尚待讨论的问题

  1. 文档数量上限:不设硬限制,依赖归档功能保持整洁。

  2. 全文搜索:文档数量增长后,通过关键词搜索文档内容。可考虑在 RAG 系统建立时顺带索引文档库内容,统一检索入口。

  3. 多项目间的文档共享:暂不做,每个项目独立。后续若需要,可在文档库 API 加一个POST /library/copy跨项目复制。

  4. 版本历史:文档库本身不内置版本管理。如果用户的某份文档被反复修改需要版本追溯,可依赖:

    • 章节管理器侧保留的中间版本
    • 用户自己手动"复制一份"再修改(文档库的目录结构天然支持)
    • 后期可考虑接入世界书的 commit/revert 机制
  5. 文档库数据量上限:如果用户疯狂导入几百 MB 的文件怎么办?建议在导入时检查文件大小(单文件上限 10MB),并在 manifest 中记录总大小,前端显示用量。


创建时间:2026-04-30 状态:十(双轨存储)、十一(已决)已讨论;十二节继续讨论

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/1 19:20:26

终极LaTeX公式转换指南:3秒将网页公式完美粘贴到Word

终极LaTeX公式转换指南:3秒将网页公式完美粘贴到Word 【免费下载链接】LaTeX2Word-Equation Copy LaTeX Equations as Word Equations, a Chrome Extension 项目地址: https://gitcode.com/gh_mirrors/la/LaTeX2Word-Equation 还在为学术论文写作时公式复制格…

作者头像 李华
网站建设 2026/5/1 19:10:58

保姆级教程:在Ubuntu 22.04上快速搭建一个DDS通信Demo(基于Fast DDS)

在Ubuntu 22.04上快速搭建Fast DDS通信Demo:从零到实时数据流 如果你正在探索现代分布式系统的通信方案,DDS(数据分发服务)绝对值得深入了解。作为一个专为实时系统设计的中间件协议,DDS的发布/订阅模型和丰富的QoS策略…

作者头像 李华