用“折叠与展开”动态管理超长上下文:一种 Token 高效的外部存储操作机制
本文提出一种新颖的上下文长度管理机制 —— 通过“折叠”与“展开”特殊 Token,动态压缩与恢复上下文块,实现超长文本推理时的 Token 节省与信息可控访问。训练数据可由 LLM 自身生成,提示工程是关键。
🎯 问题背景:上下文长度瓶颈
当前大语言模型(LLM)受限于固定上下文窗口(如 4K、8K、32K、128K),一旦输入超出,要么截断,要么使用昂贵的扩展技术(如 RoPE 插值、滑动窗口、外挂向量库)。但这些方法要么丢失信息,要么计算开销大,要么无法精准定位。
我们是否可以设计一种机制:让模型自己决定“折叠哪些块、展开哪些块”,从而在有限 Token 预算内,智能管理超长上下文?
答案是:可以 —— 通过“折叠/展开”特殊 Token + 块编号系统 + 外部存储模拟。
🧩 核心机制设计
1. 固定块划分:128 块为单位
- 将上文按固定长度(如每块 128 Token)划分为 N 个块。
- 若总长度 > 模型最大上下文,则默认折叠超出部分,仅保留初始可见块(如前 32 块)。
- 折叠的块不占用当前上下文 Token,而是存入“外部存储”(可模拟为键值对缓存)。
2. 折叠与展开 Token 系统
- 引入两组特殊 Token:
FOLD_i
:折叠第 i 个块(i ∈ [0, 127]),释放其 Token 占用。UNFOLD_i
:展开第 i 个块,从外部存储载入,恢复其内容。
- 同时引入:
NO_FOLD
:本次不折叠任何块。NO_UNFOLD
:本次不展开任何块。
- 折叠与展开使用不同 Token ID 空间,避免混淆。
✅ 示例:
当前上下文块 [0,1,2,3] 可见。
模型输出FOLD_2
→ 块2被移出上下文,标记为折叠。
后续输出UNFOLD_2
→ 块2重新载入上下文。
3. 折叠标志 Token
- 每个被折叠的块,在其原始位置插入一个特殊标记 Token,如
<FOLDED_i>
。 - 该 Token 不展开内容,仅占 1 个 Token,表示“此处曾有块 i,现已折叠”。
- 用于维持位置感知与结构完整性。
📌 例如:
原文块序列:[块0][块1][块2][块3]
折叠块2后:[块0][块1]<FOLDED_2>[块3]
4. 长度与位置预测
- 模型在生成过程中,不仅要预测下一个词,还要预测:
- 是否折叠?折叠哪一块?(输出
FOLD_i
或NO_FOLD
) - 是否展开?展开哪一块?(输出
UNFOLD_i
或NO_UNFOLD
)
- 是否折叠?折叠哪一块?(输出
- 折叠/展开决策可作为“辅助头”或“多任务输出”与主语言建模联合训练。
💡 为什么这样做?
- Token 高效:折叠后仅保留 1 Token 标记,极大节省空间。
- 信息无损:内容未丢弃,只是移入“外部存储”,可随时召回。
- 动态可控:模型根据当前推理需求,自主决定访问哪些块。
- 兼容现有架构:只需扩展 Token 表 + 修改训练目标,无需改动 Transformer 核心。
🧪 训练数据从何而来?
方案:用 LLM 自己生成训练数据!
我们可以设计提示词(Prompt),让一个已有长上下文能力的 LLM(如 GPT-4-128K、Claude 3、或本地微调的长文本模型)模拟“折叠/展开”行为,生成带操作指令的训练样本。
✍️ 提示词模板(Prompt for Data Generation)
你是一个上下文管理智能体。你的任务是阅读超长文档,并在生成答案的过程中,动态决定“折叠”或“展开”某些段落块,以节省 Token 并保持推理效率。规则:
- 文档已被划分为 128 个固定块(编号 0~127),每块约 128 Token。
- 你只能同时保留最多 32 个块在上下文中。
- 你必须使用以下特殊指令:▶ FOLD_i:折叠第 i 块(移出上下文,仅留 <FOLDED_i> 标记)▶ UNFOLD_i:展开第 i 块(从存储载入)▶ NO_FOLD / NO_UNFOLD:本次不操作
- 你的输出格式:[当前可见块列表] → [操作指令] → [生成的回答片段]示例:
输入文档:[块0: “爱因斯坦生于...”] [块1: “他提出相对论...”] [块2: “晚年移居美国...”] ...
你输出:
[0,1,2] → FOLD_1 → “爱因斯坦的出生地是德国。关于他的理论,我稍后展开。”
[0,2] → UNFOLD_1 → “他提出的相对论包含两个部分:狭义与广义。”现在,请处理以下文档并回答问题:
【插入长文档 + 问题】请按格式输出你的操作与回答。
📈 数据增强技巧
- 让 LLM 生成多个“操作路径”:同一问题,不同折叠/展开策略。
- 加入“错误操作”样本(如展开不存在的块),让模型学会容错。
- 加入“延迟展开”场景:先折叠,数轮后再展开,模拟长期记忆调用。
🚀 推理时的行为
在推理阶段,系统维护一个“块状态表”:
块状态 = {0: "visible",1: "folded",2: "visible",...
}
每当模型输出 FOLD_i
或 UNFOLD_i
,系统执行:
FOLD_i
:将块 i 移出上下文 → 替换为<FOLDED_i>
→ 更新状态为 “folded”UNFOLD_i
:从存储载入块 i → 插入原<FOLDED_i>
位置 → 更新状态为 “visible”
🔄 模型在生成过程中不断“操作外部存储”,如同一个程序员在管理内存。
🤖 为什么模型能学会这个?
- 人类阅读长文时也会“跳读”、“回看”、“标记重点”——这本质就是“折叠/展开”。
- 模型通过多任务训练,将“上下文管理”作为推理的一部分,而非外部干预。
- 类似“思维链”,但加入了“记忆管理链”。
🛠️ 实现建议
-
Token ID 分配:
FOLD_0
~FOLD_127
→ IDs [50000 - 50127]UNFOLD_0
~UNFOLD_127
→ IDs [50128 - 50255]NO_FOLD
,NO_UNFOLD
→ IDs [50256, 50257]<FOLDED_i>
→ IDs [50258 - 50385](或共享折叠标记,加参数)
-
训练目标:
- 主任务:语言建模(预测下一个词)
- 辅助任务:预测折叠/展开动作(分类头)
-
推理引擎需支持:
- 动态上下文重组
- 外部块存储缓存
- 操作指令解析器
🌟 未来方向
- 支持“部分展开”(只展开块中关键句)
- 引入“折叠优先级”(模型预测哪些块最可能被再次访问)
- 与检索增强(RAG)结合:折叠块可存入向量库,展开时语义检索最相关块
✍️ 结语
“折叠与展开”机制,本质上赋予了 LLM 自主管理记忆的能力。它不是被动接受上下文限制,而是主动压缩、调度、召回信息 —— 这是迈向“真正长程推理智能体”的重要一步。
而训练数据,无需人工标注,用 LLM 教 LLM,正是当前 AI 自我进化的最佳体现。