一、先说说RAG为什么“天生怕投毒”
检索增强生成(RAG)是企业知识库问答的标配。文档切块、向量化、塞进索引,用户提问时先检索最相关的几篇文档,再让大模型基于这些文档生成答案。知识可以随时更新,不用重新训练模型,成本低、灵活、效果好。
但问题恰恰出在这里:检索本身就是一次信任决定。RAG把外部语料库当作推理证据,谁能让自己的文档排到检索结果前几名,谁就能左右大模型的最终回答。攻击者不需要攻破模型,也不需要改参数,只需要往知识库里投几篇精心构造的文档——比如编辑一个公开网页、上传一份共享文档。只要内容能被索引、被检索到,攻击就完成了。
这种攻击叫作RAG知识库投毒(RAG corpus poisoning)。攻击者让目标问题检索到自己控制的文档,文档里写着攻击者想要的错误答案。大模型基于这些文档生成回答,看起来有凭有据,实际上已经被“带偏”了。更麻烦的是,投毒文档可以长得很“正常”:有的用自然语言写,有的用嵌入优化触发器,有的故意分散在语料库各个角落,绕开基于关键词或聚类的检测。已有防御手段面对这种多样性时,覆盖缺口很明显。
图1:RAG语料库投毒示意与RAGSieve的两种部署位置。RSG在检索前对语料库图做检查;RSQ在生成前用当前查询的检索尾部做对比。
二、现有防御都绕不开一个“死结”:参照系从哪来
检测投毒文档,核心问题不是“怎么打分”,而是“拿什么做对比”。理想情况下,我们需要一个干净的参照系:要么有一批可信的干净文档,要么有一个全局的异常阈值。但现实很尴尬——被检查的语料库本身就是攻击目标,里面可能已经混入了投毒文档;RAG服务也不知道哪个查询会被攻击。全局阈值也很脆弱:不同话题区域的语义密度本来就不同,每个语料库的背景相似度分布也差别巨大。一个固定的全局阈值在NQ上可能合适,到了MS MARCO上就完全失灵。
已有的在线防御各有各的依赖:RA-Guard依赖困惑度变化和文本相似度,GMTP依赖受害者检索器的梯度和掩码token概率,EcoSafeRAG依赖诱饵引导的上下文多样性,CEG-RAG和TRACE依赖学习好的交叉编码器激活或生成器影响力。离线方法则寻找全局结构:AHD找那些在合成探针查询中充当“通用枢纽”的文档,CleanBase通过一个语料库范围的绝对边阈值检测语义团簇。问题在于:攻击者只要把投毒文档写得流畅、词面多样、嵌入上故意分散,这些方法就可能漏检。
一句话总结困境:没有一个天然可信的参照物。所以这篇文章的思路是——既然外部参照不可靠,那就用被检查系统自己提供参照。这就是“自引用局部对比”(self-referenced local contrast)的核心。
三、RAGSieve的核心思想:让系统自己给自己当对照组
投毒文档在被注入时,其实同时扮演了两个角色:一是携带支持目标答案的内容载荷,二是要在检索排序上获得对同一查询相关文档的优势。当攻击者注入多篇共享载荷的文档时,这种注入还会改变这些文档在语料库索引中的局部几何结构。无论是“答案被推上前排”,还是“局部几何结构变化”,都可以放在它们发生的局部邻域里进行打分对比。
关键点在于:对比参照不是外部干净语料,而是“被检查事件自身所在的局部环境”。同一查询下,排在前面的候选文档和排在后面的检索尾部共享查询、检索器、语料快照,唯一的变量就是“谁进了生成上下文”。这就成了一个绝佳的匹配对照组。同理,一篇文档的邻居里,语义相近但词面不同的邻居和它自身的局部背景密度也是天然对照。
RAGSieve把这种思想落地成两个方法:RSQ(RAGSieve-Query)在检索后、生成前做查询时检测;RSG(RAGSieve-Graph)在语料入库或定期审计时做离线语料图检测。两者不需要投毒标签,也不需要可信语料库。
图2:RAGSieve方法框架图。RSQ在查询时用检索尾部评分并过滤前五候选;RSG在语料扫描时用局部语料图和邻域地板识别协同密度异常。
四、RSQ:检索后、生成前的“四合一”体检
RSQ的思路很直接:取当前查询的前5篇文档作为生成候选,第6到第20名作为“检索尾部”参照。然后对每个候选文档计算四个证据分量。
第一个分量是答案锚点集中度(Answer-Anchor Concentration)。多文档注入常常让多篇文档携带同一个目标答案的词汇,而这些词在检索尾部里很少出现。论文用超几何分布来刻画“候选文档中答案锚点词条数量异常偏高”的显著性,再用Simes方法合并多个词条的p值。通俗地说:如果某个答案词在前5篇里扎堆出现,而在第6-20名里几乎看不到,那这5篇就值得怀疑。这个分量是四个分量中贡献最大的,去掉它之后投毒检出率下降26.3个百分点。
第二个分量是脚本完整性(Script Integrity)。字符级优化攻击可能引入与当前检索上下文语言环境不协调的脚本切换,比如在中文文档里突然混入异常的西里尔字母或注音符号。RSQ把字母类Unicode字符映射到粗粒度脚本,计算每个文档中非主脚本字符的比例,再与检索尾部的15篇文档做秩对比。
第三个分量是多尺度惊讶度(Multiscale Surprisal)。嵌入优化的前缀或“载体-载荷接缝”会让文档局部出现流畅度突变,但整篇文档的平均困惑度看起来完全正常。RSQ用一个小型因果语言模型计算每个token的负对数似然,在不同窗口尺度下检测“突发高于文档典型窗口”的峰值,以及左右的变点。只有超过信息门限的异常才会计入得分,避免小波动被多尺度放大。
第四个分量是查询对齐突变(Query Alignment)。有些投毒文档载体流畅、语义自然,语言模型给出的困惑度完全正常,但文档与查询的语义相关性在中间某个位置突然切换——前半段像正常相关内容,后半段突然进入答案载荷。RSQ把文档切分成滑动窗口,用BERTScore计算每个窗口与查询的语义对齐度,然后测量相邻窗口之间对齐度跳变的最大幅度,再与检索尾部对比。这个分量对CPA-RAG这种联合优化攻击尤其有意义。
四个证据归一化后直接相加得到最终得分,超过阈值就标记为投毒,然后从候选里移除,按原始排序用后面的文档补位。整个流程在检索之后、生成之前完成,对用户是透明的。
五、RSG:入库时的“语料图巡警”
RSG处理的是另一个控制点:没有查询到来时,如何判断语料库里的哪些文档是投毒文档?它的思路是:协同注入的文档共享载荷,即使刻意分散在语料库不同区域,也会在局部图结构上留下密度异常。RSG先为每篇文档找到精确的k_G个最近邻,然后只保留那些“语义相似但词面不重叠”的邻居——语义相似用余弦相似度衡量,词面不重叠用Jaccard相似度衡量。这个过滤条件很关键:重复文档和近似重复文档天然会形成密集簇,如果不滤掉它们,检测器就会被误报淹没。
保留的邻居集合中,取最强的h_G个(论文取4个),计算它们的平均相似度。然后与文档自身的第k_G个最近邻相似度做对比——这个值就是“邻域地板”,每篇文档都有自己的地板值,这就是“局部对比”的精髓。对比的是最强保留邻居的平均相似度相对于这篇文档自身邻域地板的提升幅度。如果提升幅度异常高,说明这篇文档周围的语义密度异常偏高,它可能就是协同注入的一环。RSG最终得分取拓扑证据和脚本完整性证据的较大者,任何一类证据强到一定程度就足以触发告警。
六、实验效果:从67.4%到14.0%
论文在三个问答数据集(NQ、HotpotQA、MS MARCO)、三个密集检索器(BGE-M3、E5-large-v2、all-MiniLM-L6-v2)和六种投毒攻击(PoisonedRAG的黑盒与白盒变体、CEM的连续与分散变体、CPA-RAG、CamoDocs)的组合下做了全面评测。六种攻击覆盖了从最简单的“自然语言抄袭查询”到最复杂的“白盒梯度优化触发器”的完整谱系。
先看RSQ的独立表现。在文档级检测上,RSQ实现了95.2%的宏平均AUROC,并且在仅允许移除5%干净文档的预算下,能检测出82.2%的投毒文档。对比最强的基线GMTP,AUROC为81.1%,预算检测率只有52.5%。在问答系统运行点下,RSQ移除73.9%的投毒文档和2.2%的干净文档,而GMTP移除69.5%的投毒文档但误伤了22.3%的干净文档——GMTP虽然也移除了大量投毒文档,却以牺牲大量干净文档为代价,这对真实系统是不可接受的。
再看RSG的独立表现。在文档级检测上,RSG达到93.3%的宏平均AUROC和79.8%的预算检测率,而CleanBase只有79.4%的AUROC和37.6%的预算检测率。在54个“数据集×检索器×攻击”的组合中,RSG在37个组合上AUROC更高,在38个组合上预算检测率更高。值得注意的差异是:CleanBase用的是一个语料库范围的全局阈值,在语义密度不同的区域性能波动很大;RSG用每篇文档自己的邻域地板作参照,适应性强得多。
最关键的还是联合部署的效果。论文把RSG和RSQ串联起来:先用RSG扫描语料库并隔离可疑文档,再用RSQ对剩余结果做在线过滤。联合部署后,攻击成功率从无防御的67.4%骤降到14.0%,而未投毒检索的F1只从42.1%微降到41.3%——防御带来的可用性损失几乎可以忽略。
消融实验能告诉我们每个组件到底贡献了多少。论文对RSQ做了leave-one-out消融:每次去掉一个证据分量,看检测率掉多少。结果很清晰:去掉答案锚点集中度后,投毒检出率下降26.3个百分点——这说明多文档注入的核心特征就是“答案词汇在候选中扎堆”。去掉多尺度惊讶度分量后下降约15个百分点,主要影响的是PoisonedRAG白盒变体和CEM变体,这些攻击依赖嵌入优化的触发器,触发器的token序列会带来局部流畅度异常。查询对齐突变分量虽然平均贡献较小,但对CPA-RAG攻击的检测有不可替代的作用——这是一种联合优化检索与生成的攻击,载体自然流畅但语义突然跳变。脚本完整性分量则对基于前缀优化的黑盒攻击更有效。
实验还做了注入量的敏感性分析——最多允许注入的投毒文档数从1篇到10篇的变化。结果显示:单文档注入时RSQ的AUROC较低,这是预期中的,因为单文档注入没有多文档协同的密度特征,也不存在答案锚点在多个候选中扎堆的现象。但随着注入量增加到3篇和5篇,检测率显著上升。5篇是最优工作点——再增加到10篇时,虽然绝对检出量更高,但重复的投毒文档增加了检出冗余,相对提升有限。
成本方面,论文报告了在线和离线的计算开销。RSQ在线推理每查询约0.2秒(后检索阶段),主要开销来自Qwen3-0.6B-Base的前向传播和BERTScore计算。值得注意的是这个0.6B模型是七个小模型里最重的组件——部署时可以用更小的模型或蒸馏版来降低延迟。RSG的离线扫描在128,544文档的快照上约1.2小时完成,相当于每篇文档约34毫秒。考虑到RSG是在入库时跑,这个成本在可接受范围内。联合部署的总开销在线部分对用户体验影响很小,离线部分可以用异步任务完成。
七、龙哥点评
RAGSieve的核心贡献在于提出了“自引用局部对比”这一范式,巧妙地绕开了“干净参照系”这个死结。RSQ和RSG两个组件分别从查询时和入库时两个控制点入手,覆盖了RAG管线的关键环节。实验设计扎实,六种攻击、三个数据集、三个检索器的组合覆盖面很广,结果也很有说服力。联合部署将攻击成功率从67.4%压到14.0%,同时几乎不损失正常检索质量,这个平衡做得相当好。
当然,也有一些值得注意的局限。RSQ的在线推理每查询约0.2秒,主要开销来自0.6B语言模型和BERTScore计算,在延迟敏感的场景下可能需要优化。RSG的离线扫描虽然成本可接受,但面对超大规模语料库时仍需考虑扩展性。此外,论文主要针对英文和中文场景,跨语言场景下的表现还有待验证。
总体而言,这是一篇思路清晰、实验扎实的好工作。RAGSieve为RAG安全提供了一种不依赖外部资源的实用防御方案,值得关注。
龙迷三问
龙哥点评
论文创新性分数:★★★★☆
提出自参考局部对比框架RAGSieve,通过查询局部对比(RSQ)和语料库局部对比(RSG)两种模式,利用系统自身的检索尾部或局部语料图作为参考,检测RAG系统中的知识投毒文档。实验合理度:★★★★☆
AUROC, 5%清洁文档移除预算下的投毒检测率, 攻击成功率(ASR), F1, Exact Match (EM), Recall@5学术研究价值:★★★★☆
提出自参考局部对比框架RAGSieve,通过查询局部对比(RSQ)和语料库局部对比(RSG)两种模式,利用系统自身的检索尾部或局部语料图作为参考,检测RAG系统中的知识投毒文档;更关键的是问题定义是否可复用到同类任务。稳定性:★★★☆☆
现有材料未提供充分的极端条件、重复运行或扰动测试,稳定性暂按中性评价。适应性以及泛化能力:★★★☆☆
现有材料未完整展示跨数据集、跨场景或分布外实验,泛化能力仍需进一步验证。硬件需求及成本:★★★☆☆
RSQ在线检测平均447.3ms/查询,RSG离线扫描128,544文档语料库需46.54秒(0.362ms/文档)复现难度:★★★☆☆
https://github.com/XrazyMee/RAGSieve产品化成熟度:★★★☆☆
论文验证以研究实验为主,真实部署中的时延、成本、维护和异常场景仍需补充验证。可能的问题:1) 对单文档投毒检测能力有限(RSG在1文档注入时仅61.8%检测率);
*本文仅代表个人理解及观点,不构成任何论文审核或者项目落地推荐意见,具体以相关组织评审结果为准。欢迎就论文内容交流探讨,理性发言哦~ 想了解更多原文细节的小伙伴,可以点击"阅读原文",查看更多原论文细节哦!