Skip to content

因为它很重要,所以它被扩展

世界书命中详情说明了一件事:提示词组装过程需要被观察。 但观测能力不应当止步于世界书。 所以 TavernHeadless 需要 Prompt Runtime。

从世界书命中详情开始

上一篇文章说的是世界书。

世界书条目是否命中,为什么命中,命中之后被放到哪里,这些信息看起来很小,但很重要。

因为它们回答的不是“世界书有没有这个功能”,而是另一个问题:

这个功能在当前回合里到底怎样生效。

这个问题不只属于世界书。

提示词组装里还有预设、角色卡、用户设定、聊天历史、变量、记忆、正则、宏、预算裁剪、可见性规则、输出格式和模型参数。世界书只是其中一部分。

如果只有世界书能被观察,使用者仍然只能看到整个过程的一角。

观测能力不应只停在一个模块

一次最终发给 LLM 的提示词,不是由单个模块决定的。

它通常经历很多步骤:

  • 当前会话使用哪种 prompt mode。
  • 当前绑定了哪些角色、预设、世界书和正则配置。
  • 哪些历史楼层会进入上下文。
  • 哪些消息因为隐藏、分支或可见性规则被排除。
  • 哪些世界书条目被命中。
  • 哪些记忆被检索和注入。
  • 哪些变量参与宏展开。
  • 哪些正则规则执行了。
  • token 预算怎样分配,哪些内容被裁剪。
  • 最终消息怎样交给模型。

这些步骤中的任何一步出问题,最后的回复都可能偏离预期。

如果系统只告诉使用者“世界书命中了哪几条”,那当然有帮助。但如果问题出在宏、记忆、预算、历史裁剪或 prompt mode 上,使用者还是要继续猜。

所以,观测能力需要从世界书扩展到整个提示词运行过程。

这就是 Prompt Runtime 的位置。

Prompt Runtime 要回答什么

Prompt Runtime 用来回答一个具体问题:

当前这次聊天,会按什么规则组装提示词。

它关心的不是最终回复写得好不好。那是模型输出层的问题。

它关心的是,在模型被调用之前,引擎到底准备了什么。

更具体地说,它要回答:

  • 当前会话实际使用哪个 prompt mode。
  • 这个 mode 是显式设置的,还是来自默认值或兼容 fallback。
  • 当前 policy 是什么,包括结构、预算、来源选择和可见性规则。
  • 当前绑定了哪些 Prompt Assets。
  • 一次请求会准备出哪些 messages。
  • 哪些资源进入了提示词,哪些被排除。
  • 预算裁剪发生在哪里。
  • 宏、正则、世界书、记忆分别产生了什么运行事实。
  • 一个已提交楼层当时保存下来的提示词真相是什么。
  • 两个已提交楼层之间的提示词差异在哪里。

这些信息放在一起,才构成提示词组装的观察面。

它不是另一个聊天接口

Prompt Runtime 不是用来替代正常聊天接口的。

正常发消息,仍然走 Chat。Prompt Runtime 是给排查、预览、检查、解释和比较使用的。

它现在有几类入口:

入口作用
mode查看或修改当前会话的 prompt mode
policy查看或修改提示词运行策略
assets查看当前绑定的 Prompt Assets
preview对单段文本做宏预览
inspect无副作用地准备一次完整 prepared turn
explain读取已提交楼层保存下来的历史真相
compare比较两个已提交楼层的 Prompt Runtime 差异
capabilities查看当前公开能力和边界

这些入口的共同点是:它们都服务于理解提示词过程,而不是直接生成正文。

这条边界很重要。

Prompt Runtime 不是“另一个会话系统”。它是提示词运行过程的控制面和观察面。

preview、inspect、explain 和 compare 的边界

Prompt Runtime 里有几个容易混淆的词,需要分开看。

preview 只做单段文本预览。它适合看一段文本里的宏怎样展开。它不会调用 LLM,不会创建 Floor,也不会写 prompt snapshot。

inspect 会准备一次完整的 prepared turn。它可以让使用者在不调用模型、不创建 Floor、不提交副作用的前提下,看到这次请求会怎样被组装。

explain 面向已经提交的楼层。它读取的是历史 committed truth,也就是当时保存下来的运行事实。它不应该重新跑一遍提示词组装来猜当时发生了什么。

compare 用来比较两个已提交楼层的差异。比如两次重新生成为什么不同,两个分支在提示词层面有什么差别。

这四个入口分别对应不同时间点:

text
preview:编辑时看一段文本
inspect:请求前看一次准备结果
explain:事后看历史真相
compare:事后比较两个历史真相

它们不能混在一起。混在一起之后,使用者就会分不清自己看到的是预估结果、请求期结果,还是已经提交的历史事实。

Prompt Runtime 扩展了什么

世界书命中详情解决的是一个局部问题:世界书条目怎样生效。

Prompt Runtime 把这个思路扩展到整个提示词过程。

它把下面这些内容都纳入可观察范围:

  • runtimeTrace.worldbook:世界书命中和注入事实。
  • runtimeTrace.regex:正则规则执行事实。
  • runtimeTrace.memory:记忆摘要、检索和结构化记忆真相。
  • runtimeTrace.macro:宏 warning、使用到的宏、mutation preview 和 staged mutations。
  • runtimeTrace.budgets:预算分配和裁剪原因。
  • runtimeTrace.sourceSelection:来源选择和排除原因。
  • runtimeTrace.visibility:可见性过滤结果。
  • runtimeTrace.preset:预设运行事实和兼容边界。
  • runtimeTrace.delivery:最终发送给模型前的交付事实。

同时,它还保留 prompt_snapshot 这类历史快照,让已经提交的楼层能够被回看。

这样一来,提示词不再只是一个最后拼出来的字符串。它变成了一个可以解释、可以回放、可以比较的运行过程。

为什么不能只看最终 Prompt

有人可能会觉得,只要把最终 prompt 打印出来就够了。

这不够。

最终 prompt 能告诉你“模型看到了什么”,但它不能完整告诉你“这些内容为什么会出现在这里”。

例如:

  • 一段设定是来自世界书,还是来自角色卡。
  • 一条记忆是本轮检索命中的,还是长期摘要注入的。
  • 某段历史为什么没有进入上下文。
  • 某个宏为什么没有展开。
  • 某个变量为什么取了这个值。
  • 某段内容为什么被裁剪。
  • 当前会话为什么使用了这个 prompt mode。

这些问题都不是单靠最终文本能稳定回答的。

最终 prompt 是结果。Prompt Runtime 记录的是结果形成过程。

对于轻量聊天来说,只看结果也许够用。对于需要长期维护的 AI RP 项目来说,只看结果不够。

和 Know What & Know How 的关系

Prompt Runtime 是 Know What & Know How 在提示词层面的落实。

Know What 是:这一轮实际使用了哪些资源、哪些记忆、哪些世界书、哪些变量和哪些历史消息。

Know How 是:它们是怎样被选中、怎样排序、怎样裁剪、怎样进入最终消息的。

没有 Prompt Runtime,提示词组装就是一条隐藏流水线。使用者只能看到输入和输出,中间过程不容易确认。

有了 Prompt Runtime,使用者可以把问题拆开看。

回复不对时,不必马上怀疑模型。可以先看:

  • mode 是否正确。
  • 绑定资源是否正确。
  • 世界书是否命中。
  • 记忆是否注入。
  • 宏和变量是否按预期展开。
  • 历史消息是否被错误裁剪。
  • 预算是否把关键内容挤掉。

这会让排查问题变得更直接。

和 Agentic 的关系

Prompt Runtime 也是后续 Agentic 和 NodeGraph 的基础。

Agentic 系统不能只看到最终回复。它需要知道这条回复是在什么上下文下生成的。

Director 要决定叙事方向,需要知道当前 prompt 里有哪些约束。

Verifier 要检查输出是否违背设定,需要知道哪些设定已经进入模型上下文。

Memory Agent 要判断事实来源,需要知道一段信息来自用户输入、历史消息、世界书,还是记忆注入。

NodeGraph 要做到可解释编排,也需要每个节点的输入、输出、裁剪和失败原因能够被记录。

如果没有 Prompt Runtime,这些 Agentic 能力就很容易变成新的黑箱。

所以 Prompt Runtime 不只是调试接口。它也是后续原生编排和 Agentic 可解释性的底座。

那么,古尔丹,代价是什么呢

扩展观测能力会带来成本。

系统需要维护更多结构化字段。API 要区分 preview、inspect、explain、compare 的边界。SDK 要暴露这些返回结构。文档也要说明这些字段什么时候可信、什么时候只是请求期结果、什么时候是历史真相。

更重要的是,观测能力不能改变被观察的对象。

打开调试开关,不应该让提示词组装行为变化。

读取 explain,不应该重新组装一次 prompt 来覆盖历史事实。

preview 不能假装自己是完整 assembly。

inspect 不能偷偷创建 Floor 或提交副作用。

详细 trace 也不能默认无边界地返回,否则普通响应会变重,内部信息也可能暴露过多。

所以 Prompt Runtime 必须有清楚的能力边界和默认值。该只读的只读,该按需展开的按需展开,该保存历史真相的保存历史真相。

这是额外工作,但它和项目目标一致。

由小至大

世界书命中详情很小,但它说明了一个更大的问题:AI RP 引擎不能只提供能力,还要让使用者看见这些能力怎样生效。

观测能力不应止步于世界书。

提示词组装里的预设、宏、正则、变量、记忆、历史、预算、可见性和交付过程,也都需要有自己的观察位置。

Prompt Runtime 就是这件事的扩展。

它不是为了让普通聊天变复杂。它是为了让复杂项目在出问题时可以被检查、被解释、被比较、被维护。

因为这个观察面很重要,所以它被扩展成了一套 Runtime。