# 机器人记忆系统开发设计笔记

> 本文档记录了开发记忆系统时的一些设计思路和实现细节，以及一些遇到的问题和解决方案。本文档的目的是为了记录该系统在设计开发过程中的一些思考，以便日后回顾和参考。本文档的内容可能会随着开发的进展而不断更新，也可能会被删除。

## 1. 问题

### 1.1. 为什么要开发记忆系统？

由于 GPT3.5 模型的单次响应只能接收 4096 tokens，而我们希望 bot 能够在更长地时间范围内记忆会话中的信息，因此需要开发一个记忆系统，用于存储和检索会话中的信息。其根本目的是为了让 bot 的 “人格特征” 更加丰富，让 TA 拥有 “回忆” 的能力，拓宽数字生命的边界。

### 1.2. 为什么要使用外置记忆库？

外置记忆系统空间更大，可以保存更细节的对话信息，通过设计合理的数据结构和检索方法，可以更好地实现对话信息的细节化存储和检索。以支持更丰富的长期对话记忆，增强 bot 的人格特征。

### 1.3. 为什么要使用 sqlite 数据库？

sqlite 数据库是一个轻量级的数据库，可以在不同的平台上运行，而且可以通过 python 的 sqlite3 模块进行操作，方便快捷。同时，sqlite 数据库的数据存储在一个单独的文件中，可以方便地进行备份和迁移。

## 2. 设计

### 2.1. 记忆信息块

记忆信息块是指存储在记忆库中的对话信息，可以是一段对话，也可以是一段对话的摘要。记忆信息块的设计有两种

#### 2.1.1. 方案 1. 记忆信息块存储 bot 在会话中的聊天记录 (中立视角记录)

记忆信息块存储 bot 在会话中的聊天记录，包括用户的输入和 bot 的输出。

#### 2.1.2. 方案 2. 记忆信息块存储 bot 在会话中的聊天记录摘要 (主观视角记录)

记忆信息块存储 bot 在会话中的聊天记录摘要，对话过程中每经过特定轮次，就会生成一个摘要和一个索引标签（由 bot 总结和其它分词工具共同生成），摘要是对会话中的信息进行抽象和总结，索引标签是用于检索的关键词。

### 2.2. 记忆方法

当 bot 需要记忆信息时，需要给出一个记忆标签，记忆标签可以是一个关键词，也可以是一个关键词列表（即多个关键词），同时给出一个记忆的重要程度指数，记忆的重要程度指数越高，记忆的优先级越高。

### 2.3. 检索方法

#### 2.3.1. 检索方法 1. bot 主动检索/用户要求检索

在 bot 需要检索记忆信息块时，需要给出一个检索标签，检索标签可以是一个关键词，也可以是一个关键词列表（即多个关键词）。检索方法可以是：

1. 检索标签与记忆信息块的索引标签完全匹配 (优先级最高)

2. 检索标签与记忆信息块的索引标签部分匹配 (优先级次之)

3. 检索标签与记忆信息块的内容完全匹配 (优先级最低)

4. 检索标签与记忆信息块的内容部分匹配 (优先级最低)

#### 2.3.2. 检索方法 2. 被动检索（插件根据场景主动推送相关记忆）

在 bot 需要回复用户时，根据用户的输入，检索记忆信息块，如果检索到相关的记忆信息块，则将其推送给 bot，供 bot 进行参考。

### 2.4. 权重系统

权重指的是记忆信息块在检索时的优先级，权重越高的记忆信息块，检索时越容易被检索到。影响权重的因素有很多，比如：记忆信息块的创建时间、记忆信息块的内容、记忆信息块的使用次数等。

#### 2.4.1. 权重计算基本原则

1. 重要性权重(bot 生成)：记忆信息块的重要性越高，检索时越容易被检索到。
2. 时间距离权重(检索时计算)：记忆信息块的创建时间越近，检索时越容易被检索到。
3. 使用次数权重(检索后更新)：记忆信息块的使用次数越多，检索时越容易被检索到。
4. 邻用权重(检索后更新)：记忆信息块的上次使用时间越近，检索时越不容易被检索到。
5. 内容权重(检索时计算)：记忆信息块的内容与检索标签的匹配程度越高，检索时越容易被检索到。
6. 反馈权重(bot 生成)：检索到记忆信息块后要求 bot 给出价值评价，如果 bot 认为该记忆信息块的价值不高，那么该记忆信息块的权重就会降低。
<!-- 7. 信息块距离权重(检索时计算)：非线性，距离由进到远，权重从低到高再到低。 -->

#### 2.4.2. 权重比例

权重比例是指各个权重的比例，权重比例的设置可以根据 bot 的使用场景进行调整，比如：如果 bot 的使用场景是用于学习，那么可以将反馈权重的比例设置的更高一些，这样 bot 就会更容易记住一些价值较高的记忆信息块。

默认的权重比例如下：

- 重要性权重：0.3
- 时间距离权重：0.2
- 使用次数权重：0.1
- 邻用权重：0.2
- 内容权重：0.1
- 反馈权重：0.1

#### 2.4.3. 权重计算公式

具体的权重计算公式如下：

weight = 重要性权重 * 重要性权重比例 + 时间距离权重 * 时间距离权重比例 + 使用次数权重 * 使用次数权重比例 + 邻用权重 * 邻用权重比例 + 内容权重 * 内容权重比例 + 反馈权重 * 反馈权重比例

#### 2.4.4. 轮盘赌选择推送记忆结果

在检索出一定数量记忆信息块后，根据权重进行轮盘赌选择，选择出一个记忆信息块。这样做的目的是为了让检索的结果存在一定随机性，避免 bot 一直回复同一个记忆信息块。

### 2.5. 记忆信息块的存储结构

#### 2.5.1. 记忆信息块的基本结构

记忆信息块的基本结构如下：

- 记忆信息所属会话 id
- 记忆信息块的 id
- 记忆信息块的内容
- 记忆信息块的索引标签
- 记忆信息块的重要性权重
- 记忆信息块的反馈权重
- 记忆信息块的创建时间
- 记忆信息块的使用次数
