基础概念

RAG

检索增强生成

RAG(Retrieval-Augmented Generation,检索增强生成)是让大模型基于你的私有数据回答问题的技术。它先用向量检索找到相关文档片段,再把片段塞进 Prompt 让模型生成答案。解决了大模型'不知道企业内部数据'和'容易幻觉'两大痛点。本文用通俗语言拆解 RAG 原理、与微调的区别、4 种检索策略与落地步骤。

2026-08-14
RAG检索增强向量数据库Embedding基础概念

什么是 RAG

RAG(Retrieval-Augmented Generation,检索增强生成) 是一种让大语言模型(LLM)基于外部知识库回答问题的技术。

打个比方:

  • 纯 LLM = 闭卷考试:只能靠训练时记住的知识
  • RAG = 开卷考试:先翻书找相关段落,再答题
用户提问:"我们公司的退货政策是什么?"

纯 LLM:我不知道你们公司的退货政策(或瞎编一个)
RAG :[检索] 找到 help_center/returns.md
     [生成] 根据该文档回答:7 天无理由退货,需保留吊牌...

为什么需要 RAG

大模型有三个先天缺陷,RAG 逐一解决:

缺陷 1:不知道你的私有数据

LLM 训练数据截止 2024 年,且不包含:
  - 你的企业知识库
  - 你的产品文档
  - 你的客户数据
  - 2026 年的最新资讯

RAG 方案:把这些数据做成可检索的知识库,回答时先检索再生成。

缺陷 2:会幻觉

LLM:巴黎和会签订于 1918 年(实际是 1919 年)
原因:模型在"生成"而非"检索",遇到不确定就编

RAG 方案:把权威资料塞进 Prompt,让模型"看着资料回答"而非"凭记忆回答"。

缺陷 3:无法更新

LLM:训练一次几十万美金,更新一次再花几十万

RAG 方案:知识库随时增删改,下次提问即生效,无需重新训练。

RAG 的工作流程

┌─────────────────────────────────────────────────────────────┐
│                       RAG 完整流程                          │
│                                                             │
│  【离线阶段:建库】                                          │
│  原始文档 → 切块 → Embedding → 向量数据库                    │
│   PDF/MD     片段     向量      可检索                      │
│                                                             │
│  【在线阶段:问答】                                          │
│  用户问题 → Embedding → 向量检索 → Top-K 片段 → 拼 Prompt     │
│              ↓              ↓           ↓           ↓       │
│             向量          找相似       取前 5 段   喂给 LLM   │
│                                                             │
│  最终输出:基于检索片段的答案 + 引用来源                      │
└─────────────────────────────────────────────────────────────┘

Step 1:切块(Chunking)

把长文档切成小片段(通常 200-1000 字),因为:

  • 向量检索需要片段足够小才能精准定位
  • Prompt 长度有限,塞不下整本书
原始文档(1 万字):
┌──────────────────────────────────┐
│ 第一章 公司简介                   │
│ 第二章 退货政策  ← 用户问的就是这 │
│ 第三章 配送说明                   │
└──────────────────────────────────┘

切块后:
[chunk 1] 第一章公司简介...
[chunk 2] 第二章 7 天无理由退货...
[chunk 3] 第三章 配送说明...

切块策略:

  • 固定长度:每 500 字一切(简单但可能切断语义)
  • 按结构切:按标题/段落切(推荐)
  • 重叠切:相邻块重叠 50-100 字(保留上下文)

Step 2:Embedding(向量化)

用 Embedding 模型把文本转成向量(高维数组):

"7 天无理由退货" → [0.12, -0.34, 0.56, ..., 0.78]  // 1536 维
"7 天退换货"     → [0.11, -0.33, 0.55, ..., 0.77]  // 相似
"配送时效"       → [-0.45, 0.21, -0.67, ..., 0.03] // 不相关

向量相似度 = 语义相似度。这就是为什么"7 天无理由退货"能匹配到"7 天退换货"。

常用 Embedding 模型:

模型维度特点
OpenAI text-embedding-3-small1536性价比高
OpenAI text-embedding-3-large3072精度高
BGE-large-zh1024中文开源首选
Cohere embed-v31024多语言

Step 3:存入向量数据库

把向量 + 原文片段一起存入向量数据库:

数据库特点
Pinecone托管 SaaS,开箱即用
Milvus开源,支持十亿级向量
QdrantRust 写,快
Chroma轻量,适合原型
pgvectorPostgreSQL 扩展,复用现有库

Step 4:检索(Query 时)

用户提问时,同样的问题做 Embedding,然后在向量库找最相似的 K 个片段:

query = "怎么退货?"
query_vec = embed(query)  # [0.10, -0.32, ...]

# 在向量库找 Top 5 相似片段
results = vector_db.search(query_vec, top_k=5)
# → [chunk 2: "7 天无理由退货...", chunk 7: "退货流程...", ...]

Step 5:生成(拼 Prompt)

把检索到的片段塞进 Prompt,让 LLM 基于这些片段回答:

系统:你是客服。仅基于以下资料回答,不知道就说不知道。

资料:
[1] 7 天无理由退货,需保留吊牌...
[2] 退货流程:登录 → 我的订单 → 申请退货...
[3] 退货运费:质量问题卖家承担,其他买家承担...

用户:怎么退货?运费谁出?

LLM:根据资料[2],退货流程为:登录→我的订单→申请退货。
     根据资料[3],质量问题运费卖家承担,其他情况买家承担。

关键:Prompt 里强调"仅基于资料回答",并要求"标注引用",能大幅降低幻觉。

RAG vs 微调(Fine-tuning)

很多人问:既然要让模型懂我的数据,为什么不直接微调?

维度RAG微调
适合知识型数据✅ 强❌ 弱
适合风格型数据❌ 弱✅ 强
数据更新即时生效需重新训练
成本低(只需 Embedding)高(需训练)
可解释性高(可看引用来源)低(黑盒)
幻觉控制强(有资料兜底)弱
学新技能❌✅

经验法则:

  • 让模型"知道新事实" → 用 RAG
  • 让模型"换种说话风格" → 用微调
  • 两者也可叠加:先微调风格,再 RAG 知识

四种检索策略

策略 1:朴素向量检索(基础)

results = vector_db.search(embed(query), top_k=5)

简单快,但有问题:用户问"怎么退货",向量检索可能匹配到"退款"(语义近但非答案)。

策略 2:混合检索(向量 + 关键词)

vec_results = vector_db.search(embed(query), top_k=10)
kw_results = bm25_search(query, top_k=10)
results = rerank(vec_results + kw_results, top_k=5)

向量擅长语义匹配,关键词擅长精确匹配(如产品型号、人名)。混合两者召回更全。

策略 3:重排序(Rerank)

# 先粗召 50 个
candidates = vector_db.search(embed(query), top_k=50)
# 再用 cross-encoder 精排
results = cross_encoder.rerank(query, candidates, top_k=5)

Cross-encoder 比向量相似度更准,但慢,所以先用向量粗筛再用它精排。

策略 4:查询改写(HyDE)

# 让 LLM 先假设一个答案
hypothetical = llm("假设答案:退货流程是...")
# 用假设答案(而非原问题)去检索
results = vector_db.search(embed(hypothetical), top_k=5)

原理:答案的向量比问题的向量更接近目标片段。

完整代码示例

from openai import OpenAI
import chromadb

client = OpenAI()
db = chromadb.PersistentClient(path="./vector_db")
collection = db.get_or_create_collection("docs")

# ===== 离线建库 =====
def build_knowledge_base(docs):
    for doc in docs:
        # 切块(简化版,按 500 字切)
        chunks = [doc[i:i+500] for i in range(0, len(doc), 450)]
        for i, chunk in enumerate(chunks):
            # 向量化
            vec = client.embeddings.create(
                input=chunk, model="text-embedding-3-small"
            ).data[0].embedding
            # 存库
            collection.add(
                ids=[f"{doc['id']}_{i}"],
                embeddings=[vec],
                documents=[chunk],
                metadatas=[{"source": doc["source"], "chunk": i}]
            )

# ===== 在线问答 =====
def rag_answer(question, top_k=5):
    # 1. 问题向量化
    q_vec = client.embeddings.create(
        input=question, model="text-embedding-3-small"
    ).data[0].embedding

    # 2. 检索
    results = collection.query(query_embeddings=[q_vec], n_results=top_k)
    context = "\n\n".join(results["documents"][0])

    # 3. 生成
    prompt = f"""你是客服。仅基于以下资料回答,不知道就说不知道。
    标注引用来源([1][2]...)。

    资料:
    {context}

    问题:{question}"""
    
    return client.chat.completions.create(
        model="gpt-4o",
        messages=[{"role": "user", "content": prompt}]
    ).choices[0].message.content

常见坑点

坑 1:切块不当

✗ 每 500 字硬切 → 一个退货政策被切成两半,检索只能召回一半
✓ 按标题/段落切 → 完整保留语义

坑 2:检索 Top-K 太大

✗ top_k=20 → 塞 20 个片段进 Prompt,关键信息被稀释
✓ top_k=3-5 + rerank → 少而精

坑 3:不做查询改写

用户问:"那个东西怎么用"(代词指代不明)
✗ 直接检索 → 召回乱七八糟
✓ 先让 LLM 改写:"用户之前在问咖啡机,改写为:咖啡机怎么用"

坑 4:忽略元数据过滤

✗ 全库检索 → 召回到已下架产品的文档
✓ metadata filter: {"status": "active"} → 只检索有效文档

与本站其他内容的关系

小结

RAG 是 2026 年企业 AI 落地最主流的方案——不重新训练模型,靠检索让 LLM 用你的数据回答问题。

它解决了 LLM 三大痛点:不知道私有数据、容易幻觉、无法更新。掌握 RAG,你就能搭出"懂你业务"的 AI 助手,而不仅是个通用聊天机器人。