ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

AutoGen Core 记忆系统深入解析:用 Memory 与 ListMemory 实现跨会话长期记忆

AutoGen Core 记忆系统深入解析:用 Memory 与 ListMemory 实现跨会话长期记忆 人工智能AI 应用AI Agent【免费下载链接】Tutorial-Codebase-KnowledgePocket Flow: Codebase to Tutorial项目地址https://gitcode.com/gh_mirrors/tu/Tutorial-Codebase-Knowledge点击查看免费下载导读在多智能体应用中智能体Agent不仅需要记住当前对话的上下文还需要跨会话、跨任务地长期保存和检索关键信息例如用户的写作偏好、历史决策或领域知识。本文聚焦 AutoGen Core 的Memory抽象它是智能体的长期笔记本/数据库与负责短期对话历史的ChatCompletionContext形成互补。你将掌握MemoryContent的数据结构、add/query/update_context三个核心方法以及内置实现ListMemory的完整用法——包括如何把长期记忆注入新的对话上下文从而让 LLM 在回答前就想起用户偏好。本文属于 AutoGen Core 教程 的第 7 章与 ChatCompletionClient、ChatCompletionContext 和 Component 紧密衔接。为什么需要长期记忆从临时草稿纸到长期笔记本在 第 6 章 ChatCompletionContext 中我们了解到ChatCompletionContext负责管理单次对话的短期历史——它就像刚说过几分钟的话。例如BufferedChatCompletionContext只保留最近 N 条消息HeadAndTailChatCompletionContext只保留头部和尾部消息。但很多场景要求智能体记住更久远的信息跨越多次对话或任务。设想一个学习用户偏好的助手智能体你告诉它请永远用正式风格为我撰写邮件。数周后你请它起草一封新邮件。此时短期ChatCompletionContext很可能已经忘记了之前的指令——尤其是使用BufferedChatCompletionContext这类策略时。智能体需要的是长期记忆long-term memory这正是Memory抽象要解决的问题。从系统架构上看Memory是 AutoGen Core 的七大核心抽象之一。在 docs/AutoGen Core/index.md 的架构图中Agent通过Memory访问长期信息而Memory又通过update_context反向更新 LLM 的上下文ChatCompletionContext形成完整闭环Agent—— 访问长期记忆 ——MemoryMemory—— 更新 LLM 上下文 ——ChatCompletionContextChatCompletionClient—— 获取历史 ——ChatCompletionContext核心概念笔记本是如何工作的1. 存储的内容MemoryContent智能体可以在记忆中存储多种类型的信息纯文本笔记text/plain结构化数据如 JSONapplication/json甚至图片image/*每条信息都被包装在一个MemoryContent对象中包含数据本身、类型标识mime_type以及可选的描述性metadata# From: memory/_base_memory.py (Simplified Concept) from pydantic import BaseModel from typing import Any, Dict, Union # Represents one entry in the memory notebook class MemoryContent(BaseModel): content: Union[str, bytes, Dict[str, Any]] # The actual data mime_type: str # What kind of data (e.g., text/plain) metadata: Dict[str, Any] | None None # Extra info (optional)这个标准格式帮助系统统一管理不同类型的记忆。metadata字段特别适合记录记忆的来源、时间戳或可信度等信息例如{source: user_instruction_conversation_1}。2. 写入记忆add当智能体学到值得长期保留的信息如用户的偏好风格时调用memory.add(content)方法——就像在笔记本上写下一则新条目。3. 查询记忆query当智能体需要回忆信息时调用memory.query(query_text)——就像在笔记本中搜索相关条目。具体搜索方式取决于Memory的实现简单实现可能做纯文本匹配更高级的实现可能使用向量搜索。4. 关键衔接update_context注入对话上下文这是Memory与 LLM 交互的关键纽带在智能体调用 ChatCompletionClient 与 LLM 对话之前可以调用memory.update_context(chat_context)。该方法查看当前对话chat_context查询长期记忆Memory中的相关信息将检索到的记忆注入chat_context通常以SystemMessage的形式追加。这样一来LLM 在生成回复前除了短期对话历史之外还能获得长期记忆的加持。5. 不同的 Memory 实现就像存在不同的ChatCompletionContext策略一样Memory也有不同实现ListMemory最简单的实现把所有内容存进一个 Python 列表如同按时间顺序排列的笔记本。未来可能更高级的实现可以基于数据库或向量存储实现对海量信息的更高效存储与检索。实战用例用ListMemory记住用户偏好下面用简单的ListMemory完整实现记住用户偏好这一场景。目标创建一个ListMemory向其中添加一条用户偏好正式风格开启一个全新的对话上下文用update_context将偏好注入新对话上下文展示发送给 LLM 之前的上下文内容。Step 1创建记忆实例使用 AutoGen Core 提供的最简实现ListMemory# File: create_list_memory.py from autogen_core.memory import ListMemory # Create a simple list-based memory instance user_prefs_memory ListMemory(nameuser_preferences) print(fCreated memory: {user_prefs_memory.name}) print(fInitial content: {user_prefs_memory.content}) # Output: # Created memory: user_preferences # Initial content: []现在我们拥有了一个名为user_preferences的空记忆笔记本。注意ListMemory的构造函数接受name参数用于标识这个记忆实例。Step 2写入偏好把用户偏好作为一条文本记忆添加进去# File: add_preference.py import asyncio from autogen_core.memory import MemoryContent # Assume user_prefs_memory exists from the previous step # Define the preference as MemoryContent preference MemoryContent( contentUser prefers all communication to be written in a formal style., mime_typetext/plain, # Its just text metadata{source: user_instruction_conversation_1} # Optional info ) async def add_to_memory(): # Add the content to our memory instance await user_prefs_memory.add(preference) print(fMemory content after adding: {user_prefs_memory.content}) asyncio.run(add_to_memory()) # Output (will show the MemoryContent object): # Memory content after adding: [MemoryContent(contentUser prefers..., mime_typetext/plain, metadata{source: ...})]add是异步方法需要用await调用。至此偏好已被成功写入ListMemory笔记本。Step 3开启新的对话上下文假设时间流逝用户开启了新对话请求起草一封邮件。我们创建一个全新的ChatCompletionContext# File: start_new_chat.py from autogen_core.model_context import UnboundedChatCompletionContext from autogen_core.models import UserMessage # Start a new, empty chat context for a new task new_chat_context UnboundedChatCompletionContext() # Add the users new request new_request UserMessage(contentDraft an email to the team about the Q3 results., sourceUser) # await new_chat_context.add_message(new_request) # In a real app, add the request print(Created a new, empty chat context.) # Output: Created a new, empty chat context.这个上下文目前并不知道长期记忆中存储的正式风格偏好。这正是Memory要补上的短板。Step 4将记忆注入对话上下文在把new_chat_context发送给 LLM 之前调用update_context把相关长期记忆带入# File: update_chat_with_memory.py import asyncio # Assume user_prefs_memory exists (with the preference added) # Assume new_chat_context exists (empty or with just the new request) # Assume new_request exists async def main(): # --- This is where Memory connects to Chat Context --- print(Updating chat context with memory...) update_result await user_prefs_memory.update_context(new_chat_context) print(fMemories injected: {len(update_result.memories.results)}) # Now lets add the actual user request for this task await new_chat_context.add_message(new_request) # See what messages are now in the context messages_for_llm await new_chat_context.get_messages() print(\nMessages to be sent to LLM:) for msg in messages_for_llm: print(f- [{msg.type}]: {msg.content}) asyncio.run(main())预期输出Updating chat context with memory... Memories injected: 1 Messages to be sent to LLM: - [SystemMessage]: Relevant memory content (in chronological order): 1. User prefers all communication to be written in a formal style. - [UserMessage]: Draft an email to the team about the Q3 results.可以看到ListMemory.update_context方法自动查询了记忆在这个简单实现中它直接取出所有条目并向new_chat_context添加了一条SystemMessage。这条消息在 LLM 看到用户起草邮件的请求之前明确告知了存储的偏好。update_context返回的UpdateContextResult对象中的memories.results包含本次注入的记忆列表可用于日志或后续处理。Step 5概念发送给 LLM现在如果我们将messages_for_llm发送给 ChatCompletionClient# Conceptual code - Requires a configured client # response await llm_client.create(messagesmessages_for_llm)LLM 将同时收到正式风格偏好指令来自 Memory和起草邮件请求因此极大概率会遵循该偏好Step 6可选直接查询也可以不经过对话上下文直接查询记忆# File: query_memory.py import asyncio # Assume user_prefs_memory exists async def main(): # Query the memory (ListMemory returns all items regardless of query text) query_result await user_prefs_memory.query(style preference) print(\nDirect query result:) for item in query_result.results: print(f- Content: {item.content}, Type: {item.mime_type}) asyncio.run(main()) # Output: # Direct query result: # - Content: User prefers all communication to be written in a formal style., Type: text/plain这展示了智能体如何在需要时专门查阅自己的笔记本。深入底层ListMemory是如何注入上下文的让我们追踪ListMemory的update_context调用链。概念流程图逐步拆解智能体调用user_prefs_memory.update_context(new_chat_context)ListMemory实例访问其内部_contents列表检查列表是否为空。若非空则继续遍历列表中的MemoryContent条目将其格式化为带编号的字符串形如Relevant memory content...\n1. Item 1\n2. Item 2...创建一个包含该格式化字符串的单一SystemMessage调用new_chat_context.add_message()将此SystemMessage追加到将发送给 LLM 的对话历史中返回包含刚处理过的记忆列表的UpdateContextResult。源码速览Memory协议memory/_base_memory.py定义任何记忆实现都必须提供的方法。# From: memory/_base_memory.py (Simplified ABC) from abc import ABC, abstractmethod # ... other imports: MemoryContent, MemoryQueryResult, UpdateContextResult, ChatCompletionContext class Memory(ABC): component_type memory abstractmethod async def update_context(self, model_context: ChatCompletionContext) - UpdateContextResult: ... abstractmethod async def query(self, query: str | MemoryContent, ...) - MemoryQueryResult: ... abstractmethod async def add(self, content: MemoryContent, ...) - None: ... abstractmethod async def clear(self) - None: ... abstractmethod async def close(self) - None: ...任何想要扮演Memory角色的类都必须提供这些方法。注意基类还声明了component_type memory这与 第 8 章 Component 的组件化体系直接相关——Memory本身就是一个标准组件类型。ListMemory实现memory/_list_memory.py# From: memory/_list_memory.py (Simplified) from typing import List # ... other imports: Memory, MemoryContent, ..., SystemMessage, ChatCompletionContext class ListMemory(Memory): def __init__(self, ..., memory_contents: List[MemoryContent] | None None): # Stores memory items in a simple list self._contents: List[MemoryContent] memory_contents or [] async def add(self, content: MemoryContent, ...) - None: Add new content to the internal list. self._contents.append(content) async def query(self, query: str | MemoryContent , ...) - MemoryQueryResult: Return all memories, ignoring the query. # Simple implementation: just return everything return MemoryQueryResult(resultsself._contents) async def update_context(self, model_context: ChatCompletionContext) - UpdateContextResult: Add all memories as a SystemMessage to the chat context. if not self._contents: # Do nothing if memory is empty return UpdateContextResult(memoriesMemoryQueryResult(results[])) # Format all memories into a numbered list string memory_strings [f{i}. {str(mem.content)} for i, mem in enumerate(self._contents, 1)] memory_context_str Relevant memory content...\n \n.join(memory_strings) \n # Add this string as a SystemMessage to the provided chat context await model_context.add_message(SystemMessage(contentmemory_context_str)) # Return info about which memories were added return UpdateContextResult(memoriesMemoryQueryResult(resultsself._contents)) # ... clear(), close(), config methods ...这段代码清晰展示了ListMemory的直白逻辑存进列表 → 取回整个列表 → 把整个列表作为一条系统消息注入对话上下文。更复杂的记忆实现可能会采用更智能的检索例如基于query()中的查询文本或update_context中的最后一条消息并以不同方式注入记忆。几个值得注意的工程细节update_context在记忆为空时直接返回空的UpdateContextResult避免向对话中注入无意义的系统消息编号格式化使用enumerate(self._contents, 1)保证输出的编号从 1 开始与上节预期输出中的1. User prefers...完全对应记忆内容通过str(mem.content)序列化为纯文本——因此对text/plain类型的记忆效果最佳而对二进制或复杂结构化内容具体表现取决于实现的字符串化方式。与 Component 体系的衔接记忆的可配置化Memory并非孤立存在。正如 第 8 章 Component 所述ListMemory本身就是一个标准Component基类声明了component_type memoryListMemory可以通过dump_component()将自身包括name和已存储的memory_contents序列化为ComponentModel之后可通过load_component()从配置还原出完全一致的实例。这意味着你不仅可以在代码中创建记忆还可以把记忆配置保存为 JSON/YAML 文件随时重建、共享或替换不同的记忆实现例如把ListMemory换成向量数据库记忆而使用Memory标准接口的智能体逻辑无需改动。详情请参阅 Component 章节。本教程的生成背景与进一步阅读值得说明的是本文档及其所在的整个 AutoGen Core 教程 是由本仓库Tutorial-Codebase-Knowledge自动生成的。根据 docs/design.md 的设计系统通过FetchRepo → IdentifyAbstractions → AnalyzeRelationships → OrderChapters → WriteChapters → CombineTutorial的工作流先爬取上游仓库源码识别核心抽象Memory 正是其中之一再由 LLM 逐章撰写入门教程章节写入步骤由 nodes.py 中的WriteChaptersBatchNode见 nodes.py 第 537 行批量完成。你可以继续阅读本系列的其他章节第 5 章ChatCompletionClient——LLM 通信的标准接口第 6 章ChatCompletionContext——短期对话历史的智能管理第 8 章Component——理解Memory、ChatCompletionContext、ChatCompletionClient如何被统一配置与管理。总结本文深入剖析了 AutoGen Core 的Memory抽象——为智能体提供超越单次对话ChatCompletionContext的长期记忆能力。核心要点回顾MemoryContent统一封装记忆条目的数据结构支持文本、JSON、图片等mime_type并携带可选metadataadd写入长期记忆query检索记忆返回MemoryQueryResultupdate_context把相关记忆以SystemMessage形式注入对话上下文让 LLM 在生成回复前获得长期记忆加持返回UpdateContextResultListMemory最简单的内置实现——列表存储、整体返回、整体注入适合作为记忆机制的入门理解也是自定义更复杂记忆实现如向量检索、数据库持久化的良好起点。记忆系统对于需要学习、适应或跨交互维持状态的智能体至关重要。理解Memory之后你将能构建出记得用户偏好累积领域知识跨会话保持一致性的真正长期型智能体。赞分享人工智能AI 应用AI Agent【免费下载链接】Tutorial-Codebase-KnowledgePocket Flow: Codebase to Tutorial项目地址https://gitcode.com/gh_mirrors/tu/Tutorial-Codebase-Knowledge点击查看免费下载相关推荐AutoGen 接入长期记忆实战用 hindsight-autogen 为 Agent 构建跨会话记忆AutoGen 接入长期记忆实战用 hindsight autogen 为 Agent 构建跨会话记忆 本指南讲解如何通过 hindsight autogen人工智能AI AgentAgent 记忆MCP 服务Grok Build 长期记忆接入实战用 hindsight-memory 插件为 Grok Build 添加跨会话记忆Grok Build 长期记忆接入实战用 hindsight memory 插件为 Grok Build 添加跨会话记忆 导读 本文讲解如何通过 hinds人工智能AI AgentAgent 记忆MCP 服务ADK 跨会话记忆实战基于 Vertex AI Memory Bank 的 Agent 长期记忆实现与双目标部署ADK 跨会话记忆实战基于 Vertex AI Memory Bank 的 Agent 长期记忆实现与双目标部署 本指南以 core/python/cross示例工程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表