故事初审与编辑工作台设计
调研日期:2026-10-31。状态:工具设计,本文中的命令、目录与数据结构均为提案,尚未实现。
总路线见 docs/plan/story-rebuild-plan.md;进入编辑制作后的流程见 docs/plan/story-editorial-design.md。
1. 工具要替站长省掉什么
工具应当把“我得把全站读一遍”拆成几个有终点的动作:AI 提供可验证的类型与内容线索,站长迅速确认候选、整组看连载、只在必要时调查来源,随后把有限作品送到编辑台。
首个可用版本不需要模型:导入 → 看全文 → 标记 → 保存 → 筛选 → 导出 就是 M1。AI 在已有人工界面上补建议,不能成为唯一阅读入口。
核心约束:不修改来源博客;不自动发布;不自动给作者发消息;人工结论有版本且不会被模型覆盖。故障、拒答、没读完与“不是故事”分别记账。
2. 三层实体,避免把帖子当作品
2.1 来源、作品与出版版本
SourceDocument ── 1:N ── SourceRevision
│
多对多的段落/区间映射
│
Work ── 1:N ── Chapter ── 1:N ── ChapterRevision
│ │
└─────────── Edition/Release ─────────┘
- 来源文档:一条博客、一个旧故事文件、一份作者直接提供的稿件;身份稳定。
- 来源修订:特定时间读到的原文、格式、元数据与哈希;内容不原地覆盖。
- 作品:一部小说、一个真正的短篇集或互动故事,使用独立
workId。 - 章节:作品的阅读单元,显式
chapterId与顺序;短篇也可以只有一章。 - 章节修订:经过确认的编辑文本,可以对应多条来源,也可以只引用某来源的部分区间。
- 出版版本:锁定章节修订、署名、简介、布局、素材、公开范围与签收的可发布集合。
一篇博客可含两部短篇,一章可以由多个博客合并,作者可直接提交新定稿。数据模型必须允许这些情况;不能要求每一章都有且仅有一个博客 ID。
2.2 最小数据表与主要字段
初版使用独立工作台 SQLite,配合内容文件目录;不向业务库一次性增加十余张表。以下为逻辑表,实施时可按关系约束合并,但不能丢失人工记录与版本。
| 实体 | 最少保存的内容 |
|---|---|
source_documents |
sourceId、来源类型、博客 ID/规范相对路径、首次导入、当前修订、当前可用/软删状态 |
source_revisions |
原文引用、UTF-8 原文哈希、元数据哈希、标题、来源账号 ID、可见性、格式、更新时间快照、净文本与 source map、提取器版本 |
analysis_jobs |
修订、任务类型、分段范围、模型/服务商/提示/schema 版本、幂等键、状态、尝试次数、上游任务 ID、费用与错误 |
analysis_results |
类型建议、证据段落、读过的范围、长文聚合、相似/章序候选;永远标“机器建议” |
review_events |
人工操作者、动作前后值、理由、适用修订、时间、关联证据;追加记录,不覆写历史 |
review_current |
当前人工结论与版本号;从事件更新,支持并发版本检查 |
author_profiles |
作品署名、来源账号关联、别名候选/已确认、确认依据;联系人资料只留私有部分 |
works / chapters |
稳定 ID、作品关系、章序、状态;章序唯一且可人工调整 |
chapter_sources |
章节修订与来源修订的多对多映射、范围与编辑差异 |
permissions |
作品/版本/素材、用途、范围、许可凭据引用、确认人、失效或撤回事件 |
editorial_packets |
摘要、章纲、解释、作者意见、待办、视觉简报及各字段确认状态 |
assets / releases |
素材来源与许可、配图位置、版本、发布清单、校验结果、上下架记录 |
只有进入相应阶段才需要相应表:M1 先有来源、修订、复审、作品和导出;上线前再补编辑、素材与出版记录。不要因为远期字段多而先做通用 CMS 表单引擎。
2.3 存在哪里、谁能访问
建议工作数据放 instance/story-workbench/,其中 workbench.db 保存索引和状态,sources/ 保存必要原文快照,drafts/ 与 permissions/ 保存编辑稿和凭据。这是持久工作数据,不能放会清理的临时目录。
该目录位于现有被 Git 忽略的 instance/ 内。创建前仍通过 git check-ignore 与 git ls-files 确认未跟踪/已忽略;不把正文、密钥、私信或人工评语写进仓库文档、测试快照和构建日志。一次性调研、测试日志、截图继续放系统临时目录。
初版作为现有 Next 应用的 owner 工作台;可考虑 /admin/story 与 /api/admin/story/*,每个页面和接口都显式校验 owner。现有后台父布局允许 core,不能借父布局当 owner 校验。默认不开启,不出现在公共导航、搜索或 sitemap;关闭开关也不能留下能读取原文的 API。
后台长任务由手动启动的本地 CLI worker 运行,Web 只入队和显示结果,不把几小时任务挂在一个 HTTP 请求中,也不新增常驻微服务。接口与 CLI 共用状态逻辑。若未来迁到生产,需要先明确谁备份工作台和谁能访问,不能顺手随站点打包公开。
3. 分类词表与人工结论
3.1 先问“是什么”,再问“从哪来”
| 维度 | 建议取值 | 说明 |
|---|---|---|
| 形式 | 小说、互动叙事、诗歌、剧本、散文/随笔、评论/介绍、非文学、混合、无法判断 | 支持多选;诗歌/剧本不自动丢弃,站长可决定是否扩展故事范围 |
| 故事候选 | 是、可能、否、未评估 | 小说片段、设定和章纲也可为“可能” |
| 单元 | 完整短篇、长篇章节、片段、世界观/设定、合集、多篇混合、未知 | 与完结状态分开 |
| 来源归属 | 作者自述原创、转载、翻译、改编/同人、混合、未知 | 原创声明不等于已核验;原作者、译者与发布者分开 |
| 文字 AI 使用 | 作者/站长确认未使用、辅助、主要生成、混合、未披露、待核实 | 不把“未披露”显示成“人类原创” |
| 连载状态 | 完结、连载、暂停、片段、未知 | 由作品而不是单帖决定 |
| 编辑处置 | 候选、暂缓、需要询问、不选登、进入制作 | 不选登不表示文章质量差或需要删博客 |
| 选编层级 | 主推候选、精选候选、普通收录候选、资料保留 | 只由人工确定;内部层级不做公开评分 |
AI 输出只能写建议与证据。公开的来源/AI 标签来自独立人工字段;模型即使说“99% 是 AI”,也不能填入确认字段。
3.2 什么算证据
证据强度依次包括:作者对该作品的明确说明、站长有依据的逐篇记录、来源页/许可文本、作品附注。文风、重复句式、模型识别出熟悉情节都只是待核对线索。
站长提供“Life 的小说是 AI 生成”可登记为站长陈述、范围为其小说、待核对作品边界。不能改写为该账号所有文章都由 AI 写成。旧 ai_assisted: true 则是旧版标记,保留原值和来源,不能无证据升级成“全文 AI 生成”。
转载调查先看文章内原出处、作者自述,再做必要的逐条核实。默认不把站内原文发送到搜索引擎查重;没有线索时保留未知。相似哈希和网络命中都不自动等于转载定论。
4. 数据导入与文本提取
4.1 M0 导入步骤
- 显式选择数据库或 JSONL 输入,建立只读连接/一致快照;不默认寻找生产凭据。
- 读取博客、正文及必要作者/栏目元数据,过滤软删,记录总量、各状态与格式。
- 全文逐条建立
sourceId与修订;不要用标题做主键。 - 导入旧故事:保存相对路径、文件头、父级元数据、内容哈希和原 URL;Cattca 单独标格式。
- 导入直接投稿:只收站长明确选入的稿件文件。不要扫描整段聊天记录或把私信上下文送给模型。
- 生成对账:新增、变更、保持、已软删、缺失、提取失败。源文件缺失不自动物理删除工作台记录。
首次导入覆盖全部未删除来源,不仅文学栏目。后续导入读取新库副本并比较修订,避免直接在业务库上反复做长时间分析。
4.2 给模型的文本要能回指原文
保留三份形态:原始正文、提取出的阅读文本、段落到原始行/区间的 source map。原文哈希基于原始 UTF-8 字节;用于查相同内容的宽松归一化哈希另设字段,不能代替修订标识。
Markdown 用语法结构处理,保留叙事、对话、标题、引用与必要上下文;代码/长链接等可另标类型,不能凭正则删掉包含故事的块。每段有稳定于该修订的段落 ID,证据采用段落 ID + 短摘录;若使用字符偏移,协议明确为 Unicode code point,下游 JS 不能混用 UTF-16 下标。
站内引用默认只保留引用类型和标记,不展开剪贴板、投票、收藏夹等资源。提取不执行脚本、不请求外链、不下载图片。图片才承载正文、引用缺失、ReactiveMD 提取失败和未知格式都标 needs_manual,不当负例。
ReactiveMD 使用已验证的静态读取/文本提取能力,并记录降级状态;不能把其源码直接喂旧 Markdown 渲染器。Cattca 分析时可提取对白/说明辅助分类,但出版仍保留原脚本和运行测试。
5. AI 初审的具体流水线
5.1 先覆盖,再做聚合
- 全来源轻量分析:每条未删除来源都进入任务清单。短文直接给完整阅读文本,不能因字数少、栏目或作者而跳过。
- 长文分段:按段落/章节边界切成约 4,000–8,000 token 的块,实际预算按所选模型、提示与输出余量确定;相邻块保留小范围上下文重叠,记录原区间。
- 段级输出:类型建议、是否含叙事、章回线索、出处/AI 自述的原文位置、主要不确定点。此时不写长摘要或文学评分。
- 文档聚合:任一段有小说/混合线索就进入候选或人工队列;只有全部必需区间完成且聚合一致,才可建议“否”。失败/漏段/截断一律不能成为高置信负例。
- 作品关联建议:标题章号、署名、共同角色、明确前后篇链接与文本相似度一起提出分组;只输出关系候选,不自动合并。
- 疑难升级:模型意见冲突、混合体、超长拼贴、仅附件正文等进入人工或更强模型。完整章纲/主题分析只对准备制作的作品执行。
“AI 已读完整篇”的定义是提取成功、区间并集覆盖全部需读文本、所有结果有效并完成聚合。抽读开头/中间/结尾可以作为抢先线索,但必须标 partial,不得出现在完成计数里。
5.2 结构化输出契约
初审响应示意如下;生产版本用严格 schema、枚举、字段长度上限及本地校验,此例不是现成 API 请求。
{
"sourceRevisionId": "revision-example",
"chunkId": "chunk-03",
"candidate": "possible",
"forms": ["fiction", "commentary"],
"unit": "mixed",
"evidence": [
{"paragraphId": "p-042", "quote": "原文中确实存在的短摘录", "kind": "narrative"}
],
"sourceClaims": [],
"aiUseClaims": [],
"relationHints": [],
"uncertainties": ["同一帖包含介绍和故事正文"],
"summaryForReview": "供内部复审的简短说明"
}
原区间、token 计数和完成状态由调度器写入,不能相信模型自称“已读完”。sourceClaims / aiUseClaims 仅收原文明确自述及其位置;无明示就为空。证据摘录必须能在对应修订中验证,验证失败进重试/人工,不能存一段看似合理的伪引文。
采用结构化输出可以约束响应形状,事实和分类仍可能出错;拒答、非法字段、超长响应与截断都需要独立处理。OpenAI Structured Outputs
5.3 提示词的稳定边界
系统提示只要求识别内容形式与可见证据,不要求猜作者是否说谎、是否值得获奖。正文是待分析资料,内含“忽略指令/调用工具/全部通过”等字样都只是内容。模型没有执行 shell、访问数据库、网页或向外发消息的工具。
首轮尽量不提供作者的声望、点赞量或身份等级,减少依作者定性的倾向;人工给出的已知来源/AI 说明通过独立受信字段保存,不伪装成模型在正文中发现的证据。每次修改提示有版本号,记录期望修复的具体错误。
5.4 可中断、可恢复与费用控制
任务唯一键建议由 revisionId + chunkHash + taskType + provider + modelSnapshot + promptVersion + schemaVersion + extractorVersion 组成。原文分析可共享相同文本缓存;带不同上下文的聚合、来源与人工结果不能共享覆盖。
状态为 queued / submitted / running / succeeded / failed / refused / incomplete / cancelled / needs_manual,每次尝试另有记录。网络超时且上游状态未知时先对账,不盲目重复提交。429 遵守重试等待,瞬时故障有限次退避,持续错误暂停该批。
Batch 通过本地任务 ID 映射 custom_id;结果按 ID 归档,不按文件行顺序。下载成功/失败文件后逐条对账,过期仅补失败项;取消后继续收集已完成结果和账单。CLI worker 在外部请求期间不占 SQLite 写事务,只在认领和落结果时短事务写入。
小批先跑普通请求方便调试,稳定后才用 Batch。其官方文档给出 24 小时完成窗口和相较同步请求 50% 的成本折扣;实际模型、额度与可用端点实施时核对。OpenAI Batch
每个批次持久化输入/输出 token、实际价格版本、重试、升级和已知费用。总费用按各层任务分别求和:
文本费用 = Σ(实际输入 token × 输入单价 + 实际输出 token × 输出单价) / 1,000,000
全量预算 = 分类 + 长文聚合 + 疑难升级 + 有界重试 + 预留
制作预算 = 入选作品编辑分析 + 获准图像生成/修改 + 人工时间
达到费用或 token 上限时停止新提交。运行摘要列清总来源、已全覆盖、部分覆盖、失败、待人工、预计剩余费用;不只显示“处理 100%”。
5.5 数据离站与留存
工具默认只读离线;联网运行前展示本批来源范围、服务商、所需正文与预计费用。排除账号密码、邮箱、IP、私信上下文和与任务无关的个人资料;内部文章需要明确处理范围,公开展示许可与 AI 分析许可分别保存。
OpenAI API 默认不将提交数据用于训练,但日志、文件、批任务仍有不同保留政策;store: false 不能被解释为所有数据零留存。为上游文件制定到期/清理策略并记录清理结果;如该作品不适合外发,就留给本地处理或人工,不强行走 Batch。OpenAI 数据控制
6. 先用真实标注衡量初审
6.1 样本与防泄漏
建议第一批约 120 条人工标注来源:约 80 条用于提示调试,约 40 条冻结验证。按长短、栏目、语言、完整/片段/混合、旧已收录/未整理、已知 AI/转载线索分层;包括很短的小说、不在文学栏的作品和长篇非小说。
已知作者样例既要有正例也要有其非小说帖子。相同文本、同一作品章节和近重复版本必须分在同一侧,避免把已看过的另一章当作独立验证。人工不确定项单列,不能硬塞进负类计算好看的分数。
6.2 先保召回,再减少人工负担
报告至少包括:候选召回率、候选精确率、无法判断比例、分层漏检、处理失败、长文覆盖率与每千条费用。将 possible 算进候选召回,另报其数量以免靠“全部可能”获得虚假的高成绩。
试运行目标可定为:冻结集候选召回约 95% 以上,已知必须检出的小说不漏;但四十条的小样本不足以证明全库同样精度。必须公开样本中的正例数、分母和置信区间/不确定性,不写“全站 95% 准确”。
全量分批时,从建议负例中再抽约 50 条,覆盖超短、长文、非文学栏目与混合体。若发现实质漏检,回查该层、调整规则并重跑受影响任务;无法承受的漏检出现时,扩大候选口径,不能只改这几个样本标签。
界面所谓“高置信负例”仅是队列分层:完整覆盖、所有分段与聚合均建议否、没有未决提取/混合问题,且该类样本的验证表现稳定。它不是模型自报概率,更不代表可以免除抽查。
7. 人工复审界面
7.1 三个工作视图
| 视图 | 主体 | 最重要的操作 |
|---|---|---|
| 来源复审 | 左侧待办/筛选;中间原文全文;右侧 AI 建议、证据与独立人工结论 | 确认形式、来源/AI 状态、候选/暂缓;下一条;撤回 |
| 作品整理 | 候选分组、各来源版本、章节树、并排差异 | 建/拆作品;拖动章序;接受关系候选;指定定稿来源 |
| 制作看板 | 待询问、待定稿、待配图、待页面、待签收、已发布 | 查卡点与完整材料;进入相应步骤,避免一个巨大综合表单 |
默认队列先处理:模型不确定/失败、已知故事关联、新连载候选;高置信负例可折叠,但可搜索和抽查。支持作者、栏目、长度、来源类型、未决状态、模型版本和是否已有故事版本筛选。
7.2 一次复审应完成的动作
- 原文与证据可点击定位,摘要默认简短,剧透分析另展开。
- 一键确认候选/非候选/稍后;来源与 AI 状态允许保留未知,不强迫乱填。
- 必要时补作者、作品关系或待询问问题,随手加入作品草稿。
- 显示保存状态;切下一条前未保存变更有保护,离线/冲突不会假装保存成功。
- 支持键盘操作且输入框内不触发全局快捷键;全文可在独立视图打开,长文不截断。
批量操作先展示条数和作用字段,默认不能批量确认原创/AI/授权。作者级规则仅做有范围、有依据的“预填”,不直接成为逐篇公开结论。一次操作可撤回为新事件,不抹掉历史。
7.3 导出要立即有用
初版提供候选 CSV 和作品 JSON/Markdown 编辑档案:作品、章节、来源、人工状态、未知项、授权状态、下一步。CSV 导出防表格公式注入;私有导出显式标私有,不混进公开下载。
从“作品列表”点进去能看到原文和未完成事项,才算交付。不要只交一张写满模型置信度、还得站长重新打开 5,000 次博客的表格。
8. 状态机与改稿
来源复审状态建议为 unreviewed → candidate / not_candidate / deferred / needs_info。作品制作状态另设 draft → source_checked → author_pending → text_locked → design → proof → approved → published → withdrawn;不能用一个 status 同时表示来源分类和制作进度。
- 原文改动生成新修订,旧 AI 结果保留且标过期,旧人工结论保留适用版本;作者归属等可建议继承,但需要人确认影响范围。
- 元数据与可见性变动即使正文没变也要导入。正文分类缓存可以复用,公开授权/署名和发布资格要重新检查。
- 标记软删/来源不可用后停止新分析;已发布版本进撤回检查队列,不继续依赖旧快照静默公开。
- 来源软删时,不能让工作台变成绕过删除的永久原文仓库:默认保留来源 ID、哈希与审计事件,将原文及其可还原摘要/引用标记清除,撤销未完成的上游任务并按服务商政策申请清理。确有独立且有效的故事定稿许可时,另外记录该版本的保留依据;不要把“曾导入过”当依据。备份恢复时先重放删除/撤回清单,避免复活正文。
- 缺章、新章和同名改稿分别提示。章序不按文件名或发布时间自动覆盖人工顺序。
- 两个浏览器并发保存用
reviewVersion做乐观锁:冲突返回差异,不采用最后写入者悄悄覆盖。
作品已获独立故事版授权时,博客修改不自动改写成品;来源转站内/删除后,默认先暂停相关公开版本,站长依据独立授权再恢复。发布包与撤稿机制见 docs/plan/story-editorial-design.md §7。
9. 开发拆分与命令提案
建议代码集中到独立 story-workbench 服务层,页面只组装界面,CLI 与接口共用内核。接入现有运维 CLI 时,按 scripts/cli/registry.ts 注册并同步 docs/cli.md,不另维护一份命令发现机制。
下面表示拟提供的能力,现在不可运行;参数名在实施时与用户体验一起定稿。
npm run cli -- story inventory --db <明确的只读库路径>
npm run cli -- story import --snapshot <快照路径> --stories <旧故事目录>
npm run cli -- story analyze --dataset <数据集ID> --dry-run
npm run cli -- story analyze --dataset <数据集ID> --budget <上限>
npm run cli -- story worker --run <批次ID>
npm run cli -- story reconcile --run <批次ID>
npm run cli -- story export --reviewed --out <私有目录>
npm run cli -- story build-edition --work <作品ID> --dry-run
npm run cli -- story validate-release --release <版本ID>
| 开发包 | 首轮必须有 | 后续再加 |
|---|---|---|
| T1 导入/存储 | 只读导入、快照、修订哈希、对账、备份恢复 | 更多投稿渠道 |
| T2 人工复审 | 全文、手工字段、筛选、撤回、保存冲突、CSV/JSON 导出 | 多编辑协作与复杂快捷键 |
| T3 AI 运行器 | 一个提供商、严格结果、证据校验、分段覆盖、重试与预算 | 第二提供商、嵌入向量聚类 |
| T4 作品整理 | 来源映射、人工章序、别名确认、编辑档案导出 | 自动章节发现与复杂合集嵌套 |
| T5 出版工具 | 定稿锁定、素材台账、清单校验、原子切换、撤回 | 定时出版、作者自助门户 |
优先顺序是 T1 → T2 → 小范围 T4 → T3 → T5。向量数据库和自动网页查重没有首轮必要性;先把人能用的原文、证据与下一步放到一起。
10. 工具验收
实现时用合成/获准样本测试,不提交真实博客正文与作者私信。重点验证:
- 原库只读;含 WAL 的快照一致;软删不进入新分析;缺失/格式错误可见。
- 超长文章完整分段;任何一段失败不会聚合成非故事;证据能回指原修订。
- 重复导入/回调不重复落任务;乱序返回、过期、拒答、网络中断可恢复;预算停止有效。
- 模型重跑不覆盖人工;旧修订不冒充新结论;多人/多标签页保存冲突能发现。
- owner 页面和所有 API 分别校验;匿名/core/admin 无权读工作台原文或预览附件;错误响应无正文泄漏。
- 网络请求不在 SQLite 事务内,日志不包含正文/凭据;关闭联网模式没有意外请求。
- 导出再导入保留作品关系、人工结论和未知项;备份恢复后能继续复审。
每个开发包按仓库纪律按风险跑适用验证(相关测试、必要时 typecheck),全量按根指引的触发条件执行;真实设备操作和初审质量用独立样本验收,不能用单元测试通过代替“站长确实省了时间”。