用过大模型的人都有这个体验:对话越来越长,回复越来越慢,然后突然"失忆"——前面的对话被遗忘了。
背后的原因,不只是"上下文不够长",而是两层压缩机制的错位。
| 层级 | 操作对象 | 机制 |
|------|----------|------|
| 客户端压缩 | 文本块 | 摘要、去重、移除 |
| 模型端缓存 | Token序列 | KV Cache复用 |
冲突场景:
客户端:把历史对话A+B压缩成摘要S
模型端:之前已经缓存了A+B的KV Cache
结果:S的Token序列 ≠ A+B的Token序列
→ 缓存失效,被迫重新计算
客户端做的是语义级操作(把两段话合成一段摘要),模型端做的是序列级操作(缓存特定Token序列的中间结果)。
两者不在一个维度,自然容易"打架"。
更麻烦的是,不同模型的分词器不同:
| 模型 | 分词器 | 词表大小 |
|------|--------|----------|
| GPT-4 | tiktoken | ~10万 |
| Claude | Claude Tokenizer | ~5万 |
| LLaMA | SentencePiece | ~3万 |
同样一句话:
GPT-4可能切成10个Token
Claude可能切成12个Token
LLaMA可能切成15个Token
Token边界不同 → 缓存更难复用。
客户端如果想跨模型复用缓存,就必须理解每个模型的分词边界,复杂度陡增。
既然上下文有限,就得"挤"。但怎么挤,大有讲究。
| 策略 | 思路 | 代价 |
|------|------|------|
| 滑动窗口 | 只保留最近N个Token | 远处上下文全丢 |
| 摘要远处 | 把老对话压缩成摘要 | 细节丢失,只保留语义 |
| 去重 | 移除重复片段 | 可能丢失上下文连贯性 |
| 分层压缩 | 近处完整,远处摘要 | 实现复杂 |
核心问题:被挤出去的内容,就真的没了。没法"后悔",没法"找回"。
如果把"挤出"改成"入队"呢?
[摘要1] → [摘要2] → [摘要3] → ... → [新摘要进,旧摘要出]
↑
允许搜索/打开
设计要点:
原始上下文先压缩成摘要,再入队
挤出的是摘要而非原始Token → 信息密度更高
被挤出前,允许用向量检索"打开抽屉"
对比当前缓存:
| 维度 | 当前缓存 | 摘要队列 |
|------|----------|----------|
| 挤出物 | 原始Token | 摘要 |
| 信息密度 | 低 | 高 |
| 可检索性 | 无 | 有 |
| 实现复杂度 | 简单 | 中等 |
挑战:摘要质量、检索延迟、队列管理开销。
但这可能是上下文管理的演化方向——从"被动丢弃"到"主动归档"。
上下文管理的背后,是存储效率的问题。
先澄清一个常见误解:
| 形态 | 维度 | 存储量 |
|------|------|--------|
| Token ID | 1个整数 | 2-4字节 |
| Token向量 | 2048维float | 8KB(float32)或4KB(float16) |
Token ID是"索引",类似于字典的页码。 Token向量是"表示",类似于字典里那个词的完整释义。
模型内部用的是向量,所以一个Token在计算时确实占用几KB。
最近有个有趣的方向:不存完整权重矩阵,而是存"寻址规则+基础块"。
类比数据结构:
传统:存完整数组
优化:存哈希索引 + 基础值
效果:
空间复杂度大幅下降
时间复杂度略微上升(需要寻址)
就像升级了寻路算法——多绕几步路,但省下了大片存储空间。
这个优化引出一个更深层的问题:
如果参数可以不存"完整矩阵",那参数内部能不能不只是"传播权重"?
当前参数的形态:
输入向量 → [权重矩阵W] → 输出向量
参数是被动的乘法器,只负责"接收强度 → 分配强度"。
那参数内部能不能有算法? 比如条件判断、循环、甚至小型的子网络?
这指向一个前沿方向:神经符号融合。
无论多复杂的句子结构,进入模型后都被"压扁"成向量序列。
问题:结构信息丢失。
比如:
原句:"张三告诉李四,他明天不去开会了。"
模型看到的不是"主语+谓语+宾语+从句"的结构,而是一串向量:
[张三] [告诉] [李四] [,] [他] [明天] [不] [去] [开会] [了]
"他"指的是张三还是李四?模型得从上下文推断,而不是从结构中直接获得。
Transformer的核心是注意力机制——每个Token都要和其他Token计算关联。
问题:上下文越长,每个Token分到的注意力越少。
短上下文(100 Token):每个Token平均关注其他99个
长上下文(10000 Token):每个Token平均关注其他9999个,但"关注"被稀释
就像一个老师,面对10个学生能记住每个人的名字,面对1000个学生就只能记住"前排那个"。
当前的参数是"扁平"的:
没有"内部结构"
没有"条件逻辑"
只是简单地传播权重
但如果参数有内聚性呢?
想象一个参数单元内部有这样的逻辑:
输入向量 → 判断类型 → 选择处理路径 → 输出向量
↓
[类型A] → 路径1(小型子网络)
[类型B] → 路径2(另一套变换)
这就是参数内聚:参数不只是被动传播,而是主动处理。
挑战:
如何训练"有内部算法的参数"?
可微分编程、程序合成仍在早期
计算复杂度和可解释性的平衡
这可能是闭源模型已经在探索的方向——开源界还没普及,但不代表没人想过。
大模型每次只输出一个Token:
输入: "今天天气"
输出Token1: "很"
输出Token2: "好"
输出Token3: "。"
原因:
训练目标是"预测下一个Token"
自回归依赖:Token i+1 依赖 Token i
句子内部的Token是强关联的。
比如"今天天气很好",这五个Token拆开看:
"今"单独看没意义
"天"单独看也没意义
只有合起来"今天天气很好"才是一个完整的语义单元
那为什么推理时不一次性输出一句话?
类比强化学习:
RL可以预测连续多帧(比如未来5帧的画面)
为什么NLP不能预测连续多Token(比如一句话)?
| 方向 | 思路 | 挑战 |
|------|------|------|
| 非自回归生成(NAR) | 一次生成多个Token | Token间依赖难建模 |
| 句子级建模 | 训练时预测"下一句话" | 句子边界定义模糊 |
| 结构化预测 | 先生成句子框架,再填充 | 需要显式结构信息 |
"内联"的概念:
如果参数是"内聚"(内部有算法),那输出就是"内联"(句子内部强关联)。
从内聚到内联,中间可能需要:
映射算法(把参数内部的结构转化为输出结构)
聚合机制(把多个Token的表示聚合成句子表示)
这个方向还在早期,但你的强化学习经验——"多帧预测"——可能是关键的技术灵感来源。
回顾这篇讨论的几个层次:
| 层次 | 现状 | 演化方向 |
|------|------|----------|
| 上下文管理 | 客户端与模型端冲突 | 协议统一、摘要队列 |
| Token存储 | 被动缓存 | 寻址优化、可检索归档 |
| 参数结构 | 扁平传播权重 | 内聚参数、内部算法 |
| 输出颗粒度 | Token级生成 | 句子级输出、内联结构 |
核心洞察:
当前的大模型架构,本质上是"被动计算"——
被动地缓存Token
被动地传播权重
被动地生成Token
未来的方向,可能是"主动结构"——
主动归档和检索上下文
参数内部有条件判断和子算法
输出时考虑句子级的内联关系
一个开放问题:
如果把"参数内聚"和"输出内联"结合起来,会不会有一种架构:
参数不再是扁平矩阵,而是"可编程单元"
输出不再是Token序列,而是"结构化表达"
这可能是神经符号融合的终极形态——让神经网络学会"程序化思考"。
本文基于对长上下文管理的思考整理,涉及多个前沿方向,欢迎交流指正。