NextTavern故事在此,继续发生 最新发行 v0.2.9-rc.4

社区预设与正则

本文面向预设作者、卡作者和第三方工具开发者,说明 0.3 开发源码中的导入与执行合同。0.3 尚未正式发布;现有受支持样本的限域结果不等于所有 SillyTavern 预设、脚本插件和模型 provider 都兼容。发行状态见开发日志。

快速查阅:完整预设示例 · 条目与功能组 · 作用范围 · 宏与世界书 · 正则参考 · 排错

1. 预设在请求链中做什么

角色卡提供人物、世界和玩法;社区预设排列提示条目、选择功能、展开宏,并对请求/响应作受支持的投影。Native 保存实际历史,预设可以改变某次请求里历史的组织方式,不把存档改写成另一份伪聊天。

mermaid
flowchart LR
  A[全局或对话选择] --> B[冻结条目与变量]
  B --> C[前置宏]
  C --> D[实际卡字段与世界书准入]
  D --> E[marker及outlet绑定]
  E --> F[历史投影与Story请求]
  F --> G[响应适配与变量结算]
  G --> H[Reader显示正则]
Mermaid 流程图源码:复制到支持 Mermaid 的编辑器即可渲染。

它与“原生文风预设”是两种格式。原生文风仍有自己的 system/blend/card 模式;社区预设不能凭任意字段静默改变这份合同。受支持的社区物料链以通过角色卡导入建立的会话为前提,旧手工配置会话不能直接视为已经拥有相同卡字段、世界书和历史接线。

导入保留源文件和未知配置,运行时提取可识别的声明式能力。源文件中的 JavaScript、第三方模块、action 函数体和宿主 API 不会因为“导入成功”就执行。

2. 可导入什么文件

社区预设入口接受带 prompts 数组的 JSON 对象,常见为 SillyTavern 的聊天补全预设导出;不是任意 YAML、角色卡 JSON、纯文本 system prompt 或 NextTavern 原生文风文件。独立正则入口接受一个规则对象或规则对象数组。Izumi V2 分层方案包使用专门的方案包入口,不能当作提示词预设导入。

以下是完整最小源文件,可保存为 雾港灯塔预设.json。它保留人物、玩家资料、世界书、示例和历史槽位,并增加一段创作要求;无脚本和外部依赖:

json
{
  "temperature": 0.8,
  "openai_max_tokens": 1200,
  "prompts": [
    {"identifier": "lighthouse-main", "name": "灯塔叙事", "role": "system", "content": "围绕雾港灯塔写连续剧情。保留玩家选择,用声音、光线和海雾表现环境。"},
    {"identifier": "worldInfoBefore", "name": "人物前世界书", "role": "system", "content": ""},
    {"identifier": "charDescription", "name": "角色描述", "role": "system", "content": ""},
    {"identifier": "charPersonality", "name": "角色性格", "role": "system", "content": ""},
    {"identifier": "scenario", "name": "场景", "role": "system", "content": ""},
    {"identifier": "personaDescription", "name": "玩家资料", "role": "system", "content": ""},
    {"identifier": "worldInfoAfter", "name": "人物后世界书", "role": "system", "content": ""},
    {"identifier": "dialogueExamples", "name": "示例对话", "role": "system", "content": ""},
    {"identifier": "chatHistory", "name": "历史", "role": "system", "content": ""}
  ],
  "prompt_order": [
    {
      "character_id": 100001,
      "order": [
        {"identifier": "lighthouse-main", "enabled": true},
        {"identifier": "worldInfoBefore", "enabled": true},
        {"identifier": "charDescription", "enabled": true},
        {"identifier": "charPersonality", "enabled": true},
        {"identifier": "scenario", "enabled": true},
        {"identifier": "personaDescription", "enabled": true},
        {"identifier": "worldInfoAfter", "enabled": true},
        {"identifier": "dialogueExamples", "enabled": true},
        {"identifier": "chatHistory", "enabled": true}
      ]
    }
  ]
}

在设置 → “预设”中选择生效范围,使用“导入社区预设JSON”,选中条目,再点“应用社区预设”。导入只添加到共享库,不等于已应用。可检查面板显示 standard、9 条目、0 正则;实际人物材料取决于当前导入卡的字段映射,空字段不会凭空生成内容。采样默认关闭,因此导入这个文件不会立即把温度改成 0.8。

源文件不等于内部 Schema

层字段例用途
上传的预设源文件prompts、prompt_order、injection_position、extensions.regex_scripts社区导出格式,交给导入器
解析后的库文档schema:"community-presets.v1"、source、promptOrder、injectionPosition、profile、regexes、parameters原生归一化数据和来源留存
选择状态presetId、applySampling、prompts、contents、features、regexes、regexOrder某个范围当前怎么使用共享库
宏变量账本chat/global 值与本轮写入作者宏的持久与本轮结算

预设 Schema、选择状态 Schema、变量 Schema描述内部数据,不能把其中的 promptOrder 等字段直接当成 ST 源文件字段。面板“导出社区预设”通过导出器还原社区文件;工具应显式区分两层格式。

3. 条目、排序、功能组和采样

普通提示条目

源字段解释及默认值
identifier条目稳定身份;排序、开关、功能组均靠它定位,建议作者显式设置且保持唯一
name界面名称;部分适配器允许名称回退,但不宜用重复名字代替稳定 ID
content普通条目的提示正文;marker 用实际材料替换,不把其 content 当人物资料
rolesystem、user、assistant;其他值归一化为 system
enabled条目默认开关;选中的 order 行存在时,以该行 enabled 为准
injection_position0 为常规布局,1 表示请求内深度插入;不是任意 ST 插件位置枚举
injection_depth深度插入值,默认 4;0 在末尾方向,更大值向历史前方移动
injection_order同类深度插入的顺序,默认 100;相同值再按条目顺序
readOnly禁止在预设库正文编辑器修改,不代表运行时停用
spreset_hidden隐藏提示标记,仍保留数据;不要把 hidden 当 enabled

导入器优先使用 prompt_order 中 character_id:100001 的行,否则取第一行。只导入这一个有效顺序,不把每个 character_id 合并。该行存在时,没有列入 order 的 prompt 标为 unused,不会因自己写了 enabled:true 就自动注入。没有任何有效 order 时才按 prompts 数组顺序执行。缺失的 identifier 虽会生成 prompt-N,但条目移动后这个名字不稳定,不适合作为作者契约。

chatHistory 是布局边界:常规条目在它之前归 head,之后归 tail;injection_position:1 单独表达深度。实际 Native 执行会把 system 材料集中到拥有的系统插槽,所以 system 的尾部/深度位置不承诺与 ST 任意角色交错完全相同;user/assistant 条目才按请求插入合同定位。此适配会留有 adaptation,而不会改写原历史来伪造相同布局。

marker 是材料入口

identifier实际材料
charDescription、charPersonality、scenario当前卡映射后的对应字段,分别渲染,不用完整原卡文本占位
personaDescription当前玩家资料
worldInfoBefore、worldInfoAfter本轮已经准入且位于人物前/后的世界书
dialogueExamples实际示例对话与对应前后世界书材料
chatHistoryNative 选中的真实历史布局边界

marker 由 identifier 识别;把普通条目仅命名为“世界书”不会获得这个能力。禁用 marker 会撤去它负责的对应材料槽位,不能期待原槽位再补一份。没有准入的世界书、未导入的玩家资料和卡的空字段不会因为 marker 存在而自动填满。角色字段归属可在预设界面的卡字段归属控件核对,导入与映射过程见社区角色卡指南。

功能组与 profile

SPreset 配置条目等被识别为 configurationOnly 的内容保留为配置,不当作剧情 prompt。功能组把作者声明的控件变成原生开关,不直接执行脚本函数:

控件语义当前动作
single/multiple 组单选启用时处理组级启停和其他选项;多选允许并存
enable/disable按 identifier 或匹配名称切换目标条目;找不到目标进入 unresolved
between按上下边界名称模式选择其间条目,边界自身不包含在范围内
var_input/global_var_input写 chat/global 宏变量,可同时切换声明目标
Kemini parameters根据已提取的声明式注册、模板和规则修改参数或建立支持的条目

当前识别的 profile 有以下职责;这些名称不是用户随便加一个同名字段即可获得的执行引擎:

profile主要原生适配
standard普通 prompts/order、marker 和宏
dream识别的消息分组、静态/动态世界书 outlet 及配置控件;额外总结/修复等模型动作可保留为 deferred
kemini识别的提示参数控件和函数响应 transport,保留实际客户端工具
reborn识别的 SPreset 历史/postscript/响应包装;特定模型与 transport 仍有适配条件
izumi识别的分层方案、advice、文本 sanitizer 与声明冲突配置;部分显式动作仍为 deferred

profile 由导入器识别实际声明和静态配置,不对同名预设的所有版本作保证。Izumi V2 方案包导入只保存 plans、active 和 quickSlots,先预览,再显式应用方案;未定位条目会显示 unresolved,不把缺失目标算作成功。

采样参数

“应用预设采样参数”与选择预设是独立开关,默认 false。当前请求适配明确接入数值 temperature 和 openai_max_tokens,后者映射为 maxTokens。其他 provider 字段即使保存在 parameters 也不等于执行器使用它;stop 在开启采样时会记录未支持适配。模型/provider 自身对输出预算等仍有约束,不能把源文件字段数当作兼容覆盖率。

4. 共享库、全局与对话范围

操作影响范围
导入/复制/编辑预设库条目修改所有对话共享的库;编辑已被引用的正文会影响这些对话后续生成
在“全局”应用选择与开关为没有独立覆盖的对话提供默认基线
在“当前对话”/“指定对话”应用建立该对话的选择与配置覆盖
“社区预设沿用全局”删除对话覆盖,重新继承全局
对话世界线切换同一对话根身份共用对话预设选择,不是每条分支独立选择

条目开关、正文覆盖、功能配置、正则开关及来源顺序归属所选范围。编辑器显示的共享库草稿和范围内覆盖是两件事;调整单个对话时应使用范围控件,避免误改共享库。删除仍被选择的预设会要求先停用或切换。

一次 Story 准备会冻结实际选择、来源、变量、随机种子和时钟。生成中途改设置不应把新配置塞入旧尝试;后续新准备才消费新策略。provider 重试复用已完成准备,不能通过重试把同一轮赋值、抽签或其他作者副作用再执行一遍。

5. 宏变量、世界书与历史的组装

社区宏是在 prompt 条目内使用的 {{…}},不是 JavaScript,也不等于 EJS 或 MVU 数值。它依次处理启用条目,共享本轮变量与抽签顺序。例如把以下正文片段放进一个普通 preset prompt:

text
{{setvar::叙事地点::雾港灯塔}}
本轮地点:{{getvar::叙事地点}}。请继续描写{{char}}的行动。

当前卡人物名绑定为“守塔人”时,会得到“本轮地点:雾港灯塔。请继续描写守塔人的行动。”;赋值宏自身不输出文本。这个 chat 宏变量叫“叙事地点”,不会修改 MVU 的 世界.地点。

宏族当前例子与含义
身份/材料别名{{user}}、{{char}}、{{input}};卡字段别名由实际导入和映射提供
chat 变量setvar/getvar/addvar/incvar/decvar/unsetvar,例如 {{getvar::叙事地点}}
global 变量相应的 setglobalvar/getglobalvar/addglobalvar/incglobalvar/decglobalvar/unsetglobalvar
随机选择{{random::晴天::海雾}}/{{pick::晴天::海雾}};固定本轮种子与抽取顺序
骰子{{roll::1d6+2}},按支持的 NdM±K 文法计算,不运行算术脚本
格式{{newline}}、{{space}}、{{trim}}、{{reverse::灯塔}}、{{// 注释}}
时钟time/date/isotime/isodate/weekday 使用冻结时钟及 UTC 格式
outlet{{outlet::名称}} 读取本轮实际绑定出口;未绑定会报错

addvar 在可转数值的现值和增量上做加法,非数值场景按字符串追加;incvar/decvar 输出更新后的值。嵌套宏按语法处理,但未知宏会报“尚未支持的社区宏”。MEMORY_…/VECTOR_MEMORY… 等外部记忆插件宏没有因此接通;不能用原生记忆的存在推定这些宏可用。

宏的写入先在本轮尝试中累积,由变量 owner 按相应结算合同提交。功能控件的配置写入和一次 Story 内的宏写入也有不同身份。失败、取消或配置过期不能被当成“所有写入都肯定落盘”;恢复应沿原尝试的结果处理。

世界书与 outlet 的先后

前置宏先执行,遇到第一个世界书 marker 或依赖 outlet 的边界时暂停其后的处理。实际世界书按关键词、启用、位置和预算准入,模板 owner 渲染所需材料,再将结果绑定到 marker/outlet,继续后续条目。这样不会为了补齐世界书把已经执行的赋值或随机前缀重新跑一遍。

绑定 outlet 后,仍须有本轮实际参与请求的文本引用 {{outlet::名称}}。若引用只写在被文风策略排除的 rules.reply 等字段中,条目准入不会自动把它追加到其他位置;玩法必需的出口应放在实际生效的作者栏目或预设条目。

EJS 与前置社区宏有不同的执行阶段。例如 Native 人物内容可用 <%= 2 + 3 %>,世界书模板可用 <%= getvar('stat_data.角色.体力', 'local') %> 读取实际数值快照;普通 preset 的前置组装不会单独求值 EJS,但进入正常 Main 最终请求 slot 后,其中的 EJS 会按最终文本流程处理。getpreset/getprp 则可显式读取当前捕获目录中的首个匹配 prompt,在同一模板环境嵌套求值,包含未启用或未参加最终组装的条目。模板落点、标签、变量和 getwi/提示注入 API 见原生卡 EJS 章节,数值初始化与写入边界见状态手册。只读历史恢复不重跑这条准备链;请求投影也不改写原始历史。

历史和响应投影

Dream、Reborn、Izumi 等适配可能把连续纯文本历史合组、改成特定文本包装、放置 advice 或调整模型响应 transport。这些只影响本次请求。工具、媒体和不透明历史不是普通文本:不能跨过实际边界任意压成一条,也不能把 Native 正史改写成伪造角色行。

响应适配完成后,原生剧情和对应变量按各自合同结算。选择了某个 profile,并不证明模型一定遵从其响应格式;空输出、错误 transport 或未接入 action 应看具体错误/adaptation,不能用多次刷新代替处理。

6. 正则的导入、顺序与字段

一个可直接导入的显示规则

以下是完整独立正则 JSON 数组,可保存为 灯塔显示正则.json,通过“独立正则库” → “导入正则JSON”导入。它把模型回复中的 【旁白】 标签仅在显示时删除:

json
[
  {
    "id": "lighthouse-narrator-label",
    "scriptName": "隐藏旁白标签",
    "findRegex": "/【旁白】/g",
    "replaceString": "",
    "trimStrings": [],
    "placement": [2],
    "disabled": false,
    "markdownOnly": true,
    "promptOnly": false,
    "runOnEdit": true,
    "substituteRegex": 0,
    "minDepth": null,
    "maxDepth": null
  }
]

选择绑定“当前对话”后,打开“双通道预览”,输入 【旁白】守塔人点亮提灯。,位置选“模型回复”、深度 0,点“预览双通道”。预期“发送给模型”保持原文,“显示在界面”为 守塔人点亮提灯。。把规则改为 promptOnly:true, markdownOnly:false 则只改请求通道;两个都为 true 才同时覆盖这两个通道。

预览采用占位身份和空宏变量,不等于完整卡材料执行;Reader 的角色卡正则和实际别名还需在真实会话核对。显示规则不回写保存的原始历史;要删原存档中的文本,应使用正式正文编辑,而不是显示替换。

内嵌正则从哪个字段导入

预设中按以下优先级取第一份非空数组,避免重复容器里的同一份正则执行多次:

  1. extensions.regex_scripts(native 来源容器)。

  2. extensions.SPreset.RegexBinding.regexes。

  3. regex_scripts,否则 extensions.regexes,否则 regexes(legacy 容器)。

legacy 行内部先按字段存在的回退关系选值,不会在每个候选字段里继续寻找下一份非空数组。独立正则入口则直接读取一个对象/数组,不会替你解包 {"regex_scripts":[…]}。

生效来源和执行顺序

来源类别包含内容
global绑定全局的独立正则库
preset当前 preset 的内嵌正则,以及绑定到该 preset 的独立库
scoped当前对话根绑定的库,以及已准入的角色卡 scoped 正则

standard/dream 的默认顺序是 global → preset → scoped;kemini/reborn/izumi 为 preset → global → scoped。在“正则来源顺序”可显式调整,保存到当前选择范围。同一来源内沿有效规则顺序执行,前一个输出是后一个输入;不能仅按文件名或导入时间推测最后文本。绑定 preset 的独立库只随该 preset 生效;正则库也可在没有启用社区预设时独立使用。

规则字段的精确含义

字段当前语义
findRegex查找式,可写 /模式/gim;常用 JS g/i/m/s/u 标志写在字符串尾部。单独的 flags 字段不接入执行
replaceString替换模板,支持 $0/{{match}}、$1 等捕获组、$<name> 命名组及支持的宏;不是 JavaScript 回调
trimStrings对被引用的捕获文本删除这些字面字符串;不是对整篇正文调用 trim
placement数组形式的运行位置;本例 [2] 为模型回复
disabled/enableddisabled:true 或 enabled:false 停用;独立库可编辑启停及规则顺序
markdownOnly允许 display 通道(Reader 显示)
promptOnly允许 prompt 通道(发送给模型的材料)
runOnEdit输入被标记为已编辑版本时仍允许执行;false 会跳过编辑版本,不表示修改原文或自动重生成
minDepth/maxDepth在提供深度的消息上作含端点筛选;null 不限制,minDepth 小于 -1 不设下界,maxDepth 小于 0 不设上界;无深度的材料不按消息深度过滤
substituteRegex0 不展开查找式宏,1 直接代入宏值,2 先转义宏值中的正则特殊字符再代入

markdownOnly 和 promptOnly 同时为 false 时匹配 source 通道,不是“请求和显示都执行”的简写。在双通道预览里两边都不变化可能正是这个原因。source 是原材料处理阶段;不要把这个值当作给 Reader 增加一项通用开关。

placement 的当前 UI 名称为 1 用户输入、2 模型回复、3 快捷命令、5 世界书、6 思考内容。数据合同还容纳 0/4,但这不表示每种位置都已有实际生产调用者。只有材料链确实提供对应位置和通道时规则才执行;常规 Reader 消息是 1/2,预览也只提供这两类。

深度是该消费阶段提供的消息位置,不是世界线编号或回合号;最近消息深度为 0,向前递增。新消息到来可能改变旧消息深度,从而改变显示。规则不会因为深度改变就编辑旧存档。

要使用多行匹配,明确写 m(改变行首尾锚点)或 s(让点匹配换行)。没有 g 不表示全量替换。不承诺 PCRE、x 等非 JavaScript 语义。查找式中的宏是否展开由 substituteRegex 决定,替换模板的宏另按自己的阶段处理。

正则沿隔离 Worker 执行,有输入、输出、匹配与时限等限制。非法表达式可能报告 PROMPT_TRANSFORM_REGEX_INVALID,长耗时变换可能被终止;Reader 失败时保留可读原文并提示。缩小匹配范围、改写模式或停用该规则,优于期待刷新能修复同一表达式。

7. 作者排错顺序与验证边界

现象检查点应看到什么
导入报“需要 prompts 数组”是否把方案包/内部 schema/角色卡当作预设使用第 2 节源文件结构
导入后风格没变是否已选并点应用;当前范围;条目 enabled/unused/configurationOnly当前范围显示所选 preset 与有效条目
人物或世界书没进入请求marker identifier、当前卡字段映射、世界书实际准入、是否关闭 marker有材料的槽位才产生内容
功能组显示 unresolved控件声明的 ID/名称是否仍对应 prompt;是否删过模板修复声明或目标,不能仅改展示名
采样没变applySampling 是否打开;字段是否是已接入的两个数值字段保存未知参数不等于 provider 已使用
宏原样出现或报错是否用了未支持宏;是否把 EJS/MVU/外部记忆语法混入社区宏支持的宏由本轮绑定展开;未知依赖明确失败
正则预览没变来源绑定、开关、placement、通道标记、深度、模式/flags用显示示例先确认单规则,再检查真实链
已编辑消息没有变换runOnEdit 是否 falsetrue 才允许该版本参与变换
画面更新但数值没变是否只做了显示替换;MVU 候选是否被接受并提交数值以游戏数值面板及对应提交为准

导入、控件、宏、正则、组装和变量结算不新增模型推理请求,正常/重试/回退增量为 0/0/0。它们可以改变 Story 的 token 数、温度、预算和输出,从而改变实际费用;Ruby 与作者显式生成操作另计。

本文的 JSON 是可交给现有解析器的示例;条目、宏和正则应分别核对导入结果与预期文本。完整兼容还需要真实请求、响应与 UI 操作结果;格式通过不能代替整卡玩法验证。Native 1.1 普通执行与高级人物分类也有不同材料消费者,预设选择成功不能证明全部动态高级投影已支持,详见原生卡格式。

源码定位:导入格式、作用域、profile、控件、宏、执行、正则顺序、正则语义。