从Python列表到向量检索:揭秘Agent Memory的完整进阶之路
文章探讨了Agent Memory的重要性指出LLM的无状态特性导致传统记忆方法的局限性。文章从Python列表、Markdown文件存储、向量检索等基础方法入手逐步深入到Cognee开源方案强调向量检索和图向量混合记忆的必要性。Cognee通过整合关系型存储、向量存储和图存储实现了高效的知识检索和推理为Agent的长期记忆和持续进化提供了关键支持。文章最后强调智能需要结构化记忆而非单纯的存储结构化记忆系统是Agent从一次性智能向长期协作体转变的关键。导读这是一篇从第一性原理出发讲清楚 Agent Memory 的文章从 Python 列表、Markdown 文件、向量检索、图向量混合记忆一路讲到一个更完整、可落地的开源方案。很多人第一次做 Agent都会默认一个前提大模型已经很聪明了只要上下文足够长它就应该“记得住”。但现实恰恰相反。LLM 从设计上就是**无状态stateless**的。每一次 API 调用都是从零开始。你在 ChatGPT 里感受到的“记忆”本质上只是系统在每次请求时把整段历史对话重新发了一遍。这个技巧用于日常聊天还行。但只要你开始构建真正的 Agent它很快就会失效。一、没有记忆的 Agent会立刻暴露 7 个问题一旦跳过记忆系统下面这些故障模式会立刻出现上下文失忆你明明已经告诉过它的信息它还会反复再问一次零个性化每次交互都像第一次见面回答永远泛泛而谈多步骤任务失败中间状态在执行过程中悄悄丢失重复犯错没有情节记忆错误会一遍又一遍重演无法积累知识每个会话都从头开始没有复利上下文溢出后幻觉加重信息一旦塞不下模型就会开始编身份连续性坍塌没有连续性就没有信任感很多人的第一反应是“那就塞更多上下文进去。”这也是为什么 128K、200K 的长上下文窗口看起来像是能解决一切。但它并不能。原文提到一个关键问题当关键信息落在超长上下文的中间位置时模型准确率会下降 30% 以上这就是经典的“Lost in the Middle中间遗失”效应。而且上下文从来都不是免费空间。它是一个共享预算system prompt 要占 token检索结果要占 token对话历史要占 token模型输出本身也要占 token所以即便你有 100K 以上的上下文窗口只靠“堆文本”依然不够。真正的问题不是“塞进去多少”而是Agent 应该如何组织它的记忆才能在需要时找到最关键的信息。二、真正有用的认知框架Agent LLM Memory Planning Tool UseLilian Weng 在 2023 年给出过一个后来被广泛引用的框架Agent LLM Memory Planning Tool Use也就是说一个真正像样的 Agent不只是一个大模型外壳而是四个同等重要的支柱共同组成的系统LLMMemoryPlanningTool Use这个框架借鉴了认知科学中对人类记忆的划分。1感觉记忆Sensory Memory负责接收原始感知输入只保留极短时间。只有被注意到的部分才会继续传递下去。2工作记忆Working Memory这是进行“当前思考”的地方。经典研究认为人类工作记忆大约只能同时维持7±2 个项目。一旦注意力转移内容就会迅速消失。3长期记忆Long-term Memory这是稳定、持久、理论上容量几乎无限的存储层。它真正的瓶颈不在“存”而在“取”——你可以存下几百万条信息但仍然可能想不起眼下最需要的那一条。映射到现代 Agent 架构里长期记忆又会进一步拆成三类情节记忆Episodic具体发生过的事件例如“周二 PostgreSQL 集群宕机了”语义记忆Semantic事实、概念和通用知识例如“PostgreSQL 是关系型数据库”程序记忆Procedural技能、流程和操作规则例如“当用户申请退款时先检查购买日期”而情节记忆和语义记忆之间还存在一个关键桥梁记忆固化Memory Consolidation也就是Agent 不只是记录事件还要能从重复事件中提炼出规律。比如如果 Agent 在几十次互动里都发现“用户 consistently 更偏好 executive summary高管摘要。”那它就不应该只是记住几十条零散历史而应该把这件事固化成一条可复用规则。没有固化Agent 只是回放过去。有了固化Agent 才算真正开始学习。三、一个最小 Agent到底最先坏在哪里把所有框架都剥掉之后最小 Agent 本质上只有一个循环感知perceive→ 思考think→ 行动act原文给了一个极简版本ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line class Agent: Minimal AI agent: perceive, think, act def __init__(self): self.client anthropic.Anthropic() self.model claude-sonnet-4-20250514 def run(self, user_input: str) - str: response self.client.messages.create( modelself.model, max_tokens1024, messages[{role: user, content: user_input}], ) return response.content[0].text这个 Agent 的问题非常直观你先告诉它“我有 4 个苹果。”再问它“我吃了 1 个还剩几个”它根本不知道你在说什么。因为每一次调用都是孤立的。它根本没有记忆。四、记忆系统的第一层Python 列表很多人修复这个问题时第一反应就是把历史消息存在一个 Python list 里。ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line class Agent: def __init__(self): self.client anthropic.Anthropic() self.messages [] # 整个“记忆”就是一个列表 def chat(self, user_input: str) - str: self.messages.append({role: user, content: user_input}) response self.client.messages.create( modelclaude-sonnet-4-20250514, max_tokens1024, messagesself.messages, # 每次都把完整历史带上 ) reply response.content[0].text self.messages.append({role: assistant, content: reply}) return reply这时候多轮对话终于能工作了。苹果问题也能答对了因为每次请求都会把完整历史重新发送。但很快你就会撞上两个问题问题 1列表会无限增长到了大约第 200 轮上下文你就会开始撞上窗口上限。最早的消息会悄悄被挤掉。结果就是你在第 1 轮告诉它的名字没了但昨天一句无关紧要的玩笑可能还在它没有优先级机制只有机械的时间顺序问题 2所有内容都只活在内存里只要 Python 进程一结束Agent 对你是谁、之前聊过什么全部归零。所以Python 列表能解决“多轮对话”但解决不了“长期记忆”。五、第二层把记忆写进 Markdown 文件下一步很自然把记忆落盘。Markdown 是非常适合做这件事的格式可读性强对人友好方便版本管理Agent 也可以直接把它当纯文本读回来原文提到Claude Code 就是走的这条路线例如CLAUDE.md和MEMORY.md。示意代码如下ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line class MarkdownMemoryAgent: def __init__(self): self.client anthropic.Anthropic() self.history_file Path(memory/conversation_history.md) self.facts_file Path(memory/known_facts.md) def save_to_disk(self, role: str, content: str) - None: with open(self.history_file, a) as f: f.write(f### {role} at {datetime.now().isoformat()}\n{content}\n\n) def load_history(self) - str: if self.history_file.exists(): return self.history_file.read_text() return def chat(self, user_input: str) - str: self.save_to_disk(user, user_input) history self.load_history() response self.client.messages.create( modelclaude-sonnet-4-20250514, max_tokens1024, systemfPrevious conversation:\n{history}, messages[{role: user, content: user_input}], ) reply response.content[0].text self.save_to_disk(assistant, reply) return reply这样一来至少有两件事解决了1持久化解决了脚本重启后历史还在磁盘里。2你可以维护一个“事实文件”比如ounter(lineounter(lineounter(lineounter(line - 用户名字叫 Sarah - Sarah 管理 Acme Corp 的后端团队 - Acme Corp 是一家 B2B SaaS 公司 - 目前正在把生产数据库迁移到新的 AWS 区域这种方式在原型期非常好用因为你可以直接打开文件看见 Agent 到底记住了什么还可以手工修改当事实只有 4 条时这套方案几乎完美。把整个文件塞进上下文模型就能回答和 Sarah、公司、业务相关的问题。六、为什么 Markdown 方案到了真实规模会失效问题出在规模上。假设 3 个月后你的 Agent 已经积累了2000 条抽取事实200 份对话日志那么磁盘上的 Markdown 文本很可能已经达到50 万 token 以上。而你的上下文窗口也许只有 128K。这时候你已经不可能把所有内容全量加载进 prompt。你只能做一件事按需检索只找和当前问题最相关的那部分。但 Markdown 平铺文件一旦到了这里就会遇到一个致命问题它通常只能靠关键词检索。原文举了两个非常典型的例子。例子 1用户问“我们的云迁移现在什么状态了”你去 facts 文件里 grepounter(line grep(cloud migration, facts_file)结果返回空。为什么因为文件里写的是“正在把生产数据库迁移到新的 AWS 区域。”它的语义是“云迁移”但文本里压根没有出现cloud migration这两个词。例子 2用户问“哪个团队在负责数据库相关工作”你去 grepounter(line grep(database team, facts_file)还是返回空。因为一条事实写的是Sarah 管理后端团队另一条写的是这个团队正在迁移生产数据库两条信息分别正确但没有任何一行同时包含database和team。这就是 flat file 方案在真实规模下的核心问题它能存但不会找它能记录但不会关联所以原文用了一个非常形象的比喻没有智能检索的存储就像一座没有目录系统的图书馆。七、第三层向量检索解决了语义却撞上关系推理的墙下一步大家通常会给 Markdown 方案加 embeddings。也就是把文本切块为每个 chunk 生成向量用余弦相似度做检索这样一来语义问题就解决了很多。比如“database” 可以匹配到 “PostgreSQL”因为它们在 embedding 空间里比较接近。这时候关键词问题基本被打穿了。但新的问题又来了。原文举了一个很经典的多跳推理例子ounter(lineounter(lineounter(line - Alice 是 Project Atlas 的技术负责人 - Project Atlas 的主数据库是 PostgreSQL - PostgreSQL 集群在周二发生了故障用户问“Alice 负责的项目是否受到了周二那次故障的影响”对于向量检索来说“Alice” 和 “周二故障” 会让第 1 条和第 3 条得分很高但真正关键的中间桥梁是第 2 条“Project Atlas 使用 PostgreSQL”偏偏这一条既没有 Alice也没有 Tuesday。它是最关键的连接信息却最容易检索不出来。这就是纯向量检索的天花板它擅长“相似”却不擅长“关系”而真实世界里的业务知识天然就是关系型的人属于团队团队负责项目项目依赖系统系统会发生事故任何需要跨两跳、三跳去推理的问题都不是纯向量检索的强项。所以到了这一步真正的需求已经非常明确了你需要一个同时具备持久化、语义理解、关系推理能力的记忆层。八、真正完整的记忆层至少要同时具备三种能力原文把这个问题讲得很透如果你自己从头搭建往往意味着你要把下面这些东西一块拼起来向量数据库图数据库关系型存储实体抽取器去重管道边权重系统光把这些基础设施拼好可能就已经耗掉几周时间Agent 业务逻辑还一行没写。于是文章引出了一个作者正在使用的方案Cognee作者对它的定义是一个面向 Agent Memory 的开源知识引擎。它把向量检索、知识图谱和关系型溯源层整合成了一个统一系统。九、Cognee三种存储一个引擎四个调用它最吸引人的地方是 API 面非常小。ounter(lineounter(lineounter(lineounter(lineounter(lineounter(line import cognee await cognee.add(Your document here) # 摄入任意内容 await cognee.cognify() # 构建知识图谱 向量索引 await cognee.memify() # 让记忆自我优化 await cognee.search(Your query) # 带推理地检索看起来只有四步但背后其实是一个三存储架构three-store architecture。为什么不是一种存储而是三种因为每一种存储都在捕捉知识的不同维度1关系型存储Relational Store——负责溯源回答的是数据来自哪里是什么时候摄入的谁可以访问2向量存储Vector Store——负责语义回答的是这段内容在说什么它和什么内容语义接近3图存储Graph Store——负责关系回答的是实体和实体之间如何连接谁依赖谁谁导致了谁谁向谁汇报如果把三者中的任何一层压平都会损失检索准确性所依赖的关键信息。十、Cognee 默认栈为什么值得注意文章提到它的默认本地栈是SQLiteLanceDBKuzu全部都是嵌入式、文件级组件。也就是说你只要pip install cognee再配一个 LLM API Key基本就能跑起来。不需要 Docker不需要外部服务。而如果要上生产也可以替换后端SQLite → PostgresLanceDB → Qdrant / Pinecone / pgvectorKuzu → Neo4j / FalkorDB / Neptune关键在于无论本地开发还是生产部署对上层 Agent 暴露的 API 还是那四个调用。这一点很重要。因为它意味着你不需要为了迁移生产环境而重写 Agent 代码。十一、cognify()到底做了什么这是文章里比较有价值的一段。cognify()并不是简单“建索引”而是跑了一条多阶段管道把原始文本转成结构化、互联化知识。它大致包括按文档类型和领域进行分类做多租户访问控制的权限检查以段落结构为基础进行切块而不是机械定长切块用 LLM 抽取实体和关系并基于内容哈希自动去重生成摘要提升检索效率同时写入向量存储embeddings和图存储edges其中有一个细节尤其关键去重deduplication如果同一个实体在 50 个文档里都出现过Cognee 不会把它当作 50 个不同对象而是会把它合并成一个图节点同时保留 50 条入边。也就是说你的 Agent 不会把 “Alice” 视为 50 个毫无关系的陌生人而是会把她视为一个在不同文档里不断被补充信息的同一个实体。这会极大提升长期记忆的一致性。另一个关键点是增量处理incremental默认只重新处理新增或更新过的文件。这样你不需要每次都全量重建知识库。十二、为什么“图 向量”的双重表示很关键文章里有一句话很值得记住每一个图节点都有一个对应的 embedding。这就是双重表示的核心技巧。它带来的能力是你可以从向量入口进入先找到语义相近内容再从图结构走出去沿着关系边追踪相关实体也可以反过来先通过图关系定位节点再用向量空间做语义扩展这就是为什么它能够在保留语义检索能力的同时完成多跳问题的关系推理。十三、memify()真正让“记忆会学习”的那一步在作者看来memify()是 Cognee 区别于一般“摄入 检索”工具的关键点。它会对图做一轮类似强化学习思路的优化包括强化那些曾经导向优质检索结果的路径修剪长期没有被使用的陈旧节点根据真实使用情况自动调节边权重识别隐含关系并补充派生事实比如一个客服 Agent它会自然不断强化和产品文档退款政策常见工单路径相关的连接同时让那些几乎没人查的人力资源边逐渐衰减。换句话说这个记忆图谱会随着使用而形成自己的“相关性感知”。这就不再只是“存档系统”而更像一个真的会越用越顺手的记忆层。十四、如何把 Cognee 接进真实 Agent原文给了一个完整模式把 Cognee 接到perceive → think → act的循环里。ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line import cognee from cognee import SearchType class CogneeMemoryAgent: Agent with graph-vector hybrid persistent memory. def __init__(self, session_id: str default): self.llm_client OpenAI() self.session_id session_id async def ingest(self, text: str, dataset: str main): await cognee.add(text, dataset) await cognee.cognify([dataset]) async def recall(self, query: str) - str: results await cognee.search( query_textquery, query_typeSearchType.GRAPH_COMPLETION, session_idself.session_id, ) return results[0] if results else async def chat(self, user_input: str) - str: context await self.recall(user_input) messages [ {role: system, content: You are helpful. Use memory context.}, {role: system, content: fMemory context:\n{context}}, {role: user, content: user_input}, ] response self.llm_client.chat.completions.create( modelgpt-4o-mini, messagesmessages ) reply response.choices[0].message.content await cognee.add( fUser: {user_input}\nAssistant: {reply}, conversations ) await cognee.cognify([conversations]) return reply这个模式的本质非常清晰摄入 → 抽取 → 存储 → 检索 → 回答 → 再存储也就是每一轮交互都会反过来继续丰富知识图谱。而且因为它是增量处理所以你只需要为新增内容付索引成本。十五、Session Memory 还能解决代词指代问题原文提到一个很实用的细节ounter(lineounter(lineounter(line await cognee.search(query_textWhere does Alice live?, session_idconv_1) await cognee.search(query_textWhat does she do for work?, session_idconv_1) # she resolves to Alice from session context也就是说在同一个 session 里像 “she”“he”“that project” 这类代词或省略引用可以借助会话级上下文自动完成解析。这对于多轮复杂对话非常重要。否则用户每轮都得重新把实体名说全体验会非常差。十六、多租户能力也不是“命名空间隔离”那么简单文章还强调了一点Cognee 的多租户权限不是简单的 namespace 分隔而是图层级的权限控制可以针对数据集设置readwritedeleteshare这意味着它更接近真正企业级系统而不是一个只适合单人 demo 的记忆玩具。十七、真正该问的问题不是“要不要做记忆”而是“需要什么记忆”文章最后给出的判断路径很实用如果你今天正在构建 Agent最先该问的不是“我要不要加 Memory”而是“我的 Agent 需要记住什么它将回答什么类型的问题”如果你的问题只需要相似性检索例如“帮我找和这段对话类似的历史记录”那么纯向量记忆可能已经够用。但只要你的问题跨实体边界例如“Alice 负责的项目是否受到了周二事故影响”你就需要图遍历能力。因为这类问题的本质不只是“像不像”而是“连不连得起来”。十八、最后的结论智能需要结构而不仅仅是存储这篇文章最值得带走的一句话是智能真正需要的不是更多存储而是更好的结构。关系型、向量型、图结构这三种存储范式并不是互斥选项。它们其实是同一个记忆系统的三个互补层关系型保障可追溯、可治理向量型保障语义召回图结构保障关系推理把它们当成一个协同系统来看你才有可能把一个“无状态的大模型封装壳”变成一个真正能学习、能积累、能持续协作的 Agent。写在最后很多人做 Agent花了大量时间在Prompt 怎么写模型怎么选工具怎么接工作流怎么编排但真正决定 Agent 能不能从“会答题”走向“会持续工作”的往往不是这些表层能力而是它背后的记忆系统设计。没有记忆Agent 只是一次性智能。有了结构化记忆Agent 才开始具备“长期协作体”的雏形。如果你想做的不是一个只能聊两句的 demo而是一个能持续进化、能跨会话协作、能越用越懂你的真实系统那从今天开始记忆层就不该再是可选项。01什么是AI大模型应用开发工程师如果说AI大模型是蕴藏着巨大能量的“后台超级能力”那么AI大模型应用开发工程师就是将这种能量转化为实用工具的执行者。AI大模型应用开发工程师是基于AI大模型设计开发落地业务的应用工程师。这个职业的核心价值在于打破技术与用户之间的壁垒把普通人难以理解的算法逻辑、模型参数转化为人人都能轻松操作的产品形态。无论是日常写作时用到的AI文案生成器、修图软件里的智能美化功能还是办公场景中的自动记账工具、会议记录用的语音转文字APP这些看似简单的应用背后都是应用开发工程师在默默搭建技术与需求之间的桥梁。他们不追求创造全新的大模型而是专注于让已有的大模型“听懂”业务需求“学会”解决具体问题最终形成可落地、可使用的产品。CSDN粉丝独家福利给大家整理了一份AI大模型全套学习资料这份完整版的 AI 大模型学习资料已经上传CSDN朋友们如果需要可以扫描下方二维码点击下方CSDN官方认证链接免费领取【保证100%免费】02AI大模型应用开发工程师的核心职责需求分析与拆解是工作的起点也是确保开发不偏离方向的关键。应用开发工程师需要直接对接业务方深入理解其核心诉求——不仅要明确“要做什么”更要厘清“为什么要做”以及“做到什么程度算合格”。在此基础上他们会将模糊的业务需求拆解为具体的技术任务明确每个环节的执行标准并评估技术实现的可行性同时定义清晰的核心指标为后续开发、测试提供依据。这一步就像建筑前的图纸设计若出现偏差后续所有工作都可能白费。技术选型与适配是衔接需求与开发的核心环节。工程师需要根据业务场景的特点选择合适的基础大模型、开发框架和工具——不同的业务对模型的响应速度、精度、成本要求不同选型的合理性直接影响最终产品的表现。同时他们还要对行业相关数据进行预处理通过提示词工程优化模型输出或在必要时进行轻量化微调让基础模型更好地适配具体业务。此外设计合理的上下文管理规则确保模型理解连贯需求建立敏感信息过滤机制保障数据安全也是这一环节的重要内容。应用开发与对接则是将方案转化为产品的实操阶段。工程师会利用选定的开发框架构建应用的核心功能同时联动各类外部系统——比如将AI模型与企业现有的客户管理系统、数据存储系统打通确保数据流转顺畅。在这一过程中他们还需要配合设计团队打磨前端交互界面让技术功能以简洁易懂的方式呈现给用户实现从技术方案到产品形态的转化。测试与优化是保障产品质量的关键步骤。工程师会开展全面的功能测试找出并修复开发过程中出现的漏洞同时针对模型的响应速度、稳定性等性能指标进行优化。安全合规性也是测试的重点需要确保应用符合数据保护、隐私安全等相关规定。此外他们还会收集用户反馈通过调整模型参数、优化提示词等方式持续提升产品体验让应用更贴合用户实际使用需求。部署运维与迭代则贯穿产品的整个生命周期。工程师会通过云服务器或私有服务器将应用部署上线并实时监控运行状态及时处理突发故障确保应用稳定运行。随着业务需求的变化他们还需要对应用功能进行迭代更新同时编写完善的开发文档和使用手册为后续的维护和交接提供支持。03薪资情况与职业价值市场对这一职业的高度认可直接体现在薪资待遇上。据猎聘最新在招岗位数据显示AI大模型应用开发工程师的月薪最高可达60k。在AI技术加速落地的当下这种“技术业务”的复合型能力尤为稀缺让该职业成为当下极具吸引力的就业选择。AI大模型应用开发工程师是AI技术落地的关键桥梁。他们用专业能力将抽象的技术转化为具体的产品让大模型的价值真正渗透到各行各业。随着AI场景化应用的不断深化这一职业的重要性将更加凸显也必将吸引更多人才投身其中推动AI技术更好地服务于社会发展。CSDN粉丝独家福利给大家整理了一份AI大模型全套学习资料这份完整版的 AI 大模型学习资料已经上传CSDN朋友们如果需要可以扫描下方二维码点击下方CSDN官方认证链接免费领取【保证100%免费】