想象一场开卷考试:你翻遍课本(检索),抱回二十段“可能相关”的资料,但答题卡只有五百个格子。直接整段抄上去?写不下,老师还看得一头雾水。你会怎么做?先做笔记——把每段话提炼成一两句要点(压缩);再排顺序——把最贴近题目、最像得分点的要点写在最前面(重排)。大模型就是那位阅卷老师,RAG 系统就是你的备考流程:检索负责“翻书”,压缩负责“摘要点”,重排负责“定优先级”。三个环节配合好,答案又快又准;配合不好,要么 token 爆表,要么大模型被无关信息带偏。这篇文章带你用“备考思维”看懂 RAG 上下文压缩与重排的全部套路。

岗位关联

对 AI 从业者而言,掌握压缩与重排协同调优,是优化 RAG 回答质量与 token 成本的核心手艺,也是从“能跑通”走向“跑得好”的关键一步。

目录
  1. 可视化演示
  2. 压缩重排协作
  3. 压缩算法选型
  4. 重排模型选型
  5. 效果延迟平衡
  6. 端到端评估
  7. 工程落地实践
  8. AI 应用场景
  9. Python 演示
  10. 常见误区
  11. 面试题

可视化演示

动态演示RAG检索上下文压缩与重排策的核心机制,通过基础/核心/应用/扩展四种模式展示关键概念与交互流程。

本节配有交互动效(进入视口后自动加载,约 3KB)。

RAG检索上下文压缩与重排策:压缩与重 压缩与重排的协同工作架构 LLM压缩与抽取式压缩的算法选 核心机制可视化 RAG检索上下文压缩与重排策整体架构与关键组件

压缩重排协作

回到开卷考试。你从课本里翻出来二十段资料,第一件事是判断“答题卡装不装得下”——这就是上下文窗口瓶颈:大模型的注意力窗口就像答题卡,格子有限。第二件事是判断“哪些话最可能得分”——这就是噪声干扰:资料里大段背景介绍、重复描述,直接抄上去会让阅卷老师(大模型)抓不住重点。第三件事是省钱:每多写一个字,就多花一分 token 费用。

所以 RAG 系统的标准动作是:检索器先召回 top-50 相关段落(翻书),压缩模块把每段提炼成要点(做笔记),重排模块按相关度从高到低排序(排优先级),最后只把排序靠前的 top-10 送入大模型。压缩解决“装不装得下”,重排解决“先看哪一个”,两者配合才能达到又快又准的效果。

在重排打分的工程实践中,我们还希望重排时兼顾 token 成本,避免让一个又长又不太相关的“大块头”文档霸占前排。因此可以用一个带成本惩罚的排序公式:

这就像你整理笔记时,既要看内容靠不靠题(相关度),也要看篇幅值不值得写(成本)。两者平衡好了,答题卡才用得最值。

Score(di)=Rerank(q,di)−α×Tokens(di)TotalTokens\text{Score}(d_i) = \text{Rerank}(q, d_i) - \alpha \times \frac{\text{Tokens}(d_i)}{\text{TotalTokens}}
这个公式表示:文档的最终排序分数 = 相关度分减去一个与长度成正比的惩罚项。相当于“内容相关但废话太多”的段落会被扣分。
  1. 重排相关度分重排模型计算问题 \(q\) 与文档 \(d_i\) 的相关度得分,分越高代表这段资料越贴近题目。
    Rerank(q,di)\text{Rerank}(q, d_i)
  2. 长度占比惩罚文档 token 数占总 token 数的比例,越长、占比越大,惩罚越狠,防止长而无物的“注水段落”占据靠前位置。
    Tokens(di)TotalTokens\frac{\text{Tokens}(d_i)}{\text{TotalTokens}}
  3. 权衡系数\(\alpha\) 控制惩罚力度。\(\alpha\) 大则更看重省 token,\(\alpha\) 小则更看重相关度,工程上通常设为 0.1 到 0.3。
    α\alpha
  4. 最终排序按分数降序排列,从而让“既相关又精炼”的文档排在最前面。
    Score(d1)>Score(d2)>⋯>Score(dn)\text{Score}(d_1) > \text{Score}(d_2) > \dots > \text{Score}(d_n)

压缩算法选型

做笔记有三种风格。第一种是请学霸帮你概括:他读完整段话,用自己的话说出核心观点——这是 LLM 生成式压缩,理解语义、能针对问题提炼,但“请学霸”要花时间(延迟高),也可能偶尔自由发挥过头(幻觉)。第二种是你拿荧光笔划重点:从原文里挑出最重要的一两句,一字不改——这是抽取式压缩,速度快、绝对保真(内容都来自原文),但划出来的句子可能缺上下文、读起来不连贯。第三种是混合策略:先用荧光笔划出候选句,再请学霸把几句合并润色成通顺的要点。

三种方式各有用武之地。LLM 压缩适合复杂推理问题,比如“这两份合同有哪些冲突条款”;抽取式压缩适合延迟敏感的场景,比如实时语音助手;混合压缩则适合中等预算的常规问答。压缩率(压缩后 token 与压缩前 token 的比值)一般控制在 20% 到 50% 之间——压得太狠会把关键信息弄丢,压得太轻又省不下多少 token。

选压缩算法就像选笔记工具:学霸(LLM)贵但质量高,荧光笔(抽取)便宜但效果糙,聪明人往往口袋里两种都备着,按情况取用。

ρ=TokensafterTokensbefore×100%\rho = \frac{\text{Tokens}_{\text{after}}}{\text{Tokens}_{\text{before}}} \times 100\%
压缩率就是压缩后剩余 token 占原始 token 的百分比。20% 表示压掉了八成内容,50% 表示压掉了一半。
  1. 压缩前 token 数原始检索段落被分词器切分后的 token 总数,这是压缩的“原料量”。
    Tokensbefore\text{Tokens}_{\text{before}}
  2. 压缩后 token 数压缩完成后保留的 token 数,是“成品量”。
    Tokensafter\text{Tokens}_{\text{after}}
  3. 比值换算百分比两者相除再乘以 100%,得到压缩率。工程经验是控制在 20% 到 50%,过低会损伤信息完整性。
    ρ=TokensafterTokensbefore×100%\rho = \frac{\text{Tokens}_{\text{after}}}{\text{Tokens}_{\text{before}}} \times 100\%

重排模型选型

想象考场上有两位判卷老师。第一位是“速读型”老师:考前把所有课本内容背成了知识卡片(向量索引),考试时看到你的答案关键词和卡片对得上,就快速给分——这就是 bi-encoder:问题和文档分别编码成向量,用余弦相似度打分。好处是文档向量可以提前离线算好,在线只需编码问题一次,速度快得惊人;坏处是它只看“关键词重合”,容易把“苹果”和“苹果公司”混为一谈。

第二位是“精读型”老师:他拿着题目原文,逐字逐句跟你的答案比对——这就是 cross-encoder:把问题和文档拼接成一个整体输入模型,让模型在 token 级别上充分交互,精度明显更高。代价是每篇文档都得从头到尾过一遍模型,无法预计算,候选越多越慢。

精读老师判得准但判得慢,速读老师判得快但会看走眼。工程上的标准做法是:召回阶段用 bi-encoder 快筛出 top-100,重排阶段用 cross-encoder 对 top-20 精排。这也解释了为什么两者不是替代关系,而是上下游关系。

而 cross-encoder 没有这么简洁的公式,它把 \(q\) 和 \(d\) 拼成 [CLS] q [SEP] d 输入 Transformer,直接输出一个 0 到 1 的相关分——就像精读老师直接在试卷上写下“这题 0.92 分”。

sim(q,d)=e⃗q⋅e⃗d∥e⃗q∥×∥e⃗d∥\text{sim}(q, d) = \frac{\vec{e}_q \cdot \vec{e}_d}{\|\vec{e}_q\| \times \|\vec{e}_d\|}
这是 bi-encoder 的相似度公式:把问题和文档都变成向量,用夹角的余弦值衡量它们“方向”有多一致。方向越一致,越相关。
  1. 问题向量bi-encoder 编码器把用户问题 \(q\) 映射成一个稠密向量,这一步在线实时计算。
    e⃗q\vec{e}_q
  2. 文档向量文档 \(d\) 经过同一个编码器得到向量,可以在离线阶段预计算并存入向量库。
    e⃗d\vec{e}_d
  3. 点积与模长分子是两向量的点积,衡量逐维乘积之和;分母是两个向量模长的乘积,起到归一化作用。
    e⃗q⋅e⃗d/∥e⃗q∥×∥e⃗d∥\vec{e}_q \cdot \vec{e}_d \quad / \quad \|\vec{e}_q\| \times \|\vec{e}_d\|
  4. 余弦相似度结果结果在 \([-1, 1]\) 之间,越接近 1 表示方向和语义越一致。
    sim(q,d)→1\text{sim}(q, d) \to 1

效果延迟平衡

考试时间总是有限的。如果每一道题都让精读老师逐字比对,时间根本不够用;如果全用速读老师,又容易漏掉得分点。聪明的考生会分层处理:先把明显不相关的答案扔掉(bi-encoder 粗排淘汰 80%),再对剩下的精读判卷(cross-encoder 精排 top-20),最后摘出最稳的几条写进答题卡。这就是级联排序策略。

延迟预算是这样拆解的:检索耗时通常在几十毫秒,bi-encoder 粗排每篇约 1 毫秒,cross-encoder 精排每篇约 20 到 50 毫秒,LLM 生成则要 1 到 3 秒——生成才是大头。压缩耗时需要特别留意:LLM 压缩一次可能就要 0.5 到 2 秒,如果对 50 篇文档全做 LLM 压缩,延迟直接爆炸。因此压缩要“量力而行”:先抽取式压掉一大半,再对真正要送入模型的 top-10 做精细压缩。

另外还有动态路由:简单问题(比如“公司邮箱是什么”)走快速路径——bi-encoder + 抽取压缩;复杂问题(比如“这三份合同有哪些风险”)走完整路径——LLM 压缩 + cross-encoder 精排。就像考生先扫一眼题目难度,简单题直接写,难题才祭出精读策略。

考场上最忌讳“平均用力”。把精读留给最关键的内容,把速读用在海量筛选中,整体时间才够用——RAG 的延迟平衡,考的就是这道时间分配题。

Ttotal=tret+tcompress+trerank+tgenT_{\text{total}} = t_{\text{ret}} + t_{\text{compress}} + t_{\text{rerank}} + t_{\text{gen}}
总延迟等于检索、压缩、重排、生成四个环节的耗时之和。压缩和重排的耗时占比要控制在 20% 以内,否则就是本末倒置。
  1. 检索耗时向量索引查询耗时,通常 20 到 80 毫秒。
    trett_{\text{ret}}
  2. 压缩耗时压缩阶段耗时,抽取式约 5 毫秒,LLM 生成式可能高达 1 到 2 秒。
    tcompresst_{\text{compress}}
  3. 重排耗时与候选数成正比,cross-encoder 重排 20 篇约 0.4 到 1 秒。
    trerankt_{\text{rerank}}
  4. 生成耗时大模型生成答案的耗时,压缩上下文能直接降低这部分成本。
    tgent_{\text{gen}}

端到端评估

考试最终看总分,但要想知道哪科拖后腿,还得看分项成绩。RAG 评估也是一样:检索质量指标看召回率(Recall@k),衡量“该翻到的书页翻到了没”;重排排序指标看 MRR 和 NDCG@k,衡量“翻到的书页排得准不准”;答案质量评估看准确率、ROUGE 分数和忠实度,衡量“最终写的答案对不对、有没有瞎编”。最后还要算账:token 节省了多少、延迟涨了多少。

其中 NDCG@k 是重排效果的核心指标。它的思想是:排在第 1 位的相关文档比排在第 5 位的更有价值。公式里每个位置的收益会除以排名的对数折扣,越靠前权重越大,再除以理想排序的得分做归一化,得到 0 到 1 的分值。

实操时还要做消融实验:固定同一个评估集,分别跑“全量上下文”“只压缩不重排”“只重排不压缩”“压缩+重排”四组配置,对比回答得分、token 消耗和延迟。就像每次只改一种备考习惯,看总分到底涨在哪——这样才能精准定位瓶颈,而不是瞎调一通。

NDCG@k=∑i=1k2reli−1log⁡2(i+1)∑i=1k2relideal,i−1log⁡2(i+1)\text{NDCG}@k = \frac{\sum_{i=1}^{k} \frac{2^{rel_i} - 1}{\log_2(i+1)}}{\sum_{i=1}^{k} \frac{2^{rel_{\text{ideal},i}} - 1}{\log_2(i+1)}}
简单理解:位置越靠前的相关文档,对分数的贡献越大。NDCG 越接近 1,说明你的“笔记顺序”越接近完美答案顺序。
  1. 相关性标签第 \(i\) 个位置的文档与问题的相关性得分,通常取 0(不相关)或 1(相关),也可用 0 到 3 的多级标签。
    relirel_i
  2. 位置折扣\(\log_2(i+1)\) 让排名越靠后的文档收益被压缩得越狠,体现“前置优先”。
    log⁡2(i+1)\log_2(i+1)
  3. 累计收益 DCG分子把所有位置上的折扣收益累加,得到当前排序的总收益。
    DCG@k=∑i=1k2reli−1log⁡2(i+1)\text{DCG}@k = \sum_{i=1}^{k} \frac{2^{rel_i} - 1}{\log_2(i+1)}
  4. 归一化基准 IDCG分母是理想排序(把相关文档全排最前)下的最大收益,用当前收益除以它,得到 0 到 1 的 NDCG 值。
    NDCG@k=DCG@kIDCG@k\text{NDCG}@k = \frac{\text{DCG}@k}{\text{IDCG}@k}

工程落地实践

把备考流程变成自动流水线,还需要几样“后勤工具”。第一样是缓存复用机制:常考的重点题(热门问题)直接查错题本,不用重新做笔记和排序。第二样是批处理加速:重排模型一次处理一批候选文档,用 GPU 批量推理,比逐篇调用省一半时间。第三样是增量更新策略:知识库新增文档时,只重算新文档的向量和缓存,不必全量重建——就像课本改版时只换新章节的笔记。

第四样是监控与回退:持续跟踪端到端延迟的 P95、压缩率、缓存命中率、重排后 top-1 答案采纳率。如果重排服务超时,就自动降级为只用 bi-encoder 的粗排结果,保证回答不会彻底失败——这就是“时间不够先答最稳的题”。

缓存能显著摊薄成本,可以用一个简单的期望成本公式来理解为什么值得做缓存:

后勤到位了,整条流水线才能稳定运转:有缓存兜底、有批量提速、有更新保鲜、有回退守底线。这样一套系统,才称得上“上了考场不慌”。

Cavg=hitRate×Ccache+(1−hitRate)×CcomputeC_{\text{avg}} = \text{hitRate} \times C_{\text{cache}} + (1 - \text{hitRate}) \times C_{\text{compute}}
平均成本 = 命中率 × 命中缓存成本 + 未命中率 × 重新计算成本。命中率越高,平均成本越低。
  1. 缓存命中率请求中有多少比例直接命中了缓存,热门问题占比越高,命中率越高。
    hitRate\text{hitRate}
  2. 命中读取成本从缓存读取结果的开销,通常只有 1 到 5 毫秒。
    CcacheC_{\text{cache}}
  3. 未命中计算成本需要重新做压缩和重排的开销,可能高达几百毫秒到几秒。
    CcomputeC_{\text{compute}}
  4. 加权平均两类成本按命中率加权求和,得到每次请求的平均成本。
    Cavg=hitRate×Ccache+(1−hitRate)×CcomputeC_{\text{avg}} = \text{hitRate} \times C_{\text{cache}} + (1 - \text{hitRate}) \times C_{\text{compute}}

AI 应用场景

场景一:企业知识库智能客服

阶段:RAG 在线服务(检索后处理与生成前优化)

解决的问题:用户提问后,检索器一次召回 30 段 FAQ,直接拼接会超出上下文窗口,回答冗长且容易被无关 FAQ 带偏。传统做法是硬截断前 N 个字,结果把关键答案截没了。

具体案例:某电商售后机器人上线“抽取式压缩 + cross-encoder 重排”流水线:先把每段 FAQ 压缩成 2 句话,再重排选出 top-5 送入大模型。上线后平均 token 消耗下降 60%,答案采纳率提升 15%,P95 延迟仅增加 80 毫秒。

场景二:法律判例检索助手

阶段:离线文档索引 + 在线检索增强

解决的问题:法律判例动辄几千字,噪声多、关键信息分散。直接把原文塞进大模型,token 成本高且律师等不起。

具体案例:某法律科技公司搭建“LLM 压缩摘要 + bi-encoder 粗排 + cross-encoder 精排”三阶段流水线。每个判例先由 LLM 生成 200 字案情摘要,检索时先用 bi-encoder 快筛 top-50,再用 cross-encoder 精排 top-3。律师平均 3 秒内获得最相关的三个判例摘要,费用比全量原文方案降低七成。

场景三:智能语音助手实时问答

阶段:低延迟在线推理流水线

解决的问题:语音助手要求 500 毫秒内响应,cross-encoder 逐篇精排太慢,LLM 压缩更不可行。必须在质量可接受的前提下极限压缩延迟。

具体案例:某智能音箱团队采用动态路由:简单事实类问题(“今天天气如何”)走 bi-encoder + 抽取压缩快速路径,50 毫秒完成全部预处理;复杂推理问题(“这个药和那个药能一起吃吗”)才启用 cross-encoder 精排,且单次只精排 5 篇。整体回答延迟稳定在 350 毫秒内。

Python 演示

python78 行
# -*- coding: utf-8 -*-"""RAG 上下文压缩与重排的简化 Pipeline 演示""" import re  def retrieve(query, corpus, top_k=6):    """模拟向量检索: 按词重叠度召回 top_k 个原始段落"""    q_words = set(re.findall(r"[\w\u4e00-\u9fa5]+", query.lower()))    scored = []    for idx, doc in enumerate(corpus):        d_words = set(re.findall(r"[\w\u4e00-\u9fa5]+", doc.lower()))        hit = len(q_words & d_words) / max(len(q_words), 1)        scored.append((hit, idx, doc))    scored.sort(key=lambda x: x[0], reverse=True)    return scored[:top_k]  def extractive_compress(doc, max_sentences=2):    """抽取式压缩: 只保留前 max_sentences 个完整句, 类似荧光笔划重点"""    sents = re.split(r"[。!?!?]", doc)    sents = [s.strip() for s in sents if s.strip()]    return "。".join(sents[:max_sentences]) + "。"  def llm_compress(doc):    """LLM 压缩: 模拟生成式概括, 取最长的核心句作为摘要"""    sents = re.split(r"[。!?!?]", doc)    sents = [s.strip() for s in sents if s.strip()]    if not sents:        return ""    best = max(sents, key=len)    return "核心要点: " + best[:40]  def rerank_cross(query, docs):    """模拟 cross-encoder 重排: 用句子级 F1 重叠度打分"""    q_words = set(re.findall(r"[\w\u4e00-\u9fa5]+", query.lower()))    results = []    for doc in docs:        d_words = set(re.findall(r"[\w\u4e00-\u9fa5]+", doc.lower()))        inter = len(q_words & d_words)        precision = inter / max(len(d_words), 1)        recall = inter / max(len(q_words), 1)        f1 = 2 * precision * recall / max(precision + recall, 1e-9)        results.append((f1, doc))    results.sort(key=lambda x: x[0], reverse=True)    return results  def main():    query = "RAG 系统中为什么需要对上下文做压缩和重排"    corpus = [        "RAG 检索返回大量相关文档, 直接拼接会占用上下文窗口并引入噪声。",        "上下文压缩的目标是在保留关键信息的同时降低 token 数量。",        "重排一般使用 reranker 模型, 把最相关的文档排在最前面。",        "cross-encoder 需要问题和文档一起过模型, 精度高但速度慢。",        "bi-encoder 可以预计算文档向量, 推理速度快但精度有限。",        "压缩方法有抽取式和生成式, 生成式更灵活但延迟更高。",        "重排之后再把 top-k 片段送入 LLM, 能明显提升答案质量。",        "端到端评估要同时看答案正确率和 token 成本, 做消融实验。",    ]    raw = retrieve(query, corpus, top_k=6)    # 1. 压缩: 这里选用 LLM 压缩模拟    compressed = [llm_compress(doc) for _, _, doc in raw]    # 2. 重排: 用交叉打分精排    ranked = rerank_cross(query, compressed)    # 3. 拼接最终上下文    final_context = "\n".join(        f"[{i + 1}] (score={score:.2f}) {doc}"        for i, (score, doc) in enumerate(ranked)    )    print("最终上下文(压缩+重排后):")    print(final_context)  if __name__ == "__main__":    main()
目的:演示一条完整的“检索 → 压缩 → 重排 → 构造上下文”流水线,用词重叠模拟向量检索,用核心句提取模拟 LLM 压缩,用 F1 重叠度模拟 cross-encoder 打分。
  1. scored.sort(key=lambda x: x[0], reverse=True)检索阶段按相似度降序,排出最相关的原始段落。
  2. raw = retrieve(query, corpus, top_k=6)先召回 top-6,模拟向量检索返回的候选集。
  3. compressed = [llm_compress(doc) for _, _, doc in raw]对每个候选做生成式压缩,模拟学霸概括笔记。
  4. extractive_compress(doc, max_sentences=2)抽取式压缩的替代实现:只保留前两句,模拟荧光笔划重点。
  5. best = max(sents, key=len)LLM 压缩模拟器内部:取最长的核心句作为摘要,代表模型抓住了主要信息。
  6. ranked = rerank_cross(query, compressed)重排阶段:用 F1 重叠度对压缩后的片段重新打分排序。
  7. results.sort(key=lambda x: x[0], reverse=True)按精确分数降序排列,等价于 cross-encoder 的输出排序。
  8. final_context = "\n".join(...)把排序后的片段拼成最终上下文,带分数标注方便调试。

常见误区

误区很多人觉得上下文太长直接截断就行了,把前面 N 个 token 留下、后面的丢掉,又快又省事。反正大模型只看前面。

正解截断是最危险的压缩方式——关键信息往往藏在段落中间或结尾。就像考试让你抄重点,你只抄了试卷第一页,第二页的得分点全丢了。真正的压缩要根据问题和语义来提炼,抽取关键句或生成摘要,而不是按位置硬切。

为何常见:截断实现最简单、零延迟,且刚入门时容易忽略“信息分布不均匀”这个事实,以为开头就是重点。

误区有些人认为“反正都要做,压缩和重排先后无所谓,结果差不多”。

正解顺序会影响质量和成本。先压缩再重排是最常用的——重排模型面对的是精炼文本,打分更聚焦、耗时更短;但如果候选文档非常多,先粗排选出 top-100 再压缩,能省大量压缩开销。两者不是同一道工序的不同叫法,而是有先后依赖的流水线关系。就像考试必须先筛出可能考的章节,再逐章做笔记,顺序反了效率骤降。

为何常见:初学者把压缩和重排都理解为“检索后的简单后处理”,没有意识到它们各自的开销和对下游的影响差异。

误区既然 cross-encoder 打分准,那从召回开始就全部用它,不是效果最好吗?何必还要 bi-encoder。

正解cross-encoder 每篇文档都要和问题拼接过一遍模型,1000 篇候选就是 1000 次推理,延迟和成本直接爆炸。正确做法是分层使用:bi-encoder 负责从百万级文档中快筛到几百篇,cross-encoder 只精排最后几十篇。就像阅卷不能每次都找精读老师逐字看一千份卷子,先让速读老师筛掉明显不对的,精读老师才有时间细看。

为何常见:只在小数据集上对比过模型精度,忽视了真实场景下候选量级和延迟预算的巨大差异。

误区有人把压缩率当唯一 KPI,认为压到 5% 才是本事,token 成本降得越多越好。

正解压缩率过低会丢失关键信息和上下文关联,导致答案质量断崖式下跌。工程上 20% 到 50% 是经验区间,最终要以端到端答案得分为准。就像笔记做得越短,复习时越可能看不懂当初的上下文。压缩率要和答案质量放在一起评估,而不是单看一个数。

为何常见:token 成本最直观、最容易量化,而质量下降是间接且滞后的,容易被忽视。

误区上线后看用户反馈和回答准确率就够了,MRR、NDCG 这些中间指标没必要专门统计。

正解端到端指标只能告诉你“坏了”,不能告诉你“坏在哪”。回答变差了,到底是检索没召回、压缩丢了关键信息,还是重排把好文档排到了后面?只有分模块指标能定位瓶颈。就像学生总分下降了,不看各科成绩就不知道是数学拖后腿还是英语滑坡。消融实验加分模块指标,才是科学的调优路径。

为何常见:分模块指标需要额外埋点和评估集标注,前期投入大,容易被视为“不紧急的事”。

面试题

Q1. RAG 中为什么要对检索到的上下文做压缩?

单选题 · easy

  • A.提升检索响应速度
  • B.减少 token 与噪声← 正确答案
  • C.扩大模型参数量
  • D.替换嵌入编码模型

答案:B。压缩的核心目的是在保留关键信息的同时减少 token 占用、降低噪声干扰,让大模型在有限的上下文窗口内看到更精炼的内容。A 是检索阶段的事,C、D 与压缩无关。

Q2. 相比 LLM 生成式压缩,抽取式压缩最突出的优点是?

单选题 · easy

  • A.语义理解能力更强
  • B.速度快且不会幻觉← 正确答案
  • C.能生成全新句子
  • D.压缩率永远更高

答案:B。抽取式压缩直接挑选原文中的句子,内容百分百来自原文,因此不会产生模型编造内容(幻觉)的风险,同时不需要额外的 LLM 推理,速度更快。A、C 是生成式的特点,D 说法过于绝对。

Q3. cross-encoder 与 bi-encoder 的根本区别在于?

单选题 · mid

  • A.模型参数的规模不同
  • B.有无 token 级交互← 正确答案
  • C.训练数据来源不同
  • D.输出向量维度不同

答案:B。cross-encoder 把问题和文档拼接后输入同一模型,让 token 在注意力层充分交互,精度更高;bi-encoder 则分别编码问题和文档,互不看见对方内容。就像精读老师拿着题目逐字对照答案,而速读老师只凭印象打分。

Q4. 以下属于重排效果评估指标的有?

多选题 · mid

  • A.平均倒数排名 MRR← 正确答案
  • B.折损累计增益 NDCG← 正确答案
  • C.文本生成相似 BLEU
  • D.召回率 Recall@k

答案:AB。MRR 和 NDCG 都是衡量“相关文档是否排在前面”的排序指标,是重排质量的核心度量。BLEU 是文本生成指标,Recall@k 属于检索阶段指标,都不用于评估重排排序效果。

Q5. 级联重排策略通常指什么?

单选题 · mid

  • A.先抽取再 LLM 压缩
  • B.先粗排再精排重排← 正确答案
  • C.先缓存再重排打分
  • D.先检索再压缩整理

答案:B。级联重排指先用 bi-encoder 快速粗排,把候选从数千篇缩小到几十篇,再用 cross-encoder 精排,兼顾速度与精度。这就像先让速读老师筛一遍卷子,精读老师才有时间细看剩下的。A 是压缩策略,C 是缓存策略,D 是流程描述而非重排策略。

Q6. 工程上上下文压缩率一般控制在什么范围?

单选题 · mid

  • A.5% 到 10% 区间
  • B.20% 到 50% 区间← 正确答案
  • C.80% 到 100% 范围
  • D.完全不压缩最优

答案:B。20% 到 50% 是工程经验值:压得太狠(5%)会丢失关键信息,压得太轻(80% 以上)省不下多少 token。完全不压缩则失去了优化的意义。最优值需要通过消融实验确定。

Q7. 为平衡效果与延迟,合理的工程手段包括?

多选题 · hard

  • A.热门问题使用缓存← 正确答案
  • B.重排采用批量推理← 正确答案
  • C.简单查询走快速路径← 正确答案
  • D.只用大模型精排

答案:ABC。缓存让热点问题直接命中结果、批量推理提升 GPU 利用率、动态路由让简单查询跳过重型环节,都是成熟的降延迟手段。只用大模型精排会让所有请求都承担高延迟和高成本,属于反面做法。

Q8. bi-encoder 相对于 cross-encoder 的核心工程优势是?

单选题 · easy

  • A.打分精度更高超
  • B.文档向量可离线算← 正确答案
  • C.支持无限长文本
  • D.不需要训练数据

答案:B。bi-encoder 把文档编码为向量的过程可以在离线完成并存入向量库,在线只需编码问题一次,检索速度快。精度是它相对于 cross-encoder 的短板,长文本限制和训练数据需求两者都存在。

Q9. 消融实验发现“只压缩不重排”效果反而下降,最可能的原因是?

单选题 · hard

  • A.压缩率设定过高
  • B.噪声片段排到最前← 正确答案
  • C.检索数量过于少
  • D.压缩模型太轻量

答案:B。只压缩不重排,高噪声或低相关的片段可能仍然排在前面,大模型读到这些“先入为主”的噪声会被带偏,导致答案质量下降。这就像笔记做得很精炼但顺序混乱,得分点埋在最后,阅卷老师根本看不到。压缩率和检索数量不是直接原因,模型轻量也不必然导致变差。

Q10. 评估 RAG 回答的质量维度包括?

多选题 · mid

  • A.答案准确度← 正确答案
  • B.答案忠实度← 正确答案
  • C.token 节省量
  • D.检索召回率

答案:AB。答案准确度衡量回答是否满足问题,忠实度衡量回答是否忠于检索到的上下文(有没有瞎编),二者属于质量维度。token 节省量是成本维度,检索召回率属于检索阶段指标,都不属于“回答质量”范畴。