前言
在开发AwiseOctopus的过程中,最初对于memory的设计直限于经验记忆的设计——设计大致如下:设定一个经验总结的llm,当agent完成整个任务时,交给这个agent总结成功经验并给予权重值,然后记入memory数据库,当agent执行同类任务时即可优先调用这个经验记忆的操作。
想象美好,现实骨感。实际操作中,经验memory的注入反而导致了agent的上下文污染,产生了严重幻觉。例如:本来任务是操作A文件,但是由于历史经验操作的是B文件,注入后导致了经验错误,agent实际执行了B文件的操作。
处理思路
为了解决这一问题,以下记录了处理注入的简单实验过程。
数据分层
基本思路是,将经验记忆和当前上下文进行基本分层,基于信息提取优先级。
让agent对于当前上下文的信息做出较高优先级的提取。再整合当前的经验和上下文。而非全量注入。
- 首先优化一下记忆的读取,将一些关联度较低的经验过滤掉
def search_experience(self, task_type, instruction, top_k=3):
"""搜索历史经验,根据 weight 分为成功和失败两类"""
if not self.collection:
return ""
# 1. 向量检索最相关的 instruction
results = self.collection.query(
query_texts=[instruction],
n_results=top_k * 2,
where={"task_type": task_type}
)
if not results['ids'] or not results['ids'][0]:
return ""
# 过滤距离大于 0.3 的结果
exp_ids = []
if 'distances' in results and results['distances']:
for i, distance in enumerate(results['distances'][0]):
if distance <= 0.38:
exp_ids.append(results['ids'][0][i])
else:
exp_ids = results['ids'][0]
if not exp_ids:
return ""- 对上下文做分层,将历史经验放置到system提示词而不是用户提示词。提示词做解释
# 搜索历史经验
hint = self.memory_manager.search_experience("thinking", user_request)
if hint:
yield ("RUNNING", "\n[思考Agent 经验记忆] 检索到相关历史经验,已注入上下文。")
# 数据分层
for msg in self.messages:
if msg["role"] == "system":
msg["content"] += "\n" + (
"〖系统注入的历史经验(仅供参考,如与用户最新指令冲突,以用户指令为准)〗\n"
f"{hint}\n"
"〖经验参考结束〗"
)
break
else:
self.messages.append({
"role": "system",
"content": (
"〖系统注入的历史经验(仅供参考,如与用户最新指令冲突,以用户指令为准)〗\n"
f"{hint}\n"
"〖经验参考结束〗"
)
})注: self.memory_manager是一个memory管理工具,会负责从向量数据库提取相关数据。
整体结果:agent的智力明显提升,对于已经有经验的相关事件,操作速度和准确率得到了明显提升,出现需要操作A而去操作B的情况大幅下降。
虽然概率下降了,但依然偶有找不到,或者用户操作目录过于模糊而导致操作失误的问题。
操作工作区
新增工作区机制,让agent的每个session的操作都默认限定在某个工作区(文件夹或目录)内。除非得到了用户的指定,否则操作不出工作区。
整体结果:对于不确定,不明确的事项,当agent出现偏差操作时,由于有工作区兜底,操作行为风险降低。其次当把所需操作行为,操作对象放到工作区内,由于操作选项范围减少,agent操作更加精确,进一步减少了幻觉。


Comments | NOTHING