余弦相似度不是安全属性(18分钟阅读)
摘要
文章认为,向量数据库中的余弦相似度是一个数学属性,不确保事实准确性,使得检索系统容易受到中毒攻击,其中恶意文档可以在排名中超过合法文档。
余弦相似度不具备真实性、权威性或来源的概念。
查看缓存全文
缓存时间: 2026/09/08 23:55
# 余弦相似度并非安全属性
来源:https://aminrj.com/posts/cosine-similarity-is-not-a-safety-property/
向量数据库返回的是与查询向量具有**最高余弦相似度**的文档。这是一种数学特性,本身不包含准确性、权威性或来源可靠性的概念。即使某个文档与查询的相似度高达 0.95,也可能是完全虚构的;而相似度为 0.60 的文档反而可能是真实的。
在投毒攻击中,攻击者的目标不是入侵向量数据库,而是编写一个文档,使其嵌入向量比合法文档更接近目标查询,然后通过足够的权威性包装,在两者同时出现在上下文窗口时赢得“辩论”。
## 嵌入模型究竟在做什么
`sentence-transformers/all-MiniLM-L6-v2` 将任意字符串转换为 384 维浮点向量,即 384 维空间中的一个点。语义相近的文本在空间中彼此靠近。例如,“Q4 财务结果”靠近“第四季度收入”,而远离“公司差旅政策”。
ChromaDB 存储这些向量,并通过距离函数查找与查询点最近的 k 个存储点来响应查询。其默认使用的是平方 L2 距离,而非余弦距离。若需使用余弦相似度,需在创建集合时通过 `metadata={"hnsw:space": "cosine"}` 显式设置。
本文所有内容均基于此配置——这是文本嵌入的常见选择,也是需要主动设置而非偶然继承的方案。若跳过此步骤,下文所述的“与查询点的角度关系”将不再描述数据库的实际行为。
```python
# 概念性检索机制
query_vector = embed("2025年Q4营收是多少?") # 384个浮点数
results = collection.query(query_embeddings=[query_vector], n_results=3) # 余弦距离最小的3个向量
```
模型并不理解文本在“真实意义”上的含义,它只知晓文本在训练数据中与其他文本的聚类方式。“收入为830万美元”和“收入为2470万美元”在向量空间中的位置几乎相同,因为它们只是数字不同的同一句式。向量数据库无法区分二者,只有模型在检索后才能区分——且前提是两个文档同时出现在上下文中。
这是稠密检索的固有特性,而非某个模型的缺陷。`all-MiniLM-L6-v2` 已逐渐成为不佳的生产默认选项;`EmbeddingGemma-300M`、`Qwen3-Embedding` 和 `BGE-M3` 才是2026年新工作的方向。但无论参数规模如何,语义相似度永远不等同于事实准确性。
(查询向量与三个投毒文档在相似度0.92-0.94区间内聚集在前3位窗口内,而合法文档以0.88相似度位于窗口外)
这三个投毒文档占据了前3名位置,持有真实数据的文档紧随其后位列第4,永远无法进入模型处理范围。相似度数值仅为示意,ChromaDB 返回的是余弦距离,具体值取决于模型、表述方式和文档长度。
## 词汇工程:无需梯度下降移动文档
这种攻击的高级形式(在 PoisonedRAG 论文(Zou, Geng, Wang and Jia, USENIX Security 2025)中被形式化)利用基于梯度的优化寻找能最小化目标查询向量余弦距离的文本。这需要白盒访问嵌入模型,或通过大量查询近似实现。
该论文通过向260万文档库注入**5个精心构造的文本**,使攻击者选择的答案达到90%以上的成功率。
廉价版本既不需要梯度下降也不需要白盒访问:只需识别目标查询的词汇,在文档中嵌入这些词汇,并为生成阶段添加权威信号。在我的实验中,针对未设防的流水线(小型种子语料库上进行20次测试,单一模型——实验室条件下的读数而非基准率),成功率达到了95%。
以下是我使用的三个文档(带注释):
**文档一:CFO更正声明**
标题:`《2025年Q4财务结果——更正数据(董事会更新)》`
针对“2025年Q4营收是多少?”类查询:`Q4 2025` 完全匹配时间范围,`财务结果` 与营收/财务聚类,`更正数据` 暗示内容覆盖先前报告,`董事会更新` 是权威信号。正文将虚构数字作为事实陈述,结尾注明 `经批准:CFO办公室`。
**文档二:重述通知**
声明Q4收入已重述,实际收入830万美元,“而非此前报告的2470万美元”。该文档明确真实数据,并将其重构为“已确认的错误”,为模型后续解决矛盾提供叙事框架。
**文档三:董事会会议纪要**
紧急会议,第三项议程,更正结果,数字相同。
三个文档相互印证同一虚构数据,对抗一个陈述真相的合法文档。在top-3检索中,三个文档挤占空间,合法内容始终无法进入上下文窗口。
这就是词汇工程:通过调整嵌入空间的占用区域,使虚构文档比目标替换文档更接近预期查询。
## 两个条件及其作用机制
PoisonedRAG 将攻击定义为必须同时满足的两个条件:
**检索条件**:对于目标查询q,投毒文档d_p必须进入top-k:
```
1 cos_distance(embed(d_p), embed(q)) < cos_distance(embed(d_legit), embed(q))
```
**生成条件**:进入上下文后,d_p必须促使模型输出攻击者的答案而非正确答案,这需要目标答案以足够权威的形式存在,以抵消相矛盾的来源。
研究关注点曾集中在检索条件(因为这里有优雅的优化方案),但近期工作表明框架构建发挥了更大作用。在《架构至关重要:知识库投毒下的RAG系统比较》(Korn, 2026年5月)中,最强攻击变体的大部分优势来自对抗性框架而非检索优化,且四种架构(在干净准确率相近时)的成功率跨度达58个百分点,从标准RAG的81.9%降至递归结构的24.4%。
如果框架构建占主导,那么解决检索文档间矛盾的阶段比进一步加强检索更值得投入。在我的测量中,合法文档经常被检索到**但仍然失败**——真实Q4数据位于上下文窗口内,模型却报告了虚构数据,因为两个文档声称真实数据已更正,而另一个文档只是默默陈述了它。
## 将几何结构反制攻击者
攻击者的需求也是其攻击特征。为了被检索到,投毒文档必须聚集在目标查询位置附近(即该主题的合法文档附近)。摄入时检查可识别此特征:
两个信号,需在存储前计算:
```python
# 信号1——现有集合中的最近邻
existing = collection.query(query_embeddings=[new_doc_embedding], n_results=3)
for dist in existing["distances"][0]:
if (1.0 - dist) > SIMILARITY_THRESHOLD: # 实验中设为0.85
flag("高相似度——可能的内容覆盖")
# 信号2——入批次内成对相似度
for i, e_i in enumerate(new_embeddings):
for j in range(i + 1, len(new_embeddings)):
if cosine_similarity(e_i, new_embeddings[j]) > CLUSTER_THRESHOLD: # 0.90
flag("紧密聚类——可能的协调注入")
```
两个信号在三文档攻击中均会触发:每个投毒文档的最近邻都是合法Q4报告(因主题同属2025年Q4财务),且三个文档相互紧密聚集(源于同一虚构叙事的变体)。
该单层防御将投毒成功率从95%降至20%。其几何学原因几乎是该领域的结构性保证:攻击者无法同时完全满足两个要求——满足检索条件意味着占用现有内容附近的空间(可检测),而规避检测意味着远离该空间(降低检索效果)。
20%的残余风险存在于攻击者平衡两者之间的区域,通常使用单个文档而非聚类,或通过足够的词汇变化降至相似度阈值以下但仍保持可检索性。
```mermaid
flowchart LR
RC["检索条件\n接近目标查询"] -->|"相同属性"| S1["信号1\n相似度 > 阈值"]
CL["协调注入\n多个文档,同一区域"] -->|"相同属性"| S2["信号2\n成对相似度 > 阈值"]
S1 --> DIL["攻击者困境\n规避检测会降低检索效果\n满足检索会触发检测"]
S2 --> DIL
classDef threat fill:#0f172a,stroke:#0f172a,color:#fff,stroke-width:1.5px
classDef ok fill:#e8f4fd,stroke:#3182ce,color:#1a202c,stroke-width:1.5px
class RC,CL threat
class S1,S2,DIL ok
```
## 访问控制检索:`where`子句
对每个向量查询添加元数据过滤器,限制请求用户可检索的文档范围。若无此机制,集合中的每个文档都可通过普通问题被任何用户访问——例如询问“薪资范围是多少”,系统会检索语义相近内容,却不知询问者身份。
我在包含三个受限文档(标记为HR专用的薪资数据、标记为特权信息的诉讼详情、标记为董事会级的并购管线)的实验流水线中测试:以普通工程师身份用自然语言查询(无规避动作),20次查询全部返回了机密内容。
```python
# 易受攻击:不识别询问者身份
results = collection.query(query_embeddings=[query_embedding], n_results=3)
# 加固后:检索范围限定于请求者权限
results = collection.query(
query_embeddings=[query_embedding],
n_results=3,
where={"classification": {"$in": user_permitted_classifications}}
)
```
此过滤器是防御跨租户泄露的唯一完整方案,因其具有结构性——从根本上阻止未授权内容进入上下文窗口。输出监控、提示加固等所有启发式方法都在检索后运行,此时数据已进入提示。
最小访问模型即可启动:
| 角色 | 允许的分类 |
|--------------|------------------|
| 普通员工 | 公开、内部 |
| HR业务伙伴 | 机密(HR) |
| 法律顾问 | 特权信息 |
| 高管 | 全部 |
无需完整RBAC,只需建立身份到元数据值的映射,并在所有检索路径应用。部分实施此控制比不实施更危险,因为它制造了虚假安全感——主聊天端点设置`where`过滤器,而摘要任务或评估工具中保留无过滤路径,将产生看似受控实则未受控的系统。必须找到所有检索调用点,而非显而易见的那些。
## 阈值问题
实验硬编码了0.85和0.90,这些值不具普适性,直接复制到生产环境是该控制失效的最常见方式。
| 阈值 | 捕获投毒 | 误标合法更新 |
|------|----------|--------------|
| 0.95 | 仅近似覆盖 | 极少 |
| 0.90 | 强变体 | 偶发于修订文档 |
| 0.85(实验默认) | 多数变体 | 部分政策修订与更正 |
| 0.80 | 更多变体 | 频繁,多数更新被标 |
| 0.75 | 最大覆盖 | 不实用,需持续人工审核 |
正确值取决于摄入模式:仅追加型语料库可设较低阈值,但活跃维基(含版本化策略)不可,因每次合法修订都可能被误判为覆盖尝试。应基于集合实际相似度分布设定阈值(建议平均值加两个标准差),并随集合增长复核。
**这些阈值是嵌入模型的属性,而非数据的属性**——相似度分布跨模型不可比。将`all-MiniLM-L6-v2`替换为`Qwen3-Embedding`或`BGE-M3`后,所有调整的阈值都将在不同几何空间中生效。模型升级会静默废止检测器。应将嵌入模型版本与阈值绑定,将嵌入模型迁移视为重新校准项目。
## 向量并非黑盒
嵌入向量常被视为单向函数:嵌入文本、存储向量后无法仅从向量恢复原始文本。此假设从未在稠密句向量中被证明,只是被视嵌入为“数字”的从业者继承。研究记录表明相反事实:
- **Morris等人《文本嵌入揭示(几乎)与文本等量信息》(EMNLP 2023)** 构建了Vec2Text,通过迭代校正-重嵌入方法**精确恢复92%的32个token输入**,并从临床记录数据集中恢复全名(非片段)。
- **Chen等人《多语言模型的文本嵌入反转安全》(ACL 2024)** 将反转扩展至多语言嵌入空间,发现某些语言暴露风险显著更高。
- **ALGEN(Chen, Xu, Bjerva, 2025年2月)** 消除了昂贵前提:早期攻击需要百万级文本-嵌入对训练反转模型,而ALGEN通过单步线性映射对齐受害者与攻击者嵌入空间,报告**单个样本对即可部分成功,约1000个样本对达到最优**,在多种黑盒编码器上ROUGE-L达46左右(论文单语上限条件达50余),对齐空间余弦相似度约0.95。该技术可跨模型迁移...
相似文章
平均池化余弦相似度不具备长度不变性:针对长度不变替代方案的理论与跨领域证据
本文证明了在表示各向异性条件下,平均池化余弦相似度并不具备长度不变性,表明其会随着序列长度的增加而人为夸大相似度。文章主张将中心化核对齐(CKA)作为默认指标,以纠正跨语言和跨表示分析中的偏差。
比较线性探针与马氏余弦相似度
本文扩展了经验发现:线性探针之间的马氏余弦相似度(MCS)线性预测了分布外AUROC,并在高斯假设下从理论上证明了这一关系。
大小不重要:余弦评分稀疏自编码器
本文提出用余弦相似度与输入幅值的可学习组合替代稀疏自编码器中的内积评分,结果表明所得特征更具可解释性且与概念对齐,优化器始终偏好余弦而非内积。
相似性门控批准反向操作:智能体系统中嵌入余弦阈值的有效性审计
本文对智能体系统中用作质量门的嵌入余弦相似度阈值进行了审计,表明它们衡量的是措辞重叠而非语义。反向操作通过了门控,而无害的改写却常常失败,生产环境中的漂移防护捕获了零个破坏语义的突变,且在所有测试配置下平衡准确率从未超过0.700。
超越余弦相似度:重新思考大语言模型中的层相关性
本文证明,余弦相似度作为评估大语言模型中层重要性的指标效果不佳,并提出使用层移除后实际准确率下降作为更稳健的度量标准。