从关键词到上下文:RAG 时代的检索范式转移与预处理重塑

Ordiy Lv5

在构建生产级 AI Agent 或 RAG(检索增强生成)系统时,许多从传统数据开发转型的工程师会面临两个核心疑问:既然 Elasticsearch(BM25)已经足够快,为什么还需要向量数据库? 以及,为什么我们不再像以前在 PyTorch 中处理 NLP 任务那样,进行繁琐的“去停用词”和“词干还原”?

本文将深度拆解这两大争议点,揭示 RAG 架构背后的底层逻辑变革,并分享一套完整的评估闭环。


一、 检索范式的改变:弥合“语义鸿沟”

传统的全文搜索(如 Lucene/ES 内置的 BM25 算法)本质上是一种字面匹配。它记录了词项在文档中的频率,但在处理人类自然语言的复杂意图时,存在天然的“语义鸿沟”。

1. 离散词袋 vs. 连续向量空间

  • BM25 (Sparse Retrieval): 将文档视为离散词汇的集合。如果你搜索“番茄”,系统很难感知到“西红柿”的存在。这种精确性在处理错误代码(如 Error 404)或特定 ID 时是优势,但在处理意图模糊的查询时则显得力不从心。
  • Vector (Dense Retrieval): 通过 Transformer 架构将文本映射到高维连续空间。在这个空间里,“番茄”与“西红柿”的物理距离极近。向量检索捕捉的是上下文隐藏维度(Latent Dimensions)

单纯的向量检索容易产生“语义幻觉”。目前主流的架构是使用 RRF (Reciprocal Rank Fusion) 算法将两者的结果融合:

Python 实现:混合检索融合逻辑

1
2
3
4
5
6
7
8
9
10
11
12
13
def reciprocal_rank_fusion(search_results: list[list[str]], k: int = 60):
"""
目的:融合全文搜索与向量搜索的结果。
逻辑:rank 为文档在各引擎中的排名,k 为平滑常数。排名越靠前,倒数得分越高。
"""
fused_scores = {}
for engine_results in search_results:
for rank, doc_id in enumerate(engine_results):
score = 1.0 / (k + rank) # 核心公式:降低低排名结果的权重影响
fused_scores[doc_id] = fused_scores.get(doc_id, 0) + score

# 按综合得分从高到低重排
return sorted(fused_scores.items(), key=lambda x: x[1], reverse=True)

二、 预处理的“退场”:为什么“洗数据”反而变笨了?

在经典 NLP 流程中,我们习惯执行“规范化 -> 标记化 -> 去停用词 -> 词干还原”。但在 Transformer 时代,这些操作往往是负优化

1. 注意力机制对完整性的依赖

现代大模型(LLM)的底层是 Attention 机制

  • 停用词包含关键逻辑: 在“如何学习 Python”中,“不(not)”是传统意义上的停用词,但在语义中它彻底反转了意图。去掉它,检索结果将南辕北辙。
  • 语法即语义: 词干还原(Stemming)会抹杀时态信息。在法律或技术文档中,“已修复(fixed)”和“待修复(fixing)”的区别是巨大的。

2. 从词级到子词(Subword Tokenization)

传统的 NLTK 依赖词级分词,容易遇到 OOV(词表外)问题。而现代模型采用 BPE (Byte Pair Encoding),将生僻词拆解为更小的语素片段,在编码阶段就自动处理了规范化。


三、 预处理的“重塑”:RAG 的新重心

虽然我们不再进行词干提取,但 RAG 时代的预处理转移到了 ETL 的结构化保留 与 语义分块 上。

1. 语义分块 (Semantic Chunking)

与其强行去除停用词,不如通过递归切分保留文档的逻辑结构。

Python 实现:递归字符分块

1
2
3
4
5
6
7
8
9
10
from langchain.text_splitter import RecursiveCharacterTextSplitter

# 逻辑:与其按字数死板切割,不如按段落、句子的优先级进行递归切分。
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=500, # 目标:保持单次检索的上下文信息量适中
chunk_overlap=50, # 目的:设置重叠窗口,防止语义在切分点断裂
separators=["\n\n", "\n", "。", "!", "?", " "] # 优先级:段落 > 换行 > 标点
)

chunks = text_splitter.split_text(raw_document)

2. 精排阶段:Rerank 重排序

初步检索(Recall)为了速度通常使用向量相似度。而 Reranker 通过 Cross-Encoder 架构计算查询与候选文档的全量注意力,彻底消除语义幻觉。


四、 RAG Evaluate:评估链路的闭环

没有评估的 RAG 只是“开盲盒”。我们现在不再关注 BLEU 或 ROUGE(字符相似度),而是关注 RAG 三元组(The RAG Triad)

  1. 忠实度 (Faithfulness): 生成的回答是否完全源于检索到的上下文?(防止幻觉)
  2. 相关性 (Answer Relevance): 回答是否真正解决了用户的提问?
  3. 上下文精准度 (Context Precision): 检索回来的片段是否真的有用?

Python 实现:LLM-as-a-Judge 评估逻辑

1
2
3
4
5
6
7
8
def evaluate_rag(query, context, answer):
"""
逻辑:利用高性能模型(如 GPT-4o)作为裁判,对三元组进行量化打分。
目的:建立自动化的评估看板,指导检索参数(如 Top-K, Chunk Size)的迭代。
"""
prompt = f"请评估以下回答的忠实度(0-10分)。背景知识:{context},回答:{answer}"
# 模拟 LLM 评分输出...
return {"faithfulness_score": 9.0, "reason": "回答严格遵循了背景知识"}

五、 技术范式对比总结

技术维度 传统 NLP (NLTK 时代) 现代 RAG (Agent 架构)
基础单位 词项 (Word/Lemma) 子词/语义块 (Subword/Chunk)
检索核心 BM25 (字符精确匹配) 混合搜索 + Rerank (语义理解)
数据清洗 降维(去停用词/词干还原) 结构化保留(PDF to Markdown/ETL)
评估指标 BLEU / ROUGE (字面相似) RAG Triad (逻辑对齐/忠实度)

结语

在 RAG 的 world 里,“保留即理解”。我们不再需要通过剔除词汇来降低计算复杂度,因为 Transformer 赋予了我们处理全量上下文的能力。作为架构师,我们的关注点应当从底层的“词汇过滤”提升到更高维度的“语义治理”与“检索融合”。

总结: 在传统 NLP 中,我们通过“减法”提炼特征;在 RAG 时代,我们通过“加法”(上下文保留)与“乘法”(多维检索融合)构建智能,最终通过“除法”(评估链路)剔除幻觉。

References

  • Title: 从关键词到上下文:RAG 时代的检索范式转移与预处理重塑
  • Author: Ordiy
  • Created at : 2026-03-23 13:58:00
  • Updated at : 2026-03-23 15:48:10
  • Link: https://ordiy.github.io/posts/2026-03-23-rag-paradigm-shift-preprocessing/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments