语言模型产品做久了,你会发现“context-mode”这个词被提得越来越频繁。圈子里聊它、项目里写它、发布会上也讲它,但落到实际开发里,每个人对它的理解其实不太一样。有人拿它当“多轮对话记忆开关”,有人把它理解成“上下文窗口的调度策略”,还有人干脆把它当成一种产品交互模式来设计。我的理解更朴素一些:context-mode 是对话式 AI 应用里,围绕“怎么用、用好、用不完上下文”的一整套工程方案。它解决的是同一个矛盾——模型再强的上下文窗口也有限,而真实产品的对话永远比窗口长。这篇就围绕这个核心展开,聊聊我在实际项目里对 context-mode 的拆解、落地和避坑经验,给正在做 AI 应用开发的同行一个可复用的参考框架。
先说个共识。做 LLM 应用的人都清楚,把全部历史对话一股脑塞给模型是不现实的。你塞得下,但响应速度和成本会先把你压垮;就算你真塞下了,模型对不同位置信息的注意力也不是均匀分布的,中间那段历史经常被“选择性遗忘”。所以 context-mode 不是什么高深理论,而是每个 AI 应用都要做的一道必答题:当前这轮请求,到底该带哪些上文给模型,不带哪些。
1. context-mode 是什么:一个概念,三个真问题
context-mode 不是一个标准术语,更像是工程界对“上下文管理方式”的一个统称。我在 GitHub 上见过有人把它封装成库,在论文里见过它指代“上下文压缩策略”,在几个开源框架里则是“记忆模式”的配置项。结合自己做过的几个 AI 产品,我倾向于把它拆成三个问题去看:模型侧的上下文窗口限制、产品侧的记忆策略、以及用户侧的感知模式。
模型侧的上下文窗口是硬约束。不同模型的窗口大小差异很大,GPT-4o 的 128K、部分开源模型的 32K/64K、以及一些支持百万级上下文的实验性模型。但窗口大不等于能随便用。上下文越长,推理延迟越高、单位请求成本越高,模型在中段信息的召回能力也会下降。你给模型塞 100K 的对话历史,它可能只“认真看”了前面和最后的部分,中间的关键信息反而丢了。这就是业内常说的“迷失在中间”现象。
产品侧的记忆策略是真正的设计空间。同样一个客服机器人,你可以让它只记住最近 6 轮对话,也可以让它记住用户三个月前的投诉记录,也可以让它把历史对话摘要成几条要点塞进 system prompt。不同的做法就是不同的 context-mode,没有绝对最优,只有场景适配。
用户侧的感知模式则容易被忽略。用户感知不到 token 窗口,但他们感知得到一件事——AI 还记不记得我上句话说了什么、三天前说过什么、甚至去年提过的偏好。这是产品体验的分水岭。context-mode 的终极目标不是“塞得最多”,而是“记得最准”。
1.1 上下文窗口的物理与注意力限制
理解模型上下文窗口,不能只把它当成“容量限制”。窗口大小决定的是模型“能看到的材料范围”,但真正影响输出质量的,是模型对这段材料里有效信息的提取效率。
我习惯用一个比喻:模型像是一个阅读速度极快但笔记有限的临时工。你给他 100 页资料,他能快速翻完,但你要他准确说出第 47 页第 3 段的措辞,他大概率会记混。你说“第 47 页大致讲了什么”,他能答得不错。这决定了 context-mode 的核心策略:不能指望模型从完整历史里精确提取每一个细节,而应该由产品层替模型做信息筛选与结构化压缩。
另一个实际约束是性能。实测中,把上下文从 4K 拉到 32K,单次请求的延迟通常会翻倍甚至更高。对实时性要求高的产品(比如客服、语音助手),这是不可接受的。所以 context-mode 在工程上还要回答:如何在“信息完整度”和“响应速度”之间取一个业务可接受的值。
1.2 产品侧上下文管理的三个维度
我在设计 context-mode 时,会从三个维度考虑:信息分层、时间衰减、内容结构化。
信息分层是把上下文分成“恒定层”(系统指令、产品规则、用户长期画像)、“会话层”(当前任务的中间状态、最近几轮对话)和“临时层”(一次性指令、临时上传的文件内容)。恒定层每次必带,会话层按窗口预算动态裁剪,临时层用完即丢。
时间衰减对应的是“多久以前的信息还值得带”。这不是简单的按轮数截断。比如一个购物助手,用户 10 分钟前咨询过退换货政策,这个信息在后续对话里高度相关;而用户 3 天前闲聊过一句“今天天气不错”,这个信息基本可以丢弃。好的 context-mode 应该对上下文做相关性排序,而不是机械地按时间顺序保留。
内容结构化则是把非结构化的历史对话转成更紧凑、更可用的形态。比如把“用户抱怨了三次物流慢、一次包装破损”压成一句“用户对物流时效敏感,曾反馈包装破损”,模型后续生成回复时,就不需要每次都读原始抱怨才能理解用户情绪。这一层做得好不好,直接决定了 context-mode 的“智能感”。
2. 三种主流 context-mode 实现方式与选型
把概念落到代码之前,先看现在工程里最常见的三种实现方式。它们不是互斥关系,实际产品里通常是组合使用,但作为独立方案理解更容易看清各自的边界。
2.1 滑动窗口模式
滑动窗口是最简单、最直觉的做法:只保留最近 N 轮对话,超出窗口的信息直接丢弃。实现上就是一个固定长度的队列,新消息进来,旧消息出去。
优点是成本低、实现快、响应稳定。对质量要求不高、对话轮次普遍较短的场景(比如简单的 FAQ 机器人、表单填写助手),滑动窗口完全够用。
缺点也明显——它没有任何“记忆”能力。用户在第 3 轮提供的信息,到第 10 轮就查无此人了。这会导致两个常见问题:一是模型反复询问用户已给过的信息(用户会觉得 AI 是金鱼),二是用户需要手动复述旧信息才能继续任务(交互效率极低)。另外,窗口长度怎么定是个玄学。太短,信息不够;太长,延迟和成本飙升。我见过不少项目把窗口定在 10-20 轮,理由是“差不多够用”,但几乎从没验证过这个数字是否真的匹配业务场景。
2.2 摘要压缩模式
摘要压缩是为了解决滑动窗口“健忘症”而生的。核心思路是把超出窗口的历史对话,交给模型(或用更轻量的算法)生成一段摘要,然后把摘要保留在上下文中,替代原始对话。
这个方案比滑动窗口聪明得多。它保留了“更久远但更重要”的信息,同时大幅压缩 token 占用。举个例子,50 轮对话原始内容可能有 20K token,压缩成 400 token 的摘要后,配合最近 10 轮原始对话,总窗口占用可以控制在 3-4K 以内,而关键信息几乎没有丢失。
但摘要压缩有几个工程痛点。第一,摘要有损。模型概括信息时可能会遗漏细节、模糊数字,最怕的是把“用户说不要A”概括成“用户偏好A”,语义颠倒是致命伤。第二,摘要会累积误差。每 20 轮做一次摘要,摘要的摘要的摘要……迭代几轮之后,原始内容已经面目全非。第三,摘要时机不好把握。做太频繁浪费调费,做太少又跟不上对话进展。我在项目里通常用一个阈值策略:历史对话超过窗口上限的 60% 时触发压缩,同时把“压缩前的重要信息核对”当成一个独立校验步骤来做。
2.3 长期记忆模式
长期记忆模式是现在的热门方向,也是把 context-mode 从“工程技巧”升维到“产品能力”的关键。它的核心思路是:对话结束后,把有价值的信息提取出来,写入结构化的记忆库;新对话开始时,根据当前意图从记忆库检索出相关记忆,注入上下文。
这套思路和 RAG(检索增强生成)高度重合。你可以把长期记忆理解成一个“私人 RAG 库”,但有几个不同点:记忆的写入是隐式发生的(模型自己判断哪些信息值得记)、记忆的粒度更细(一条记忆可能只是“用户养了一只叫豆包的柯基”)、记忆的时效性更复杂(有些信息一次有效,有些需要长期保留,有些过段时间需要更新)。
长期记忆模式的优势是上限极高——它能真正实现“AI 懂你”的体验。但落地难度也最大:怎么写记忆、怎么去重、怎么更新、怎么避免记忆冲突,每个问题都需要细致的规则设计。目前业界的做法也五花八门,有人用纯文本写“用户档案”,有人用向量库做相似检索,有人上知识图谱。我自己的实践是把三者结合起来:结构化的画像用文本/JSON 保存,非结构化的事件记录用向量存,关系类信息(用户A关注商品B、用户C与用户D是家人关系)用图来建模。
2.4 三种模式对比选型表
| 模式 | 实现成本 | 记忆能力 | 上下文占用 | 信息失真风险 | 适用场景 |
|---|---|---|---|---|---|
| 滑动窗口 | 低 | 近程记忆 | 受窗口限制 | 低(但有遗漏) | 短对话、FAQ、表单 |
| 摘要压缩 | 中 | 中程记忆 | 低 | 中(摘要有损) | 客服、销售、咨询 |
| 长期记忆 | 高 | 远程记忆 | 低(按需注入) | 低(但设计复杂) | 陪伴、教育、个性化助手 |
选型上没有“最好”,只有“合适”。我的建议是从业务里最痛的那个点出发:如果用户反馈“AI 总忘记我前面说的话”,直接上摘要压缩;如果用户反馈“AI 一点不了解我”,再考虑长期记忆。别一开始就奔着最复杂的方案去,系统复杂度上去了,bug 和成本也会跟着上去。
3. context-mode 的具体工程实现
理论说再多,最终还是要落到代码。这里我把一个混合型 context-mode(滑动窗口 + 摘要压缩 + 简单记忆)的工程实现拆开讲。这套代码我跑过多个项目,逻辑上做了简化,但框架可以直接复用。
3.1 第一步:先管好 token 预算
任何 context-mode 的起点都是 token 预算。不估算 token 盲目拼上下文,生产环境必炸。
OpenAI 系的模型可以用 tiktoken 做精准计数,开源的 BGE 家族或者其他模型可以用 AutoTokenizer(transformers)来算。我的建议是:所有上下文相关逻辑,统一封装一个估算函数,不要在生产环境里用 len(text.split()) 这种粗糙办法,中文场景尤其不准。
import tiktoken def estimate_tokens(text: str, model: str = "gpt-4o") -> int: """ 估算一段文本的 token 数,用于上下文的预算控制。 注意:不同模型的 tokenizer 可能不同,切换模型时务必同步切换。 """ encoding = tiktoken.encoding_for_model(model) return len(encoding.encode(text)) def trim_to_budget(text: str, budget: int, model: str = "gpt-4o") -> str: """ 把文本裁剪到指定 token 预算内。注意裁剪不要切在 token 中间, 这里用迭代逼近来保证语义相对完整。 """ encoding = tiktoken.encoding_for_model(model) tokens = encoding.encode(text) if len(tokens) <= budget: return text return encoding.decode(tokens[:budget])token 预算要留余量。假如模型窗口是 8K,我不会把上下文填到 8K。原因很简单:模型还要在剩余空间里生成回复,生成内容本身也要占 token。我一般把上下文预算设为窗口的 75%-80%,剩下的空间留给系统提示语和模型输出。具体留多少,取决于你期望的回复长度:回复越长,预留越大。
3.2 第二步:滑动窗口的落地代码
滑动窗口的本质是“如何从完整消息列表里选出一批消息”。这里有几个容易踩坑的细节:system 消息永远保留、最新的消息优先保留、单条消息如果超出预算需要单独处理,另外一个容易忽略的是——你给模型看的上下文里,不能只塞消息正文,角色标记还要带上。
from typing import List, Dict, Any def build_sliding_window_context( messages: List[Dict[str, str]], max_context_tokens: int = 6000, model: str = "gpt-4o", reserve_tokens: int = 1500, ) -> List[Dict[str, str]]: """ 构造滑动窗口上下文。 - 保留所有 system 消息 - 从最新消息开始往前累计,直到预算耗尽 - reserver_tokens 为模型回复预留的 token 空间 """ budget = max_context_tokens - reserve_tokens system_messages = [m for m in messages if m["role"] == "system"] history_messages = [m for m in messages if m["role"] != "system"] selected: List[Dict[str, str]] = [] used = 0 for msg in reversed(history_messages): cost = estimate_tokens(msg["role"] + msg["content"], model) if used + cost > budget: # 如果单条消息超预算,做截断处理(这是最后手段) if not selected: trimmed_content = trim_to_budget(msg["content"], budget, model) selected.insert(0, {"role": msg["role"], "content": trimmed_content}) used = budget break selected.insert(0, msg) used += cost return system_messages + selected几个容易被忽略的实现细节。第一,消息里的 role 字段也要计入 token 消耗,别小看这一两 token,消息多了也是成本。第二,当一条历史消息本身就超过剩余预算时,不要简单丢弃它——用户刚发的这条消息如果丢了,模型就完全不知道用户在说什么了;激进的做法是截断处理,或者干脆把预算放宽到至少能容纳最后一条消息。第三,这个实现里没有处理“消息内容为空”的情况,实际项目中要加个过滤,避免空消息影响 token 计算。
3.3 第三步:加摘要与长期记忆的分层方案
只有滑动窗口的 context-mode 是“残缺”的,因为它的记忆覆盖范围太短。我在生产项目里用的是一套三层结构:
第一层(恒定层):system prompt 里的产品规则、人格设定、全局知识。这个基本不变。
第二层(摘要层):之前多轮对话的压缩摘要,每 20 轮或每超预算一半时刷新一次。摘要内容不是简单“总结对话”,而是按业务维度提取:用户说了什么需求、给出过什么关键信息、做过什么决定、还有哪些未完成事项。
第三层(短期层):最近几轮原始对话。和滑动窗口方案一致,只是窗口可以调小,因为前两层已经承担了记忆职责。
def build_hybrid_context( user_profile: Dict[str, Any], conversation_summary: str, recent_messages: List[Dict[str, str]], max_context_tokens: int = 6000, model: str = "gpt-4o", ) -> List[Dict[str, str]]: """ 混合型 context-mode 拼接: 1. 用户画像 -> 恒定层 2. 历史摘要 -> 摘要层 3. 最近对话 -> 短期层 顺序不能乱,模型对不同位置信息的敏感性不同。 """ system_parts = [] if user_profile: profile_text = "用户画像:" + ", ".join( f"{k}是{v}" for k, v in user_profile.items() ) system_parts.append(profile_text) if conversation_summary: system_parts.append("历史对话摘要:" + conversation_summary) system_prompt = "\n".join(system_parts) if system_parts else "你是智能助手。" system_msg = {"role": "system", "content": system_prompt} # 短期层直接复用滑动窗口逻辑 return build_sliding_window_context( [system_msg] + recent_messages, max_context_tokens=max_context_tokens, model=model, reserve_tokens=1500, )摘要生成我单独写一个函数,并且加了两个约束。第一个约束是“摘要必须用事实性语言,不准带模型自己的推测”。第二个约束是“保留数字、日期、商品名等精确信息”。当时加这两个约束,是因为遇到过模型在摘要里写“用户好像对价格有疑问”,但这种含糊表述后续根本没法用——你要么花额外 token 去猜,要么就丢失了“价格敏感”这个关键标签。
def generate_conversation_summary( messages: List[Dict[str, str]], model: str = "gpt-4o" ) -> str: """ 把一段对话压缩成结构化摘要。 关键:明确告诉模型要保留哪些信息,宁可长一点,不要丢关键事实。 """ dialog_text = "\n".join( f"{m['role']}: {m['content']}" for m in messages ) prompt = ( "你是对话记录员。请把下面的对话压缩成结构化摘要,要求:\n" "1. 只记录客观事实,不输出主观评价;\n" "2. 必须保留:用户的需求、提供的具体信息(订单号/日期/数字/产品名)、明确表达过的偏好、未完成事项;\n" "3. 输出格式:按‘事实-要点’分组,每行一条,不要编造原文没有的信息。\n\n" f"对话内容如下:\n{dialog_text}" ) # 实际调用你选择的模型接入层 response = call_llm(prompt, model=model, temperature=0.2) return response.strip()这个函数有个前提:摘要生成本身也要消耗 token 和时间。所以触发策略很关键。我在项目里用的是双重条件:历史对话轮数超过 N 轮或者历史消息总 token 超过预算的一半,就触发摘要生成,并且把旧的摘要和新的对话合并后再生成新摘要,而不是每次都从零开始。
3.4 关于缓存与性能的补充
context-mode 做复杂了之后,性能问题会暴露出来。尤其是摘要生成和 token 重算,每次请求都做一遍,延迟会很难看。
我的做法是加两层缓存。第一层是 token 计数缓存——同一段文本的 token 数量不会变,计算一次后用 content hash 做 key 存起来,直接省掉大量重复计算。第二层是摘要缓存——同一批历史消息不做重复摘要。通常在对话流的每一轮结束时,异步把“本轮新增消息 + 上一版摘要”提交给摘要模型,生成新摘要并存储。下一轮请求直接读取缓存,不用实时计算。这样核心链路的延迟几乎不受摘要影响,代价是要多维护一个存储,但用 Redis 就够。
4. 按业务场景配置 context-mode 的实战参考
框架有了,但具体项目怎么配?这一节按业务场景给配置参考。注意,这些配置来自我的项目实践和同行的公开经验,不是标准答案。你是要根据自己产品的对话特征做微调的。
4.1 客服问答场景
客服场景的特点是:对话轮次不长、信息精度要求高、用户情绪需要照顾。上下文的配置重点不是“记住多少”,而是“不要把关键信息弄丢”。
system prompt 里保留:产品规则、退换货政策摘要、客服话术红线。滑动窗口保留最近 8-12 轮,覆盖一次完整交互基本够用。摘要层只需要做一件事:把用户的历史工单记录、历史投诉点、会员等级压成几句话。
这个场景尤其要注意“数字精度”。用户报的订单号、金额、日期,一旦被摘要模型模糊化,后续处理全是坑。我的处理是:在摘要生成 prompt 里明确列出“必须原样保留订单号、金额、日期”,并在注入上下文时把新鲜对话里的数字信息用正则抽出来,单独放进一个“关键信息”区,不让它们躺在对话流里随窗滑动丢出去。
4.2 编程助手场景
编程助手和客服差别很大。用户会粘贴大量代码片段,对话本身往往长达几十上百轮,而且中途常常切换任务(刚从重构函数切到排查 bug,又切去写测试)。
这个场景我反而建议少用摘要压缩。代码语义对精度极其敏感,摘要一旦曲解了逻辑(比如把变量名替换错了、把函数签名简化错了),模型后续生成的代码大概率是错的。宁可窗口滚大一点,用原始代码做上下文,也不要贪 token 省成本。
长期记忆在这里倒是很有价值。可以记录用户项目的技术栈、偏好(“用户喜欢用 Python 的 dataclass 而不是 dict”)、常见错误模式。这些信息以“编码规范附加说明”的形式注入 system prompt,对生成质量的影响立竿见影。窗口配置上,代码片段天然占 token 多,我会把单条消息的预算放宽,但控制消息条数(比如最多 15 条),避免上下文变成一锅粥。
4.3 角色扮演与陪伴场景
这类场景对“记忆连续性”的要求是最高的。用户可能上一周说“我最近在准备考研”,这周就聊“今天模拟考心态崩了”。如果 AI 忘了考研这回事,用户会瞬间出戏。
这里的 context-mode 配置是:摘要是绝对主力,短期窗口只要 4-6 轮,保持对话自然感就够了。长期记忆模块要做厚:用户表格式的画像(职业、家庭、兴趣爱好、最近情绪状态)必须有专门的结构化字段,不能只在摘要里带一笔。角色设定(AI 扮演的人设)属于恒定层,每一次请求都要完整携带,不能省。
我用过一个技巧:在记忆模块里维护“情感状态时间线”。每次对话结束后,模型判断用户当前情绪(正/中/负),并记录触发原因。下次对话时,如果近 3 次对话都是负面情绪,模型会在回复中加入安抚性的表达。这种细节的“记忆感”,比记住十个事实更有温度。
4.4 场景配置速查表
| 场景 | 窗口轮数 | 摘要频度 | 长期记忆 | 关键注意点 |
|---|---|---|---|---|
| 客服问答 | 8-12 | 每轮异步 | 可选 | 保数字精度,防情绪冲突 |
| 编程助手 | 10-15 | 不使用 | 强推荐 | 保留原始代码,不压缩 |
| 角色陪伴 | 4-6 | 每次重大转折 | 必须 | 画像结构化,情感时间线 |
| 文档分析 | 按文档分块 | 不用 | 可选 | 用 RAG 按块检索,不做全局摘要 |
文档分析场景补一句。用户上传一个 200 页 PDF 时,你不可能把它整个塞进上下文。正确思路是把它切成块、建索引,然后按当前问题检索出相关块再拼入上下文。这也是 context-mode 的一种——“检索式上下文模式”。partial RAG 和 long-term memory 底层是同一套东西,差别只在数据源和写入逻辑。
5. 我在 context-mode 上踩过的坑与排查实录
讲完方案,分享一些真实踩过的坑。这些都是线上事故级别的教训,写出来希望你能避开。
5.1 坑一:摘要里的错误信息被模型当成“事实”反复使用
这个坑发生在一次客服机器人迭代里。用户先咨询了“A 商品的退货政策”,后来改口说“不退了,想换 B 商品”。对话摘要第一次生成时是正确的,但结合上一条摘要再次压缩时,模型把“用户要退 A 商品”和“用户想换 B 商品”混在了一起,生成了“用户要求退换商品”——看似没错,实际模糊掉了用户的关键意向。后果是后续客服话术一直围绕退货展开,用户怎么解释都拉不回来。
排查耗时很久,最后在日志里对比了多版本摘要才定位。解决办法:给每一条摘要加上置信标记和时间戳;摘要生成后,用正则/关键词检查是否有“歧义句式”(比如“退换”这种多义组合词),触发二次确认。更重要的是,我把摘要模型 temperature 调低了,减少它“发挥”的概率。
5.2 坑二:上下文拼接顺序导致用户指令覆盖系统指令
prompt 的顺序问题比很多人以为的更严重。有一次我调整了上下文拼接逻辑,把滑动窗口消息放在了 system prompt 之前。结果用户一个略带攻击性的问题居然把系统指令顶掉了——模型开始按用户的口吻说话,而不是按设定好的客服人设。
原因是模型对文本序列最后位置的注意力权重更高。当用户消息在上下文中“压过” system prompt 时,模型的指令遵循优先级会被带偏。
解决办法有两个层面:一是结构上保证 system prompt 永远在用户消息之前;二是用 XML 标签把各段上下文隔开,让模型更清楚信息的边界。推荐这个模板:<system>...</system><context>历史摘要...</context><user>...</user>,实测对模型理解指令边界有明显帮助。
5.3 坑三:滑窗太短导致模型“失忆”并自我重复
这个坑出现在一个陪伴类产品上。我把聊天窗口从 12 轮调到 6 轮之后,用户反馈“AI 突然变得很傻,同样的建议给了一遍又一遍”。查日志发现,模型在每轮都只看到最近 6 轮的内容,它不知道自己已经在 10 轮前推荐过“去看心理咨询师”,于是每次听到情绪低落话题,都会再次给出同样的建议。
这类问题用摘要压缩就能解决——把更早轮次里“模型给出过什么建议”记入摘要,后续轮次就不会重复推荐。另外我加了一个内存变量:在逻辑层记录“最近 3 次已给出的核心建议”,拼接上下文时如果检测到模型即将再次推荐相同内容,就手动注入“你之前已经推荐过 X,用户未接受,请换一种角度回应”的提示词。
5.4 我的排查三步法
context-mode 出问题,特征往往隐蔽,不像普通 bug 那么好定位。我总结了三个排查步骤,你可以直接拿去用。
第一步,拉全量上下文日志。每一轮请求发出前,把最终拼装好的上下文完整记录下来(系统提示语、摘要、消息列表、token 预算)。线上问题出现时,这组日志就是你唯一的线索。注意给日志加唯一 request_id,不然多轮排查会把你绕晕。
第二步,回放对比。把同样的问题,用不同的 context-mode 配置去回放。比如线上是“滑动窗口 8 轮”,你离线改成“摘要压缩 + 最近 4 轮”,看输出是否改善。这一步能快速定位问题是出在“信息缺失”还是“信息错误”。我说个捷径:准备一个自动化回归集,里面放 30-50 个典型用户问题,每次改动上下文逻辑就整体跑一遍,比人工点半天效率高太多。
第三步,检查 token 分布。打印每一段上下文的 token 占比。如果某段摘要占了 70% 的预算,但输出的关键信息很少,那这段摘要就是优化对象。生产上我见过最离谱的情况:一份 300 字的用户画像反复拼接了 20 遍,占了 8K token——bug 出现在一个 for 循环里把画像加到了每轮消息中。这类问题,看一眼 token 分布立刻就能发现。
最后聊一点我自己的体会。做 context-mode 越久,越发现它的核心不是技术,而是产品判断。你要清楚你的 AI 产品到底需要记住什么、忘记什么。记住一切是灾难,忘记一切是智障,平衡点在哪里,取决于你的用户是谁、他们用你的产品做什么。技术只是实现平衡的手段。
如果让我给一条最想分享的经验,那就是:context-mode 的代码写出来不难,难的是你为它设计的那套“记忆边界”。每次迭代上下文策略之前,先问问自己——这一版是让用户感觉到“AI 更懂我了”,还是只是让你自己的 token 成本降下来了。这两者不矛盾,但排序不能反。
另外,无论你最终选了哪种模式,务必从第一天就维护好回归测试集。上下文逻辑是 AI 应用里最容易被改坏的模块,一个看似微小的调整(比如窗口从 8 轮改成 10 轮),都可能在某个用户的超长对话里引爆一个从未出现过的问题。有测试集兜底,你才能放心大胆地迭代。