AI agent里的长期记忆和短期记忆

news/2024/11/17 3:04:53/文章来源:https://www.cnblogs.com/bonelee/p/18382383

AI Agent 是时下热门的一个方向,在 OpenAI 应用研究主管 LilianWeng 写的万字长文中[1],她提出 Agent = LLM+ 记忆 + 规划技能 + 工具使用。

 

图1 Overview of a LLM-powered autonomous agent system

组件二:记忆

  • 我们可以将上下文学习(context)看成是利用模型的短期记忆(也就是模型能接受输入的最大长度)来学习

  • 长期记忆为 Agent 提供了长期存储和召回信息的能力,通常利用外部向量储存和快速检索来实现。

记忆是指获取、储存、保留和后续检索信息的过程。人脑中有多种记忆类型:

  • 感觉记忆(Sensory Memory):这是记忆的最早阶段,提供在原始刺激结束后保留感官信息(视觉、听觉等)的印象的能力。感觉记忆通常只持续几秒钟。

  • 短期记忆(Short-Term Memory, STM)或工作记忆(Working Memory):它储存我们当前意识到的信息,用于进行复杂的认知任务,比如学习和推理。短期记忆容量通常为7个项目左右,持续时间为20-30秒。

  • 长期记忆(Long-Term Memory, LTM):长期记忆可以储存信息很长一段时间,从几天到几十年,其储存容量基本上是无限的。长期记忆有两个子类型:

  • 显性 / 陈述记忆(Explicit / declarative memory):指可被有意识回忆的事实和事件的记忆,包括情景记忆(经历和经验)和语义记忆(事实和概念)。

  • 隐性 / 程序记忆(Implicit / procedural memory):这种记忆是无意识的,涉及自动执行的技能和例行程序,比如骑自行车或打字。

对于 Agent 来说:

  • 感觉记忆作为原始输入,可以是文本、图像或者其他模态的输入。

  • 短期记忆则用于上下文学习。它是短暂和有限的,因为它受到Transformer有限上下文窗口长度的限制。

  • 长期记忆则是 Agent 可以在查询和关注的外部向量存储,通过快速检索来访问。

 

 

在AI代理中,短期记忆(short-term memory)和长期记忆(long-term memory)是用于存储和处理信息的两种不同机制。它们的实现方式各有不同,通常结合使用以提高AI的性能和智能水平。

短期记忆(Short-term Memory)

短期记忆通常用于存储和处理当前任务或会话中的信息。它的特点是容量有限,信息保留时间较短。以下是一些实现短期记忆的技术:

  1. 缓存(Cache):在计算机科学中,缓存是一种用于存储临时数据的高效存储机制。AI代理可以使用缓存来快速访问最近使用的数据。

  2. 循环神经网络(RNN):RNNs,尤其是长短时记忆网络(LSTM)和门控循环单元(GRU),是处理序列数据的神经网络架构,能够在短期内保留信息。

  3. 上下文窗口(Context Window):在自然语言处理任务中,AI模型可以使用上下文窗口来处理和记住当前会话中的信息。

长期记忆(Long-term Memory)

长期记忆用于存储需要长时间保留的信息,通常涉及更复杂的数据结构和存储机制。以下是一些实现长期记忆的技术:

  1. 数据库(Database):使用关系型或非关系型数据库来存储和检索长期信息。这种方法适用于需要持久化存储的数据。

  2. 知识图谱(Knowledge Graphs):知识图谱是一种用于表示实体及其关系的结构化数据模型,适合存储和检索复杂的知识。

  3. 文件系统(File System):将信息存储在文件中,以便长期保存和访问。

  4. 强化学习中的经验回放(Experience Replay):在强化学习中,经验回放用于存储过去的经验,以便在训练过程中反复使用。

  5. 向量数据库(Vector Database):用于存储和检索高维向量数据,适合处理嵌入和相似性搜索。

 

记忆流与检索

记忆流(Memory Stream)记录了Agent的全部经历。它是一个内存对象列表,每个对象包含自然语言描述、创建时间戳和最近访问时间戳。记忆流的基本元素是观察(Observation),这是Agent直接感知的事件。观察可以是Agent自身执行的行为,也可以是Agent感知到其他Agent或非Agent对象执行的行为。每个Agent都有自己独立的记忆流。

检索功能根据Agent的当前情况,从记忆流中检索一部分记忆,供语言模型使用。排序打分包括三个方面:

  • 近期性(Recency):最近访问的记忆对象得到更高的分数,因此刚刚发生的事件或今天早上的事件可能会更受Agent关注。近期性使用指数衰减函数来衡量,衰减因子为0.99,衰减的基准是上次检索记忆以来的时间。

  • 重要性(Importance):根据Agent认为的重要程度,为记忆对象分配不同的分数,区分普通记忆和核心记忆。例如,平凡的事件(比如吃早餐)得到低重要性分数,而与重要的人开会这事件得到高分。重要性分数可以使用不同的实现方式,类似的解决方案就是使用了这个具体的评分模型来输出一个整数分数。

  • 相关性(Relevance)为与当前情况相关的记忆对象分配更高的分数。使用常见的向量检索引擎来实现相关性评估。

 

千问AI agent的memory代码实现==》属于长期记忆

import json
from importlib import import_module
from typing import Dict, Iterator, List, Optional, Unionimport json5from qwen_agent import Agent
from qwen_agent.llm import BaseChatModel
from qwen_agent.llm.schema import ASSISTANT, DEFAULT_SYSTEM_MESSAGE, USER, Message
from qwen_agent.log import logger
from qwen_agent.settings import (DEFAULT_MAX_REF_TOKEN, DEFAULT_PARSER_PAGE_SIZE, DEFAULT_RAG_KEYGEN_STRATEGY,DEFAULT_RAG_SEARCHERS)
from qwen_agent.tools import BaseTool
from qwen_agent.tools.simple_doc_parser import PARSER_SUPPORTED_FILE_TYPES
from qwen_agent.utils.utils import extract_files_from_messages, extract_text_from_message, get_file_typeclass Memory(Agent):"""Memory is special agent for file management.By default, this memory can use retrieval tool for RAG."""def __init__(self,function_list: Optional[List[Union[str, Dict, BaseTool]]] = None,llm: Optional[Union[Dict, BaseChatModel]] = None,system_message: Optional[str] = DEFAULT_SYSTEM_MESSAGE,files: Optional[List[str]] = None,rag_cfg: Optional[Dict] = None):"""Initialization the memory.Args:rag_cfg: The config for RAG. One example is:{'max_ref_token': 4000,'parser_page_size': 500,'rag_keygen_strategy': 'SplitQueryThenGenKeyword','rag_searchers': ['keyword_search', 'front_page_search']}And the above is the default settings."""self.cfg = rag_cfg or {}self.max_ref_token: int = self.cfg.get('max_ref_token', DEFAULT_MAX_REF_TOKEN)self.parser_page_size: int = self.cfg.get('parser_page_size', DEFAULT_PARSER_PAGE_SIZE)self.rag_searchers = self.cfg.get('rag_searchers', DEFAULT_RAG_SEARCHERS)self.rag_keygen_strategy = self.cfg.get('rag_keygen_strategy', DEFAULT_RAG_KEYGEN_STRATEGY)function_list = function_list or []super().__init__(function_list=[{'name': 'retrieval','max_ref_token': self.max_ref_token,'parser_page_size': self.parser_page_size,'rag_searchers': self.rag_searchers,}, {'name': 'doc_parser','max_ref_token': self.max_ref_token,'parser_page_size': self.parser_page_size,}] + function_list,llm=llm,system_message=system_message)self.system_files = files or []def _run(self, messages: List[Message], lang: str = 'en', **kwargs) -> Iterator[List[Message]]:"""This agent is responsible for processing the input files in the message.This method stores the files in the knowledge base, and retrievals the relevant partsbased on the query and returning them.The currently supported file types include: .pdf, .docx, .pptx, .txt, .csv, .tsv, .xlsx, .xls and html.Args:messages: A list of messages.lang: Language.Yields:The message of retrieved documents."""# process files in messagesrag_files = self.get_rag_files(messages)if not rag_files:yield [Message(role=ASSISTANT, content='', name='memory')]else:query = ''# Only retrieval content according to the last user query if existsif messages and messages[-1].role == USER:query = extract_text_from_message(messages[-1], add_upload_info=False)# Keyword generationif query and self.rag_keygen_strategy.lower() != 'none':module_name = 'qwen_agent.agents.keygen_strategies'module = import_module(module_name)cls = getattr(module, self.rag_keygen_strategy)keygen = cls(llm=self.llm)response = keygen.run([Message(USER, query)], files=rag_files)last = Nonefor last in response:continueif last:keyword = last[-1].content.strip()else:keyword = ''if keyword.startswith('```json'):keyword = keyword[len('```json'):]if keyword.endswith('```'):keyword = keyword[:-3]try:keyword_dict = json5.loads(keyword)if 'text' not in keyword_dict:keyword_dict['text'] = queryquery = json.dumps(keyword_dict, ensure_ascii=False)logger.info(query)except Exception:query = querycontent = self.function_map['retrieval'].call({'query': query,'files': rag_files},**kwargs,)if not isinstance(content, str):content = json.dumps(content, ensure_ascii=False, indent=4)yield [Message(role=ASSISTANT, content=content, name='memory')]def get_rag_files(self, messages: List[Message]):session_files = extract_files_from_messages(messages, include_images=False)files = self.system_files + session_filesrag_files = []for file in files:f_type = get_file_type(file)if f_type in PARSER_SUPPORTED_FILE_TYPES and file not in rag_files:rag_files.append(file)return rag_files

  

 

这段代码定义了一个继承自 Agent 类的 Memory 类,专门用于文件管理和检索增强生成(RAG)任务。以下是它如何实现“记忆”的详细说明:

初始化

  1. 参数和配置:

    • Memory 类在初始化时接受多个参数,包括工具列表(function_list)、语言模型(llm)、系统消息、文件列表(files)和RAG配置字典(rag_cfg)。
    • RAG配置包括参数如 max_ref_tokenparser_page_sizerag_searchers 和 rag_keygen_strategy。这些参数有默认值,如 DEFAULT_MAX_REF_TOKEN
  2. 功能设置:

    • Memory 类通过扩展的 function_list 初始化其父类 Agent,其中包括具有特定设置的 retrieval 和 doc_parser 工具。
  3. 文件管理:

    • 它维护一个系统文件列表(system_files),可以在多个会话中使用。

记忆实现

记忆的实现主要用于管理与文件相关的操作,并与检索工具集成以支持RAG功能。

  1. 文件处理:

    • get_rag_files:该方法从消息列表中提取文件,并将其与任何系统文件结合,创建一个文件列表(rag_files),这些文件由解析器支持并准备好进行检索。
    • 它根据 PARSER_SUPPORTED_FILE_TYPES 检查文件类型,以确保只处理合适的文件。
  2. 查询处理和检索:

    • _run 方法:该方法管理与检索工具的交互。它处理输入消息并提取任何查询。
    • 关键词生成:可以使用指定的 rag_keygen_strategy 生成关键词。这涉及动态加载策略类并运行它以根据查询生成关键词。
    • 调用检索:使用组装的查询和文件调用 retrieval 函数以获取相关信息。
    • 输出处理:检索到的内容作为来自 ASSISTANT 角色的消息返回。
  3. 迭代响应生成:

    • _run 方法是一个生成器(使用 yield),这使得它能够通过在结果准备好时逐步返回结果来平稳处理可能较长或异步的操作。

总结

这个 Memory 类充当一个专门的代理,用于管理文件输入、生成查询、执行基于关键词的信息检索,并以对话格式返回这些结果。这里的记忆更多是概念上的,通过其对数据的处理和持久化来模拟一种“记忆”,而不是传统的记忆系统,如那些在会话中存储用户数据的系统。它利用工具和策略,通过处理和持久化数据来实现一种记忆功能

 

上述代码本质上是在实现基于关键词的知识检索。以下是代码如何实现这一点的详细说明:

  1. 关键词生成:

    • 代码中有一个关键词生成策略(rag_keygen_strategy),用于从用户的查询中提取关键词。这是通过动态加载一个关键词生成策略类并运行它来实现的。
    • 关键词生��的结果用于构建更有效的查询,以便在文件中检索相关信息。
  2. 文件处理和检索:

    • get_rag_files 方法负责从消息中提取文件,并确保这些文件是支持的类型。
    • 在 _run 方法中,提取的关键词和文件一起被传递给 retrieval 工具。这个工具负责在文件中搜索与关键词匹配的内容。
  3. 检索工具的调用:

    • retrieval 工具被调用时,会使用生成的关键词和文件列表来查找相关信息。
    • 检索到的内容被格式化并返回给用户,模拟了一个基于关键词的知识检索过程。

通过这些步骤,代码实现了一个简单的基于关键词的知识检索系统,能够从用户提供的文件中提取相关信息并返回给用户。

 

而在阿里的superAGI里的做法==》属于短期记忆

agent_summary.txt

1
要求AI生成系统、用户和助手之间先前互动的简洁总结。总结应涵盖对话的主要点,突出讨论的关键问题、做出的决定以及分配的任何行动。这应作为过去互动的回顾,提供对话内容和结果的清晰理解。请确保总结不超过设定的字符限制。

==》这种思路对于缩减对话长度很有用!  

 

原始:

AI, your task is to generate a concise summary of the previous interactions between the system, user, and assistant.
The interactions are as follows:

{past_messages}

This summary should encapsulate the main points of the conversation, highlighting the key issues discussed, decisions made, and any actions assigned.
It should serve as a recap of the past interaction, providing a clear understanding of the conversation's context and outcomes.
Please ensure that the summary does not exceed {char_limit} characters.

 

agent_recursive_summary.txt

1
2
3
4
5
6
7
8
9
10
11
AI,你需要根据系统、用户和助手之间的先前交互总结以及原始总结中未包括的额外对话来提供信息。
如果先前的总结为空,你的任务是仅基于新的互动创建一个总结。
 
先前总结:{previous_ltm_summary}
 
{past_messages}
 
如果先前的总结不为空,你的最终总结应将新的互动整合到现有总结中,以创建一个全面的所有互动的回顾。
如果先前的总结为空,你的总结应概括新对话的主要点。
在两种情况下,都要突出讨论的关键问题、做出的决定以及分配的任何行动。
请确保最终总结不超过{char_limit}个字符。

  

原始:

AI, you are provided with a previous summary of interactions between the system, user, and assistant, as well as additional conversations that were not included in the original summary.
If the previous summary is empty, your task is to create a summary based solely on the new interactions.

Previous Summary: {previous_ltm_summary}

{past_messages}

If the previous summary is not empty, your final summary should integrate the new interactions into the existing summary to create a comprehensive recap of all interactions.
If the previous summary is empty, your summary should encapsulate the main points of the new conversations.
In both cases, highlight the key issues discussed, decisions made, and any actions assigned.
Please ensure that the final summary does not exceed {char_limit} characters.

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/787912.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Yolov5模型训练+转ncnn模型

配置YOLOv5依赖 打开yolov5开源地址:https://github.com/ultralytics/yolov5 可根据自身要求下载对应版本(无要求可跳过): 下载:下载完成安装依赖包: 如需使用显卡进行训练需按照显卡版本安装部分依赖包:这两个包注掉,然后根据显卡版本安装依赖 在cmd获取显卡版本:nvi…

windows更新在哪里删除,教你关闭windows更新

电脑自动更新的彻底关闭方法可以根据不同的Windows系统版本(如Windows 10、Windows 11等)和用户的具体需求来选择。以下是一些常用的方法: 一、 使用系统设置关闭自动更新 步骤: 1.点击开始菜单,在搜索栏中输入“设置”,并打开设置窗口。 2.在设置窗口中,找到“更新和安…

k8s给多个外部静态IP作负载均衡、反向代理

在 Kubernetes (K8s) 中,Ingress、Endpoints 和 Service 是三个重要的概念,它们协作实现了集群内部和外部应用程序的访问和服务发现。 Ingress:Ingress 用于提供集群外部到集群内部服务的 HTTP/HTTPS 路由。 Ingress 定义了访问集群内部服务的规则,如路径映射、虚拟主机等。 In…

nuxt3项目自定义环境变量,typescript全局提示

最近使用nuxt3框架来写项目,其中有一点就是 typescript 语法提示让人闹心,使用 vscode 编辑器,如果有语法提示进行编码,工作效率可以提升一个档次。本篇文章说的就是如何在 vscode 中使用 nuxt3 框架,自定义环境变量,支持 typescript 语法提示。列出当前使用的环境版本no…

STM32与Linux串口双向通信

STM32 与 linux 双向串口通信实验本文记录STM32 与 linux 双向串口通信,包含stm32发送、Linux阻塞式接收;Linux发送,STM32阻塞式接收;本实验的目的在于调通数据链路,为之后使用奠定基础。 实验平台为:STM32方面用的是STM32H723ZGT6为核心的开发板;开发环境为 VSCode + AC…

Java基础-学习笔记14

Collection、Map 类实现14 集合 Collection、Map 第一部分 Collection的框架体系 1) 可以动态保存任意多个对象,使用比较方便 2) 提供了一系列方便的操作对象的方法:add、remove、set、get等 3) 使用集合添加、删除新元素简单便捷。 集合 Collection 主要是两组:单列集合…

Apache SeaTunnel技术架构演进及其在AI领域的应用

随着数据集成需求的增长,Apache SeaTunnel作为新一代的数据同步引擎,不仅在技术架构上不断演进,也在AI领域展现出其独特的应用价值。在CommunityOverCode Asia 2024大会上,Apache SeaTunnel PMC Chair 高俊 深入探讨SeaTunnel的技术演进路径,分析其在AI领域的应用案例,并…

Windows 系统 局域网文件夹共享无法访问的终极解决方法

先介绍 Win10 无法访问其他电脑的解决方法首先,Win10 能成功访问共享文件夹,必须有安装 SMB1 协议,否则会提示找不到网络名称的提示。 方法很简单,点击 微软小娜 Cortana 输入 启用或关闭 Windows 功能(或者直接输入 功能 也能找到),打开 启用或关闭 Windows 功能 对话框…

使用 updateAppConfig 更新 Nuxt 应用配置

title: 使用 updateAppConfig 更新 Nuxt 应用配置 date: 2024/8/27 updated: 2024/8/27 author: cmdragon excerpt: 通过使用 updateAppConfig,你可以轻松地在应用运行时更新配置,而无需重新启动应用。这对于需要在运行时调整设置的应用场景非常有用。 categories:前端开发…

AtCoder Beginner Contest 051

A - Haiku 直接模拟。 #include <bits/stdc++.h>using namespace std; using i64 = long long;int main() {ios::sync_with_stdio(false), cin.tie(nullptr);string s;cin >> s;string a, b, c;a = s.substr(0, 5);b = s.substr(6, 7);c = s.substr(14);cout <&…

PEP 508:为不同版本Python指定不同依赖

如果使用Python第三方包的某一个版本有问题,而不同版本Python所对应的软件最新版本又不一致,这种情况下如何在requirements.txt文件中指定软件最高版本是非常重要的。这里根据PEP 508的规范,做了一个Numpy版本要求numpy<=1.21.6 || 1.28>numpy>=1.23的示例。问题背…

经验分享|如何发现并利用信息泄露漏洞?

信息泄露漏洞是发现和报告的重要目标。虽然它们可能不会带来很丰厚的回报,但发现它们表明Web应用程序的安全性较差,这可能有助于发现更严重的漏洞。 一、常见的信息泄露漏洞类型 1.1服务器标识版本 服务器标识版本能够揭示服务器上运行的特定软件及其版本,这可以被用来寻找已…