ERNIE用户记忆机制实践教程
大模型用户记忆能力介绍
当我们使用大模型能力去重构或赋能已有的产品时,或者使用大模型能力进行产品创新时,期望大模型具备支撑个性化产品形态、满足终端用户个性化需求的能力,而记忆机制就是在使用大模型满足"个性化"需求的完整的一套解决方案。记忆机制可以解决包括但不限于以下几类痛点问题:
- 用户在一个对话中让模型记住有关自己的重要信息,模型当即表示自己记住了,新建对话后模型就不记得、不知道了…
- 用户希望得到更个性化的回复时,模型好像总是“套模版”,车轱辘话来回说,无法提供体贴、个性化的帮助…
- 用户与模型的对话超过最长上下文场景后,模型就不记得用户之前说过的话了…
- 客户为了让模型基础超过上下文限度的信息,总结上文并拼接到query中,占用过多token数…
针对上述痛点问题,我们开放了大模型的用户记忆能力。用户记忆存储了User的人设,即Bot对User重要信息的记忆:
用户记忆(User memory) | Bot对User信息的长期记忆 | User维度相对稳定的,比较重要的信息会作为Bot的长期记忆作为管理,在实际使用时会按需进行提取或使用,例如:当User希望讨论职业规划问题时候,Bot会调取长期记忆中的用户职业、用户学历等信息,生成更个性化的回复。 |
---|
用户记忆的应用场景
- 个性化问候:在用户与模型开始第一次对话,或重启对话时,Assistant可以根据用户记忆生成不同的问候语;
- 生产力任务:在用户需要Assistant完成写作、解题指导等任务时,Assistant根据用户记忆有侧重性地回答用户问题;
- 与用户个人情况紧密相关的任务:Assistant根据用户记忆,生成个性化的职业规划、内在洞察,帮助解决人际关系困扰;
- 个性化推荐:Assistant用户偏好进行推荐,例如推荐鞋服、美食等。
记忆内容管理
API接口列表:
操作 | appid 维度 |
userMemoryId 维度 |
memories 维度 |
---|---|---|---|
创建 | / | 创建用户记忆id | 写入用户记忆内容 |
修改 | / | / | 修改用户记忆内容 |
查询 | 查询应用内所有用户记忆id | 查询用户记忆内容 | 查询用户记忆内容 |
删除 | / | 删除用户记忆id和记忆内容 | 删除用户记忆id和记忆内容 |
最佳实践
以下,我们以"文小言"Ai助手为例,展开关于用户记忆能力的应用实践:
文小言是百度旗下新搜索智能助手,基于文心一言大模型开发。提供多模态搜索、问题解答、文章创作、图片创作与识别、语聊数字人、自由订阅、专业智能体等丰富的AI能力。通过用户记忆能力,文小言能够更好地理解用户的喜好,为用户提供更有针对性的问候、问题解答、商品推荐等帮助。
获得鉴权认证
以下在完成系统记忆机制的实践中,我们使用Postman环境进行,具体鉴权步骤如下:
对API请求进行签名计算
当您将HTTP请求发送到百度智能云时,您需要对您的请求进行签名计算,以便百度智能云可以识别您的身份。您将使用百度智能云的访问密钥来进行签名计算,该访问密钥包含访问密钥ID(Access Key Id, 后文简称AK)和秘密访问密钥(Secret Access Key, 后文简称SK).
注意:
仅当您手动创建HTTP请求(RESTful API调用)时,您才需要了解如何对请求进行签名计算。当您使用智能云提供的SDK时,在SDK中已经封装了完整的签名算法,使用者无需自己实现。
了解如何创建、查看和下载Access Key Id(AK)和Secret Access Key(SK), 请参考管理您的AKSK.
使用IAM工具生成认证字符串(Authorization)
认证字符串(Authorization)是向HTTP服务发送与记忆相关请求时需要输入的必要参数,因此您需要首先使用IAM工具生成认证字符串后,才能使用记忆功能。
- 在IAM签名工具中设置以下参数:
HTTP请求信息 | 信息设置 |
---|---|
http方法 | POST |
路径 | /v2/memory |
参数 | 创建用户记忆id:Action=CreateUserMemory 写入用户记忆内容:Action=ModifyUserMemory 修改用户记忆内容:Action=ModifyUserMemoryContent 查询应用内所有用户记忆id:Action=DescribeUserMemories 查询用户记忆id和记忆内容:Action=DescribeUserMemory 删除用户记忆id和记忆内容:Action=DeleteUserMemory |
AccessKeyld(ak): | 依靠千帆获得 |
SecretAccessKey(sk): | 依靠千帆获得 |
Host | qianfan.baidubce.com |
时间戳 | 务必确保右侧时间戳和左侧x-bce-date保持一致 |
签名有效期(秒): | 为了避免重复生成鉴权带来的麻烦,可以设置更长时间的有效期(默认为1800s) |
- 点击一键计算,可在红框处复制认证字符串(Authorization),复制后粘贴到postman的Headers参数下的Authorization处。
在postman中设置发送记忆相关请求的参数
- 设置请求方法:POST
- 在请求地址栏中输入:https://qianfan.baidubce.com/v2/memory
- 添加并设置Params:可一次添加所有Key-Value对,使用时保证Action与你的请求动作(增删改查)保持一致。
Key-Value对介绍 | Key | Value |
---|---|---|
创建用户记忆id | Action | CreateUserMemory |
写入用户记忆内容 | Action | ModifyUserMemory |
修改用户记忆内容 | Action | ModifyUserMemoryContent |
查询应用内所有用户记忆id | Action | DescribeUserMemories |
查询用户记忆id和记忆内容 | Action | DescribeUserMemory |
删除用户记忆id和记忆内容 | Action | DeleteUserMemory |
- 设置Headers参数:在Headers下需要设置3个参数,参数解释见下
Key | Value |
---|---|
Content-Type | application/json |
x-bce-date | 必须与生成鉴权时的x-bce-date保持一致 |
Authorization | 通过IAM平台计算获得 |
创建用户记忆id
接口文档:创建用户记忆id:用于创建用户记忆id。
创建用户记忆id的实践案例
以下以“文小言”Ai助手为例,展示创建用户记忆的过程:
- 其中
appId
是您的千帆应用ID,后续在调用推理服务时需要使用与此相同appId
的应用,以确保记忆生效。 - 其中
description
是为了方便您辨认用户特征信息的参数,不能为空,但并不会传入模型进行推理。
{
"appId": "48886xxx",
"description": "小A,一名女性用户"
}
得到的响应字段的Body内容如下,表明该用户记忆创建成功:
{
"requestId":"1bef3f87-c5b2-4419-936b-50f9884fxxx",
"result": {
"userMemoryId" : "um-9a8cfb8eexx"
}
}
至此,您获得了唯一标识用户身份的userMemoryId,不同userMemoryId对应不同用户的记忆,接下来我们逐步使用这个userMemoryId去增加(更新)、删除、全量更改或插入(更新)单个用户的记忆。
写入用户记忆内容
接口文档:写入用户记忆内容:用于全量写入/更新用户记忆内容。
全量写入/更新记忆的实践案例
全量写入/更新记忆时,新存入的用户记忆信息会覆盖用户过往所有的历史记忆信息。
我们继续以“文小言”Ai助手为例,之前我们在创建用户记忆步骤中若创建成功,会返回用户小A所对应的唯一用户人设标识userMemoryId
。
我们使用这个userMemoryId
和用户小A归属的appId
写入多条记忆内容。
由于是全量写入/更新,所以此时 operator
参数设置为“cover”,并在 memories 字段中写入新的记忆信息。
由于我们刚刚才创建了小A的人设,因此我们此处输入的记忆内容,会被全部写入(全量写入);如果您在实践过程中,某个userMemoryId
已存储记忆信息,此时原有记忆内容会被全部更新(全量更新)。
以下是请求示例:
{
"appId":"48886xxx",
"userMemoryId": "um-j4gnrcrchehvv4ii",
"operator":"cover",
"memories":[
[
{ "role": "user",
"content": "你好,我叫小A,请你记住我的口味偏好:我的口味偏清淡,喜欢喝绿茶,很注重饮食健康。"
},
{
"role": "system",
"content": "好的小A,我记住你的口味清淡,喜欢健康饮食,而且喜欢喝绿茶"
}
],
[
{
"role": "user",
"content": "记住我的点单偏好:不另外加糖、少冰、不加小料。"
},
{
"role": "system",
"content": "好的小A,我已经记住了你的偏好。"
}
]
]
}
得到的响应字段的Body内容如下,表明以上用户记忆写入成功。
{
"requestId":"1bef3f87-c5b2-4419-936b-50f9884f10d4",
"result": true
}
写入用户记忆内容的实践案例
另外,我们还可以直接为用户写入单条或多条记忆对内容。
由于是直接写入,所以此时operator
参数设置为“insert”,并在 memories 字段中写入新的记忆信息,此时用户原有的记忆信息不会被覆盖。
以下是写入用户记忆内容的请求示例:
{
"appId":"48886xxx",
"userMemoryId": "um-j4gnrcrchehvv4ii",
"operator": "insert",
"memories":[
[
{
"role": "user",
"content": "我很喜欢吃粤菜。"
},
{
"role": "system",
"content": "已记住您的菜系偏好。"
}
]
]
}
出现以下示例代表单条插入操作成功完成。
{
"requestId": "74e3a9fb-d962-49e5-9c4f-fe73f751233c",
"result": true
}
在插入后检查该用户记忆是否插入成功,查询的具体操作请参看文档:查询用户记忆内容
查询用户记忆内容
接口文档:查询用户记忆内容,具体功能为:
- 查询单个用户所有的记忆内容,即查询一个
userMemoryId
和对应的discription
、memories
- 查询单个用户的单条记忆内容,即查询一个
userMemoryId
下的单条memoryContentId
内容
查询单个用户所有的记忆内容的实践案例
之前,我们在创建用户记忆步骤中,若创建成功,会返回用户小A所对应的唯一用户人设识userMemoryId
。
我们使用用户小A的userMemoryId
和其归属的 appId 查询,目前用户小A所有的记忆内容。
以下是请求示例:
{
"appId": "48886017",
"userMemoryId":"um-j4gnrcrchehvv4ii" # 替换需查询记忆的用户的唯一userMemoryId
}
得到的响应字段的Body内容如下,表明查询该用户所有的记忆内容成功,我们可以看到之前为小A写入的所有记忆信息。
其中,我们可以从memories
数组中的memoryContentId
参数中,获得一个记忆问答对的独特id,我们可以使用memoryContentId
参数单个用户的单条记忆内容进行查询、修改与删除。
{
"requestId": "616142e9-fdac-4c49-8d91-b1da7c187370",
"result": {
"appId": "48886xxx",
"userMemoryId": "um-j4gnrcrchehvv4ii",
"description": "小A,一名女性用户",
"memories": [
[
{
"memoryContentId": "jNyxRZQB38Wmv6Rt4QHZ",
"role": "user",
"content": "你好,我叫小A,我的口味偏清淡,喜欢喝绿茶,很注重饮食健康。",
"type": "profile"
},
{
"memoryContentId": "jNyxRZQB38Wmv6Rt4QHZ",
"role": "system",
"content": "好的小A,我记住你的口味清淡,喜欢健康饮食,而且喜欢喝绿茶。",
"type": "profile"
}
],
[
{
"memoryContentId": "i9yxRZQB38Wmv6Rt4QHZ",
"role": "user",
"content": "记住我的点单偏好:不另外加糖、少冰、不加小料。",
"type": "profile"
},
{
"memoryContentId": "i9yxRZQB38Wmv6Rt4QHZ",
"role": "system",
"content": "好的小A,我已经记住了你的偏好。",
"type": "profile"
}
],
[
{
"memoryContentId": "N4a4RZQBl86Vmrtv8b-1",
"role": "user",
"content": "我很喜欢吃粤菜。",
"type": "profile"
},
{
"memoryContentId": "N4a4RZQBl86Vmrtv8b-1",
"role": "system",
"content": "已记住您的菜系偏好。",
"type": "profile"
}
]
]
}
}
单个用户的单条记忆内容的实践案例
刚才我们查询了用户小A的所有记忆内容,并且从memories
数组中的memoryContentId
参数。
现在我们以memoryContentId
为''N4a4RZQBl86Vmrtv8b-1"的记忆问答对为例,展示如何用查询单个用户的单条记忆内容。
以下是请求示例:
{
"appId":"48886xxx",
"userMemoryId": "um-j4gnrcrchehvv4ii", #替换需查询记忆的用户的唯一userMemoryId
"memoryContentId": ["N4a4RZQBl86Vmrtv8b-1"] # 对应的用户单条记忆内容id,目前单次请求仅支持查询一个内容id
}
得到的响应字段的Body内容如下,表明小A这个用户的单条记忆内容查询成功:
{
"requestId": "6d0fd2c9-22d3-4cb0-a134-c5ad273bc346",
"result": {
"appId": "48886xxx",
"userMemoryId": "um-nbb533nb0pmrxs43",
"description": "小A,一名女性用户",
"memories": [
[
{
"memoryContentId": "WCtm35QBKRPsy3wO9_px",
"role": "user",
"content": "我很喜欢吃粤菜。",
"type": "profile"
},
{
"memoryContentId": "WCtm35QBKRPsy3wO9_px",
"role": "system",
"content": "已记住您的菜系偏好。",
"type": "profile"
}
]
]
}
}
修改用户记忆内容
接口文档:修改用户记忆内容:修改用户记忆中的单条记忆内容:
修改用户记忆内容的实践案例
刚才我们在查询用户小A的所有记忆内容时,从memories
数组中获取了memoryContentId
参数。
假设,随着小A生活地点发生的变化,小A从广州搬家到了成都工作,她逐渐爱上川菜,川菜取代粤菜成为她最喜欢的菜系,此时我们需要修改与小A口味偏好相关的单条记忆内容,这条记忆内容示例如下:
{
"requestId": "6d0fd2c9-22d3-4cb0-a134-c5ad273bc346",
"result": {
"appId": "48886xxx",
"userMemoryId": "um-nbb533nb0pmrxs43",
"description": "小A,一名女性用户",
"memories": [
[
{
"memoryContentId": "WCtm35QBKRPsy3wO9_px",
"role": "user",
"content": "我很喜欢吃粤菜。",
"type": "profile"
},
{
"memoryContentId": "WCtm35QBKRPsy3wO9_px",
"role": "system",
"content": "已记住您的菜系偏好。",
"type": "profile"
}
]
]
}
}
以下是修改这条用户记忆的请求示例,在示例中,我们将小A的菜系偏好由粤菜
改为川菜
:
{
"requestId": "6d0fd2c9-22d3-4cb0-a134-c5ad273bc346",
"result": {
"appId": "48886xxx",
"userMemoryId": "um-nbb533nb0pmrxs43",
"description": "小A,一名女性用户",
"memories": [
[
{
"memoryContentId": "WCtm35QBKRPsy3wO9_px",
"role": "user",
"content": "我之前喜欢吃粤菜,现在我最喜欢的菜系是川菜。",
"type": "profile"
},
{
"memoryContentId": "WCtm35QBKRPsy3wO9_px",
"role": "system",
"content": "已将您的菜系偏好更新为川菜,以后我会给你推荐更多好吃的川菜馆噢。",
"type": "profile"
}
]
]
}
}
得到的响应字段的Body内容如下,表明修改这条用户记忆的请求成功:
{
"requestId":"1bef3f87-c5b2-4419-936b-50f9884f10d4",
"result": true
}
删除用户记忆id和记忆内容
接口文档:删除用户记忆id和记忆内容,具体功能:
- 删除单条用户记忆内容,即删除一个
userMemoryId
下的单条memoryContentId
内容 - 删除用户记忆id及该id对应的所有用户记忆内容,即删除一个
userMemoryId
和对应的discription
、memories
删除单条用户记忆内容的实践案例
当误将某些不重要的信息写入用户记忆内容时,我们可以删除该条记忆。
删除前小A的所有用户信息如下:
{
"requestId": "616142e9-fdac-4c49-8d91-b1da7c187370",
"result": {
"appId": "48886xxx",
"userMemoryId": "um-j4gnrcrchehvv4ii",
"description": "小A,一名女性用户",
"memories": [
[
{
"memoryContentId": "jNyxRZQB38Wmv6Rt4QHZ",
"role": "user",
"content": "你好,我叫小A,我的口味偏清淡,喜欢喝绿茶,很注重饮食健康。",
"type": "profile"
},
{
"memoryContentId": "jNyxRZQB38Wmv6Rt4QHZ",
"role": "system",
"content": "好的小A,我记住你的口味清淡,喜欢健康饮食,而且喜欢喝绿茶。",
"type": "profile"
}
],
[
{
"memoryContentId": "i9yxRZQB38Wmv6Rt4QHZ",
"role": "user",
"content": "记住我的点单偏好:不另外加糖、少冰、不加小料。",
"type": "profile"
},
{
"memoryContentId": "i9yxRZQB38Wmv6Rt4QHZ",
"role": "system",
"content": "好的小A,我已经记住了你的偏好。",
"type": "profile"
}
],
[
{
"memoryContentId": "N4a4RZQBl86Vmrtv8b-1",
"role": "user",
"content": "我之前喜欢吃粤菜,现在我最喜欢的菜系是川菜。",
"type": "profile"
},
{
"memoryContentId": "N4a4RZQBl86Vmrtv8b-1",
"role": "system",
"content": "已将您的菜系偏好更新为川菜,以后我会给你推荐更多好吃的川菜馆噢。",
"type": "profile"
}
]
]
}
}
我们想要删除的记忆信息为:
[
{
"memoryContentId": "i9yxRZQB38Wmv6Rt4QHZ",
"role": "user",
"content": "记住我的点单偏好:不另外加糖、少冰、不加小料。",
"type": "profile"
},
{
"memoryContentId": "i9yxRZQB38Wmv6Rt4QHZ",
"role": "system",
"content": "好的小A,我已经记住了你的偏好。",
"type": "profile"
}
]
我们在请求主体中输入该用户唯一的记忆IDuserMemoeyId
及需要删除的单条记忆内容IDmemoryContentId
(请注意,目前仅支持单条记忆删除,即一次请求仅支持传入一个memoryContentId
),以下是请求示例:
{
"appId":"48886xxx",
"userMemoryId":"um-cc60b5dp8y5snc5t",
"memoryContentId": ["i9yxRZQB38Wmv6Rt4QHZ"]
}
得到的响应字段的Body内容如下,表明该条用户记忆删除成功:
{
"requestId": "9f23711b-3aa3-48f2-b2e1-3cb81e69a498",
"result": true
}
删除用户记忆id的实践案例
当需要删除小A的用户id和该id对应的所有用户记忆内容时,可以发送如下请求:
{
"appId":"48886xxx",
"userMemoryId":"um-j4gnrcrchehvv4ii"
}
得到的响应字段的Body内容如下,表明该用户记忆id删除成功:
{
"requestId": "b800a9ef-4538-4998-99dd-f9d92a79fdda",
"result": true
}
查询应用内所有用户记忆id
接口文档:查询应用内所有用户记忆id:查询应用内所有用户记忆id,即查询一个 appId 下所有的 userMemoryId 和对应的 discription
查询应用内所有用户记忆id的实践案例
在上文的实践案例中,我们已展示了对一个用户的记忆进行增删改查的全过程。
而当我们需要对应用appId
中的所有记忆id进行全局总览时,请求Body中需要提供千帆应用的唯一标识符appld
,可以发送以下请求示例:
{
"appId": "48886xxx"
}
得到的响应字段的Body内容如下,表明该用户记忆id删除成功:
{
"requestId": "1bef3f87-c5b2-4419-936b-50f9884f10d4",
"result": {
"items": [
{
"appId": "48886xxx",
"userMemoryId": "um-j4gnrcrchehvv4i2",
"description": "用户B,男性。"
},
{
"appId": "48886xxx",
"userMemoryId": "um-j4gnrcrchehvv4i1",
"description": "用户C,女性,天津人。"
}
],
"pageInfo": {
"marker": "um-9a8cfb8ee59",
"isTruncated": false,
"nextMarker": "um-9a8cfb8ee55",
"maxKeys": 3
}
}
}