核心问题:有没有一种办法,让 RAG 系统既不用把整篇文档塞进 prompt,又能把“搜什么”和“怎么答”放在同一张梯度图里一起训练?
答案:CLaRa 用“压缩向量 + 可微 Top-k”把检索与生成一次性对齐,上下文长度缩短 4×–128×,效果反而更好。
本文核心速览
| 维度 | 传统 RAG | CLaRa |
|---|---|---|
| 上下文长度 | 原始文本 | 128× 压缩向量 |
| 检索-生成优化 | 割裂、无梯度 | 同一 LM loss 端到端 |
| 监督信号 | 人工标注相关句 | 仅答案文本(NTP) |
| 推理延迟 | 随文档线性增长 | 离线压缩,常数时间 |
目录
-
背景:RAG 的两只“拦路虎” -
关键洞察:共享连续空间 -
SCP 预训练:先让压缩向量“看得懂”文档 -
CLaRa 联合训练:可微 Top-k 打通梯度 -
实验结果:更短上下文,更高指标 -
场景化示例:HotpotQA 多跳问答一条流 -
作者反思:我们踩过的三个坑 -
实用摘要 / 一页速览 -
FAQ
1. 背景:RAG 的两只“拦路虎”
核心问题:为什么传统 RAG 总是“搜得挺准,答得一般”?
-
优化墙
检索器用相似度排序,生成器用交叉熵训练,两者目标函数不互通,梯度流被离散 top-k 截断。 -
效率墙
检索阶段把文档压成 512 d 向量,生成阶段又把原文 2 k token 塞进 prompt——同一篇文档被重复编码,上下文爆炸,推理昂贵。
CLaRa 把“墙”拆掉的办法:
① 把文档先离线压成 32~256 个“记忆 token”向量;② 让查询向量与文档向量在同一连续空间里做可微 top-k;③ 用生成器的 next-token prediction 作为唯一损失,反向传播到查询编码器。
2. 关键洞察:共享连续空间
| 模块 | 输入 | 输出 | 作用 |
|---|---|---|---|
| SCP Compressor | 原始文档 | 记忆向量 M_i | 语义骨架,长度固定 |
| Query Reasoner | 问题 Q | 查询向量 q | 与 M_i 同维度 |
| Generator | [q; M_{1:k}] | 答案文本 | 直接生成,无需原文 |
因为三者共用同一套词表与 Transformer 权重,梯度可以一路从答案 token 回流到查询向量,再回流到文档压缩器——检索与生成第一次在同一张图里联合更新。
3. SCP 预训练:先让压缩向量“看得懂”文档
核心问题:压缩向量那么短,怎么保证它不掉信息?
SCP(Salient Compressor Pre-training)用三把“筛子”把文档精华逼出来:
-
Simple QA
一条文档只问一个原子事实,例如
Q: Trichocladus crinitus 属于哪个科?
A: Hamamelidaceae
→ 压缩器必须保留“科名”实体。 -
Complex QA
把多条事实串成多跳问题,例如
Q: 哪位球员 2014-10-02 加盟 Newport County 并在 4 日替补登场?
A: James Loveridge
→ 压缩器得同时保留“日期 + 俱乐部 + 人名”。 -
Paraphrase
让模型自己把文档换一种说法,但语义不变。
→ 压缩向量被迫丢弃表层词序,只留语义骨架。
训练套路
-
数据:200 万条 Wikipedia 2021 文档,本地 Qwen-32B 自动生成 QA 与改写。 -
结构:共享底座 + 两套 LoRA(compressor / generator)。 -
损失:
ℒ_total = ℒ_CE(生成) + λ·ℒ_MSE(记忆向量 vs 平均词向量)
λ=0.1 时,压缩向量与原文空间重合度最高(t-SNE 可视化见原文附录)。
场景示例
假设你要把 50 页技术手册塞进手机端聊天助手。SCP 阶段把每页压成 64 个记忆 token(约 0.5 kB),离线存进向量库。用户提问时,只需把 64×50=3200 个浮点数读入 GPU,无需再把 50 页原文送进 LLM,上下文长度瞬间从 >16 k token 降到 320 token。
4. CLaRa 联合训练:可微 Top-k 打通梯度
核心问题:top-k 是离散操作,怎么让梯度“溜”过去?
CLaRa 用 Straight-Through (ST) Gumbel-Softmax 思路:
前向:hard top-k(真的只取 k 个向量)
反向:soft top-k(用 softmax 权重近似)
算法伪代码(PyTorch 风格)
scores = cosine(q, M) # [batch, D]
soft = softmax(scores / tau) # 用于反向
hard = one_hot(argmax(scores)) # 用于前向
Z = hard + (soft - soft.detach()) # ST 估计
M_topk = einsum("bkd,bdv->bkv", Z, M) # 选 Top-k 向量
损失只有一项:
ℒ_CLaRa = −Σ_t log p(a_t^* | Q, M_{1:k}, a_{<t}^*)
没有“相关/不相关”人工标签,全靠答案文本驱动。
实验发现:当温度 τ=0.3,k=5 时,Recall@5 在 HotpotQA 上比全监督 BGE-Reranker 还高 10.28%。
5. 实验结果:更短上下文,更高指标
5.1 压缩有效性(Oracle 设定:保证正例在候选池)
| 方法 | 压缩比 | NQ | HotpotQA | Musique | 2Wiki | 平均 |
|---|---|---|---|---|---|---|
| PISCO | 16× | 73.44 | 66.53 | 33.80 | 60.45 | 58.55 |
| SCP-Mistral-7B | 16× | 75.48 | 70.79 | 43.15 | 66.16 | 63.90 |
| SCP-Mistral-7B | 128× | 69.96 | 62.09 | 30.86 | 59.08 | 55.50 |
结论:
-
128× 极限压缩下,SCP 仍比同为 128× 的 xrag 高 27.8%。 -
16× 压缩的 SCP 向量直接替代原文,指标反超未压缩的 BGE 检索(+2.5%),说明压缩过程滤掉了噪声。
5.2 端到端问答(Normal 设定:从 Wikipedia-2021 Top-20 里现搜)
| 方法 | 上下文长度 | NQ F1 | 2Wiki F1 |
|---|---|---|---|
| DRO-Mistral-7B | 1× | 51.01 | 43.65 |
| CLaRa-Mistral-7B | 16× | 51.41 | 47.18 |
反思 / 学到的教训
-
压缩不是“偷工减料”,而是显式去噪:SCP 预训练让模型学会丢弃与问答无关的修饰语,留下实体、关系、数字。 -
联合优化比“先训检索、再冻住训生成”更稳:训练曲线显示,CLaRa 的验证集 F1 在 3 个 epoch 后就超过两阶段方案,且方差更小。 -
温度 τ 是隐形“学习率”:τ 太大,soft 权重太平,梯度信号被稀释;τ 太小,近似 argmax 导致梯度方差大。经验上 τ=0.3–0.5 最稳。
6. 场景化示例:HotpotQA 多跳问答一条流
问题
“How many yards did the nephew of Ivory Lee Brown get during his 2004 true freshman season?”
传统 RAG 痛点
-
需先搜“Ivory Lee Brown nephew”→得“Adrian Peterson” -
再搜“Adrian Peterson 2004 freshman yards”→得“1,925”
两次检索、两次重排,延迟翻倍。
CLaRa 单步流程
-
Query Reasoner 把问题压成 32 个记忆 token; -
与离线压缩的维基百科向量做 cosine,Top-5 已包含“Peterson 2004 season”片段; -
生成器直接读 [q; M_1:5] 输出“1,925 yards”。
Logit-Lens 可视化
把查询向量过 LM 头,Top-50 token 出现“NFL”“Oklahoma”——这些词原问题里根本没有,说明联合训练把“隐含实体”也压进了查询向量,从而一步召回关键文档。
7. 作者反思:我们踩过的三个坑
-
MSE 对齐损失不能省
早期尝试只靠生成损失,记忆向量很快“飘”到与原文不同的区域,检索召回掉 8%。加上 λ=0.1 的 MSE 后,t-SNE 显示两组向量基本重合,指标回升。 -
指令微调初始化 ≠ 万能
直觉上“先指令微调再联合训练”应该更强,结果发现指令微调会让查询向量过于聚焦“答案句”局部语义,反而丢失全局检索能力。最终方案:SCP 预训练 → 直接联合训练,只在下游 QA 数据上做 early stopping。 -
压缩比不是越高越好
128× 以后继续压到 256×,指标开始下滑;但延迟不再线性下降(向量 IO 成为瓶颈)。产品落地时,16×–32× 是延迟-质量甜点。
8. 实用摘要 / 一页速览
适用场景
-
长文档问答:技术手册、法律条文、医疗指南 -
端侧部署:手机、车载、嵌入式 GPU -
多跳知识库:Wiki、企业知识图谱
落地步骤
-
用 SCP 脚本把知识库所有文档压成记忆向量(一次性,离线)。 -
把 Query Reasoner LoRA 插到现有 LLM,训练数据只需“问题-答案”对。 -
推理时:
a. 问题 → 查询向量(32 token)
b. FAISS 搜 Top-5 文档向量(共 160 token)
c. 拼接后送进生成器,答案即出。
硬件收益
-
原文 16 k token → 192 token,显存占用降到 1/80。 -
100 k 文档库,向量总大小 < 20 GB,一张 A100 可全放显存。
9. FAQ
-
CLaRa 与 Retrofit 类“先检索再精排”方案有何不同?
传统方案检索、精排、生成三阶段目标不一致;CLaRa 用同一套 LM loss 端到端训练,梯度直达查询编码器,无需人工标注相关句。 -
记忆 token 数量如何选?
经验:每 100 字用 1 个记忆 token;新闻/百科 16 足矣,科技论文建议 32–64。 -
压缩向量会“遗忘”表格或数字吗?
SCP 预训练用 Simple QA 显式保留数字、实体,实验表明在需要数值回答的 2Wiki 数据集上,CLaRa 仍比原文 BGE 基线高 2-4%。 -
温度 τ 需要调吗?
0.3–0.5 区间对结果不敏感;若候选池 >10 k,可适当升至 0.7 防止 softmax 太平。 -
能否直接用在中文?
输入文件实验仅覆盖英文维基,但框架与语种无关。只需用中文语料重新走 SCP 预训练即可。 -
离线压缩多久?
单卡 A100,7B 模型,200 万篇维基约 18 小时;一次完成,后续无需再动。 -
向量库更新怎么办?
新增文档只需单独压向量并追加到 FAISS,无需重训模型;删除文档则做软删除标记即可。
