> For the complete documentation index, see [llms.txt](https://docs.convai.com/api-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.convai.com/api-docs/zh/cha-jian-yu-ji-cheng/unity-plugin-beta-overview/dynamic-context-1.md).

# 动态上下文

## 简介

Convai 角色有两层上下文：

* **角色级别** ——背景故事、个性和行为规则。配置在 Convai 仪表板中，并在所有会话中持续保留。
* **会话级别** ——仅与当前交互相关的信息：玩家是谁、刚刚发生了什么、当前游戏状态。

Dynamic Context 是 Convai Unity SDK 的运行时功能，可让你的游戏在活动对话期间向 Convai AI 角色推送短暂的、会话特定的信息。与在 Convai 仪表板中配置的角色固定背景故事不同，Dynamic Context 是在运行时注入的，并且是临时的——它只在当前会话期间存在。

可用它来弥合游戏世界与 AI 之间的鸿沟：告诉角色刚刚发生了什么、玩家是谁、他们携带了什么、身处何处，或任何其他应当影响角色回复、但不应硬编码进提示词的内容。

***

## 工作原理

当你调用 `UpdateDynamicContext`，SDK 会序列化一个 `上下文更新` 消息，并通过活动会话的数据通道将其发送到 Convai 后端。后端接收该更新，并在处理下一条用户输入之前，把新信息折叠进角色的活动上下文窗口。

流程如下：

```
你的游戏代码
      │
      ▼
ConvaiRoomManager.UpdateDynamicContext(text, mode, runLlm)
      │
      ▼
通过会话数据通道发送的序列化上下文更新消息
      │
      ▼
Convai 后端 → LLM 上下文窗口
```

这是一个 **即发即弃、仅出站** 操作。上下文更新本身没有直接响应——其效果会体现在角色下一次开口回复中。

***

## 关键概念

在编写任何代码之前，请先了解控制每次 `UpdateDynamicContext` 调用的这三个参数。

#### `text`

你希望角色知晓的内容。这是一个普通字符串——它可以是一句完整的话、一个结构化段落，或者你喜欢的任何格式的键值数据。

```
“玩家的名字是 Aria。她是 12 级，目前正在进行任务‘迷雾中的失落’。”
```

`text` 为 **必需** 用于 `追加` 是位于 `替换` 模式。在使用 `重置` 模式时，会被忽略。

***

#### `模式`

控制如何将新文本应用到角色现有的临时上下文中。

| 模式   | 行为                                | 何时使用                  |
| ---- | --------------------------------- | --------------------- |
| `追加` | 将 `text` 添加到任何现有的临时上下文中。先前的条目会保留。 | 逐步添加信息——在会话展开时不断补充事实。 |
| `替换` | 丢弃所有当前的临时上下文，并用新的内容完全替换它。 `text`. | 干净的状态切换——进入新场景、开始新章节。 |
| `重置` | 清除所有运行时临时上下文。 `text` 会被忽略。        | 重置所有已累积的运行时上下文。       |

**默认值：** `"append"`

***

#### `runLlm`

在上下文更新之后是否触发一次 LLM 推理。

| 值       | 行为                           |
| ------- | ---------------------------- |
| `自动`    | 服务器会根据其内部流水线状态来决定。推荐用于大多数用例。 |
| `true`  | 在上下文更新之后总是立即触发一次 LLM 回复。     |
| `false` | 静默更新上下文——不会触发 LLM 回复。        |

**默认值：** `"auto"`

使用 `"false"` 当你批量发送多个上下文更新，并且只希望 LLM 在最后一次之后才作出回应时使用 `"true"` 当上下文更新本身应当引发角色反应时使用。

***

## 访问 API

Dynamic Context 通过 `ConvaiRoomManager`，这是 Convai Unity SDK 的中央会话管理器。它可通过 `ConvaiRoomManager.Instance`.

以持久单例的形式访问。根据谁拥有连接生命周期，存在两种不同模式。

### 模式 A——自包含

在该组件负责自身初始化时使用。

所需的就绪级别取决于 `runLlm`:

* **`runLlm: "false"` 或 `"auto"`** ——等待 `IsConnectedToRoom` 就足够了。上下文会被静默注入，不会期待立即的音频响应。
* **`runLlm: "true"`** ——在发送前，完整的音频流水线必须就绪。参见下面的说明。

```csharp
using System.Collections;
using Convai.Scripts;
using UnityEngine;

public class ExampleSelfContained : MonoBehaviour
{
    private ConvaiRoomManager _roomManager;

    private IEnumerator Start()
    {
        // 轮询直到 ConvaiRoomManager 单例可用。
        // 在正常情况下会在一两帧内解析完成。
        while (ConvaiRoomManager.Instance == null)
            yield return null;

        _roomManager = ConvaiRoomManager.Instance;

        // 等待房间连接建立。
        // 先检查 IsConnectedToRoom：如果此组件在会话已经建立后才初始化，
        // OnRoomConnectionSuccessful 将永远不会触发。
        if (!_roomManager.IsConnectedToRoom)
        {
            bool connected = false;
            _roomManager.OnRoomConnectionSuccessful.AddListener(() => connected = true);
            yield return new WaitUntil(() => connected);
        }

        OnReady();
    }

    private void OnReady()
    {
        bool sent = _roomManager.UpdateDynamicContext("...", mode: "replace", runLlm: "false");
        if (!sent)
            Debug.LogWarning("[Example] UpdateDynamicContext returned false.");
    }

    private void OnDestroy()
    {
        if (_roomManager != null)
            _roomManager.OnRoomConnectionSuccessful.RemoveListener(OnConnected);
    }

    private void OnConnected() { }
}
```

{% hint style="warning" %}
**如果你使用 `runLlm: "true"` 来触发即时角色回复**，等待 `IsConnectedToRoom` 还不够。角色的音频流水线在房间连接后会经历三个异步阶段：机器人参与者加入、音轨订阅，以及音频缓冲区初始化。在这三者全部完成之前发送，会导致服务器的 TTS 响应被静默丢弃。

请改用下面的模式：

```csharp
using System.Collections;
using System.Linq;
using Convai.Scripts;
using UnityEngine;

public class ExampleImmediateGreeting : MonoBehaviour
{
    private ConvaiRoomManager _roomManager;

    private IEnumerator Start()
    {
        while (ConvaiRoomManager.Instance == null)
            yield return null;

        _roomManager = ConvaiRoomManager.Instance;

        while (!_roomManager.IsConnectedToRoom)
            yield return null;

        // 等待直到机器人的音频流水线完全就绪：
        //   1. 机器人参与者已加入房间      (ParticipantConnected)
        //   2. 机器人的音轨已发布           (TrackPublished)
        //   3. 音轨已订阅                   (TrackSubscribed)
        //   4. 已调用 AudioSource.Play()     (AudioStream 构造函数)
        while (_roomManager.NpcToParticipantMap == null ||
               !_roomManager.NpcToParticipantMap.Values.Any(d => d.AudioStream != null))
        {
            yield return null;
        }

        bool sent = _roomManager.UpdateDynamicContext("...", mode: "replace", runLlm: "true");
        if (!sent)
            Debug.LogWarning("[Example] UpdateDynamicContext returned false.");
    }
}
```

{% endhint %}

***

### 模式 B——注入

在会话协调器或父系统负责提供 room manager 时使用。该组件假定在调用其公共方法时，管理器有效。

```csharp
using Convai.Scripts;
using UnityEngine;

public class ExampleInjected : MonoBehaviour
{
    private ConvaiRoomManager _roomManager;

    /// <summary>
    /// 使用当前活动的 room manager 初始化此组件。
    /// 必须在 Convai 会话建立后由会话所有者调用。
    /// </summary>
    public void Initialize(ConvaiRoomManager roomManager)
    {
        _roomManager = roomManager;
    }

    public void DoSomething()
    {
        // ?. 用于防止尚未调用 Initialize。
        bool sent = _roomManager?.UpdateDynamicContext("...", mode: "append", runLlm: "false") ?? false;
        if (!sent)
            Debug.LogWarning("[Example] UpdateDynamicContext returned false.");
    }
}
```

{% hint style="info" %}
`UpdateDynamicContext` 返回 `false` 如果会话未连接。务必检查返回值。
{% endhint %}

***

## API 参考

```csharp
bool UpdateDynamicContext(string text, string mode = "append", string runLlm = "auto");
```

可用于 `ConvaiRoomManager`。也可通过 `ConvaiNPC.UpdateDynamicContext(...)`调用，它会内部委托给 `ConvaiRoomManager.Instance` 。

| 参数       | 类型       | 所需      | 默认值        | 说明                                            |
| -------- | -------- | ------- | ---------- | --------------------------------------------- |
| `text`   | `string` | 是（除非重置） | —          | 要注入的上下文文本。                                    |
| `模式`     | `string` | 没有      | `"append"` | 如何应用该文本： `"append"`, `"replace"`，或 `"reset"`. |
| `runLlm` | `string` | 没有      | `"auto"`   | 是否触发 LLM 回复： `"true"`, `"false"`, `"auto"`.   |

**返回：** `true` 如果消息已发送到传输层； `false` 如果会话未连接（RTVIHandler 尚未初始化）或者 `text` 为空且 `模式` 不是 `"reset"`.

***

#### **`模式`**

控制如何将新文本应用到角色现有的临时上下文中。

| 模式   | 行为                                | 何时使用                  |
| ---- | --------------------------------- | --------------------- |
| `追加` | 将 `text` 添加到任何现有的临时上下文中。先前的条目会保留。 | 逐步添加信息——在会话展开时不断补充事实。 |
| `替换` | 丢弃所有当前的临时上下文，并用新的内容完全替换它。 `text`. | 干净的状态切换——进入新场景、开始新章节。 |
| `重置` | 清除所有运行时临时上下文。 `text` 会被忽略。        | 重置所有已累积的运行时上下文。       |

**默认值：** `"append"`

***

## 常见陷阱

* **在会话连接前调用** `UpdateDynamicContext` 返回 `false` 并静默丢弃该更新。请使用协程或订阅 `ConvaiRoomManager.OnRoomConnectionSuccessful` （一个 `UnityEvent`）来延迟上下文注入，直到会话处于活动状态。
* **使用 `追加` 无限期地** 每个 `追加` 会扩展上下文窗口。在长会话中，这会降低回复连贯性并增加延迟。请使用 `替换` 定期地，或采用 `DynamicContextManager` 模式。
* **发送 `text` 其带有 `重置` 模式** `text` 在 `模式` 为 `"reset"`时会被忽略。请 `null` 显式传入，以使意图清晰。
* **期望同步效果** Dynamic Context 在端到端上是异步的。在下一次 LLM 推理之前，角色不会知道这次更新。不要设计依赖即时生效的逻辑。
* **过度使用 `runLlm: "true"`** 每次更新都强制立即响应会造成对话噪音。仅在确实期望角色作出反应的时刻使用它。

***

## 快速参考

```csharp
ConvaiRoomManager room = ConvaiRoomManager.Instance;

// 将新信息追加到现有的临时上下文中（默认）
room.UpdateDynamicContext("Player just entered the dungeon.");

// 用新内容替换所有临时上下文
room.UpdateDynamicContext("Player is now in Act 2.", mode: "replace");

// 清除所有临时上下文
room.UpdateDynamicContext(null, mode: "reset");

// 静默累积（无 LLM 回复）
room.UpdateDynamicContext("Player picked up the golden key.", runLlm: "false");

// 更新并触发即时角色回复
room.UpdateDynamicContext("The village is on fire!", runLlm: "true");

// 注入情绪状态
room.UpdateDynamicContext("Speak with urgency. A threat is approaching.", mode: "replace", runLlm: "false");
```

***

## 结论

Dynamic Context 是连接游戏或应用程序的实时状态与 AI 角色对其理解之间的桥梁。角色的永久配置——个性、背景故事、行为规则——保持在 Convai 仪表板中稳定不变。所有属于本次会话、这个用户和这一刻的内容都通过 `UpdateDynamicContext`.

API 的设计刻意保持简洁：一个方法，三个参数。复杂性体现在你如何使用它——无论是在会话开始时个性化对话，在会话中途响应阈值变化，静默累积事件直到值得评论，还是在整个训练会话中跟踪能力差距。

下面有几条原则值得记住：

* **静默更新是默认姿态。** 使用 `runLlm: "false"` 用于状态同步。保留 `runLlm: "true"` 给真正值得角色响应的时刻。
* **把上下文窗口视为一种资源。** 无限制的 `追加` 会随着时间推移降低质量。请在 `替换` 这样的自然边界使用——场景切换、模块变更、会话重置。
* **你的应用程序负责状态。角色接收它。** Dynamic Context 正是让这种分离得以清晰落实的机制。

{% hint style="info" %}
**需要帮助？** 如有疑问，请访问 [**Convai 开发者论坛**](https://forum.convai.com/).
{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.convai.com/api-docs/zh/cha-jian-yu-ji-cheng/unity-plugin-beta-overview/dynamic-context-1.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
