这个问题其实问的是,当模型上下文窗口成为瓶颈时,怎么在有限空间里塞进最有价值的历史信息。说白了,不是能不能记住所有东西,而是怎么在遗忘和保留之间做聪明的取舍。
我的核心思路是分层记忆。你可以类比人类记忆,工作记忆就是手边最近两三轮对话,直接拼进prompt,保证当前任务连贯。短期记忆是当前会话里几小时内的历史,按对话轮次[[分块]],维护时间索引和主题标签。长期记忆才是跨会话的持久化知识,存到[[向量数据库]]里,按需检索。这个分层的好处是,高频访问的放在最上层,成本最低,低频的沉到下层,检索时才拉出来,这样既控制了每次推理的输入长度,又保留了整体信息的可回溯性。
具体检索时,我不会只用语义相似度。因为用户可能问的是昨天刚提过的事,语义上跟今天的话题不相关,但时间近就应该优先。所以我的策略是混合打分:语义相似度用 [[Embedding]] 加 [[HNSW]] 做近似检索,时间衰减用指数函数,重要性由LLM自动打标,比如用户确认过的关键决策、异常事件,这些节点权重高,不容易被遗忘。最后综合得分是语义、时效性和重要性的加权和,权重可以按场景调。举个例子,客服场景里用户问退款进度,语义上跟历史退款单关联大,时间上最近的操作也关键,重要性标记过的退款确认信息优先级最高,这样检索出来的片段才准。
记忆的动态更新和遗忘是另一个重点。每次新对话进来,我不会直接存原始文本,而是让LLM提取结构化记忆,实体、关系、摘要,然后做语义去重。如果同一个实体有新信息,就增量更新,保留时间戳链。对于长期不访问且重要性低的记忆,我把它打入冷存储,可以配置彻底删除。这样既控制了存储成本,也避免了陈旧信息干扰。这里有个坑:如果去重做不好,同一个实体反复出现,检索时就会重复命中,浪费上下文窗口,甚至引入矛盾。上线前我会特别关注去重阈值和摘要质量。
最后是[[RAG]]的深度集成。检索回来的结果不能一股脑塞进去,我会先做 [[重排]],用 [[Cross-Encoder]] 精排Top-K,然后筛选信息密度高的片段,优先保留包含实体、动作、结论的句子。Prompt里固定给工作记忆留槽位,RAG结果弹性填充,总token控制在模型上限的80%以内,留余量给模型思考。这个平衡很微妙:RAG结果太少,记忆不够;太多,模型可能迷失在上下文里。我的做法是设一个token预算,如果检索结果超了,就按相关性截断,相关性低的直接丢掉。
还有一个有意思的方向:当记忆规模大到一定程度,比如跨天、跨用户,单纯向量检索的召回率会下降,因为语义漂移。我倾向于引入图结构,把实体之间的关系显式存起来,这样检索时能沿着关系链找到间接相关的记忆。比如用户之前问过A商品的优惠,后来问B商品,如果A和B同属一个品类,图结构就能把A的优惠信息关联过来,而向量检索可能因为语义不直接匹配而漏掉。
所以整体上,我会把记忆管理看成一个分层存储加[[混合检索]]的工程系统,核心是平衡上下文窗口利用率和信息密度。前提是LLM的摘要和打标能力要可靠,否则下游检索和更新都会受影响。常见失败场景是摘要丢失关键细节,或者重要性打分不准导致重要记忆被遗忘,这些都需要通过可观测链路持续调优。