Skip to content

动态 AI 人格切换

做几个按钮,一键切换 AI 的人格、说话风格或语言。使用「告诉 AI」和「停止告诉 AI」来动态修改 AI 的系统提示词 -- 不需要重启会话,在对话中途无缝切换。


你将构建什么

一个嵌入聊天中的人格切换器:

  • 三种模式 -- 普通叙事、喜剧模式、恐怖模式
  • 一键切换 -- 点击按钮即可改变 AI 的说话风格,立即生效
  • 视觉反馈 -- 当前激活的模式按钮会高亮显示,玩家始终知道当前处于什么模式
  • 无缝过渡 -- 切换不会中断对话;AI 的下一条回复就会使用新风格

工作原理

Yumina 的行为系统有两个强大的动作:「告诉 AI」和「停止告诉 AI」。

  • 告诉 AIinject-directive)-- 向 AI 的系统提示词中注入一条指令。只要指令存在,AI 在每次回复时都能看到并遵循它。你可以指定它在提示词中的位置、是否永久存在,以及多少轮后自动过期。
  • 停止告诉 AIremove-directive)-- 通过 ID 移除之前注入的指令。一旦移除,AI 就不再看到该指令。

将这两个动作组合使用,我们可以这样做:

玩家点击「喜剧模式」按钮
  → 行为触发:先移除旧的人格指令(如果有的话)
  → 然后注入新的喜剧风格指令
  → AI 的系统提示词中现在包含:「用幽默、有趣的语气叙述一切……」
  → AI 的下一条回复转变为喜剧风格

这和知识条目有什么区别? 知识条目(启用条目/禁用条目)非常适合大段的世界观文本。通过「告诉 AI」注入的指令更轻量、更灵活 -- 它们不是条目,而是直接插入系统提示词中的小片段文本。非常适合简短的风格指令、临时规则或一次性提示。你可以同时使用两者。


逐步操作

第 1 步:创建变量

我们需要一个变量来跟踪当前激活的模式。Root Component 读取它来决定高亮哪个按钮。

编辑器 → 侧边栏 → 变量 选项卡 → 点击「添加变量」

字段原因
显示名称Current Mode供你自己参考
IDcurrent_mode行为和 Root Component 通过此 ID 读写
类型String因为值是文本("normal""comedy""horror"
默认值normal新会话从普通模式开始
分类Custom人格系统专用分类
行为规则Do not modify this variable. It is controlled by the player's UI buttons.告诉 AI 不要自行修改 -- 只有玩家按钮可以

第 2 步:创建行为

我们需要 3 个行为 -- 每种模式一个。每个行为的逻辑是:移除旧指令 → 注入新指令 → 更新变量 → 通知玩家

编辑器 → 行为 选项卡 → 逐个添加行为

行为 1:切换到喜剧模式

WHEN(触发器):

字段原因
触发类型Action当代码调用 executeAction("mode-comedy") 时触发
Action IDmode-comedyRoot Component 中的按钮调用此 ID

DO(动作):

按顺序添加以下动作:

#动作类型设置用途
1停止告诉 AI指令 ID:personality-override移除之前的人格指令(如果有的话)。如果不存在,什么都不会发生 -- 不会报错
2告诉 AI指令 ID:personality-override,内容见下方,位置:角色定义之后注入喜剧风格指令
3修改变量current_mode 设为 comedy更新变量,让 Root Component 知道当前模式
4显示通知消息:Switched to Comedy Mode,样式:info给玩家视觉反馈

「告诉 AI」指令内容:

[Narration Style: Comedy Mode]
From now on, narrate everything in a humorous, comedic tone. You may:
- Use exaggerated metaphors and absurd analogies
- Occasionally break the fourth wall and whisper asides to the reader
- Have NPCs deliver hilariously ill-timed lines
- Describe serious scenes in a lighthearted voice for comedic contrast
Keep the story moving — don't just tell jokes. Humor should be woven into the narration, not replace it.

为什么在「告诉 AI」之前要「停止告诉 AI」? 因为两个指令使用相同的 ID(personality-override)。如果玩家从恐怖模式切换到喜剧模式,不先移除旧指令的话,需要依赖 injectDirective 自动替换同一 ID -- 它确实会这样做 -- 但显式地先移除再注入是更好的习惯。逻辑更清晰,也避免了潜在的边界情况。


行为 2:切换到恐怖模式

WHEN:

字段
触发类型Action
Action IDmode-horror

DO:

#动作类型设置用途
1停止告诉 AI指令 ID:personality-override移除旧的人格指令
2告诉 AI指令 ID:personality-override,内容见下方,位置:角色定义之后注入恐怖风格指令
3修改变量current_mode 设为 horror更新变量
4显示通知消息:Switched to Horror Mode,样式:danger使用 danger 样式的通知 -- 红色符合恐怖氛围

「告诉 AI」指令内容:

[Narration Style: Horror Mode]
From now on, narrate everything with a dark, unsettling atmosphere. You should:
- Use slow, oppressive pacing for scene descriptions, focusing on sensory details (sounds, smells, textures)
- Hint that something is watching the character from the shadows, but never reveal it directly
- Make the environment itself feel wrong — doors close on their own, shadows move the wrong way, reflections in mirrors lag by half a beat
- Give NPCs dialogue with subtle wrongness, as if they know something they shouldn't
- Occasionally use second person to describe the character's physiological reactions (neck hairs standing up, heartbeat quickening, pupils dilating)
Build sustained tension, but don't throw a monster into every paragraph. True horror lives in the unknown.

行为 3:切换回普通模式

WHEN:

字段
触发类型Action
Action IDmode-normal

DO:

#动作类型设置用途
1停止告诉 AI指令 ID:personality-override移除自定义人格指令。移除后,系统提示词中不再有风格覆盖 -- AI 回退到默认叙事风格
2修改变量current_mode 设为 normal更新变量
3显示通知消息:Restored Normal Mode,样式:info反馈

注意: 普通模式不注入任何指令。只要移除之前的覆盖就够了 -- AI 会恢复到你在角色条目和系统指令中定义的默认风格。


第 3 步:理解指令位置和持久性

配置「告诉 AI」动作时,你会看到两个重要设置:位置持久性/轮次时长。以下是它们的含义。

指令位置

位置控制注入的指令在系统提示词中出现的位置。

位置标签描述何时使用
auto自动引擎选择最佳位置(通常在角色定义之后)大多数情况下足够用
top顶部系统提示词的最开头,最高优先级紧急全局规则(例如「从现在开始只用英文回复」)
before_char角色定义之前在角色定义之前影响 AI 如何解读角色的全局设置
after_char角色定义之后在角色定义之后风格指令、语气调整(本食谱使用这个)
bottom底部系统提示词的最末尾最后提醒、「越狱」式指令
depth深度按深度插入(在倒数第 N 条最近消息之前)需要出现在对话中间而非系统提示词中的指令

为什么本食谱使用「角色定义之后」? 因为人格切换指令是叙事风格的覆盖。放在角色定义之后,AI 先读到「我是谁」(角色),然后读到「我应该怎么说话」(风格指令)。顺序自然,效果最好。

持久性 vs. 临时指令

设置描述用途
持久(默认)指令一直留在系统提示词中,直到被「停止告诉 AI」显式移除本食谱使用此设置 -- 模式保持激活,直到玩家再次切换
临时(设置轮次时长)指令在指定轮次数后自动过期适合一次性效果,例如「接下来 3 轮,角色喝醉了说话含糊不清」

示例: 如果你在「告诉 AI」动作中将轮次时长设为 3,指令会在注入后第 3 轮结束时自动消失 -- 不需要手动移除。


第 4 步:在 Root Component 中添加模式切换按钮

在最后一条消息下方显示三个模式按钮。当前激活的模式按钮会高亮显示。

编辑器 → 自定义 UI 部分 → 打开 index.tsx → 粘贴以下代码(替换默认的 return <Chat />):

tsx
export default function MyWorld() {
  const api = useYumina();

  // ---- 读取当前模式 ----
  const currentMode = String(api.variables.current_mode || "normal");

  // ---- 三种模式配置 ----
  const modes = [
    {
      id: "normal",
      label: "Normal",
      actionId: "mode-normal",
      color: "#94a3b8",
      activeColor: "#e2e8f0",
      activeBg: "rgba(148,163,184,0.2)",
      border: "#475569",
      activeBorder: "#94a3b8",
    },
    {
      id: "comedy",
      label: "Comedy",
      actionId: "mode-comedy",
      color: "#fbbf24",
      activeColor: "#fef3c7",
      activeBg: "rgba(251,191,36,0.2)",
      border: "#a16207",
      activeBorder: "#fbbf24",
    },
    {
      id: "horror",
      label: "Horror",
      actionId: "mode-horror",
      color: "#f87171",
      activeColor: "#fecaca",
      activeBg: "rgba(248,113,113,0.2)",
      border: "#991b1b",
      activeBorder: "#f87171",
    },
  ];

  // ---- 消息列表,用于找到最后一条 ----
  const msgs = api.messages || [];

  return (
    <Chat renderBubble={(msg) => {
      const isLastMsg = msg.messageIndex === msgs.length - 1;
      return (
    <div>
      {/* 正常渲染消息文本(平台已将 Markdown 转为 HTML -- 直接使用 contentHtml) */}
      <div
        style={{ color: "#e2e8f0", lineHeight: 1.7 }}
        dangerouslySetInnerHTML={{ __html: msg.contentHtml }}
      />

      {/* 模式切换按钮 -- 仅在最后一条消息上 */}
      {isLastMsg && (
        <div style={{
          display: "flex",
          gap: "8px",
          marginTop: "16px",
          flexWrap: "wrap",
        }}>
          {modes.map((mode) => {
            const isActive = currentMode === mode.id;
            return (
              <button
                key={mode.id}
                onClick={() => {
                  if (!isActive) {
                    api.executeAction(mode.actionId);
                  }
                }}
                style={{
                  padding: "8px 16px",
                  background: isActive ? mode.activeBg : "transparent",
                  border: `2px solid ${isActive ? mode.activeBorder : mode.border}`,
                  borderRadius: "8px",
                  color: isActive ? mode.activeColor : mode.color,
                  fontSize: "13px",
                  fontWeight: isActive ? "700" : "500",
                  cursor: isActive ? "default" : "pointer",
                  opacity: isActive ? 1 : 0.7,
                  transition: "all 0.2s ease",
                }}
              >
                {isActive ? "● " : ""}{mode.label}
              </button>
            );
          })}
        </div>
      )}
    </div>
      );
    }} />
  );
}

逐行说明:

  • api.variables.current_mode -- 读取当前模式变量的值
  • modes -- 一个数组,定义了每种模式的 ID、显示标签、对应的行为 action ID 和颜色配置
  • isActive -- 检查当前模式是否匹配此按钮的模式。如果匹配,按钮高亮显示;否则灰色半透明
  • api.executeAction(mode.actionId) -- 触发我们在第 2 步创建的行为。注意只有在 !isActive 时才触发 -- 如果你已经在此模式中,点击什么都不做
  • "● " -- 激活的按钮获得一个小圆点前缀作为视觉指示
  • transition: "all 0.2s ease" -- 按钮状态变化时的平滑动画

不想自己写代码?使用 Studio AI

编辑器顶部 → 点击「进入 Studio」→ AI 助手面板 → 用自然语言描述你想要什么,AI 会为你生成代码。


第 5 步:保存并测试

  1. 点击编辑器顶部的 保存
  2. 点击 开始游戏 或返回主页开始新会话
  3. 正常与 AI 聊几轮 -- 你处于普通模式
  4. 点击 Comedy 按钮 -- 按钮高亮为金色,通知显示「Switched to Comedy Mode」
  5. 发送一条消息 -- AI 的回复应该变得幽默、夸张,可能还会打破第四面墙
  6. 点击 Horror 按钮 -- 按钮高亮为红色
  7. 再发送一条消息 -- AI 的回复变得阴暗、紧张,充满不安的暗示
  8. 点击 Normal 按钮 -- 回到默认风格
  9. 再发一条消息 -- 确认 AI 已恢复正常叙事

如果出了问题:

症状可能原因修复方法
看不到模式按钮Root Component 代码没有保存或有语法错误检查自定义 UI 面板底部的编译状态 -- 应该显示绿色「OK」
点击按钮没有反应行为的 action ID 与代码不匹配确认行为的 action ID 是 mode-comedymode-horrormode-normal,与代码中 executeAction() 的参数一致
按钮状态没有变化变量没有被行为更新检查每个行为的「修改变量」动作是否正确设置了 current_mode
切换后 AI 风格没有变化指令内容为空或位置不对检查「告诉 AI」动作中是否填写了指令内容,位置是否设为「角色定义之后」
切回普通模式后风格依然保留「停止告诉 AI」的指令 ID 不匹配确认所有三个行为都使用相同的指令 ID:personality-override

进阶用法

添加更多模式

想添加一个「诗意模式」?只需:

  1. modes 数组中添加一个条目(ID、标签、颜色)
  2. 创建一个新行为,action ID 为 mode-poetic,与喜剧/恐怖相同的动作模式(移除旧指令 → 注入新指令 → 更新变量 → 通知)
  3. 完成。按钮会自动出现在 Root Component 中

使用轮次限制的临时「人格爆发」

假设你想要一个「醉酒按钮」-- 点击后 AI 以醉态说话 3 轮,然后自动恢复:

在「告诉 AI」动作中,将轮次时长设为 3。指令在 3 轮后自动过期 -- 不需要玩家再次点击取消。

语言切换

同样的模式也适用于切换 AI 的回复语言。将指令内容改为「From now on reply entirely in English」或「从现在开始用日语回复」,你就有了一个语言切换器。


快速参考

你想做什么怎么做
动态修改 AI 的系统提示词在行为动作中使用「告诉 AI」(inject-directive)-- 填写指令 ID、内容和位置
移除之前注入的指令使用「停止告诉 AI」(remove-directive)-- 填写要移除的指令 ID
让指令在 N 轮后自动过期在「告诉 AI」中设置轮次时长
永久保留指令(直到手动移除)不设置轮次时长(默认行为)
将风格指令放在角色定义之后将位置设为「角色定义之后」(after_char
将紧急规则覆盖放在顶部将位置设为「顶部」(top
将最后提醒放在末尾将位置设为「底部」(bottom
切换前移除旧指令使用相同的指令 ID -- 先「停止告诉 AI」,再「告诉 AI」
高亮显示激活的按钮在 Root Component 中读取变量,使用条件样式(isActive)控制高亮

自己试试 -- 可导入的演示世界

下载此 JSON 并作为新世界导入,查看完整效果:

recipe-11-demo.json

如何导入:

  1. 前往 Yumina → 我的世界创建新世界
  2. 在编辑器中,点击 更多操作导入包
  3. 选择下载的 .json 文件
  4. 一个新世界会被创建,所有变量、行为和 Root Component 都已预配置
  5. 开始新会话并试用

包含内容:

  • 1 个变量(current_mode 跟踪当前激活的人格模式)
  • 3 个行为(切换到喜剧 / 切换到恐怖 / 恢复普通)
  • 一个 Root Component(三个带高亮指示的模式切换按钮)

这是食谱 #11

本食谱演示了「告诉 AI」/「停止告诉 AI」的核心用法 -- 动态地在系统提示词中注入和移除指令。同样的模式可以用于语言切换、难度调整、叙事视角切换(第一人称/第三人称),甚至「AI 人格渐变」(每隔几轮自动注入不同强度的指令)。