尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

17 大模型的记忆只有“一杯水“,长对话怎么不翻车?

17 大模型的记忆只有“一杯水“,长对话怎么不翻车? 面试官翻着简历你做过 AI 客服候选人点头对知识库问答 多轮对话。用户跟 AI 聊了 20 轮之后AI 还记不记得第一轮说了什么……应该记得吧你确定你了解上下文窗口吗如果 Token 超了会发生什么候选人沉默了。他做多轮对话时确实没考虑过这个问题——反正框架自动处理历史消息用户聊到一半 AI 突然失忆他还以为是模型的问题。这不是模型的问题是记忆管理的问题。大模型的记忆是有限的、有成本的、还是一次性的。这篇聊透。大模型的记忆到底有多小很多人以为大模型像人一样记性好。错了。大模型每次回答只能看到你这次请求里塞给它的所有文字。上一次对话它根本记不住——除非你把历史对话重新发给它。所以所谓多轮对话本质是每轮都把之前所有的对话重新拼进 Prompt 里再发给模型。而模型一次能看到的文字总量就是上下文窗口Context Window。GPT-4o 一般是 128K Token但很多国产模型只有 8K、32K。8K Token 是什么概念大概 6000 个汉字或者 20 轮左右的简单对话。一杯水就这么点。更麻烦的是窗口不是只有历史对话在占用系统提示词占一块、历史对话占一块、RAG 检索结果占一块、用户当前问题占一块。四块加起来不能超过窗口上限。超了怎么办两个后果1. API 直接报错maximum context length exceeded2. 框架自动截断——最早的历史被丢掉AI 就失忆了失忆的代价一个很典型的场景举个典型场景AI 保险顾问用户咨询理赔。用户第一轮说我父亲去年买的 XX 重疾险今年确诊了肺癌。AI 答得挺好给了一堆理赔指引。聊了 30 轮用户问那像我父亲这种情况之前说的那个免赔额条款还适用吗AI 答您父亲是哪款产品之前没有提到过请补充说明。用户当场炸了我刚说了一万遍技术排查发现历史对话超过了窗口最早的几轮被截断丢弃模型压根不知道用户父亲买的是什么保险。这不是模型蠢是记忆管理没做好。用户不会理解上下文窗口这种技术概念他只知道这 AI 记性真差。记忆管理方案一滑动窗口最朴素的做法只保留最近 N 轮对话更早的直接丢弃。public ListMessage slidingWindow(ListMessage history, int maxTurns) { if (history.size() maxTurns) { return history; } // 保留系统消息 最近 maxTurns 轮 Message system history.get(0); ListMessage recent history.subList(history.size() - maxTurns, history.size()); ListMessage result new ArrayList(); result.add(system); result.addAll(recent); return result; }优点实现简单几乎零成本速度最快。缺点早期信息全丢。用户第一轮说的关键信息父亲买的保险第 21 轮就被丢了。滑动窗口适合客服问答、单轮为主、对历史依赖不强的场景。记忆管理方案二摘要记忆既然原始对话太占空间那就压缩。每隔几轮让模型把之前的对话总结成一段摘要以后只带摘要 最近几轮。public class SummaryMemory { private final ChatModel chatModel; private String summary ; // 累积摘要 public ListMessage buildMessages(ListMessage recentTurns) { ListMessage messages new ArrayList(); // 先放压缩后的历史摘要 if (!summary.isEmpty()) { messages.add(new SystemMessage(历史对话摘要 summary)); } // 再放最近几轮原始对话 messages.addAll(recentTurns); return messages; } // 每 5 轮触发一次摘要更新 public void maybeSummarize(ListMessage allHistory) { if (allHistory.size() % 10 0) { this.summary chatModel.call( 把以下对话压缩成 200 字以内的摘要保留关键事实\n allHistory ); } } }摘要的本质是丢细节换容量。用户父亲买的是哪款保险、确诊什么病、问过哪些条款——这些关键事实会被摘要保留但对话的细枝末节就没了。优点能记住早期关键信息容量可控。缺点摘要本身有信息损失每 5 轮多一次模型调用有成本和延迟摘要更新时机要设计好。记忆管理方案三向量记忆最重的方案也是大厂 Agent 产品的主流做法。思路把每一轮对话或每个知识点向量化存进向量数据库。用户提问时先从向量库里语义检索出最相关的几条历史拼进 Prompt。Service public class VectorMemory { private final VectorStore vectorStore; // 每轮对话结束后把内容存入向量库 public void remember(String sessionId, String userMsg, String aiMsg) { Document doc new Document( 用户说 userMsg \nAI 答 aiMsg, Map.of(sessionId, sessionId, timestamp, System.currentTimeMillis()) ); vectorStore.add(List.of(doc)); } // 用户提问时检索相关历史 public ListDocument recall(String sessionId, String question, int topK) { return vectorStore.similaritySearch( SearchRequest.builder() .query(question) .topK(topK) .filterExpression(sessionId sessionId ) .build() ); } }优点容量大存多少都行、检索精准只带相关历史、天然支持跨会话长期记忆。缺点架构重要引入向量库、多一次检索延迟几十毫秒、历史片段怎么切分有讲究。实战Token 预算怎么算面试官问你怎么控制 Token光说压缩历史不够得有具体方法。第一步估算。中文场景有个粗略公式1 个汉字 ≈ 1.5~2 个 Token1 个英文字符 ≈ 0.3 个 Token。不够精确但做预算够用。要精确就调 API 的 tokenizer 接口或者用 tiktoken 库// OpenAI 官方 tiktoken 的 Java 移植版 int tokens EncoderFactory.get().encoder() .encode(prompt) .size();第二步分级预算。我习惯按比例分配以 8K 窗口为例public class TokenBudget { private static final int WINDOW 8000; // 各部分预算给当前问题留足空间 private static final int SYSTEM_BUDGET (int) (WINDOW * 0.15); // 1200 private static final int HISTORY_BUDGET (int) (WINDOW * 0.50); // 4000 private static final int RAG_BUDGET (int) (WINDOW * 0.20); // 1600 private static final int QUESTION_BUDGET (int) (WINDOW * 0.15); // 1200 public ListMessage assemble(String question, ListMessage history, ListDocument ragDocs) { // 历史超预算 → 从旧到新截断或触发摘要 ListMessage trimmedHistory fitHistory(history, HISTORY_BUDGET); // RAG 文档超预算 → 只保留最相关的 ListDocument trimmedDocs fitDocs(ragDocs, RAG_BUDGET); return buildMessages(trimmedDocs, trimmedHistory, question); } }第三步超预算的降级策略。按优先级丢弃先丢最老的对话 → 再触发摘要压缩 → 再丢低相关度 RAG 文档 → 如果还不够明确告诉用户对话太长请开启新会话。宁可降级不要硬塞导致 API 报错。这里有个反直觉的点RAG 文档的优先级要高于早期对话。因为早期对话的信息大概率已经进了摘要而 RAG 文档是当前问题的答案依据丢了就直接答错。三种方案怎么选面试这样答方案成本记忆能力适用场景滑动窗口零只记最近 N 轮客服、单轮问答摘要记忆低记关键事实丢细节多轮业务对话向量记忆高精准召回容量大Agent、长期记忆生产环境的正确姿势是组合拳滑动窗口保底防止超窗报错 摘要记忆兜底保留关键事实 向量记忆增强需要时精准召回。另外两个必答的细节第一Token 预算要主动控制。不要等窗口满了再截断。每次组装请求前估算一下总 Token系统提示 历史 检索 问题给当前问题留足空间。常见做法历史压缩到窗口的 50% 以内检索结果 20%系统提示 15%问题 15%。第二128K 窗口不是让你全塞进去的。这是面试官最爱挖的坑。窗口越大越贵按 Token 计费、越慢处理时间长、越容易分心注意力被无关内容稀释。上下文管理的目标不是塞满是只带该带的。 面试官视角的标准回答如果面试官问长对话中 AI 失忆了怎么办先解释根因大模型本身没有记忆所谓多轮对话是把历史重新拼进 Prompt 再发送。上下文窗口有限历史太长就会超窗框架自动截断最早的部分导致 AI失忆。我的解决方案是三层记忆第一层滑动窗口保底。保留最近 N 轮防止超窗报错。这是兜底方案保证系统不崩。第二层摘要记忆。每隔几轮让模型把历史压缩成摘要保留关键事实。这样即使早期对话被丢弃用户说过的关键信息比如买了什么保险、什么病情还在摘要里。第三层向量记忆。把历史对话向量化存库提问时语义检索最相关的片段。适合 Agent 和需要长期记忆的场景。另外我会主动做 Token 预算管理每次请求前估算各部分的 Token 占比给当前问题留足空间。还要强调一点上下文窗口不是越大越好越大越贵越慢记忆管理的核心是只带该带的。下一篇聊 AIGC 面试必考的另一座大山——幻觉。AI 一本正经地胡说八道根因到底是什么RAG、提示约束、解码参数、事后校验四层防线怎么搭
返回列表