> 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).

# 动态上下文

了解动态上下文如何实现更相关、更自适应、且具上下文感知的 AI 角色交互。

## 简介

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` 是 **必需** 用于 `append` 和 `replace` 模式。当使用 `reset` 模式时，将被忽略。

***

#### `模式`

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

| 模式        | 行为                               | 使用时机                    |
| --------- | -------------------------------- | ----------------------- |
| `append`  | 添加 `text` 到任何现有的临时上下文中。先前的条目会保留。 | 渐进式信息——在会话展开过程中逐步添加事实。  |
| `replace` | 丢弃所有当前的临时上下文，并将其完全替换为新的 `text`.  | 一次干净的状态切换——进入新场景，开启新章节。 |
| `reset`   | 清除所有运行时临时上下文。 `text` 会被忽略。       | 重置所有已累积的运行时上下文。         |

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

***

#### `runLlm`

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

| 值       | 行为                           |
| ------- | ---------------------------- |
| `auto`  | 服务器会根据其内部流水线状态来决定。推荐大多数用例使用。 |
| `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 返回 false。");
    }

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

    private void OnConnected() { }
}
```

{% hint style="warning" %}
**如果你使用 `runLlm: "true"` 来触发角色立即响应**，仅等待 `IsConnectedToRoom` 还不够。角色的音频管线在房间连接后会经历三个异步阶段：bot 参与者加入、音轨订阅，以及音频缓冲区初始化。在这三步全部完成之前发送，会导致服务器的 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;

        // 等到 bot 的音频管线完全就绪：
        //   1. bot 参与者已加入房间      (ParticipantConnected)
        //   2. bot 音轨已发布           (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 返回 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 返回 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` | 是（除非 reset） | —          | 要注入的上下文文本。                                    |
| `模式`     | `string` | 没有          | `"append"` | 如何应用该文本： `"append"`, `"replace"`，或 `"reset"`. |
| `runLlm` | `string` | 没有          | `"auto"`   | 是否触发 LLM 响应： `"true"`, `"false"`, `"auto"`.   |

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

***

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

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

| 模式        | 行为                               | 使用时机                    |
| --------- | -------------------------------- | ----------------------- |
| `append`  | 添加 `text` 到任何现有的临时上下文中。先前的条目会保留。 | 渐进式信息——在会话展开过程中逐步添加事实。  |
| `replace` | 丢弃所有当前的临时上下文，并将其完全替换为新的 `text`.  | 一次干净的状态切换——进入新场景，开启新章节。 |
| `reset`   | 清除所有运行时临时上下文。 `text` 会被忽略。       | 重置所有已累积的运行时上下文。         |

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

***

## 常见陷阱

* **在会话连接前调用** `UpdateDynamicContext` 返回 `false` 并静默丢弃更新。请使用协程，或订阅 `ConvaiRoomManager.OnRoomConnectionSuccessful` （一个 `UnityEvent`）以便在会话上线前延迟上下文注入。
* **使用 `append` 无限期** 每个 `append` 会扩展上下文窗口。在长会话中，这会降低响应连贯性并增加延迟。请使用 `replace` 定期地，或者采用 `DynamicContextManager` 模式。
* **发送 `text` 使用 `reset` 模式** `text` 在以下情况下会被忽略： `模式` 是 `"reset"`。请传入 `null` 以明确表达意图。
* **期望同步效果** 动态上下文在端到端上是异步的。角色要到下一次 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"` 给真正值得角色响应的时刻。
* **将上下文窗口视为一种资源。** 无上限的 `append` 会随着时间推移降低质量。请使用 `replace` 在自然边界处——场景切换、模块变更、会话重置。
* **你的应用拥有状态。角色接收它。** 动态上下文正是干净地强制这种分离的机制。

{% 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 by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

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

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

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.
