> 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/web-plugins/convai-web-sdk/long-term-memory.md).

# 使用长期记忆

让 Convai 角色记住跨会话的每个最终用户，并从你的 Web 应用中列出、添加或删除这些记忆。

让角色通过连接稳定的终端用户 ID 来跨会话记住某个终端用户，然后通过记忆管理器读取或更改该用户的记忆。当你已识别用户并希望角色记住他们，或者你的应用需要初始化或清理其所记住的内容时，请使用此页面。

### 先决条件

* 已安装 Convai Web SDK 且连接正常。请参见 [Web SDK 快速入门](/api-docs/zh/cha-jian-yu-ji-cheng/web-plugins/convai-web-sdk/quickstart.md).
* 一个 Convai API 密钥或认证令牌，以及来自 <code class="expression">space.vars.dashboard\_url</code>.
* 在 Convai 仪表板中为角色启用长期记忆：打开该角色，选择 **Memory** 选项卡，并在下方启用长期记忆 **记忆设置**.

<figure><img src="https://2402152281-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FEtUJA212Zc1S9ACc8T4l%2Fuploads%2FzXOCfJacFgTrPdKUkmc2%2FMemory.png?alt=media&amp;token=f523e099-b5f8-4236-85ac-bdf32f05a1df" alt="The Memory tab of a character in the Convai dashboard, showing the Memory Settings panel with the long-term memory toggle"><figcaption></figcaption></figure>

### 使用终端用户 ID 连接

传入 `endUserId` 在配置中。任何非空字符串都可接受。使用一个能在每次会话中标识同一人的值，例如 UUID 或电子邮件地址。没有 `endUserId` 该会话是匿名的，并且没有记忆管理器。

{% tabs %}
{% tab title="React" %}

```tsx
import { useConvaiClient } from '@convai/web-sdk/react';

const client = useConvaiClient({
  apiKey: 'YOUR_API_KEY',
  characterId: 'YOUR_CHARACTER_ID',
  endUserId: 'a1b2c3d4-5678-90ab-cdef-1234567890ab',
});
```

{% endtab %}

{% tab title="TypeScript" %}

```typescript
import { ConvaiClient } from '@convai/web-sdk/core';

const client = new ConvaiClient({
  apiKey: 'YOUR_API_KEY',
  characterId: 'YOUR_CHARACTER_ID',
  endUserId: 'a1b2c3d4-5678-90ab-cdef-1234567890ab',
});
```

{% endtab %}
{% endtabs %}

之后 `connect()` 解析后， `client.state.endUserId` 保存的是 Convai 返回的终端用户 ID，它可能与您传入的不同。

### 获取记忆管理器

`client.memoryManager` 是一个 `MemoryManager` 实例或 `null`。SDK 会在连接期间创建它 `connect()` 仅当 Convai 为该会话返回终端用户 ID 且客户端持有一个 `apiKey` 或者一个 `authToken`。它使用与连接相同的凭据。SDK 会将其重置为 `null` 在断开连接时。

```typescript
const memory = client.memoryManager;

if (!memory) {
  // 未连接，或者该会话没有终端用户 ID。
  throw new Error('在使用记忆之前请先使用 endUserId 连接');
}
```

每个方法都限定于该会话的角色 ID 和终端用户 ID。

### 列出记忆

`listMemories()` 接受一个可选的 `{ page, pageSize }` 对象，并返回一页记忆。

```typescript
const result = await memory.listMemories({ page: 1, pageSize: 50 });

console.log(`总数：${result.total_count}，更多页：${result.has_more}`);
for (const m of result.memories) {
  console.log(m.id, m.memory, m.created_at, m.updated_at);
}
```

| 选项         | 类型   | 默认值  | 范围             |
| ---------- | ---- | ---- | -------------- |
| `page`     | `数值` | `1`  | 限制为 `1`–`1000` |
| `pageSize` | `数值` | `50` | 限制为 `1`–`100`  |

响应是一个 `MemoryListResponse` 与 `memories`, `total_count`, `page`, `page_size`，以及 `has_more`. 每个 `Memory` 都具有 `id`, `memory`, `created_at`，以及 `updated_at`; 时间戳为 ISO 字符串。

### 添加记忆

`addMemories()` 接受一个字符串数组。数组为空时会抛出 `必须提供 Memories 数组且不能为空` 当数组为空时。

```typescript
const added = await memory.addMemories([
  '已完成叉车安全模块。',
  '偏好简短步骤的说明。',
]);

for (const m of added.memories) {
  console.log(`已添加 ${m.id}：${m.memory}`);
}
```

每个返回的条目都有 `id`, `事件` （始终 `"ADD"`），以及 `memory`.

### 读取或删除一条记忆

`getMemory()` 返回一个单独的 `Memory`. `deleteMemory()` 返回 `{ message, memory_id, deleted }`。二者都会抛出 `必须提供 Memory ID` 当 ID 为空时。

```typescript
const m = await memory.getMemory('f4cbdb08-7062-4f3e-8eb2-9f5c80dfe64c');
console.log(m.memory);

const result = await memory.deleteMemory(m.id);
if (result.deleted) {
  console.log('已删除', result.memory_id);
}
```

### 删除该终端用户的所有记忆

`deleteAllMemories()` 会移除当前角色与终端用户配对的所有记忆。由于 Convai 上的删除是异步的，响应确认的是请求，而不是结果。

```typescript
const result = await memory.deleteAllMemories();
console.log(result.message, result.character_id, result.end_user_id);
```

{% hint style="warning" %}
删除无法撤销。稍后再次列出记忆，以确认它们已消失后再告诉终端用户。
{% endhint %}

### 在没有会话的情况下使用记忆管理器

导入 `MemoryManager` 来自 `@convai/web-sdk/core` 例如在管理工具中，无需连接即可管理记忆。

```typescript
import { MemoryManager } from '@convai/web-sdk/core';

const manager = new MemoryManager(
  'YOUR_API_KEY',
  'YOUR_CHARACTER_ID',
  'a1b2c3d4-5678-90ab-cdef-1234567890ab',
);

const page = await manager.listMemories();
```

构造函数签名为 `new MemoryManager(apiKeyOrAuthToken, characterId, endUserId, baseUrl?, useAuthToken?)`:

| 参数                  | 类型        | 默认值                        | 描述                                            |
| ------------------- | --------- | -------------------------- | --------------------------------------------- |
| `apiKeyOrAuthToken` | `string`  | 无                          | API 密钥，或者当 `useAuthToken` 是 `true`.           |
| `characterId`       | `string`  | 无                          | 记忆所属的角色。                                      |
| `endUserId`         | `string`  | 无                          | 记忆所属的终端用户。                                    |
| `baseUrl`           | `string`  | `'https://api.convai.com'` | 记忆 API 的源地址。末尾斜杠会被移除。                         |
| `useAuthToken`      | `boolean` | `false`                    | 将凭据发送为 `API-AUTH-TOKEN` 而不是 `CONVAI-API-KEY`. |

构造函数会抛出 `需要提供 API 密钥或认证令牌`, `需要提供角色 ID`，或 `需要提供终端用户 ID` 当参数为空时。要在现有实例上切换作用域，请调用 `setEndUserId()` 或 `setCharacterId()`；使用以下方法读取当前值： `getEndUserId()` 并且 `getCharacterId()`.

### 故障排查

#### 记忆管理器为空

**症状：** `client.memoryManager` 是 `null` 在连接后。

**原因：** 配置中没有 `endUserId`, `connect()` 尚未解析，或者客户端已断开连接。

**修复：** 传入 `endUserId`，并读取 `client.memoryManager` 之后 `connect()` 解析成功。

**验证：** `client.state.endUserId` 是一个字符串，并且 `client.memoryManager` 不在 `null`.

#### 记忆调用会被拒绝

**症状：** 一个 `MemoryManager` 方法会以一个 `错误`.

**原因：** Convai 拒绝了该请求。错误消息是响应中的 `ERROR` 字段，或者 `HTTP 错误！状态：<code>` 当响应中没有该字段时。

**修复：** 请检查消息中的凭据、角色 ID 和记忆 ID。

**验证：** `listMemories()` 会按预期解析为 `total_count`.

### 后续步骤

{% content-ref url="/pages/534e8cdc1d57114dcd7601d4455823f77a9ad2ef" %}
[使用认证令牌连接](/api-docs/zh/cha-jian-yu-ji-cheng/web-plugins/convai-web-sdk/auth-tokens.md)
{% endcontent-ref %}

{% content-ref url="/pages/f1fc7386520b3ebeeafa719a8d9efb554e1d7024" %}
[ConvaiClient 参考](/api-docs/zh/cha-jian-yu-ji-cheng/web-plugins/convai-web-sdk/vanilla-typescript/convaiclient-core-api.md)
{% endcontent-ref %}

{% content-ref url="/pages/dff296725774f9173a7391e28344f5f94cf35b60" %}
[配置和类型参考](/api-docs/zh/cha-jian-yu-ji-cheng/web-plugins/convai-web-sdk/vanilla-typescript/best-practices-and-type-definitions.md)
{% endcontent-ref %}


---

# 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/web-plugins/convai-web-sdk/long-term-memory.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.
