9.4 文本嵌入与语义检索

双编码器架构原理

上一节介绍了词嵌入的理论基础。本节进一步探讨如何将这些原理应用到实际的文本检索中——文本嵌入(Text Embedding)技术如何支撑 RAG 系统的语义检索能力。

9.4.1 从词向量到文档向量

词袋模型的局限

早期的文本表示方法是词袋模型(Bag of Words, BoW)。它把一段文字看作词语的集合,统计每个词出现的频率,忽略词序和语法结构。

词袋模型的一个变体是简单平均法:先为每个词分配一个向量(词向量),然后把句子中所有词向量取平均,作为句子的表示。

这种方法存在明显缺陷:

  1. 语序丢失:「央行加息」和「加息央行」得到相同的向量
  2. 语义稀释:句子越长,平均后的向量越趋向通用含义,区分度下降
  3. 无法处理多义词:「苹果」在「吃苹果」和「苹果公司」中的含义完全不同,但词向量相同

文本嵌入的目标

文本嵌入(Text Embedding)要解决的核心问题是:如何将任意长度的文本映射到固定维度的向量空间,使得语义相近的文本在向量空间中距离相近。

与简单平均不同,现代文本嵌入模型能够:

  • 捕捉词序信息:「央行加息」和「加息预期」表达不同含义
  • 理解上下文:同一个词在不同语境中获得不同表示
  • 保持语义一致性:「降低利率」和「降息」应映射到相近位置

这正是 Transformer 架构带来的突破。

9.4.2 Transformer 编码器与文本表示

Self-Attention 的直观理解

Transformer 是 2017 年提出的神经网络架构,如今已成为自然语言处理的基础设施。其核心机制是自注意力(Self-Attention)。

自注意力的作用可以这样理解:在处理一个句子时,模型会让每个词关注句子中的其他词,根据相关性加权汇总信息。

以句子「央行宣布下调存款准备金率」为例:

  • 「下调」会重点关注「央行」(谁下调)和「准备金率」(下调什么)
  • 「准备金率」会关注「存款」(哪种准备金)和「下调」(发生什么变化)
  • 每个词的最终表示融合了它与其他词的语义关联

这种机制使模型能够理解长距离依赖关系。在传统的循环神经网络中,句首和句尾的词很难建立直接联系;而在 Transformer 中,任意两个词都能直接建立关联。

注记知识卡片

Transformer 架构由 Vaswani 等人在论文「Attention Is All You Need」(2017)中提出。这篇论文的核心洞见是:仅用注意力机制就能构建高性能的序列模型,不需要循环或卷积结构。如今,几乎所有主流大语言模型(GPT、Claude、LLaMA)都基于 Transformer 架构。

BERT 与句子表示

BERT(Bidirectional Encoder Representations from Transformers,双向编码器表示)是 Google 于 2018 年推出的预训练语言模型。它专门用于生成文本的向量表示。

BERT 的核心设计是双向上下文建模。在处理一个词时,它同时考虑左侧和右侧的上下文。这与 GPT 类模型不同——GPT 只能看到左侧的词(用于生成下一个词),而 BERT 能综合利用完整的句子信息。

[CLS] Token 的作用

BERT 在输入文本的开头添加一个特殊标记 [CLS](Classification)。这个标记不代表任何具体的词,而是用于汇聚整个句子的语义信息。

处理流程如下:

输入: [CLS] 央行 宣布 降准 0.5 个 百分点 [SEP]

   Transformer 编码器(多层 Self-Attention)

输出: [CLS]向量  央行向量  宣布向量  降准向量  ...

[CLS] 向量即为整个句子的语义表示

[CLS] 位置的输出向量浓缩了句子的整体含义,可直接用于下游任务:文本分类、语义相似度计算、信息检索等。

编码器与生成模型的区别

理解 BERT 类编码器与 GPT 类生成模型的区别很重要:

特征 编码器(BERT 类) 生成模型(GPT 类)
注意力方向 双向(看完整句子) 单向(只看左侧)
主要任务 理解、分类、检索 生成、续写、对话
输出形式 固定维度向量 下一个 token 的概率分布
典型应用 文本嵌入、语义搜索 聊天机器人、内容生成

在 RAG 系统中,编码器负责将文档和查询转换为向量,用于相似度计算;生成模型负责基于检索结果生成最终回答。两者各司其职。

9.4.3 双编码器架构

查询与文档分别编码

在实际的语义检索系统中,通常采用双编码器架构(Bi-Encoder)。其核心思想是:用同一个编码器分别处理查询和文档,将它们映射到同一个向量空间。

查询编码:
"降准政策的影响" → 编码器 → 查询向量 (1024维)

文档编码:
"央行降准有助于释放流动性..." → 编码器 → 文档向量 (1024维)

相似度计算:
查询向量 · 文档向量 = 相似度分数

这种架构的关键优势在于:文档向量可以离线预计算。知识库中的所有文档在索引阶段就完成向量化,存入向量数据库。检索时只需计算查询向量,然后与预存的文档向量比较,速度极快。

双编码器的权衡

双编码器架构有明显的优缺点:

优点 缺点
文档可离线索引,检索速度快 查询与文档独立编码,交互信息损失
支持大规模向量库(百万级) 细粒度语义匹配能力有限
计算成本可控 对复杂查询(多条件、否定句)效果较差

这些缺点可以通过重排序(Reranking)来弥补。初检使用双编码器快速筛选候选文档,精排使用交叉编码器(Cross-Encoder)对查询-文档对进行联合建模,获得更精确的相关性判断。

9.4.4 余弦相似度的数学与直觉

定义与计算

余弦相似度(Cosine Similarity)衡量两个向量方向的一致程度。分子是两个向量的点积,分母是两个向量长度的乘积。这个比值等于两向量夹角的余弦值。

注记知识卡片

余弦函数的性质决定了相似度的取值范围:当两向量方向完全相同时,夹角为 0°,余弦值为 1;当两向量垂直时,夹角为 90°,余弦值为 0;当两向量方向完全相反时,夹角为 180°,余弦值为 -1。

为何用方向而非距离

一个自然的问题是:为什么不直接用欧氏距离衡量相似性?

欧氏距离计算两点之间的直线距离。问题在于,它对向量的长度敏感。假设两段文本语义相同,但其中一段更长,其向量的模长(长度)可能更大。用欧氏距离衡量,这两段文本反而显得不相似。

余弦相似度只关注方向,忽略长度。这意味着:

  • 一篇 1000 字的政策解读和一段 100 字的摘要,只要表达的核心含义相同,余弦相似度就会很高
  • 文本长度的差异不会干扰语义相似度的判断

这正是文本检索所需要的特性。用户的查询通常很短(一句话),而文档片段可能有几百字,但只要语义匹配,就应该被检索到。

数值范围与实际含义

余弦相似度的取值范围是 [-1, 1]:

相似度范围 含义 文本检索中的例子
0.85 - 1.0 高度相似 同义改写、精确匹配
0.65 - 0.85 相关 讨论同一话题的不同表述
0.4 - 0.65 弱相关 同一领域但话题不同
0 - 0.4 基本无关 不同领域的内容
< 0 语义相反 在实际应用中较少见

在 RAG 系统中,通常设置相似度阈值(如 0.6),低于阈值的检索结果不予采纳。这个阈值需要根据具体场景调整——金融政策查询对精确度要求高,可以设置较高阈值;一般性问答可以适当放宽。

9.4.5 嵌入模型的选择

维度的权衡

嵌入模型输出的向量维度是一个重要的设计参数。维度越高,能够编码的语义信息越丰富,但计算和存储成本也越大。

维度 存储成本 检索速度 语义精度 适用场景
256-384 一般 原型开发、资源受限
512-768 中等 较快 良好 大多数生产应用
1024 中等偏高 中等 较高 高精度检索需求
3072-4096 较慢 最高 极致精度场景

对于金融文档检索,768-1024 维通常是合适的选择。维度过低会损失细微的语义差异(如区分「加息」和「降息」的政策取向),维度过高则带来不必要的计算开销。

多语言与中文优化

嵌入模型的训练数据决定了它对不同语言的处理能力。选择模型时需考虑:

  • 英文为主的模型(如 all-MiniLM-L6-v2):英文效果好,中文能力有限
  • 多语言模型(如 OpenAI text-embedding-3):覆盖多种语言,中文表现尚可
  • 中文优化模型(如 bge-small-zh、text2vec-chinese):专门针对中文训练,中文效果最佳

金融领域存在大量中文专业术语(如「逆回购」「MLF」「LPR」),选用中文优化模型能更准确地理解这些概念。

主流嵌入模型概览

模型 提供方 维度 特点 推荐场景
text-embedding-3-small OpenAI 1536 多语言、质量高 快速起步、API 调用
text-embedding-3-large OpenAI 3072 最高精度 对精度要求极高
bge-small-zh-v1.5 BAAI 512 中文优化、轻量 中文场景、本地部署
bge-large-zh-v1.5 BAAI 1024 中文优化、高精度 高精度中文检索
bge-m3 BAAI 1024 多检索模式 混合检索场景
Qwen2.5-Embedding-0.6B 阿里云 1024 中英双语、平衡 双语场景、本地部署
提示选型建议

对于本书的学习者,推荐以下选择路径:

  1. 快速上手:使用 OpenAI text-embedding-3-small,通过 API 调用,无需本地配置
  2. 本地部署:使用 bge-small-zh-v1.5 或 Qwen2.5-Embedding-0.6B,免费且中文效果好
  3. 生产环境:根据实际测试结果选择,通常 bge-large-zh 或 text-embedding-3-large 表现最佳