Journal Article

RAG检索增强生成:深入理解嵌入与重排

RAG(检索增强生成)是一种结合检索系统与大语言模型的技术。本文深入讲解RAG的工作原理,重点介绍嵌入(Embedding)将文本转换为向量的数学原理,以及重排(Reranking)对检索结果重新排序的方法,附完整Python代码示例。

11 min8 views
加载3D可视化中...

RAG检索增强生成:深入理解嵌入与重排

什么是RAG?

RAG(Retrieval-Augmented Generation,检索增强生成)是一种将检索系统大语言模型相结合的技术架构。它通过从外部知识库中检索相关信息,来增强语言模型的回答质量和准确性。

为什么需要RAG?

传统的大语言模型存在以下问题:

  • 知识截止:模型只知道训练数据截止日期之前的信息
  • 幻觉问题:模型可能生成看似合理但实际错误的内容
  • 缺乏领域知识:通用模型难以回答特定领域的专业问题

RAG通过引入外部知识检索,有效解决了这些问题。


RAG工作流程

一个典型的RAG系统包含以下步骤:

  1. 文档预处理:将文档切分为适当大小的片段(chunk)
  2. 向量化:使用嵌入模型将文本转换为向量
  3. 存储:将向量存入向量数据库
  4. 检索:根据用户查询检索相关文档片段
  5. 重排:对检索结果进行重新排序
  6. 生成:将检索结果作为上下文输入给LLM生成回答

嵌入(Embedding)原理

什么是嵌入?

嵌入是将文本转换为数值向量的过程。这些向量能够捕捉文本的语义信息,使得意思相近的文本在向量空间中距离相近。

2026年主流嵌入模型

模型来源参数量维度特点
Microsoft Harrier微软27B/0.6B/270M可变MTEB-v2全球第一(74.3分),32k上下文,100+语言
ML-Embed蚂蚁集团+上海交大140M~8B可变ICML 2026,282种语言,3D-ML框架
Qwen3-Embedding阿里0.6B/4B/8B可变MTEB多语言冠军(70.58分),Apache 2.0开源
BGE-M3BAAI568M1024开源多语言,支持8192 token
F2LLM-v2开源社区多规格可变ML-Embed基线版本,MTEB榜单前列

嵌入的数学原理

嵌入模型通过深度神经网络将文本映射到高维向量空间。例如:

  • 文本「猫是哺乳动物」→ 向量 [0.12, -0.45, 0.78, ...]
  • 文本「狗是哺乳动物」→ 向量 [0.15, -0.42, 0.81, ...]
  • 文本「今天天气很好」→ 向量 [-0.67, 0.23, -0.12, ...]

前两个向量的余弦相似度很高(语义相近),而与第三个向量差异较大(语义不同)。

余弦相似度计算

python
import numpy as np

def cosine_similarity(vec1, vec2):
    dot_product = np.dot(vec1, vec2)
    norm1 = np.linalg.norm(vec1)
    norm2 = np.linalg.norm(vec2)
    return dot_product / (norm1 * norm2)

向量数据库

向量数据库用于高效存储和检索向量数据。常见选择:

  • Milvus:高性能,支持分布式
  • Chroma:轻量级,适合原型开发
  • Pinecone:全托管云服务
  • FAISS:Facebook开源,单机高性能

使用Chroma存储文档

python
import chromadb
from chromadb.utils import embedding_functions

client = chromadb.PersistentClient(path="./chroma_db")

ef = embedding_functions.OpenAIEmbeddingFunction(
    api_key="your-api-key",
    model_name="text-embedding-3-small"
)

collection = client.get_or_create_collection(
    name="documents",
    embedding_function=ef
)

collection.add(
    documents=[
        "RAG通过检索外部知识来增强LLM的回答",
        "嵌入是将文本转换为向量的过程",
        "向量数据库用于存储和检索向量"
    ],
    ids=["doc1", "doc2", "doc3"]
)

results = collection.query(
    query_texts=["什么是RAG"],
    n_results=2
)
print(results)

重排(Reranking)原理

什么是重排?

重排是对初始检索结果进行重新排序的过程。由于向量检索基于语义相似度,可能遗漏一些关键词匹配但语义相似度较低的文档,重排可以弥补这一不足。

为什么要重排?

  1. 召回率 vs 精确率:向量检索侧重召回,重排侧重精确
  2. 多路召回融合:结合多种检索方式的结果
  3. 领域适配:根据特定领域调整排序

常见的重排方法

1. Cross-Encoder重排

Cross-Encoder将查询和文档拼接后一起编码,计算相关性分数:

python
from sentence_transformers import CrossEncoder

reranker = CrossEncoder("cross-encoder/ms-marco-MiniLM-L-6-v2")

query = "什么是RAG"
documents = [
    "RAG是检索增强生成的缩写",
    "Python是一种编程语言",
    "检索增强生成结合了检索和生成"
]

pairs = [(query, doc) for doc in documents]
scores = reranker.predict(pairs)

ranked_results = sorted(zip(documents, scores), key=lambda x: x[1], reverse=True)
for doc, score in ranked_results:
    print(f"{score:.4f}: {doc}")

2. BGE-Reranker

BGE-Reranker是BAAI开发的重排模型,支持多语言:

python
from FlagEmbedding import FlagReranker

reranker = FlagReranker("BAAI/bge-reranker-v2-m3", use_fp16=True)

query = "什么是RAG"
documents = [
    "RAG是检索增强生成的缩写",
    "Python是一种编程语言",
    "检索增强生成结合了检索和生成"
]

pairs = [[query, doc] for doc in documents]
scores = reranker.compute_score(pairs, normalize=True)
print(scores)

3. Cohere Rerank

Cohere提供云端重排API:

python
import cohere

co = cohere.Client("your-api-key")

results = co.rerank(
    query="什么是RAG",
    documents=[
        "RAG是检索增强生成的缩写",
        "Python是一种编程语言",
        "检索增强生成结合了检索和生成"
    ],
    model="rerank-v3.5",
    top_n=3
)

for result in results.results:
    print(f"{result.relevance_score:.4f}: {result.index}")

完整RAG示例

python
import numpy as np
from openai import OpenAI
import chromadb
from sentence_transformers import CrossEncoder

class RAGSystem:
    def __init__(self):
        self.client = OpenAI(api_key="your-api-key")
        self.chroma_client = chromadb.PersistentClient(path="./rag_db")
        self.collection = self.chroma_client.get_or_create_collection(
            name="knowledge_base"
        )
        self.reranker = CrossEncoder("cross-encoder/ms-marco-MiniLM-L-6-v2")
    
    def get_embedding(self, text):
        response = self.client.embeddings.create(
            model="text-embedding-3-small",
            input=text
        )
        return response.data[0].embedding
    
    def add_document(self, doc_id, text):
        embedding = self.get_embedding(text)
        self.collection.add(
            ids=[doc_id],
            documents=[text],
            embeddings=[embedding]
        )
    
    def retrieve(self, query, top_k=5):
        query_embedding = self.get_embedding(query)
        results = self.collection.query(
            query_embeddings=[query_embedding],
            n_results=top_k
        )
        return results["documents"][0]
    
    def rerank(self, query, documents, top_k=3):
        pairs = [(query, doc) for doc in documents]
        scores = self.reranker.predict(pairs)
        ranked = sorted(zip(documents, scores), key=lambda x: x[1], reverse=True)
        return [doc for doc, score in ranked[:top_k]]
    
    def generate(self, query, context):
        response = self.client.chat.completions.create(
            model="gpt-4",
            messages=[
                {"role": "system", "content": "你是一个有帮助的助手,根据提供的上下文回答问题。"},
                {"role": "user", "content": f"上下文:{context}\n\n问题:{query}"}
            ]
        )
        return response.choices[0].message.content
    
    def answer(self, query):
        docs = self.retrieve(query, top_k=10)
        reranked_docs = self.rerank(query, docs, top_k=3)
        context = "\n".join(reranked_docs)
        answer = self.generate(query, context)
        return answer

嵌入 vs 重排:关键区别

特性嵌入检索重排
速度
召回率
精确率
模型Bi-EncoderCross-Encoder
用途初步召回精细排序

最佳实践:先用嵌入检索快速召回大量候选文档,再用重排模型精选最终结果。


总结

  • RAG 结合了检索和生成的优势,解决了LLM的知识截止和幻觉问题
  • 嵌入 将文本转换为向量,实现语义级别的相似度计算
  • 重排 对检索结果进行精细排序,提高最终结果的准确性

通过合理运用这些技术,可以构建出高质量的知识增强问答系统。