返回学习地图
llmPhase B · 第 11

2.4 RAG基础

检索增强生成:LangChain/Chroma/VectorDB/检索策略——让LLM拥有知识库的完整指南

6 个章节·按类别展开/折叠
知识

RAG是什么?——让大模型有记忆的知识库

你有没有问过ChatGPT"昨天发生了什么新闻"?它会回答:"抱歉,我的训练数据截止到某个日期,我不知道最新信息。"

这就是大模型最大的局限:知识截止在训练日期。GPT-4训练数据截止到2023年12月,对之后发生的事情一无所知。而且对所有用户的问题都给出同样的答案,无法处理私有文档。

RAG(Retrieval-Augmented Generation,检索增强生成)就是解决这个问题的方法。它的核心思想很简单:

让LLM在回答问题前,先去知识库找到相关资料,然后基于资料回答。

这个过程就像开卷考试和闭卷考试的区别:

普通LLM = 闭卷考试——全靠记在脑子里的东西

RAG = 开卷考试——你可以翻书找答案再作答

RAG的好处:

  • 准确回答关于私有文档的问题(公司内部资料、产品手册等)
  • 减少幻觉——因为回答基于检索到的文档而非模型凭空想象
  • 实时更新——只需更新知识库,不用重新训练模型
  • 可溯源——可以告诉用户"这个答案来自文档X的第Y页"

RAG的完整流程:

  1. 用户提问:"我们公司去年的营收是多少?"
  2. 向量检索:在公司的文档库中搜索最相关的几段文本
  3. 找到相关文档后,将【检索到的文档 + 用户问题】一起发给LLM
  4. LLM基于检索到的信息生成回答
知识

Embedding与向量数据库:把文字变成数学

搜索引擎怎么知道"苹果手机"和"iPhone"是同一回事?Google的搜索引擎用了很多技术,但RAG用的是向量嵌入(Embedding)

Embedding是什么?

把一段文字转换成一串数字(向量),这串数字编码了文字的语义(含义)。语义相近的文字,它们的向量在空间中距离很近。

举个例子(这些数字只是演示,真实向量是几百到几千维):

"今天天气很好" → [0.2, 0.5, 0.1]

"今日天气不错" → [0.3, 0.4, 0.2] (距离很近——意思差不多)

"机器学习算法" → [-0.8, 0.1, 0.9] (距离很远——意思完全不同)

向量空间中的"距离"就是语义相似度。距离越近=意思越接近。

常用Embedding模型:

  • OpenAI text-embedding-3-small:1536维向量,效果好,但要付费
  • BGE系列(BAAI):开源中文最好的Embedding之一,bge-large-zh-v1.5
  • M3E:MokaAI开发的中文Embedding,开源免费,部署方便
  • Jina Embeddings:支持多语言,特别适合长文本

向量数据库专门存储和检索这些向量。普通数据库用"WHERE name = '张三'"精确匹配,向量数据库用"找最近似的Top K"——不要求一模一样,但要求最相似。

就像图书馆里,传统的书号检索让你找"书号=12345的书"。向量检索让你找"和这本最相关的几本书"。

代码

LangChain实现完整RAG系统

知识

检索策略与优化

基础RAG用简单的向量相似度检索。但真实场景中可能遇到很多问题:"我想找北京的公司"——关键词检索可能更好。或问题很复杂需要分步推理。

1. 混合检索(Hybrid Search)

向量检索(语义相似)+ 关键词检索(BM25精确匹配)的结合。

score = α × 向量相似度 + (1-α) × BM25得分

α=0.5~0.7时效果最好。向量的语义能力弥补关键词的"只看字面",关键词的精确性弥补向量的"有时候跑偏"。

2. 重排序(Re-Ranking)

先用向量检索快速召回Top 50个候选,再用Cross-Encoder精挑出Top 5。

为什么?向量检索快但精度有限,Cross-Encoder更准但太慢。两步走:第一阶段扫一遍(快),第二阶段细选(准)。

3. 查询分解(Query Decomposition)

复杂问题拆解成多个子问题,分别检索再合并。

"比较Transformer和RNN的优缺点"→

子问题1:"Transformer有什么优点和缺点?"

子问题2:"RNN有什么优点和缺点?"

分别检索每个子问题,找到的文档更精确。

4. 上下文压缩(Context Compression)

检索到的文档可能太长,Token不够用。用LLM压缩/摘要后再回答问题。Extract-then-Answer策略。

实例

RAG实战:构建公司产品知识库问答系统

实例

场景:一家电商公司有100份产品文档(功能说明、保修政策、使用指南等),要构建一个内部客服系统。

设计思路:

文档选择:将PDF、Word都转成txt格式放入docs目录

切割策略:chunk_size=800(中文产品文档段落较长),chunk_overlap=100

Embedding:用BGE-large-zh做中文向量化

向量库:ChromaDB(轻量级,本地运行)

LLM:通过API调用GPT-3.5-turbo

完整代码结构:

# 1. 文档预处理
from langchain.document_loaders import PyPDFLoader, Docx2txtLoader
# 不同格式用不同loader,统一转成Document对象

# 2. 嵌入
from langchain.embeddings import HuggingFaceEmbeddings
embeddings = HuggingFaceEmbeddings(
    model_name="BAAI/bge-large-zh-v1.5",
    model_kwargs={'device': 'cuda'},
    encode_kwargs={'normalize_embeddings': True}
)

# 3. 向量库
vectordb = Chroma(
    embedding_function=embeddings,
    persist_directory="./product_kb"
)

# 4. Prompt模板
from langchain.prompts import PromptTemplate
template = "你是产品专家。基于以下信息回答用户问题:\n\n{context}\n\n问题:{question}\n回答:"
prompt = PromptTemplate(template=template, input_variables=["context", "question"])

# 5. 使用
result = qa_chain({"query": "手机屏幕碎了怎么处理?"})
# 回答:"根据保修政策,非人为损坏的屏幕在购买7天内可以免费更换..."
练习

练习题

练习

Q1:RAG的全称是什么?它解决了LLM的什么核心问题?

Q2:文本切割时chunk_size=300和chunk_size=1000分别有什么影响?

Q3:向量检索和关键词检索各有什么优点?为什么要混合使用?

Q4:RAG流程中k=3是什么意思?设成k=10会怎样?

Q5:设计一个RAG系统需要哪几个核心组件?

查看答案

A1:Retrieval-Augmented Generation。解决了LLM的知识截止问题(无法回答训练截止日期之后的事)和无法处理私有文档的问题。让LLM在回答前先检索知识库,基于资料回答,减少幻觉。

A2:chunk_size=300:块太小,可能切碎完整段落,丢失上下文。但检索时更精确匹配用户问题。chunk_size=1000:块太大,保留更多上下文,但可能包含与问题无关的内容,引入噪声。

A3:向量检索理解语义("苹果"≈"iPhone"),但可能跑偏。关键词检索精确匹配字面(只找有"苹果"二字的),但不懂同义词。混合检索取长补短,score=α×向量+ (1-α)×关键词,α通常0.5-0.7。

A4:k=3表示检索最相似的3个文本块。k=10时返回10块,信息更全面但也引入了更多可能不相关的噪声,而且更消耗Token。需要根据文档质量和问题复杂度调整。

A5:五个核心组件:1) 文档加载器(读取PDF/Word/txt);2) 文本切割器(把长文档切成块);3) Embedding模型(把文本转成向量);4) 向量数据库(存储和检索向量);5) LLM(基于检索到的文档生成答案)。