
1. 从“失忆”说起为什么你的AI Agent总是记不住事最近在折腾AI Agent项目时你是不是也遇到过这种让人抓狂的场景你让Agent帮你分析一份长文档它前半部分分析得头头是道但当你基于前半部分的分析追问一个关于文档后半部分的细节问题时它却一脸茫然要么答非所问要么直接告诉你“根据提供的信息无法回答”。又或者在一个多轮对话中你和Agent讨论了A、B、C三个方案最后你问“那我们综合刚才讨论的A和C的优点来制定最终计划吧”结果Agent却反问“您提到的方案A和C具体是指什么”如果你的Agent有这种“健忘症”那问题大概率出在上下文管理上。这可不是简单的“内存不足”而是一个涉及模型能力边界、工程架构设计和成本控制的复杂问题。简单来说上下文Context就是喂给大语言模型LLM的“记忆面包”它包含了对话历史、系统指令、工具调用结果、知识库片段等所有模型做出下一次决策所需的信息。而管理这片“面包”的大小、新鲜度和有效性就是上下文管理的核心。为什么这如此关键因为今天的LLM无论是OpenAI的GPT系列、Anthropic的Claude还是开源的Llama、DeepSeek它们都有一个硬性的“饭量”上限——最大上下文长度Context Window通常以Token数来衡量。你肯定见过类似api error: 400 this models maximum context length is 1048576 tokens这样的报错。这意味着一旦你塞给模型的“记忆”超过了这个Token数请求就会直接失败。更常见且隐蔽的问题是即使没超限随着上下文越来越长模型对最早信息的“记忆”也会模糊、失真导致回答质量下降这就是“中间层衰减”现象。因此构建一个健壮的AI Agent上下文管理不是可选项而是生死线。它决定了你的Agent是能进行深度、连贯协作的智能伙伴还是一个聊两句就重启、毫无连续性的“金鱼脑”。接下来我将结合实战拆解构建一个高效、经济且可靠的上下文管理系统的核心思路与具体方案。2. 理解上下文管理的核心挑战与目标在动手设计解决方案之前我们必须先厘清要解决的具体问题。上下文管理绝非简单的“截断”或“压缩”它需要平衡多个相互冲突的目标应对以下几个核心挑战2.1 挑战一有限资源与无限需求的矛盾模型的上下文窗口是昂贵的稀缺资源。以GPT-4 Turbo的128K上下文为例虽然看起来很大但在复杂的Agent工作流中消耗极快。一次交互可能包含系统指令System Prompt定义Agent角色、能力和约束的“宪法”通常固定且必要。对话历史Conversation History用户与Agent的所有过往问答。工具调用结果Tool Call ResultsAgent调用搜索引擎、数据库、API等外部工具返回的可能很长的文本数据。检索到的知识Retrieved Knowledge从向量数据库等知识库中查找到的相关文档片段。中间链式思考Chain-of-ThoughtAgent内部推理过程产生的文本。如果不加管理这些内容会迅速填满上下文窗口。我们的目标是在有限的Token预算内尽可能保留对当前决策最关键的信息。2.2 挑战二信息相关性与时效性的权衡并非所有历史信息都对当前问题有同等价值。一段10轮对话前的寒暄可能对当前解决一个技术问题毫无帮助。而刚刚检索到的一篇关键文档的某个段落可能至关重要。同时信息的时效性也很关键。在股票分析场景中一小时前的股价和一分钟前的股价价值天差地别。因此上下文管理需要一套“价值评估”机制能够动态判断哪些信息应该被优先保留哪些可以被舍弃或压缩。2.3 挑战三长期记忆与短期工作记忆的协同人类有长期记忆和短期工作记忆。AI Agent也需要类似的架构。短期工作记忆就是当前的上下文窗口用于处理即时任务。长期记忆则可以存储在外部如数据库在需要时被“唤醒”并选择性加载到工作记忆中。如何设计这种“加载-卸载”机制让Agent既能记住关键事实如用户偏好又不会让这些信息长期占用宝贵的上下文空间是一大难点。2.4 挑战四成本与性能的博弈更长的上下文意味着更高的API调用成本对于按Token收费的模型和更长的推理延迟。无节制地使用长上下文是极不经济的。例如仅仅为了记住用户的名字而让一个128K上下文的模型去处理每一个请求成本会高得离谱。我们的管理系统必须在保证任务完成质量的前提下尽可能压缩上下文规模降低成本。综上一个优秀的上下文管理系统的目标是在给定的Token预算和成本约束下通过动态筛选、压缩、组织和存储信息最大化Agent在当前任务上的表现并维持对话的连贯性与智能体的人格一致性。3. 构建上下文管理系统的四大核心策略面对上述挑战我们不能依赖单一方法而需要一套组合策略。下面这四种策略从易到难构成了上下文管理的工具箱。3.1 策略一滑动窗口与智能截断这是最基础、最常用的策略。其核心思想是只保留最近N轮对话或最近X个Token的内容。基础实现固定长度滑动窗口def sliding_window_context(messages, max_tokens8000): 保持消息列表的总Token数不超过max_tokens从最旧的消息开始删除。 total_tokens calculate_tokens(messages) while total_tokens max_tokens and len(messages) 1: # 通常从索引1开始删保留最新的系统指令 removed_msg messages.pop(1) # 假设messages[0]是system message total_tokens - calculate_tokens([removed_msg]) return messages注意计算Token数需要使用与目标模型匹配的Tokenizer如tiktokenfor OpenAI不同模型的分词方式不同自行估算会很不准确。进阶实现基于优先级的智能截断固定窗口太“笨”了它可能一刀切掉重要的早期指令。更智能的做法是为每条消息或每个信息片段赋予优先级。优先级打分可以根据消息类型系统指令 用户最近提问 工具结果 早期历史、包含的关键词、甚至是利用一个小型模型来评估该信息对当前问题的潜在重要性来打分。动态剔除当需要腾出空间时优先移除优先级最低的消息而不是最旧的消息。这样可以确保核心指令和最近的关键上下文得以保留。3.2 策略二摘要与压缩当历史信息很重要但又过于冗长时摘要Summarization是利器。其核心是将一大段文本压缩成保留核心信息的简短版本。何时使用摘要对话轮数过多但早期讨论形成了重要结论或约束。工具调用返回了长篇报告如市场分析、代码仓库扫描结果。用户上传了长文档并要求基于其进行多轮问答。实现模式增量摘要在每轮对话后自动对累积的对话历史生成一个摘要。下一轮对话开始时将“摘要”“最新一轮对话”作为上下文替代完整的原始历史。# 伪代码示例 history_summary “” # 初始为空 for each new interaction: context_for_llm system_prompt history_summary latest_user_query agent_response call_llm(context_for_llm) # 生成新的摘要包含本轮交互 new_summary_prompt f“””请将以下对话摘要成一段简洁的文字保留所有关键决策、事实和用户偏好 旧摘要{history_summary} 最新对话 用户{latest_user_query} AI{agent_response} “”” history_summary call_llm(new_summary_prompt) # 使用一个更便宜、快速的模型来做摘要选择性摘要并非所有历史都需要摘要。可以设定规则例如超过5轮的对话部分才触发摘要或者只对工具返回的超长文本进行摘要。提取式 vs. 抽象式摘要提取式直接摘取原文关键句保真度高抽象式由模型重新组织语言概括更连贯但可能有幻觉。对于需要高准确性的技术文档可优先考虑提取式。成本考量摘要本身也是一次LLM API调用需要权衡摘要的成本与它所带来的上下文缩短所节省的成本。通常对于长周期对话摘要的收益是正的。3.3 策略三向量检索与按需加载这是实现“长期记忆”和解决超长文本问题的关键。其核心思想是不把所有信息都塞进上下文而是将信息存储在外部的向量数据库中仅在需要时检索最相关的片段加载进来。工作流程存储索引将Agent运行过程中产生的所有“记忆单元”如完整的对话记录、处理过的文档、工具执行结果进行分块Chunking通过嵌入模型Embedding Model转换为向量存入向量数据库如Chroma, Pinecone, Weaviate。检索召回当新的用户查询到来时用同样的嵌入模型将查询转换为向量在向量数据库中搜索与之最相似的若干个“记忆块”。加载注入将这些检索到的、最相关的记忆块作为上下文的一部分与系统指令和当前查询一起发送给LLM。实战要点分块策略分块大小和重叠度Overlap直接影响检索质量。技术文档可能适合按章节或固定Token数分块对话记录可能按轮次分块。重叠可以避免关键信息被割裂。元数据过滤除了语义相似度检索时应结合元数据过滤。例如只检索“昨天”的记忆或只检索来自“代码执行工具”的结果。这能大幅提升精度。查询重写直接使用用户当前查询进行检索有时效果不好。可以先让LLM根据对话历史将当前查询重写成一个更适合检索的“独立问题”。例如用户问“它怎么说”重写为“关于XX功能的用户手册第三章节内容是什么”。混合检索结合关键词检索BM25和向量检索可以兼顾精确匹配和语义相似度效果往往更好。这种策略完美解决了“长期记忆”问题并且能处理远超模型上下文窗口长度的文档如整本书。Dify、LangChain等框架的知识库功能其底层就是这套逻辑。3.4 策略四结构化记忆与递归查询对于需要高度结构化记忆和复杂推理的Agent我们可以更进一步将记忆本身组织成一个可查询的“知识图谱”或“数据库”。基本思路信息结构化在信息存入长期记忆前不仅做向量化还尝试用LLM或预定义模板将其解析成结构化数据。例如从会议记录中提取[主题 决策项 负责人 截止日期]从用户对话中提取[用户偏好咖啡口味加奶不加糖]。存储到结构化数据库将这些结构化数据存入SQLite、PostgreSQL等关系型数据库或图数据库。递归查询Agent在需要记忆时不是直接检索文本而是生成一个数据库查询语句如SQL或一个针对性的问题来从结构化存储中精确获取所需信息。LLM非常擅长将自然语言问题转换为查询语句。优势精确性避免向量检索的“近似性”带来的噪音。可推理便于执行复杂的多步查询和逻辑判断“找出所有未完成且优先级高的任务”。易于更新对记忆的修改变得简单直接UPDATE语句。挑战实现复杂需要设计稳定的信息提取流程和数据结构。依赖模型能力提取和查询生成的质量直接影响效果。这套策略通常用于对记忆保真度和可操作性要求极高的场景如个人AI助理、项目管理系统Agent。4. 实战架构设计一个分层上下文管理器理论说完我们来设计一个可落地的、结合了上述多种策略的分层上下文管理器。这个架构模仿了计算机存储体系寄存器CPU缓存- 内存 - 硬盘。第一层工作上下文Working Context - “寄存器/内存”内容系统指令 最近2-3轮对话 本次检索到的关键信息 本次工具调用结果。管理策略固定Token数滑动窗口如4096 Tokens。这是直接喂给LLM的“热数据”。目标确保最低延迟和成本下的当前轮次响应质量。第二层会话缓存Session Cache - “内存/高速硬盘”内容本次会话Session内的完整对话历史、重要的中间结果。存储存储在应用服务器的内存或Redis等高速缓存中以Session ID为键。管理策略摘要压缩当会话轮次超过阈值如10轮启动后台任务对早期历史进行摘要用摘要替换原文。向量化备份同时将完整的对话历史或摘要前的历史块化后存入向量数据库第三层作为长期记忆备份。目标维持单次会话的连贯性并为长期记忆提供素材。第三层长期记忆库Long-term Memory - “硬盘/云存储”内容跨会话的、所有被认为有价值的记忆。包括用户画像、项目知识、重要决策记录等。存储向量数据库 可选的结构化数据库。管理策略向量检索每次用户请求到达时用当前查询和简短的工作上下文去向量库检索最相关的N个记忆片段。相关性过滤设置相似度阈值过滤掉低相关度的结果。新鲜度衰减为记忆片段添加时间戳在检索评分中引入时间衰减因子让较新的记忆有更高权重。目标实现Agent的“个性化”和“知识化”记住用户是谁以及过去发生过什么。第四层外部知识库External Knowledge - “网络/图书馆”内容不属于Agent自身经历但可供查询的静态或动态知识如产品手册、API文档、实时新闻。接入方式通过工具调用如搜索API或RAG检索增强生成系统在需要时实时获取。目标扩展Agent的能力边界提供实时、准确的外部信息。这个分层管理器的工作流程如下用户发起请求。系统从长期记忆库中检索相关记忆。结合会话缓存中的近期历史可能是摘要版组装出初始上下文。将初始上下文、用户当前查询送入工作上下文层进行Token数检查和智能截断确保不超过LLM限制。LLM处理请求可能调用工具访问外部知识库。将本轮交互的结果写回会话缓存并选择性地将重要信息归档至长期记忆库。5. 避坑指南与性能优化经验在实际搭建和调试上下文管理系统时我踩过不少坑也总结了一些优化心得。5.1 避坑一Token计算不准导致请求失败这是最常见的错误。不同模型的Tokenizer差异巨大。坑点用GPT-2的Tokenizer去估算GPT-4的Token数或者自己用简单规则如len(text)/4估算。解决方案务必使用模型提供商官方的或兼容的Tokenizer库。对于OpenAI使用tiktoken对于开源模型使用Hugging Facetransformers库中对应的Tokenizer。在上下文组装完成后、发送请求前做一次精确的Token计数并留出安全余量比如预留100个Token给模型的内部格式和可能的消息角色标记。5.2 避坑二摘要引入“幻觉”或信息丢失摘要是一把双刃剑。坑点使用抽象式摘要时LLM可能会“创造”出原文没有的结论或者丢失关键的数字、名称等细节。解决方案指令工程在摘要指令中强调“严格基于原文”、“保留所有具体数据、名称、日期”。混合摘要对于关键信息采用“提取关键句抽象概括”结合的方式。先提取出包含实体和数字的句子再让模型对这些句子进行连贯性概括。验证机制对于非常重要的摘要可以设计一个验证步骤例如用摘要去回答一个关于原文的简单问题看答案是否与原文一致。5.3 避坑三向量检索召回无关信息检索到的信息不相关会严重污染上下文导致LLM输出混乱。坑点分块不合理如把不相关的句子切在一起、嵌入模型不适合领域、检索时没有结合元数据过滤。解决方案分块优化根据文本类型调整分块大小。法律合同可能适合按条款分块技术博客可能适合按小节分块。使用有重叠的分块。领域微调嵌入模型如果条件允许使用在特定领域数据上微调过的嵌入模型语义理解会更精准。多路召回与重排序不要只依赖向量检索。可以同时进行关键词检索然后将两者的结果混合再用一个更小的、训练过的“重排序模型”对结果进行精排选出Top-K最相关的。清晰定义元数据为每个记忆块添加丰富的元数据如source来源文档、timestamp、type对话/工具结果/知识、topic等检索时利用这些元数据进行强力过滤。5.4 性能优化成本与延迟的平衡异步处理摘要生成、向量化存储等耗时操作应该放在后台异步执行不要阻塞主请求链路。缓存检索结果对于相同或相似的查询其检索结果在一定时间内是稳定的。可以缓存(查询向量, 过滤条件) - 结果的映射有效降低对向量数据库的查询压力和响应延迟。分级使用模型摘要、查询重写、相关性评分等辅助任务不一定需要用最强大、最贵的模型。使用小尺寸、低成本但专门优化的模型如text-embedding-3-small做向量化gpt-3.5-turbo做摘要可以大幅降低成本。监控与评估建立监控指标如平均上下文长度、Token消耗成本、检索命中率、用户满意度通过隐式或显式反馈。定期评估根据数据调整策略参数如滑动窗口大小、摘要触发阈值。6. 面向未来上下文管理的演进思考随着LLM技术的飞速发展上下文管理也在演进。这里有几个值得关注的方向1. 原生超长上下文模型像Claude 3.5 Sonnet200K、GPT-4o128K以及一些开源模型正在不断突破上下文长度极限。但这并不意味着管理不再重要。超长上下文会带来更高的成本和更严重的“中间层衰减”问题。“支持长”和“高效用”是两回事。管理策略需要进化为如何在百万Token的海洋中为模型精准定位最关键的信息。2. 模型自身的上下文管理能力一些研究和新模型开始内置更智能的上下文处理机制。例如通过“标记”或“注意力引导”让模型更关注上下文中的特定部分。作为开发者我们需要了解这些机制并通过系统指令System Prompt与之配合引导模型更好地利用我们提供的结构化上下文。3. 推理与记忆的架构分离这是更根本的范式转变。与其把所有记忆都塞进一个“思考模型”的上下文不如采用多模型协作架构。一个专用的“记忆模型”负责存储、检索和总结信息一个“推理模型”负责基于记忆模型提供的精炼信息进行思考和行动。这类似于人类大脑中海马体与大脑皮层的关系。LangGraph、CrewAI等框架正在向这个方向探索。对于现在的我们而言扎实掌握分层管理、摘要压缩、向量检索这些基本功并保持对新技术趋势的敏感就能构建出在当下稳定可靠、在未来也能平滑演进的高效AI Agent。上下文管理不是一劳永逸的配置而是一个需要持续观察、测量和调优的动态系统。