novel_style_report
baseline / baselineChapterCount / baselineScope / baselineMode 随之变化;勾选的章一章都取不到时回退按全书并在 baselineScope 里按原因写明(选择已失效 / 只选中了本章自身两种文案)。范围只影响「基线」这一项——文风指纹 / 高频词 / 题材流派 / 情感量化 / 氛围 12 维 / 语义风格距离,以及渲染层附的「原著段落 / 句式骨架」,仍全部是全书口径(它们回答的是「这本书是什么样」,不是「拿什么当基准」)。semanticDiagnostics: { reason, detail, count, at },表示本次语义风格计算的原因、细节、结果数与时间;功能未启用为 not-run,引擎不可用为 no-engine,精简报告省略明细。
风格画像报告。对基线范围内的章节(默认全书)逐章测量六个文笔维度,汇总为基线带 μ±σ,并聚合文风指纹、高频词、题材流派、情感量化、氛围 12 维与语义风格距离,作为「测量数据」交给调用方模型做风格判断。插件只报数、不下结论:模型的判断可通过 aiJudgment 回传存盘,供后续续写时复用。
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
book | string | 是 | 书名,即 novels/ 下的子目录名。经 sanitizeSegment 过滤,拒绝路径分隔符与上跳。 |
root | string | 否 | 章节库根目录。MCP 形态下必须落在启动参数 --root 指定范围内,越界会被静默回退。 |
action | string | 否 | report(默认)生成测量报告;get 只读取已保存的 AI 判断,不重算。 |
brief | boolean | 否 | true 返回一句话精简结论,用于省 token 的场景。 |
aiJudgment | string | 否 | 模型给出的风格气质判断。传入后与测量数据一同写入 style-reports/<book>.json。 |
输出结构
契约字段(output.schema):book 与 report 为必返;其余按需出现。渲染层会在正文之后追加「风格锚·原著段落」与「句式骨架」两段,供生成端照样例写,而不是只盯数字。
| 字段 | 类型 | 内容 |
|---|---|---|
report | string | 人类可读的完整报告文本 |
baseline | object | 六维基线与每章测量值,见下文「基线带」 |
baselineChapterCount | integer | 实际参与基线统计的章数(已按面板「基线范围」筛选、并剔除正文 < 40 字的章节) |
baselineScope | string | 基线说明(v6.5.5,仅完整报告返回;brief: true 时该键不出现,范围文案并进 brief 文本,形如「六维基线(自定义基线 N 章…)」且只在自定义时才有):写明本次基线取自哪些章——按全书 时为「全书 N 章」(语料只有 1 章时直接给章名)——注意本路没有「本章」概念(它不判定某一章,不排除任何章),故不写「除本章外」,这是本版新增字段,无历史读取方、不涉及兼容;按部分 时为「自定义基线 N 章(选中 M 章)」(有取不到的章时括注为「(选中 M 章,其中 K 章未纳入基线(已删除、或正文过短无法测量))」;两种档位下 N 都是真正进 μ/σ 的可测章数——本路会用可测章池再解析一次范围(只覆盖回报口径),故 N 与同一返回体里的 baselineChapterCount 恒等(按部分时若选中的章全过短而回退,则保留章池口径,由报告正文的"基线不足"另行说明,避免写出「回退全书 0 章」这种自相矛盾的文案);M = 配置里选中的总数(含取不到的)),一章都取不到而回退时按原因给两种文案:「(自定义选择已失效,已回退全书)」或「(选中的章只有本章自身,不能作为自己的基线,已回退全书)」 |
baselineMode | string | 范围档位(v6.5.5):all = 按全书(默认) / custom = 按选中的部分章。回退后取值是 all,要区分「本来就是按全书」与「回退」,读 baselineScope 文案里的后缀(按原因两种:「(自定义选择已失效,已回退全书)」/「(选中的章只有本章自身,不能作为自己的基线,已回退全书)」) |
dimensions | object | 指纹 / 词汇 / 题材 / 情感 / 氛围 12 维 / 语义距离(全书口径,不受基线范围影响) |
anchors / skeletons | array | 原著代表性段落与句式骨架样例(全书口径,与 dimensions 一样不受基线范围影响——本工具里只有 baseline 系列字段跟着范围走) |
brief | string | 精简模式下的单句结论 |
savedJudgment | string | action:"get" 时返回的历史判断 |
六个维度的定义与公式
全部维度零依赖、纯规则统计,不做模型推理。所有计数先按千字归一,量纲统一:
测量前先剥离 Markdown 标题行(^#{1,6}[ \t]+[^\n]*),章节标题不参与任何统计。
1 · 句法复杂度 complexity
切句用与 analysis.js 共用的句末符集合(。!?…!?),正则为「句末符后紧跟非句末符处切分,或遇换行切分」;句末符后的闭合引号会被吞掉(她说:「走吧。」 不产生孤儿引号句),纯标点残片(!!!)丢弃。小句按 [,,;;::] 切分后计非空段。该维度是「平均每句由几个小句构成」,近似嵌套深度。
2 · 修饰密度 modifierDensity
「的」作为词尾(真的 / 似的 / 目的 / 有的 / 是的)或词首(的确 / 的士)时都不是修饰助词,用两张停用词表按命中位置的 2 字窗口排除;刻意不收录「中的 / 的话」——它们在「梦中的场景」「他的话很多」里是真修饰语。X地 侧按「地」的位置分两张名词表:以「地」结尾的(土地 / 原地 / 目的地…)用后缀判定,以「地」开头的(地上 / 地下 / 地方…)用命中之后的 2 字窗口判定。
3 · 抽象度 abstractDensity
采用「最长匹配 + 区间消费」而非正则前瞻:旧写法要求抽象词后必须是非汉字,导致「她的感情很深。」计 0 而「她的感情,很深。」计 1——同词只因后随标点不同而结果相反。已知取舍:相邻两个抽象词若被一个 4 字窗口跨越(如「感情和理性」),只计 1 个。
4 · 动作密度 actionDensity
词表本身是文档:单字表无法区分「分(分开)」与「十分」、「行(行走)」与「行李」,因此用 2 字黑名单在命中处兜底,窗口取命中字的前一字与后一字两种组合。第 ③ 条修的是越过文本末位与句末动词的漏检。
5 · 不确定性 hedgeDensity
最长优先 + 占位符是为了避免重叠计数:像是要 不再被算成 像是 两次加 像是要 两次。
6 · 留白指数 gapIndex
两项都按千字归一是硬性要求:早期版本把千字密度与「未完句百分比」(0–100 量级)直接相加,15 字文本能算出 222.22,量纲不可比。未完句定位用顺序游标推进,重复文本不会误判。
基线带 μ±σ 的计算
先按基线范围筛出语料章,再逐章测量后汇总,跳过正文长度不足 40 字的章节(不足则不参与统计,也不计入 baselineChapterCount):
minSigmaRatio 默认 0.15,即 σ 下限为均值的 15%。推荐容差取「作者自身章节波动的 1.5 倍 σ」,四舍五入到 5 的倍数,下限 10%、上限 100%;μ=0 时回退 15 以避免除零。
与容差不同层:范围写在
<root>/.novel-writer/baseline/<书名>.json({ mode, chapters, updatedAt };mode 只认 all / custom,其余回落 all;单条文件名截 220 字、上限 2000 章),文件不存在即等于「按全书」;面板里的容差(styleTolerance)是全局一份、所有书共用。小样本:实际参与统计的章少于 3 章时推荐容差抬到至少 ±25%——所以单章也能当基线,不会因 σ=0 把一切都报成偏差(此时
baselineChapterCount 会等于 1,读取方应据此降低结论强度)。回退:勾选的章一章都取不到时回退「按全书」,并在 baselineScope 里按原因写明「(自定义选择已失效,已回退全书)」或「(选中的章只有本章自身,不能作为自己的基线,已回退全书)」;取不到的章(已删除 / 正文过短)会被跳过并如实计数(文案「…,其中 K 章未纳入基线(已删除、或正文过短无法测量)」)——绝不返回空基线:空基线算出的 μ 是假的,会把「没有基线」伪装成「全都在带内」。范围只动「基线」,不动「这本书是什么样」:指纹 / 高频词 / 题材流派 / 情感量化 / 氛围 12 维 / 语义距离(
dimensions)以及渲染层附的「原著段落 / 句式骨架」仍按全书统计;跟着范围走的只有 baseline / baselineChapterCount / baselineScope / baselineMode。brief: true 时这一点最明显——文案形如「全书 1329 字:六维基线(自定义基线 12 章(选中 12 章))μ=…」:字数是全书,基线才是那几章,别读成「整份报告只统计了那几章」。
sigmaMeasured(原始样本标准差)、sigmaUsed(参与 low/high/recTol 的钳制值)与 sigmaClamped(是否发生钳制)。早期版本只返回钳制后的值,展示层把 0.15μ 的下限当成「作者自身波动」念给用户——实测真实 σ=0.0084 被报成 0.15,差 18 倍。
偏离判定
给新章指标 v 与基线 μ:
tol 默认取 { low: −recTol, high: +recTol },也接受调用方逐维自定义。容差语义有明确区分:显式 0 表示零容差(任何偏差都判 out),只有缺失 / null / 空串 / 非有限值才回退推荐值——早期用 Number(x) || -recT 把 null 也当 0,单侧缺失时那一侧会退化成零容差。
约束与边界(对调用方模型)
- book 必填,且经
sanitizeSegment过滤;root在 MCP 形态下必须落在启动时的--root之内——越界时由 MCP 层静默回退到--root并只写 stderr 日志,调用方不会收到错误,因此不要把root当作可靠的越权探测手段。 - 测量与判断分离:本工具不返回风格结论。需要「这本书的文风是什么气质」这类判断时,由模型阅读报告后给出,并通过
aiJudgment回传,插件负责存盘与复用。 - 过短章节被排除:正文 < 40 字的章节不参与基线;
baselineChapterCount会小于实际章数,这是预期行为。v6.5.5 起它还受面板「基线范围」影响:按部分时只统计勾选的章(实际参与数 = 勾选章中正文 ≥ 40 字者),取不到的章(已删除 / 正文过短)被跳过并如实计数;一章都取不到则回退按全书,并在baselineScope按原因写明「(自定义选择已失效,已回退全书)」或「(选中的章只有本章自身,不能作为自己的基线,已回退全书)」。 - 基线范围不改变维度定义与阈值:换范围只会换语料,
μ/σ/recTol的公式与偏离判据(out/warn/ok)一字未改;因此同一本书在不同范围下的基线带不可直接互比(这是两种标杆,不是两次采样)。范围按书存于<root>/.novel-writer/baseline/<书名>.json,与全局的容差设置不同层;action:"get"只读已保存的 AI 判断,不会因范围变化而重算。 - 只有 1 章基线时分辨力很低:
μ由单章得出、σ不可估计(会被minSigma或 25% 下限接管),此时baselineChapterCount = 1——读取方应据此降低结论强度,不要把它当作「作者风格」的代表样本。 - 维度可能被跳过:当某维基线 μ=0 且 σ=0 时无法做相对判定,该维进入
skippedDims,summary会写明「另有 N 个维度基线均值为 0、未做相对判定」。调用方不应把「无维度超出容差带」读成「全部维度合格」。 - 数值不可跨版本横比:v4.3.0 统一了句末符口径(省略号单独成句)、清洗了动作词表(去重 29 + 剔除 11 个非动词)、抽象度改为最长匹配、修饰密度增加停用词表——同一本书在新旧版本下的报告数值不可直接比较。v6.9.5 又改动了两维的口径:动作密度清出了 70 余个混在动词表里的非动词(于/属/象/头/绪/脉络/框架/程序/环节/焦/热/痛/弱/短/难 等),并把「十分 / 非常 / 格外 / 无比 / 极其 / 特别 / 相当」等双字程度副词纳入性质形容词豁免(旧版只判前一个字,「十分香」会被计成动作);抽象度增加词首排除(代词 / 副词 / 介词 / 动词不得作为抽象词词首)并大幅扩充停用表(天空 / 办法 / 整理 / 写信 / 认真 / 醒来 / 做梦 / 救命 等)。因此动作密度、抽象度、修饰密度在多数书上会下降。v7.0.0 的细节密度去噪与本页无关:它只作用于
novel_sentence_analysis的density(口径标识METRIC_CALIBER = "v7.0.0"),六维基线的口径本次未变,本页六维数值不会因它而下降。 - 落盘位置:报告写入
<root>/.novel-writer/style-reports/<book>.json;action:"get"只读取该文件,不重算。
相关工具
- novel_style_check —— 用同一套维度做「新章 vs 基线」的对照判定;基线会先剔除目标章再计算,范围同样取自面板「基线范围」。
- novel_sentence_analysis —— 九类句式分布、情感曲线与风格指纹,是本报告「维度」部分的原始来源。
- novel_semantic_search —— 语义风格距离所依赖的本地向量引擎。
源码位置
- lib/style-metrics.js —— 六维测量、基线计算、偏离判定(
measureStyleMetrics/computeBaselineFromPerChapter/judgeAgainstBaseline) - lib/core.js ——
resolveBaselineScope(v6.5.5 基线范围的唯一裁决点,配套readBaselineScope/writeBaselineScope/normalizeBaselineScope与buildTolerance) - lib/analysis.js ——
TERMINATORS句末符常量、句式与情感分析 - lib/index.js —— 工具注册:参数、输出契约与
execute实现 - lib/vibe.js —— 氛围光谱 12 维