让 AI 队友真正“成长”:从跨局记忆到状态演化的 PHASE-Tree 实践

2026-08-26 32 预计阅读时间: 1 分钟
来源: oschina.net AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:11 分钟

今年 6 月,KRAFTON 与 NVIDIA 将 PUBG Ally 带入公开 Beta。这个 AI 队友不再把每局游戏当成孤立会话:它能够记住玩家偏好的武器、常去的跳点和过往战绩,并在下一局继续使用这些信息。跨局记忆让 AI 从“会聊、会打”迈向“有连续性”,但也带来更难的问题:角色记得过去之后,它的立场、策略和说话方式是否应该随经历变化?

这正是 PHASE-Tree 关注的状态演化难题。记忆只是输入,成长则需要一套可控、可解释、不会失控的状态更新机制。

记住事实,不等于形成角色状态

一个简单的记忆系统可能只保存事件:

{
  "event": "玩家在山地决赛圈选择绕后",
  "outcome": "成功淘汰两名敌人",
  "timestamp": "match-1842"
}

这类记录对检索很有用,但它没有说明 AI 应该如何改变自己。要让角色呈现出“成长”,至少需要区分三层信息:

  • 事件记忆:发生了什么,例如玩家喜欢 M416,或者曾经因为过早冲锋输掉比赛。
  • 归纳认知:从多次事件中提炼出的判断,例如“玩家在资源充足时更愿意主动进攻”。
  • 当前状态:角色此刻的信任度、谨慎程度、主动性、情绪和战术偏好。

事件是证据,认知是解释,状态才是下一次决策真正会读取的变量。如果每次对话都只把历史记录拼进 prompt,AI 可能“说自己记得”,却没有稳定地改变行为。

可以把角色状态抽象成一个随时间变化的向量:

state(t+1) = clamp(
    state(t)
    + learning(event, outcome, feedback)
    - decay(time, contradiction)
    + phase_transition(trigger),
    valid_range
)

这里的关键不是公式本身,而是把状态更新从生成文本中分离出来。语言模型负责理解事件、提出候选更新和表达角色;规则或状态机负责确认哪些变化可以落地。

PHASE-Tree:用阶段和分支组织变化

“成长”不应该意味着所有数值都持续上升。一个经历过背叛的角色可能变得谨慎,也可能因为后来重新建立合作而恢复信任。角色的变化更像一棵树:

  • 阶段(Phase)规定角色当前处于什么发展区间,例如初识、磨合、信任或冲突。
  • 轴(Axis)描述可连续变化的属性,例如信任、冒险倾向、依赖程度和表达直接性。
  • 触发器(Trigger)来自游戏事件,例如连续获胜、关键时刻被救援、违反约定或长时间没有互动。
  • 转移条件(Transition)决定何时进入新阶段,并规定进入后可以改变哪些行为。

例如,“初识”阶段的 AI 可能更多询问玩家意图;进入“信任”阶段后,它可以主动提出战术建议;如果玩家多次违背共同计划,角色进入“戒备”分支,语气和行动都会收缩。

这种设计有两个实际好处。第一,状态变化有边界,产品团队能审查每条转移路径。第二,调试时可以回答“角色为什么这样说”,而不是只能回看一长串 prompt。

一个可改造的最小状态引擎

下面的 Python 示例演示了最小实现。它不是完整游戏 AI,而是可以嵌入服务端的状态更新核心:事件经过规则判断后,修改角色状态并检查阶段转移。运行前只需要 Python 3.10 或更高版本。

from dataclasses import dataclass, field
from typing import Dict


@dataclass
class AllyState:
    phase: str = "初识"
    trust: float = 0.20
    caution: float = 0.50
    initiative: float = 0.40
    facts: Dict[str, str] = field(default_factory=dict)

    def apply_event(self, event: str, outcome: str) -> None:
        self.facts[event] = outcome

        if event == "player_rescued_ally":
            self.trust += 0.20
            self.initiative += 0.05
        elif event == "player_broke_plan":
            self.trust -= 0.15
            self.caution += 0.20
        elif event == "team_won":
            self.trust += 0.05
            self.initiative += 0.05

        self.trust = min(1.0, max(0.0, self.trust))
        self.caution = min(1.0, max(0.0, self.caution))
        self.initiative = min(1.0, max(0.0, self.initiative))
        self._update_phase()

    def _update_phase(self) -> None:
        if self.trust >= 0.70 and self.caution < 0.65:
            self.phase = "信任"
        elif self.trust < 0.15 and self.caution >= 0.70:
            self.phase = "戒备"
        elif self.trust >= 0.40:
            self.phase = "磨合"
        else:
            self.phase = "初识"


state = AllyState()
for event, outcome in [
    ("player_rescued_ally", "玩家在决赛圈救起队友"),
    ("team_won", "小队获胜"),
    ("player_broke_plan", "玩家再次独自冲锋"),
]:
    state.apply_event(event, outcome)
    print({
        "phase": state.phase,
        "trust": round(state.trust, 2),
        "caution": round(state.caution, 2),
        "initiative": round(state.initiative, 2),
    })

在真实项目中,可以把 apply_event 前置为一个事件解析层:由模型将自然语言日志转换为受限的事件类型和参数,再由服务端校验。不要让模型直接返回任意状态值,否则一次异常输出就可能把角色从“合作”跳到“绝对忠诚”。

让状态影响行为,而不只是影响台词

状态演化的验收标准不应是“角色说话更像人”,而应是同一个事件在不同状态下产生不同决策。例如:

输入:敌人在东侧,玩家弹药不足。

初识: “东侧可能有敌人。你想绕开还是观察?”
信任: “我掩护你换弹,我们从北侧压过去。”
戒备: “我不会跟着你冲东侧。先撤到掩体,再决定。”

三种表达背后应该对应不同的行动约束:是否主动标记目标、是否共享资源、是否跟随玩家进入高风险区域。否则,状态只是一个会被 prompt 读取的装饰字段。

可以将决策上下文拆为稳定规则和动态信息:

{
  "character_policy": {
    "never": ["泄露其他玩家隐私", "绕过战术安全限制"],
    "phase_rules": {
      "信任": {"share_loot": true, "risk_tolerance": 0.75},
      "戒备": {"share_loot": false, "risk_tolerance": 0.25}
    }
  },
  "runtime_state": {
    "phase": "信任",
    "trust": 0.78,
    "recent_events": ["player_rescued_ally", "team_won"]
  }
}

模型可以在这个上下文中生成候选计划,但最终动作仍应经过游戏规则、权限和安全检查。

工程落地时要处理的边界

状态不能无限累积。 跨局记忆会越积越多,需要摘要、过期和冲突处理。一次偶然失误不应该永久改变角色;重复发生且结果一致的事件,才适合提升为长期认知。

状态转移必须可回放。 每次更新记录旧状态、事件、规则版本和新状态。出现“角色突然变了”的问题时,开发者才能复现完整路径。

玩家应当拥有可感知的反馈。 角色不必展示内部数值,但可以通过战术建议、资源分配和关系台词让玩家理解变化来自哪里。若成长完全不可预测,玩家感受到的可能不是深度,而是不稳定。

模型输出需要受限。 采用枚举事件、数值范围、阶段白名单和人工审核样本,可以降低提示注入、幻觉归因以及状态漂移的风险。

评测要覆盖长线轨迹。 单轮对话测试无法证明角色会成长。应准备包含成功、失败、矛盾、冷却期和关系修复的多局剧本,检查角色是否保持连续性,也检查它是否有能力改变。

采用清单

可以按下面的顺序启动一个可控版本:

  1. 先定义 5 到 10 个可观测状态轴,并为每个轴设定范围和含义。
  2. 将游戏日志归一化为有限事件类型,区分短期记忆和长期认知。
  3. 用阶段树写出允许的转移条件,禁止模型自行创建新阶段。
  4. 让状态同时影响计划、动作和台词,而不是只改 prompt 中的描述。
  5. 为每次转移保存可回放日志,并用长线剧本做回归测试。
  6. 观察玩家是否能理解变化、是否愿意继续与角色合作,再调整变化速度。

跨局记忆解决的是“AI 还记得什么”,PHASE-Tree 要解决的是“这些经历如何改变它”。当事件、认知、状态和行为之间形成可追踪的闭环,AI 队友才会从一组会话技巧,变成一个能够在长期关系中保持连续性、同时允许变化的游戏角色。


相关推荐