T
traeai
登录
返回首页
Towards Data Science

嵌入向量并非魔法:RAG检索的可预测失败模式

8.7Score
嵌入向量并非魔法:RAG检索的可预测失败模式

TL;DR · AI 摘要

RAG系统中嵌入向量并非魔法,其失败模式高度可预测:当查询与文档使用不同术语(如“overtime” vs “non-employee labor”)、含否定词、或依赖精确编号/代码时,检索会失效;文章强调企业级可靠性应优先依赖上游过滤(如专家关键词、结构化元数据),而非堆叠重排序器。

核心要点

  • 嵌入模型在处理同义词/拼写变体时表现优异(如‘cancel’→‘termination procedures’),但对术语不一致问题无能为力
  • 4种主流嵌入模型(GloVe-avg, all-MiniLM-L6-v2, ada-002, 3-large)均无法解决语义错位问题,换模型不能根治失败
  • 企业级RAG可靠性提升关键在于上游过滤策略(如关键词标注、文档结构分析),而非仅靠重排序器或LLM微调

结构提纲

按章节快速跳转。

  1. 通过两个对比场景说明RAG初期效果惊艳(支持同义词/语言/拼写容错),两周后暴露核心缺陷(术语不一致、否定词、精确引用失效),指出失败非偶然而是可预测的。

  2. 嵌入本质是将文本转为向量,相似词汇在空间中靠近;当前主流模型(GloVeMiniLM、Ada、3-large)虽有进化,但都缺乏对上下文语义差异的建模能力。

  3. 归纳出三类可预测失败:①术语错位(query用overtime,doc用non-employee labor);②逻辑否定(如‘not allowed’被误匹配);③精确标识符断裂(产品代码→错误层级)。

  4. 作者主张将可靠性投入转向上游——如构建专家关键词库、提取文档结构元数据、做预筛选;重排序器和LLM微调只能缓解,不能根治。

  5. 本篇为《企业文档智能》系列第一卷第二篇,聚焦从基础管道到大规模语料架构的渐进式构建路径,强调工程实践中的可扩展性设计。

思维导图

用一张图看清主题之间的关系。

查看大纲文本(无障碍 / 无 JS 友好)
  • RAG检索的可预测失败模式
    • 失败类型
      • 术语错位
      • 逻辑否定
      • 精确标识符断裂
    • 根本原因
    • 应对策略

金句 / Highlights

值得收藏与分享的关键句。

  • 最接近RAG魔法的东西就在眼前,且无需手写同义词表即可实现——但当文档使用‘non-employee labor’而非‘overtime’时,这种魔法便失效了。

    Scene 1

    ⬇︎ 下载 PNG𝕏 分享到 X
  • 这些失败无法通过更换嵌入模型来修复——失败模式是结构性的,而非算法性的。

    Paragraph 5

    ⬇︎ 下载 PNG𝕏 分享到 X
  • 大多数企业级可靠性提升来自强大的上游过滤(专家关键词、文档结构),而非在弱检索基础上叠加重排序器。

    Paragraph 6

    ⬇︎ 下载 PNG𝕏 分享到 X
#RAG#嵌入#检索#企业AI#文档智能
打开原文

标题:嵌入并非魔法:RAG 检索的可预测失败模式

原文链接:https://towardsdatascience.com/embeddings-arent-magic-the-predictable-failure-modes-of-rag-retrieval-enterprise-document-intelligence-vol-1-2/ 发布时间:2026-05-30T15:00:00+00:00

Markdown 内容:

.

场景 1:一个 RAG 系统部署在几百页政策文档上,供一个小团队使用。

  • 首先令所有人印象深刻的是其对同义表达的处理能力。有人提问 _“我该如何取消?”_,而文档中从未出现过 _cancel_ 这个词,而是使用了 _termination procedures_(终止程序),但系统仍成功找到了相关内容。
  • 另一位用户用法语提问,而政策文件为英文版本,系统依然返回了正确页面;此处拼写错误、那里音近拼写,均无影响。几天后,团队成员真正感到惊叹——RAG 所拥有的“魔法”就摆在眼前,且无需人工构建同义词表即可实现。

场景 2:两周后,同一套系统再次被使用。

  • 用户提问 _“关于承包商加班的规定是什么?”_,系统却回答 _“未找到相关信息。”_。这位用户恰好是撰写该手册一半内容的业务专家,他皱起眉头,打开 PDF 文件,输入 _non-employee labor_ 进行 Ctrl+F 搜索,三秒内便定位到准确段落。问题不在于用户提问方式,而在于文档中实际使用的术语并非 _overtime_,而是 _non-employee labor_。专家清楚这一点,但嵌入模型并未理解。

很快,类似情况陆续浮现:否定句式失效、精确合同编号无法匹配、内部产品代码返回错误层级……这些都不是更换嵌入模型就能解决的问题。

本系列开篇即明确立场:大多数企业级可靠性提升来自于强大的上游过滤机制(如专家关键词、文档结构识别),而非在薄弱检索基础上叠加重排序器。

传统架构按成本从低到高排列如下:

  • 底层为廉价的嵌入相似度计算;
  • 中间可选加入交叉编码器重排序器;
  • 最顶层为对话生成大语言模型(LLM)。

它们均非“魔法”,各自都有特定的失效路径。

本文是更广泛系列 《企业文档智能 Vol. 1》 的一部分,该系列将从基础流水线逐步构建至大规模语料库级的 RAG 架构。

1. 嵌入模型真正擅长之处 [](file:///C:/Users/shike/Documents/Github/rag/book/02_embeddings.html#what-embeddings-nail)

在讨论失败之前,我们需先了解嵌入模型的实际优势——只有通过对比,失败才显得合理。

嵌入模型将一段文本转换为向量表示。具有相似 词汇 的文本,在向量空间中彼此靠近。

嵌入是一组数字列表,用于捕捉文本的语义信息:长度越长,所承载的细微差别越多。随着模型迭代,嵌入质量持续提升。下述所有案例均基于同一组四款模型(由弱到强):

加载各模型仅需一行代码。本地模型来自 sentence-transformers(首次调用时从 HuggingFace 下载权重并缓存至本地磁盘),而 OpenAI 模型则通过 API 调用。四种模型接口一致,均返回对应维度的向量:

code
from sentence_transformers import SentenceTransformer
from openai import OpenAI

# 本地模型:从 HuggingFace 下载权重,进程内运行。
glove  = SentenceTransformer("average_word_embeddings_glove.6B.300d")  # 2014, 300-dim
minilm = SentenceTransformer("all-MiniLM-L6-v2")                       # 2021, 384-dim

# OpenAI 模型:通过 API 调用。
client = OpenAI()
def openai_embed(text: str, model: str) -> list[float]:
    return client.embeddings.create(input=text, model=model).data[0].embedding

# 四种模型接口统一,各自返回对应维度的向量。
v_glove  = glove.encode("policy renewal")
v_minilm = minilm.encode("policy renewal")
v_ada    = openai_embed("policy renewal", "text-embedding-ada-002")   # 2022, 1536-dim
v_large  = openai_embed("policy renewal", "text-embedding-3-large")   # 2024, 3072-dim

每种模型拥有独立的向量空间与余弦分布,因此跨列原始得分不可比。真正有意义的是单列内的 分离程度:目标项是否显著优于干扰项?观察这一差距随模型增强而扩大,即是嵌入性能真实提升的实证证据。

下方所有对比表格均采用相同基准:分别用四种模型对查询语句和候选文档进行嵌入,以余弦相似度打分,并为每个候选项生成一行结果:

code
def _cos(u, v):
    """余弦相似度:两向量点积除以其模长乘积"""
    return float(np.dot(u, v) / (np.linalg.norm(u) * np.linalg.norm(v)))
python
def compare_models(query, candidates, target=None):
    qg = glove.encode(query)
    qm = minilm.encode(query)
    qa = openai_embed(query, "text-embedding-ada-002")
    ql = openai_embed(query, "text-embedding-3-large")
    rows = []
    for c in candidates:
        rows.append({
            "candidate": c,
            "GloVe-avg":  _cos(qg, glove.encode(c)),
            "MiniLM":     _cos(qm, minilm.encode(c)),
            "ada-002":    _cos(qa, openai_embed(c, "text-embedding-ada-002")),
            "3-large":    _cos(ql, openai_embed(c, "text-embedding-3-large")),
        })
    return pd.DataFrame(rows).set_index("candidate")

1.1 概念接近性

car(汽车)会匹配关于 vehicles(车辆)、automobiles(机动车)、motor vehicles(机动车辆)的段落;fire damage(火灾损害)能检索到 smoke damage(烟雾损害)和 scorching(灼烧)相关内容;manager approval(经理批准)则与包含 executive approval(高管批准)条款的条文相匹配。模型捕捉的是语义场,而不仅仅是表面词汇。这正是嵌入表示令人感到强大的原因:用户无需猜测文档中的术语体系;嵌入模型自动弥合了这一差距。

Image 1

*非正式查询可通向正式改写表达。所有四种模型均选中目标项;更大规模模型进一步拉大了与目标项的差距 —— 作者供图*

1.2 同义词与改写表达

Phone number(电话号码)匹配 telephone(电话);Policy cancellation(保单取消)对应标题为 termination procedures(终止程序)的章节;Fee(费用)匹配 charge(收费);Monthly cost(月度成本)匹配 premium(保费);Expiration(到期)匹配 policy end date(保单截止日期);Doctor(医生)匹配 physician(医师),lawyer(律师)匹配 attorney(律师),car(汽车)匹配 vehicle(车辆)。无论是单字还是多词复合结构,模型都已学会识别不同词汇表达同一含义——包括用户日常口语与文档正式语言之间的差异。这种映射并非人工硬编码。

测试场景:以查询 what is the monthly fee(每月费用是多少?)对比三个候选项——一个同义词目标项(A flat charge of $9.99...,即“固定收费9.99美元……”),一个仅因共享关键词 monthly 而产生字面重叠的干扰项(Premium payments are due monthly...,即“保费按月支付……”),以及两个无关干扰项。

Image 2

*查询“monthly fee”。三种模型均将 fee ↔︎ charge 关联起来;唯独 GloVe 误选了字面重叠干扰项 —— 作者供图*

仅有 GloVe-avg 被字面重叠干扰项误导。 句子级编码训练(早在2021年的 MiniLM 中已引入)才是实现真正同义处理的关键。若无此能力,只要候选项只是以任意顺序重复查询中的词元,它就可能胜出;而有了句子级训练后,模型即使在 feecharge 完全无共用字母的情况下,也能建立二者间的语义关联。此外,查询采用疑问句式(what is the monthly fee),而目标项为陈述句式(A flat charge of $9.99...),正是同义处理能力在此处发挥了决定性作用。但请注意,最终答案本身(例如仅输出 $9.99 这个数字,或对是非题回答 Yes)是否能胜出,并不必然取决于模型强度;第2.2节将对此进行直接验证。

1.3 拼写错误与笔误

insurence(拼错的 insurance)仍能靠近 insurance(保险)的嵌入空间;polciy(拼错的 policy)依然可定位到保单相关章节;deductable(拼错的 deductible)即便元音错误,仍能命中扣除额页面;法语词 resiliation 若省略重音符号(即 resiliation),也仍能与标准形式匹配。现代嵌入模型是在大量网络抓取文本上训练而成,其中此类拼写错误频繁出现,因此它们已学会有效吸收这类噪声。

Image 3

*拼写错误的查询。GloVe 的余弦相似度降至负值;从 MiniLM 到 3-large,与目标项的差距逐步扩大 —— 作者供图*

请关注得分差值而非绝对分数。GloVe-avg 对拼写错误毫无概念;拼写错误的词元属于未登录词,其嵌入会坍缩,导致余弦相似度变为负数,排序基本随机。而 OpenAI 模型则能干净利落地处理这些拼写错误。字符级鲁棒性真实存在,并且随模型容量提升而增强。

1.4 跨语言匹配

多语言嵌入模型将 premium(保费)、prime(首期费)、Prämie(德语:保费)置于相近的向量空间区域;同样地,deductible(免赔额)/ franchise(自付额)/ Selbstbeteiligung(德语:自付额),claim(索赔)/ sinistre(法语:事故)/ Schadensfall(德语:事故事件)亦如此。一个法语关键词可检索到英文文档中描述相同概念的内容。对于拥有混合语言语料库的企业(如法语合同、英语信函、德语保单细则),当该功能生效时,其价值尤为显著;而在现代模型中,这种情况通常都能实现。

Image 4

*法语查询针对英文候选项。GloVe 与 MiniLM 表现吃力;ada-002 与 3-large 则能流畅跨语言匹配 —— 作者供图*

GloVe 完全失效:它选择了 Coverage limit: $50,000 per year.(保障限额:每年5万美元),而非 Annual premium: $1,200.(年保费:1200美元),因为法语 annuelle(年度)在其平均词向量空间中与 year(年)形成 lexical association,且它根本不知道 prime 就是 premium 的意思。MiniLM 理论上选中了目标项,但余弦相似度仅约 0.12,几乎等同于随机噪音。而 ada-002 与 3-large 是通过多语言训练构建的(类似 BGE-M3 和 multilingual-e5),能够干净利落地完成法语到英语的语义桥梁搭建。此处的选择并非“向量 vs 关键词”,而是“多语言向量模型 vs 单一语言模型”。

1.5 复合多义性

多义词具有多种含义,上下文可对其进行消歧:

code

*   `bank`(银行 / 河岸)  
*   `claim`(保险事件 / 声称)  
*   `store`(动词:存放 / 名词:零售店)  
*   `green card`(移民文件 / 一张绿色的卡片)  
*   `hot dog`(食物 / 一只热狗)  

当候选词在错误语境下使用了字面含义时,强嵌入模型仍应能选出语义正确的解释。这也正是**弱模型中“字面词元偏见”**表现得最明显之处:GloVe-avg 无法区分复合词的两种含义,而是选择与查询共享最多词元的候选项。句子编码器则逐步恢复正确语义,但其恢复程度取决于该复合词在训练数据中是否常见。

我们测试了两个复合词,先易后难。

**首先,`green card`,即简单情形。** 移民相关含义在训练语料库(新闻、法律文本、维基百科等)中被大量标注,因此即便是 MiniLM 也能正确解析该复合词。测试设置为:查询 `green card`,并给出三个候选项——一个是对移民文件的改写(TARGET,零个共享词元),一个是在游戏语境中同时以字面意义包含 `green` 和 `card` 的句子(陷阱),以及一个无关干扰项。

![Image 5](https://contributor.insightmediagroup.io/wp-content/uploads/2026/05/image-310-1024x408.png)

_“green card”与移民文件改写句 vs 游戏陷阱对比。仅 GloVe 掉入陷阱 —— 作者制图_

**仅有 GloVe 掉入陷阱。** 词元平均模型完全不了解“green card”作为复合词特指移民事务这一事实;它们只看到两个词元,寻找共享这些词元的候选项,于是游戏陷阱胜出。MiniLM 已经足以扭转局面,因为其句子级训练捕捉到了机构性含义;ada-002 以明显优势选择了 TARGET;3-large 则以更宽裕的优势做出判断。这类多义性正是嵌入模型擅长处理的情形,因为公共网络已将该复合词的用法广泛传播。

**接下来是 `hot dog`,即困难情形。** 相同结构设定(一个同样具有字面含义的复合词),但字面含义(一只热狗)在训练文本中同样被大量标注。模型已见过大量关于炎热天气与狗的句子。食物含义与字面含义势均力敌,而弱模型和中等规模模型的“字面词元偏见”最终占了上风。

![Image 6](https://contributor.insightmediagroup.io/wp-content/uploads/2026/05/image-311-1024x368.png)

_“hot dog”与食物改写句 vs 字面词元陷阱对比。唯有 3-large 能清晰地化解多义性 —— 作者制图_

这是第 1 节中模型梯度提供最大帮助的场景。**GloVe-avg、MiniLM 和 ada-002 全部掉入陷阱。** 它们不顾语义错误,仅凭共享的 `hot` + `dog` 词元就做出了判断。这种现象在第 1.2 节中 GloVe 上已初现端倪(如字面 `monthly` 词元压倒了 `fee ↔︎ charge` 的近义关系)。复合词多义性正是此类问题的极端情况:查询中的字面词元**看似**出现在干扰项中,连 ada-002 都无法分辨两种含义。**只有 3-large 实现了恢复:** 即使 TARGET 与查询零词元重合,它仍以显著优势选择了食物改写句。

**因此,对您的语料而言,关键问题并非“是否存在多义性”,而是“我所拥有的多义性有多‘制度化’”。** 一份保险语料中存在大量复合词多义性,却未出现在公共训练分布中(例如工作流中的动词用法 `claim handling`,或风险分摊工具 `pool`)。对于这类情况,即便 ada-002 的表现也如同 GloVe 在 `hot dog` 上的表现。2024 年级模型才是现实可行的解决方案;其余模型则聚焦于结构性改进。

### 1.6 这些成功案例真正说明了什么,又未说明什么[](file:///C:/Users/shike/Documents/Github/rag/book/02_embeddings.html#what-these-wins-really-show-and-dont)

本节词汇有一个共同点:它们都属于**公开领域**。模型在数百万份训练文档中已见过 `green card ↔︎ permanent resident card`、`prime ↔︎ premium`、`polciy → policy` 等对应关系。嵌入模型之所以能良好处理这些内容,是因为其权重中已固化了这些等价关系。学界所称的模型**参数记忆**(即无需检索即可“知道”的知识部分)在此类任务中承担了主要工作。

值得提前指出两点影响:

**1. 对于这些情形,您或许根本不需要 RAG。** 向 GPT-4 提问:“green card 的别名是什么?”即可直接获得答案,无需检索。模型的参数部分早已掌握该知识。RAG 的价值恰恰体现在参数部分无法覆盖的领域:那些未出现在公共网络上的事实、无法泛化的合同条款、模型从未接触过的内部产品编码等。第 1 节采用的是广为人知的词汇,因此演示可复现且表述清晰。但在实际生产环境中,RAG 并非用于回答这类问题。

**2. 第 1 节的成功经验无法直接迁移到企业级词汇体系中。** 一家保险公司拥有诸如 `ShieldPro Elite`(产品层级)、`pool`(风险分摊工具,而非游泳池)、`non-employee labor`(合同中对“承包商”的特定表述)、监管引用如 `Solvency II Article 7` 等术语。这些内容均未进入模型的训练分布。面对企业专有术语,嵌入模型会像 GloVe 在 `hot dog` 上那样失效,因为其需要恢复的机构性含义,在公司外部并无统一规范。

解决之道并非依赖更大的嵌入模型,而是引入**熟悉该术语体系的专家**,将其知识编码为关键词典(第 3.3 节详述此方法)。第 2.1 节通过 `pool` 示例具体呈现了此类失败情形。

第 2 节系统梳理了嵌入模型的结构性缺陷。请带着以下认知阅读:在企业级语料中,上述所有问题皆属常态,而非例外。

第1节中所述的能力是真实存在的;而下文所列的失败同样真实、可重复,并且在所有四个模型中均持续存在。更大的模型并不会改变这一排名顺序。问题的根源在于架构设计,而非“选择一个更强的嵌入模型”。

第1.6节已明确指出显而易见的反例(“对于这类情况,直接向大语言模型提问即可”)。然而,在语料库规模下,这种方法无法扩展:一个包含20万份文档的语料库不可能在每次查询时都通过大语言模型进行处理。因此,必须先进行检索步骤。主流流程通常在嵌入层与大语言模型之间加入重排序器(reranker);本系列文章的答案则是通过专家关键词和文档结构进行上游过滤(详见第6、7、9章)。无论如何,下文所列举的失败现象均发生在嵌入阶段。**这些层级中没有任何一个是魔法。**

### 2.1 最简单的失效:该词未出现在模型中[](file:///C:/Users/shike/Documents/Github/rag/book/02_embeddings.html#the-simplest-break-the-term-isnt-in-the-model)

在结构性失效之前,最基础的一种失效形式。第1.6节已用文字描述过它。以下是演示案例。

以 `pool` 为例:在保险合同中,`pool` 是一种风险共担工具——由一组被保险人组成,通过汇总保费共同承担损失;而在日常英语中,`pool` 指的是人们可以游泳的水体。同一个词具有两种含义,其中一种截然不同:游泳义项在公共网络上随处可见;而风险池义项则深藏于精算教科书、监管文件及再保险协议之中,模型在训练期间几乎未曾接触过这些内容。

测试方案模仿了第1.5节中的热狗(hot-dog)设置,但增加了一个关键变化:直接查询裸词 `pool`。候选答案包括三类:  
- 一种关于游泳的同义改写(公共义项,句中无 `pool` 字符);  
- 一种使用真实行业术语的再保险相关改写(专业义项,同样不含 `pool` 字符);  
- 一句随机控制句(关于火车发车时间),既不含 `pool`,也无保险或游泳关联。

![Image 7](https://contributor.insightmediagroup.io/wp-content/uploads/2026/05/image-312-1024x431.png)

_查询 `pool`。在三种模型中,再保险义项排名低于随机控制句 —— 作者制图_

游泳义项在所有模型中均大幅胜出(余弦相似度介于0.353至0.843之间,具体数值依模型而异)。而使用真实行业术语撰写的再保险义项,**在四种模型中有三种排名低于随机的火车时刻表控制句**。即便是 ada-002——当前企业级RAG部署中最常用的模型——也将火车时刻表排在专业句子前0.010。仅有 3-large 在控制句基础上获得0.006的微弱提升,远在测量误差范围内。

这是最直接的失效模式:嵌入空间根本未编码 `pool` 的专业义项。即使在其之上叠加重排序器也无济于事,因为重排序器重新评估的候选结果本身已是噪声数据。更大的嵌入模型亦无法解决此问题,因为见过百万次“游泳池”的模型,与仅见过约百次“再保险池”的模型,仍将优先赋予“游泳”义项更高的权重。

事实上,`pool` 属于一种**软性** OOV(Out-of-Vocabulary)情形:游泳义项与风险义项共享同一语域,而 3-large 已能捕捉到部分信号。更严峻的情形则是严格 OOV 术语:如虚构产品线 `ShieldPro Elite`、真实法规引用 `Solvency II Article 7`、内部产品代码 `ZRX-2025` 等。对这些词汇,嵌入模型完全缺乏锚点,将其视作随机字节串;将其与其他文本进行排序,本质上是一场受分词特性影响的“抛硬币”游戏。

解决方案是引入**熟悉该领域术语的专家**,并将其知识编码为关键词字典。第3.3节将详细展开该工作流程。

第2节其余部分将探讨即便该词存在于模型中,仍会出现结构性失效的情形。`pool` 案例属于最先出现的简单失效类型。

### 2.2 结构性失效:词语相似性,而非答案相关性[](file:///C:/Users/shike/Documents/Github/rag/book/02_embeddings.html#the-structural-break-term-similarity-not-answer-relevance)

第2.1节讨论了该词根本不在模型中的情形;而本节其余部分则聚焦于该词确实在模型中,但嵌入结果依然错误的情况。这些失败具有共同的结构性根源:**嵌入模型仅依据词语相似性对文本进行排序,根本不建模问题与答案之间的关系。** 两个最简单的提问方式可使这一点更加清晰具体——它们并非企业级边缘案例,而是世界上最普遍的问题类型。

![Image 8](https://contributor.insightmediagroup.io/wp-content/uploads/2026/05/image-313-1024x428.png)

_是非问题。裸词 `Termination` 在所有模型中均压倒实际答案 “Yes” —— 作者制图_

“是”才是是非问题的正确答案,但它从未获胜。真正胜出的是查询中名词的字面复现。从2014年到2024年的所有模型均如此。

**值得特别指出的一个细节**:尽管该失效看起来严重,但在实际应用中危害反而较小。对于是非问题,我们真正需要的并非单词 “yes”,而是支撑该结论的相关证据——即规则所在的页面。最终由答案阶段的大语言模型基于这些证据生成 “yes/no” 回答。因此,若检索阶段返回的是与主题相关的匹配项(如 `Termination` 或 `Termination may be required.`),而非字面匹配的 “Yes, it is possible.”,其行为反而更贴近理想预期。本文反复强调的核心原则在此再次显现:**检索阶段并非答案阶段,二者必须分离,并作为两个独立步骤分别优化。** 第6、7、8章将进一步阐述这种分离策略。

在下一个例子中,检索任务确实需要找到承载答案的具体句子,此时失效表现得更为尖锐。

现在来看世界上最简洁的事实性问题:“法国的首都是什么?”互联网上,“巴黎是法国首都”这句话已被反复提及数百万次。如果问答映射关系能在任何嵌入空间中体现,那么此处便是最可能显现的位置。

![Image 9](https://contributor.insightmediagroup.io/wp-content/uploads/2026/05/image-314-1024x387.png)

_查询“法国的首都是什么”。巴黎从未获胜;与“首都”或“法国”共享短语的干扰项(topic-decoys)总是胜出——作者供图_

巴黎从未排名第一。在四种模型中的三种(GloVe、ada-002、3-large)中,胜出者是“意大利的首都”,该候选答案与查询共享了“首都”这一字面短语。而在MiniLM模型中,胜出的是另一个干扰项:“法国位于欧洲。”,因为它与查询共享了“法国”这一词元。尽管干扰项不同,但其根本原因一致:主题相似性,而非答案相关性。从2014年300维的bag-of-words模型升级到2024年3072维的OpenAI模型,并未改变这一陷阱。对于事实性问题,检索系统本应获取包含答案的那一行文本;然而,所有模型均选择了在主题上与查询最匹配的句子。

**第二个值得命名的细微差别。** 现代嵌入模型在问答-段落对(如MS MARCO、Natural Questions、BEIR数据集)上进行训练。这确实会将承载答案的段落略微拉近至其所回答的问题。这种偏差确实存在,但程度较弱。在高度通用的事实性问题上,它有时会导致决策反转;而在训练中未曾见过的专业词汇(如内部产品代码、专家术语、合同用语)上,该偏差则完全消失。此时,主题相似性再次占据主导地位。

下文将从四个具体失败形态(否定、数值大小、主题邻近性、信号稀释)及常见案例调查出发,系统性地归纳这一根本原因。每一种情形都体现了同一机制在不同查询类型上的应用。

### 2.3 否定(Negation)

否定性问题将逻辑关系彻底颠倒:用户希望获得的是与主题**互补**的候选答案,而非与主题**最接近**的候选答案。而嵌入模型无法实现这一点;它们衡量的是主题邻近性,而非逻辑上的补集关系。测试越严格,失败表现就越清晰。

查询:“什么是**不是**城市?” 四个候选答案中,三个为真实实体(两个具体城市 + 字面意义上的“City”),一个为“Table”——一个平凡物体,恰好是唯一能正确回答该问题的选项。

![Image 10](https://contributor.insightmediagroup.io/wp-content/uploads/2026/05/image-315-1024x348.png)

_查询“什么是 NOT 一个城市?”。所有模型都将正确答案排在最后;否定关系在嵌入空间中几乎完全不可见——作者供图_

所有模型以相同方式失败:与主题匹配的候选答案(“City”、“Paris”、“New York”)位居前列,而真正正确答案“Table”却排在最后。查询词“NOT”在嵌入空间中几乎不携带任何有效信号:嵌入模型仅将其视为一个包含“city”的词袋,并据此将所有与“city”相关的项排在非相关项之前。解决之道并非依赖更强的嵌入模型,而是需在问题解析阶段识别出否定关系,并在检索前将其反向处理(参见第6节)。

**“当然,但现实中没人会写否定式查询。”** 这是一个合理质疑,但在实际部署中很快就会失效。用户并不会直接提问“什么是 NOT 一个城市?”;他们更可能问“这份保单的保费是多少?”——系统却错误返回了“免赔额”(deductible)。用户感到沮丧,自然会修正查询:“我想要的是保费,而不是免赔额。”——第二次查询本质上就是一次否定表达,而这正是真实企业用户实际书写否定句的时刻。

人类读者本能地将“not”理解为排除操作;而嵌入模型却恰恰相反。即使在查询中添加“not”前缀并加入“deductible”,嵌入模型仍会将含“deductible”的文档拉得更近,而非更远。用户的修正反而使错误比原始查询更加严重。

这正是本节反复强调的核心原则:**原始问题从来都不是检索器的合适输入。** 解决方案应在上游——即问题解析阶段:识别否定关系,将其从原文中剥离出来,编码为结构化的排除过滤器,并在检索之后、而非与其余查询内容一同嵌入时应用。第3.2节和第3.3节将回到此点,提出积极版本:检索器实际接收的应是结构化表示(关键词、过滤条件、排除项),而非用户自由表述的句子。

### 2.4 数值与阈值(Magnitudes and thresholds)

数值比较、日期、合同金额、账户余额等一切依赖于具体数值本身的问题皆属此类。以简化版为例:查询“找出大于1M的数值”,四个候选均为纯数字。

![Image 11](https://contributor.insightmediagroup.io/wp-content/uploads/2026/05/image-316-1024x348.png)

_查询要求“值 > 1M”。所有模型均选择“1M”;“3B”作为唯一正确答案,却排在最后——作者供图_

所有模型均选择“1M”,即与阈值相等但并未严格大于它的候选答案。胜利纯粹源于字面匹配:查询中出现了“1M”这个词元。而真正正确的答案“3B”(唯一满足“>1M”条件的选项),在ada-002与3-large模型中均排在第四位(即最后一名)。嵌入模型完全不具备对数值大小的概念;它仅看到“1M”与“1M”相邻,便判定其胜出。

这一现象可推广至所有涉及数值比较或阈值判断的问题:货币门槛、日期范围(如“2020年后”)、持续时间(如“超过30天”)、计数等。嵌入模型天生就不擅长这类任务——它们将意义压缩为稠密向量,而其中最具区分力的信号(即数值本身或用于筛选数值的操作符)恰恰正是压缩过程所摧毁的部分。解决方案已广为人知:使用BM25或全文索引完成字面匹配,再辅以问题解析步骤,将操作符与阈值提取为结构化字段(参见第6节),以便下游过滤器执行精确比较。

“谁签署了合同?”语料库中有一段文字描述了合同必须如何签署(授权代表、签名要求),还有一段文字则包含了实际的签名内容(“签署人:约翰·史密斯,市场总监,日期:2025年3月15日”)。第一段文字只是**谈论**签署过程;而第二段文字**就是**实际的签名。那么,哪一段更胜一筹?

![图12](https://contributor.insightmediagroup.io/wp-content/uploads/2026/05/image-317-1024x368.png)

_“谁签署了合同?”——关于签署流程的说明性段落压倒了实际的签名行 —— 作者供图_

这是模型梯度无法修复的结构性缺陷。**嵌入相似度衡量的是主题上的接近程度,而非问题与答案之间的对应关系。** 一篇仅**谈论**某主题的页面,往往比一篇**直接回答**该主题相关问题的页面得分更高。定义性内容优于具体数值;背景介绍优于结论;程序性描述优于其所描述的具体实例。

在四个模型中,有三个确认了这一模式(GloVe、ada-002、3-large),MiniLM 是例外:其句子对训练方式使具体答案表述的得分略高于程序性密集表述。其他三个模型中的该模式稳定存在,并在我们尝试过的大多数事实型问题与程序型问题配对中得以复现。

### 2.6 长上下文中的信号稀释[](file:///C:/Users/shike/Documents/Github/rag/book/02_embeddings.html#signal-dilution-in-long-context)

前述测试中使用的候选文档长度大致与查询相当。但真实语料库中的页面并非如此。真实页面通常包含 300–500 个单词,信息密集,其中针对特定问题的答案可能仅隐藏于中间某一句中。当整页内容被嵌入为一个单一向量时,那句承载答案的句子所携带的信号会被周围所有其他内容平均掉,导致页面级嵌入逐渐偏离噪声中心,趋向于整体的平均值。

最清晰的观察方式是进行单变量实验:固定答案句不变,向前添加越来越多的无关办公生活类句子(如办公时间、停车规定、人力资源模板等,均不涉及免赔额或水损相关内容),然后评估其与一个固定对照项的匹配度。该对照项与查询无任何具体词汇重合,仅共享同一保险/理赔领域的宽泛术语。

*   查询:`water damage claims 的免赔额是多少?`
*   答案(可变):`对于水损索赔,标准免赔额为 500 美元。`  
    前置 N ∈ {0, 1, 2, 4, 8, 16} 句无关句子
*   对照(随 N 不变):`索赔须附带照片、维修估价单及适用情况下的警方报告。`

![图13](https://contributor.insightmediagroup.io/wp-content/uploads/2026/05/image-318-1024x632.png)

_答案信号 vs 噪声:在答案前添加无关句子后,所有模型中答案得分均急剧下降 —— 作者供图_

每个模型都在不同时间点失效,但最终全部失败。GloVe 因词袋平均机制,在仅加入一句无关内容后即迅速被噪声拖拽;MiniLM 能坚持到四句后才因句子编码器表示失效;ada-002 和 3-large(均为 2022 年后 OpenAI 训练的问答对模型)表现最长,但当候选文本达到 144 词(八句无关句子)时,正确答案已排在完全不含 `deductible`、`water` 或 `damage` 这些关键词的候选项之后。**将 300 词长的页面嵌入,本质上就是“答案 + 16 句噪声”的生产版本。**

这正是为何许多以页面级嵌入为核心的生产管道即便答案确实在页面上,仍常常漏掉正确文档的原因:页面向量将一两句话的答案信号与 300–500 词的主题噪声混合平均。**第 3.1 节提出的解决方案是架构层面的修正:应逐行嵌入,而非逐页嵌入。** 仅在生成阶段需要上下文时,才将多个行向量聚合为页面向量。这样一来,即使在嘈杂页面中,真正承载答案的那一行也能再次被有效检索出来,因为其嵌入不再与其他内容混杂平均。

### 2.7 明显情形(无需演示)[](file:///C:/Users/shike/Documents/Github/rag/book/02_embeddings.html#the-obvious-cases-no-demo-needed)

某些查询类型会以如此明显的方式破坏嵌入效果,以至于四模型对比只会重复相同结果。此处列出它们是为了完整性,并进一步强调一个核心观点:**没有任何嵌入升级能挽救这类问题。** 解决方案需前置处理(如问题解析,参见第六章),或依赖其他工具(如 BM25、元数据过滤器、聚合流水线)。

*   **未登录词标识符与内部行话**:合同引用(`Section 4.2.1`)、法规条文引用(`GDPR Art. 17.3`)、发票编号、工单ID、内部产品名称(`ShieldPro Elite`、`SAP-MRP`、`KPI-Q4-V3`)。嵌入模型将它们视为不透明的序列,无法从语义层面对其进行排序。解决方案:对查找操作采用 BM25 或精确匹配索引,并辅以一个术语映射表(glossary),将别名映射到标准术语(如 `ShieldPro Elite` → 高端家庭计划),并将其作为专家关键词维护(参见第6节)。
*   **布尔逻辑组合**:例如,“由爱丽丝审阅但未由鲍勃审阅的文档”、“包含损坏信息且有证人的索赔”。词袋平均法会抹除逻辑运算符。解决方案:将问题解析为结构化过滤条件(参见第6节),并在检索后应用该条件。
*   **计数与聚合操作**:例如,“爱丽丝签署了多少份合同?”、“列出所有开放的索赔”。嵌入模型仅返回最相似的一段文本;而计数类答案则需要全量扫描或在索引上执行类似 SQL 的查询。解决方案:将此类请求路由至聚合处理管道(参见第15–20节)。
*   **时间谓词**:例如,“最新版本”、“2020年后提交的索赔”、“12月前到期的保单”。嵌入模型无法表达时间顺序。解决方案:在问题解析阶段提取时间过滤条件,并将其作为元数据过滤器应用于索引。
*   **多跳推理**:例如,“签署合同 X 的人之经理是谁?”每一步都是一次独立的检索;而嵌入模型仅提供一次机会。解决方案:采用代理式链式调用,或在经过适当索引的语料库上进行图遍历。

上述模式具有一致性。当嵌入模型明显失效时,答案通常并非“购买更大规模的嵌入模型”,而是“将查询从嵌入路径中剥离出来,转而使用更合适的工具”。

### 2.8 页面级同样存在相同缺陷(真实文档)

上述四种缺陷已在手写候选样本中得到验证,当检索过程以页面为单位作用于真实文档时,这些缺陷依然原样重现。我们将《Attention Is All You Need》(Vaswani 等,2017;arXiv 非独占分发许可,详见 [arXiv 摘要页](https://arxiv.org/abs/1706.03762);共15页)的每一页分别嵌入,并针对三个问题展开测试;每个问题均在页面粒度下暴露出一种不同的排序异常现象。

**各结果所揭示的问题如下:**

*   **Q1,勉强胜出。** 三页之间的相似度仅相差0.01;正确页面(第7页,Adam学习率公式所在处)以0.007的优势胜出。这本质上是运气使然,而非检索能力所致。属于第2.5节(主题邻近性)与通用排名脆弱性的叠加效应。
*   **Q2,前3名救场。** 第8页优于第9页,但答案(表3中 `d_k` 行的消融实验结果)实际位于第9页。前3名足以覆盖此情况;若仅依赖第1名,则可能无声失败。与第2.4节(数值表格内精确值)的问题同源。
*   **Q3,彻底失败。** 正确答案页(第8页,`ε_ls = 0.1` 所在处)完全落选前3;反而是第15页(含大量公式中出现 `ε` 符号的示例句)意外进入前三。这是第1.5节(复合多义性)在 `ε` 上的体现:嵌入模型无法区分第7页中 Adam 优化器的 `ε`、第8页中标签平滑的 `ε_ls`,以及第15页中无关公式的 `ε`。

同一类缺陷在真实文档尺度下被放大呈现。其解决方法与第3节所提出的方案一致。

## 3. 如何真正加以利用

第1节展示了嵌入模型所能展现的优势;第2节则指出了其失效之处,根源可归结为两点:一是词汇本身未出现在模型中(第2.1节),二是词汇虽存在于模型中,但其语义相似性并不等同于答案相关性(第2.2节及之后)。在此基础上,自然引出下一个问题:在实际生产环境中,我们应如何有效运用嵌入模型?

本节分为四部分:**第3.1节**:建立正确的认知模型(即逐行容忍同义词的搜索);**第3.2节**:弥合问题与答案之间鸿沟的关键技巧,并非单纯依赖嵌入,而是聚焦于提取答案中必然包含的关键词;**第3.3节**:一套面向生产的流程,通过专家参与发现语料库中的词汇体系,将其编码为关键词字典,再基于该字典开展精准检索;**第3.4节**:情感密集型语料(如人力资源反馈、客户调研、客服工单)的特殊情形,其中相同的发现机制同样适用于情感词汇的识别与建模。

### 3.1 重新定位视角:逐行同义词容错搜索

理解嵌入模型最简单的方式是将其视作:**向量搜索本质上是一种能处理同义词、拼写错误及其他语言变体的关键词搜索,且逐行执行**。它并非魔法,也不代表“整页语义理解”。在单行文本中,模型会将 _cancel_ 与 _terminate_ 视为相近;将 _polciy_ 自动修正为 _policy_;还能跨越语言实现 _prime_ 与 _premium_ 的关联。第1节中所有成功案例皆源于此原理。

然而,若将整页内容压缩为单一向量(如第2.6节所示),则某一行的优质信号会被其余内容稀释,导致关键行被淹没在以其他主题为主的页面中。因此,应逐行嵌入——仅在生成阶段需上下文时,才将多行聚合为页面级别表示。

尽管如此,页面级嵌入仍具其适用场景:当单行中完全缺失关键词(如整页讨论车险却从未提及“car insurance”)、当主题由周边词汇隐含(如医疗文档提及 A1C / 胰岛素 / 血糖但未直接出现 _diabetes_)、当文体或语域至关重要,或标题泛化(如“Notes”、“Section 5”)时。除此之外,逐行嵌入几乎总能取得更优效果。

下方的演示实例以一篇真实论文为例,使概念更加具体化。前几节中我们嵌入了少量手写候选内容;而此处则对《Attention Is All You Need》这篇论文(共15页、约1000行)的每一条文字都进行了嵌入,并通过一个简短的关键词锚点进行检索。返回的Top-K结果为匹配的文本行,附带其所在页码与行号。你可以逐条阅读每个匹配项,并直观看到它为何被选中——锚点中的关键词或清晰的同义表达就直接出现在原文中。

在 pandas 和 numpy 的基础上仅需五步操作:对查询语句进行编码、将各行嵌入向量堆叠成矩阵、批量计算余弦相似度(单次矩阵乘法)、按相似度排序、返回 Top-K 结果。无需向量数据库、无需框架、无需基础设施支持。“向量存储”仅由 DataFrame 的一列加上一个 numpy 点积运算构成。

def top_lines_for(question: str, line_df: pd.DataFrame, k: int = 10) -> pd.DataFrame: """根据与 question 的余弦相似度对所有行进行排序,并返回 Top-k 结果。""" q_vec = get_embedding(question, client=client) line_matrix = np.vstack(line_df["embedding"].values) sims = line_matrix @ q_vec / ( np.linalg.norm(line_matrix, axis=1) * np.linalg.norm(q_vec) ) return ( line_df.assign(similarity=sims) .nlargest(k, "similarity")[["page_num", "line_num", "similarity", "text"]] .reset_index(drop=True) )

code
![Image 14](https://contributor.insightmediagroup.io/wp-content/uploads/2026/05/image-320-1024x876.png)

> **“multi-head attention” 的 Top 10 匹配行**:来自第1、4、5、10页的同义表达与字面匹配结果 —— 作者绘制

**从该行级演示中可总结出两点关键启示。**

**1. 匹配的行段落本身即说明了其为何被选中。** 没有神秘机制,也没有排名不透明的问题。每一个Top结果要么包含锚点关键词,要么是该词的明确同义改写。这正是行级嵌入的核心价值所在:一种模糊且容忍近义词的“Ctrl-F”式文档搜索。

**2. 匹配的行只是“锚点”,而非直接送入生成模型的上下文片段。** 这一行是一个小型、可被检索器精准定位的实体;而真正送往大语言模型(LLM)的通常是更大范围的内容——例如其所在的段落、章节,甚至整页内容。文章第7节进一步将其发展为两阶段模式:首先在行级、关键词级或结构级层面识别锚点,再根据问题需求,在每个锚点周围选取合适的上下文片段。**目标性检索 = 小规模 N 围绕一个精确锚点**,而非一次性向 LLM 投掷30篇模糊文档。

### 3.2 HyDE:搜索答案应包含的内容,而非问题本身  
([链接](file:///C:/Users/shike/Documents/Github/rag/book/02_embeddings.html#hyde-search-what-the-answer-would-contain-not-the-question))

第2.2节已表明,嵌入向量并不理解问题本身,它们只关注词项之间的相似性。自然的应对方式便是:停止将原始问题输入检索器,转而输入一段**看似答案的文本**。这就是 **HyDE(Hypothetical Document Embeddings)** 的核心思想——撰写(或让 LLM 自动生成)一句“合理回答该问题”的句子,且使用文档中可能出现的词汇体系,随后对这一“假设答案”进行嵌入,再由检索器将其与语料库比对。

人们普遍强调 HyDE 的优势在于嵌入侧:“重写后的查询语句更可能落在文档语义邻域内,而非用户原始提问所处的位置。” 这确实成立并带来帮助。**但 HyDE 的真正价值,尤其在企业级场景中,其实体现在另一层面上。** 撰写假设性答案的过程本身也是一种信息抽取步骤:它能显式地揭示出答案中会包含哪些关键词——如 _“终止程序”_、_“撤销权”_、_“解约费用”_。这些才是驱动搜索的关键锚点,无论检索器是基于向量还是基于关键词实现的。

![Image 15](https://contributor.insightmediagroup.io/wp-content/uploads/2026/05/image-321-908x1024.png)

> 原始查询命中目标 #4;HyDE 改写注入文档术语后,目标跃升至 #1 —— 作者绘制

**为何 HyDE 在此有效,以及真正起作用的因素是什么?**  
原始查询仅含单词 `cancel`,而目标行中出现的是 `rescission` 和 `terminate`,二者无任何共享词元。候选池中三个干扰项均多次重复 `cancel`/`cancellation`,共同将正式目标压至第4位。而 HyDE 改写是一段虚构的答案,恰好包含了 `rescission`, `terminate`, `written notice`, `renewal` 等目标文档中的确切术语。一旦这些词进入查询侧,排名立即反转,目标上升至第1位。

**主导因素是改写中所包含的关键词。** 注册匹配效应(即改写文本的正式声明语气与文档风格一致)以及 LLM 训练带来的潜在语义关联,属于次要影响因素(详见文章第6节深入拆解);但在企业级词汇受限语料库中,这些因素几乎无法改变最终结果。若直接对 `{rescission, terminate, written notice, renewal}` 这组术语执行关键词搜索,同样可以得到相同的目标结果,且完全无需嵌入过程。

**HyDE 实质上是一种通过嵌入步骤实现的隐式关键词扩展策略。** LLM 写出完整假设答案 → 系统对其嵌入 → 检索器在语料库上运行余弦相似度计算。整个流程只为将少数几个关键词注入查询中。相比之下,以下两种更简洁路径也能达成相同的词汇增强效果:

1. **直接向 LLM 提问获取关键词。** 示例提示词:_“在典型保险合同中,该问题的答案通常会包含哪些术语?”_ 输出结果:`rescission, terminate, written notice, renewal`。后续即可用于关键词搜索,无需虚构文档、无需嵌入、无需余弦计算。
2. **由领域专家提供术语映射表。** 律师、理赔员、合规人员早已熟知:用户语言中的 `cancellation` 对应合同语言中的 `rescission`。只需一次性建立该映射关系,便可持续复用;每次查询都让 LLM 重新发现它,则是低效之举。

两种路径在三个方面均优于 HyDE 流程:**可审计性**——匹配的关键词对团队和监管机构都清晰可见;而 `0.83` 的余弦相似度分数则无法直接观察。**延迟性**——仅需一次大语言模型(LLM)调用,无需为每个查询进行嵌入向量的往返交互。**持久性**——关键词以字典形式持久保存,可在后续查询中重复复用;而 HyDE 每次都会从头重新生成假设。

第 6 条(问题解析)将此明确归纳为一个**专家关键词字典**,该字典会随着语料库的增长而不断扩充。

**面向消费者 vs 面向企业。** 在面向消费者的语料库(如通用保险常见问题、电商客服问答、公共服务表格)中,LLM 已经在大量训练文本中接触过相应语域,因此其关键词猜测通常较为准确;HyDE 甚至无需专家介入即可运行。而在企业级语料库(如内部产品编码、法规引用、合同术语、自定义缩写)中,LLM 往往退回到通用法律套话(“……将在条款与条件中详述……”),从而遗漏文档实际使用的词汇。此时,专家早已熟知这些词汇。每次查询都要求 LLM 去猜测专家本可以随手提供的内容,这无疑是低效的路径。

### 3.3 生产环境中的答案:通过专家发现关键词[](file:///C:/Users/shike/Documents/Github/rag/book/02_embeddings.html#the-production-answer-discover-keywords-with-experts)

常规建议(“使用嵌入向量进行语义检索”)过于笼统。更精准的问题是:**嵌入向量究竟在何时才真正值得进入整个流程?** 四种情形,每一种都指向不同的适用场景:

- **已知正确关键词?** 直接使用关键词搜索。它更快、更便宜、可审计,且不像向量匹配那样具有黑箱特性。若监管方询问为何某段文字被检索出来,“该行包含 _force majeure_ 和 _pandemic_” 是一个有说服力的解释;而“余弦相似度为 0.83”则难以令人信服。

- **查询中存在拼写错误?** 修正查询即可。只需一次 LLM 调用,即可将 _polciy_ 修正为 _policy_,回归到干净的关键词搜索流程,无需嵌入管道。

- **文档中存在拼写错误?** 此时嵌入向量才真正发挥不可替代的作用。例如 OCR 识别的合同、扫描的表格、手打笔记等。关键词搜索根本无法匹配拼写错误的词元,但基于句子级别的嵌入仍能将相关文本定位到正确邻域。这是向量搜索在结构上无可替代的典型场景。

- **多语言语料库?** 同样适用上述结论,但机制不同。例如法语合同、英语往来函件、德语附件并存。多语言嵌入模型允许用户用一种语言提问,并从其他语言的文档中提取相关内容。例如 `prime annuelle` 可命中 `Annual premium: $1,200.`(第 1.4 节已展示)。手动维护双语关键词字典虽可行,但成本高昂;而多语言嵌入则免费实现跨语言桥梁,专家只需维护单语字典,其余由嵌入作为跨语言回退方案。注意:需要支持多语言的模型,如 ada-002、3-large、BGE-M3 等;GloVe 或仅支持英文的句向量编码器则不适用。

- **尚不知晓的企业专属同义词?** 这是最具生产价值的场景,也是嵌入向量最能发挥作用之处:**作为发现工具,而非直接检索器**。

**原因至关重要。** 在法律、医疗、保险、金融等专业领域,有意义的同义词并非词典意义上的标准同义词。例如,在合同中,“force majeure” 与 “act of God” 表达相同含义,但嵌入模型并不知晓这一点;它们既非词汇层面的邻近词,也非嵌入空间中的邻近点;而是只有专家(律师、理赔员、合规专员)才掌握的业务特定等价关系。

**各领域中“领域同义词”的具体实例:**

*   **保险合同:**  
    `cancellation` ↔︎ `rescission`, `termination`, `lapse of cover`, `surrender of the policy`;  
    `deductible` ↔︎ `excess`(英式)、`franchise`(法式);  
    `claim` ↔︎ `loss notification`, `incident report`;  
    `policyholder` ↔︎ `insured`, `assured`, `named party`。

*   **医疗记录:**  
    `blood sugar` ↔︎ `glycemia`, `A1C`, `HbA1c`, `fasting plasma glucose`;  
    `heart attack` ↔︎ `myocardial infarction`, `MI`, `acute coronary event`;  
    `high blood pressure` ↔︎ `hypertension`, `elevated BP reading`。

*   **法律与合同条款:**  
    `force majeure` ↔︎ `act of God`, `unforeseeable circumstances`, `events beyond reasonable control`;  
    `non-compete` ↔︎ `restrictive covenant`, `restraint of trade clause`;  
    `confidentiality` ↔︎ `non-disclosure`, `NDA`, `proprietary information clause`。

*   **人力资源与雇佣关系:**  
    `dismissal` ↔︎ `termination of employment`, `separation`, `severance event`;  
    `salary` ↔︎ `compensation`, `base pay`, `gross remuneration`;  
    `harassment` ↔︎ `unwanted conduct`, `hostile environment`, `inappropriate behaviour`。

以上所有别名均非传统词典意义上的同义词,而是由保险核保人、临床医生、合同律师及 HR 专业人士验证过的领域专用等价关系。嵌入模型仅将其视为**候选项**,最终是否成立仍需专家确认。“Force majeure” 等于 “act of God”,前提是你知道它确实如此。

HyDE 将这一过程隐含化(LLM 即时生成文档可能的词汇表,第 3.2 节已指出其局限性),而本系列文章则将其显性化:即由领域专家持续维护的**精编关键词字典**。

发现循环。同一语料库,种子词由专家已知。

与第 3.1 节相同的 `top_lines_for` 原语,无需新增基础设施。

SEED_TERMS = ["cancellation", "deductible", "claim", "policyholder"]

draft_aliases = { seed: top_lines_for(seed, corpus_lines, k=10) for seed in SEED_TERMS }

每个草案均为与种子词最接近的 top-k 语料短语。

提交给专家审核:保留真实同义词,剔除偶然匹配项。

code

validated_dictionary = { "cancellation": ["rescission", "termination", "lapse of cover", "surrender of the policy"], "deductible": ["excess", "franchise"], "claim": ["loss notification", "incident report"], "policyholder": ["insured", "assured", "named party"], }

生产环境的检索直接调用该字典,无需在热路径上进行嵌入计算;

嵌入仅在发现阶段运行一次。

code

**结果展示(基于小型保险语料库)**:将种子词 `cancellation` 与七条候选句子进行比对(其中四条为真实别名,三条为无关干扰项),最终四个真实别名均位列前四。

![Image 16](https://contributor.insightmediagroup.io/wp-content/uploads/2026/05/image-323-1024x692.png)

_一个种子查询,七个候选项。在四种模型中,有三种模型将四个真实别名排进前四名 —— 作者供图_

这一模式正是发现工作流的体现:模型按相似度列出候选项;专家审阅后保留 `rescission`、`termination`、`lapse of cover`、`surrender of the policy`,剔除如 `premium payments` 等无关条目,从而一次性完成 `cancellation` 条目的构建。此后,所有检索均转为对字典的关键词搜索。

**该工作流是渐进式的,并始终与专家协同推进,而非绕过他们**。在新语料库的初期阶段,仍需逐行运行嵌入(如第 3.1 节所述),以揭示用户未曾预料的文档表达方式:合同中使用了 _non-employee labor_,而用户却用了 _contractor_;医疗记录中出现 _A1C_,而用户则表述为 _blood sugar level_;操作手册中引用 _section 4.2_,但用户却提到 _overtime rule_。将这些表达作为关键词别名收录进不断扩大的字典中,并由专家逐一验证——他们清楚哪些是真实等价关系,哪些只是偶然重合。

后续查询则改用增强后的字典进行关键词搜索,无需再调用嵌入模型。此时每次检索均可追溯(我们能明确知道哪些关键词命中)、更快速(热路径上无 LLM 或嵌入延迟),且字典本身成为一项持久的企业资产,可抵御工程人员更迭带来的影响。

这种重构比标准做法更为精准:嵌入模型并非生产环境中的主要检索器,而是用于“启动”生产检索器的工具——它通过与已熟悉语料库的专家协作,逐个构建关键词别名,逐步完善检索能力。第 6 章《理解问题》深入探讨了字典工程方法:领域提示、专家别名、多种替代表达形式以及与检索结果的反馈闭环;第 7 章《检索》则进一步阐述了面向字典的定向检索架构设计。

### 3.4 人力资源与客户反馈案例[](file:///C:/Users/shike/Documents/Github/rag/book/02_embeddings.html#the-hr-and-customer-feedback-case)

多数企业文档并不侧重情感表达。合同、监管文本、财务报告和技术规格书属于事实性语料;第 3.1 至 3.3 节所构建的方法正适用于此类场景。然而,部分企业语料具有特殊性:客户调研原文、员工满意度评论、客服工单自由文本及社交媒体上的品牌提及。这类文本的词汇更具情绪色彩(如 `drained`、`frustrated`、`delighted`、`let down`),而非技术术语(如 `force majeure`、`Solvency II`、`cedent`)。

尽管如此,发现工作流依然适用。例如,一位 HR 分析师正在构建倦怠信号词典,输入其关注的概念 `feeling overwhelmed`。嵌入模型会从语料库中找出处于同一情感簇内的表达方式。下图所示的最优匹配项与查询词完全无共享词汇;但在所有四种模型(从 GloVe 到 3-large)中,它均排名第一。

![Image 17](https://contributor.insightmediagroup.io/wp-content/uploads/2026/05/image-324-1024x431.png)

_查询 `feeling overwhelmed` 对应一条零共现词的情感同义句。TARGET 在所有模型中均居首位 —— 作者供图_

**此处并无真正的情感理解能力**。情感词汇在模型空间中聚类的方式,与保险领域词汇在第 1.2 节中的分布逻辑一致(如 `fee ↔︎ charge`)。早在上下文嵌入出现之前,TF-IDF + 逻辑回归模型在 2010 年 IMDB 情感分类任务中已达到约 88% 的准确率,原因在于情感词汇本身即携带显著信号。嵌入模型在此基础上进一步拓展了同义关系:`overwhelmed`、`drained`、`empty`、`hollow`、`on the edge` 在向量空间中自动彼此靠近,因此只要查询其中一个词,即可触发包含任一表达的句子。这本质上是第 1.2 节机制在另一类词汇上的应用。

**这对生产系统而言具有实用意义**:若目标是情感**分类**(如对每条反馈打分、聚合趋势、检测危机峰值),专用情感模型表现更优——因其专为该任务训练;而嵌入模型的目标是衡量相似性。若目标是**词汇发现**(即识别本语料中表达“痛苦”的各种说法),嵌入模型仍是最佳选择——它能挖掘出专家后续验证的词典内容。两项任务对应两种工具。讽刺语气(如 `_“Oh great, another Monday”_`)则可能同时破坏两者,而其可靠性依赖于原始文本通常无法提供的上下文信息。

本节呈现的核心模式,正是本文整体思路的缩影:初看之下,这似乎展现了某种涌现式情感理解能力;细察之后,实则是基于更精妙“接近”定义的关键词相似性。据此应对:利用模型发掘你尚未掌握的词汇;但不要期望它理解这些词汇背后的意图。

## 4. 结论[](file:///C:/Users/shike/Documents/Github/rag/book/02_embeddings.html#conclusion)

嵌入是《企业文档智能》[第一卷](https://towardsdatascience.com/document-intelligence-a-series-on-building-rag-brick-by-brick-from-minimal-to-corpus-scale/) 中的一块基石,该系列文章旨在从最小规模逐步构建企业级 RAG 系统。本文结尾处的关键词字典,正是第 7 章《检索》中生产检索模块在查询时所读取的内容,具备高速、可审计的特性。
Image 18

嵌入(Embeddings)功能强大,但其能力在特定、可预测的范围内存在局限性。

  • 第一部分:它们能处理什么。 同义词、改写表达、拼写错误、跨语言查询以及一词多义现象均能良好应对;每一代模型的演进都进一步拓宽了其“安全边界”。
  • 第二部分:它们在何处失效。 存在两个根本性问题。首先,某些术语可能根本不在模型词汇表中。

第二部分第 2.1 节通过 pool 这一例子具体说明了这一点:一句随机的列车时刻表句子,在四款模型中有三款上击败了再保险相关改写句的匹配效果。企业领域专有词汇正位于这一区域。其次,当该术语确实在模型中时,嵌入向量仅依据词语相似度进行排序,而非基于问题与答案之间的映射关系。

  • 第二部分第 2.2 节直接展示了最简单查询中的此类失效现象:从第二个根本原因出发,出现了否定逻辑的级联失效(第 2.3 节)、精确值匹配失败(第 2.4 节)、主题相近性压倒答案相关性(第 2.5 节),以及长上下文中的信号稀释问题(第 2.6 节)。一系列“显而易见”的失败案例(如未登录词标识符、布尔组合、计数操作、时间谓词、多跳推理等)无需演示即可理解。
  • 第三部分:如何在生产环境中使用嵌入。 可将嵌入逐行应用,作为对同义词具有容忍性的 Ctrl-F 搜索工具(第 3.1 节)。当确实需要弥合问题与答案之间的鸿沟时,核心支撑模块是答案中应包含的关键词,而非重写后查询的嵌入表示(第 3.2 节)。最终的生产回答依赖于一个由专家构建并辅以逐行嵌入发现机制自动扩展的关键词字典(第 3.3 节)。嵌入并非生产环境中的检索器;它们的作用是快速、可审计地找出检索器所使用的关键词。

来自真实项目的案例。 一支团队为商业保险合同构建了一个 RAG 系统,并花费三个月时间追求召回率提升。他们最初采用 OpenAI 的 text-embedding-3-small,召回率为 71%;随后测试了 Voyage、Cohere 和 BGE-M3(召回率在 69%–73% 之间);最后在合成问答对上微调了 BGE 模型,召回率提升至 76%。经过三个月的努力,仅提升了 5 个百分点。接着,他们按问题类型拆解了 200 个问题:概念类问题召回率达 92%,否定类仅为 23%,精确引用类为 31%,内部缩略语类仅 18%。整体 76% 的召回率掩盖了两类近乎零表现的问题——任何微调都无法解决。随后,他们在向量搜索中引入 BM25,仅用两天便将精确引用召回率提升至 88%;再通过公司术语表对缩略语进行查询扩展,又用一天时间将内部缩略语召回率从 18% 提升至 71%。一周的结构性改进,远胜于三个月的嵌入微调投入。

团队过度投入嵌入的两大信号:

  1. 项目路线图中,“微调嵌入模型”被列为下一阶段里程碑,甚至在尚未拆解实际失败案例前就已提出;
  2. 报告检索指标时仅给出单一召回率数值,且无按问题类型细分的数据,从而掩盖了嵌入在结构层面本就不适用的类别。

你刚刚目睹了嵌入在可预测、结构性方式下的失效过程。尤其对于拥有机器学习背景的工程师而言,第一反应往往是修复模型本身:增加训练数据、微调模型、更换服务提供商或开展超参数扫描。然而,本文第三部分指出,这种思路实属误判。你刚刚看到的失败并非模型可以靠学习自行修正的缺陷。RAG 并非机器学习任务,将其当作 ML 问题来对待,正是团队浪费六个月时间优化系统中并未出错部分的根本原因。

5. 进一步阅读[](file:///C:/Users/shike/Documents/Github/rag/book/02_embeddings.html#further-reading)

本文所呈现的经验模式(同义词、拼写错误、一词多义表现良好;否定、精确标识符、未登录词缩略语则失败)与所有针对域外企业语料库上密集检索器的受控研究结果高度一致。Reimers 和 Gurevych(Sentence-BERT,2019)是关于“对单行文本进行嵌入”这一技术含义的标准参考文献。Ravichander 等人(CONDAQA,2022)清晰记录了否定逻辑失效的现象。本文重新诠释了 HyDE(Gao 等人,2023):真正起支撑作用的是假设答案中包含的关键词,而非嵌入步骤本身;直接让大语言模型生成这些关键词,即可实现相同效果,且所需基础设施更少。在企业语料上微调嵌入模型的内容超出了本文范围,将在第 21 篇文章(生产实践篇)中再次探讨。

与本文方向一致的文献:

  • Reimers & Gurevych, _Sentence-BERT_, EMNLP 2019 (arXiv:1908.10084)。关于“对单行文本进行嵌入”这一技术含义的标准参考文献。
  • Ravichander et al., _CONDAQA_, EMNLP 2022 (arXiv:2211.00295)。明确记录了密集模型在否定逻辑上的系统性失效,与本文经验模式方向一致。
  • Gao et al., _HyDE: Precise Zero-Shot Dense Retrieval without Relevance Labels_, ACL 2023 (arXiv:2212.10496)。本文重新诠释的 HyDE 技术:真正起作用的是假设答案中提取的关键词,而非嵌入步骤本身。
  • Formal et al., _SPLADE_, 2021 (arXiv:2107.05720)。一种学习得到的稀疏检索方法,架起了关键词与嵌入世界之间的桥梁,其思想与“向量搜索本质上即关键词搜索”的框架一脉相承。

不同视角、不同语境下的文献:

  • Karpukhin 等人,《密集段落检索用于开放域问答》,EMNLP 2020(arXiv:2004.04906)。该研究在开放域问答基准上实现了“密集检索优于 BM25”的经典结果。其背景是领域内训练数据;本文则聚焦于领域外的企业语料库,发现该结果在此类场景中无法直接迁移。
  • Wang 等人,《通过弱监督对比预训练生成文本嵌入》(E5),2022(arXiv:2212.03533)以及 Lee 等人,《NV-Embed》,2024(arXiv:2405.17428)。该“规模修复问题”路线表明:更大规模的对比预训练语料可缩小未登录词(OOV)差距。本文主张失败的根本原因在于模型结构(压缩过程会破坏精确值信号),而非单纯的数据量不足。
  • Khattab 与 Zaharia,《ColBERT》,SIGIR 2020(arXiv:2004.12832)。晚期交互式检索作为应对嵌入层下精确词匹配问题的方案;与“精确数值、内部缩写”这类失效模式密切相关。
  • Muennighoff 等人,《MTEB:大规模文本嵌入基准测试》,EACL 2023(arXiv:2210.07316)。该基准推动了“选择得分最高的嵌入”这一思维范式。虽对模型选型有参考价值,但本文指出:排行榜并非衡量企业领域外词汇能力的关键指标。

AI 可能会生成不准确的信息,请核实重要内容