【RAG扫盲系列】RAG基础认知
一、检索增强生成(RAG)前言
1. LLM的缺陷分析
试想这样一个例子,有人问了你这样一个问题:木星有多少颗卫星?可能你之前曾经看到过有人说,木星有92颗卫星,于是你就自信地回答说92颗。但实际上,当你上网一搜,被网上众多消息迷住眼睛,看得头晕眼花,最后勉强确定最新消息说木星有95颗卫星,你知道的92颗卫星已经是过时的消息了。这种情况也出现在大模型身上。
大语言模型(LLM, Large Language Model) 在近几年展现了惊人的语言理解与生成能力,但它们并非完美无缺。它们也会和人类犯一样的错误。
- 比如说,它们的知识库里的信息是过时的,但它们并不知道,就会自信地告诉你一个错误的、过时的答案。
- 再比如说,它们可能干脆就不知道答案,但是以为自己知道,于是自信地编出一个驴唇不对马嘴的答案。
- 继续比如说,这些答案它们说不出一个具体的来源,甚至当你给它一大段信息让它阅读并回答时,它也很难给出一个确定的答案,就像你也不知道你知道的“木星有92颗卫星”是从哪里看到的、搜索起来也很费劲一样。
总的来说,大语言模型有以下局限性:
| 局限 | 解释 |
|---|---|
| 知识时效性不足 | LLM 的知识来自训练语料,通常存在时间“冻结点”,无法自动更新 |
| 幻觉问题(Hallucination) | 模型可能生成看似合理但事实错误的内容 |
| 缺乏可控性 | 模型回答往往是“黑箱式”的,难以保证引用来源或解释推理过程 |
| 上下文窗口限制 | 输入长度有限,难以直接处理大规模文档或数据库 |
因此,单纯依赖大语言模型并不足以满足高可靠性场景的需求。我们需要一种方法,既能发挥 LLM 的语言生成能力,又能引入外部的、可更新的知识库来弥补它的不足——这就是 检索增强生成(RAG) 出现的背景。
2. RAG的定义
检索增强生成(Retrieval-Augmented Generation, RAG) 是一种结合信息检索与文本生成的混合范式。其核心思想是:
-
检索:从外部知识库(文档、数据库、向量库等)中找到与用户问题相关的内容。
-
增强:将检索到的内容作为额外上下文,拼接到提示词中。
-
生成:LLM 在增强后的上下文基础上生成答案。
这样,RAG 既能利用 LLM 的语言生成能力,又能借助外部知识库保证答案的准确性、时效性和可解释性。
3. RAG的三大范式
RAG 的发展大致可以分为三个层次(或范式):
| 范式 | 核心特征 | 优点 | 局限 |
|---|---|---|---|
| Naive RAG | 简单检索 + 拼接上下文 | 实现容易,适合做原型(初步模型) | 检索粗糙,易受噪声干扰 |
| Advanced RAG | 引入重排序、过滤、动态上下文选择 | 提高相关性与答案质量 | 架构更复杂,需额外计算 |
| Agentic RAG | 多智能体协作,带推理链与任务分解 | 可处理复杂问题,具备自适应能力 | 设计难度高,计算开销大 |
4. Prompt 工程 vs RAG vs Fine-tuning
除了 RAG 之外,提升大语言模型能力的常见手段还包括 Prompt 工程 和 Fine-tuning。三者在原理、成本和适用场景上各有不同。
先前的文章里介绍过Prompt工程,此处不再赘述,只简单介绍Fine-tuning。Fine-tuning是在预训练模型基础上,用特定领域数据继续训练,让模型更适应某个任务或领域。可以理解为让一个刚毕业的高中生选择某个专业(如医学),然后进行学习训练,最终成为专业的医生。接下来,我们将比较这三者的差别。
| 方法 | 是否改动模型 | 成本 | 知识更新 | 优势 | 局限 | 典型场景 |
|---|---|---|---|---|---|---|
| Prompt 工程 | ❌ 不改动 | 低 | 无法更新知识 | 简单灵活,快速试验 | 效果不稳定,难以解决知识缺失 | 原型验证、轻量级应用 |
| RAG | ❌ 不改动 | 中 | 更新知识库即可 | 时效性强,可解释性好 | 依赖检索质量,架构更复杂 | 企业知识库问答、科研助手 |
| Fine-tuning | ✅ 改动 | 高 | 需重新训练 | 针对性强,性能提升大 | 成本高,更新慢 | 专业化任务(法律、医疗、金融) |
😈 选择 Prompt 工程、RAG 还是 Fine-tuning,取决于你的任务复杂度、数据可控性和资源预算。一般建议:轻量任务优先 Prompt 工程,知识密集型任务用 RAG,高精度定制任务考虑 Fine-tuning。
二、Naive RAG Pipeline
在上一节中,我们介绍了 RAG(Retrieval-Augmented Generation)的基本概念和三大范式。现在,我们将从最基础的 Naive RAG Pipeline 开始,手把手带你构建一个最小可用的 RAG 系统,帮助大语言模型“读懂”你的知识库,并基于外部文档回答问题。
我们可以将 Naive RAG 的核心流程拆解为四个步骤:
- 准备目标文档(Load):收集你希望大模型“参考”的资料,比如产品手册、论文、FAQ 等,并导入大模型。
- 文档切片(Split):将长文档切成小块(chunk),便于后续处理。
- 向量化(Embed & Store):将每个文本块转化为向量(embedding),存入向量数据库。
- 问答检索(Query):用户提问时,从向量库中找出最相关的文本块,拼接到 Prompt 中交给大模型生成答案。
接下来我们将详细拆解步骤。
1. 知识库构建
(1)文档加载与摄取
第一步是将你的原始资料导入系统。常见的文档来源包括:
- PDF、Word、Markdown、TXT 等本地文件
- 网页内容(通过爬虫或 API 抓取)
- 数据库或企业知识库导出内容
PS:常用工具
- langchain.document_loaders:支持多种格式的文档加载器
- PyMuPDF、pdfplumber:用于解析 PDF
- BeautifulSoup:用于解析 HTML 网页
from langchain.document_loaders import PyMuPDFLoader
loader = PyMuPDFLoader("example.pdf")
docs = loader.load()
(2) 文档分块策略
大语言模型的输入长度有限(如 4K、8K、32K tokens),所以我们需要将长文档切分成更小的“语义单元”,每个单元称为一个 chunk。
常见分块策略:
- 按段落/句子/章节切分:每段/句/章为一个 chunk,适合结构清晰的文档。
- 固定长度滑窗:每 N 个 token 为一个 chunk,支持重叠(overlap)以保留上下文。
- 按语义切分:使用句法分析或语义边界进行智能切分(如 NLTK、spaCy)。
示例代码(固定长度切分):
from langchain.text_splitter import RecursiveCharacterTextSplitter
splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=100)
chunks = splitter.split_documents(docs)
2. 索引&向量化
(1)Embedding向量化
📌 什么是向量化?
向量化(Embedding)是将文本转化为多维空间中的向量表示,使得语义相近的文本在向量空间中距离更近。这样我们就可以用“找最近的向量”来实现语义检索。
🔧 向量化实践
- 使用API向量化(如OpenAI)
from langchain.embeddings import OpenAIEmbeddings
embedding_model = OpenAIEmbeddings()
vectors = embedding_model.embed_documents([chunk.page_content for chunk in chunks])
- 本地部署向量模型(如Ollama + Instractor)
如果你希望在本地运行向量模型(例如在隐私敏感场景),可以使用 Ollama + instructor-embedding 模型:
ollama run nomic-embed-text
然后通过 HTTP 请求或 Langchain 的 HuggingFaceEmbeddings 接口调用本地服务。
(2)向量间的相似度计算
当用户提问时,我们会将问题也向量化,然后与知识库中的所有向量进行相似度计算,找出最相关的几个 chunk。
常见相似度指标
| 指标 | 公式 | 特点 |
|---|---|---|
| 余弦相似度 | $$\cos(\theta) = \frac{\vec{A} \cdot \vec{B}}{|\vec{A}| |\vec{B}|}$$ | 衡量方向相似度,常用于文本 |
| 欧氏距离(L2) | $$L_2(A, B) = \sqrt{\sum_{i=1}^{n} (a_i - b_i)^2}$$ | 衡量距离远近,受向量长度影响较大 |
实际使用中,向量数据库通常默认使用余弦相似度。
(3)Indexing:构建向量索引
为了加速向量检索,我们需要将向量存入一个支持高效相似度搜索的数据库,称为向量数据库(Vector DB)。
- 主流向量数据库功能对比
| 向量数据库 | 特点 | 是否开源 | 适合场景 |
|---|---|---|---|
| FAISS | Facebook 开源,轻量、快速 | ✅ | 本地开发、原型验证 |
| Milvus | 分布式、支持亿级数据 | ✅ | 企业级部署 |
| Weaviate | 内建 REST API,支持多模态 | ✅ | 快速集成、云部署 |
| Pinecone | 托管服务,免运维 | ❌ | 商业化应用,快速上线 |
- 如何选型向量数据库
| 需求 | 选择 |
|---|---|
| 本地开发 | FAISS、Chroma |
| 需要 REST API / 多语言支持 | Weaviate |
| 大规模部署 | Milvus、Qdrant |
| 不想自己运维 | Pinecone、Zilliz Cloud |
三、常见误区小节
- ❌ “我是不是要先训练一个模型才能用 RAG?” → 不需要,RAG 是无模型改动的增强方式。
- ❌ “我是不是要把所有文档都一次性向量化?” → 可以分批处理,支持增量更新。
- ❌ “向量越多越好?” → 不一定,质量比数量更重要,太多会影响检索效率。
本篇内容聚焦于 RAG 的原理与流程,帮助你建立清晰的认知框架。下一篇我们将动手搭建一个最小可运行的 RAG 系统,从环境配置到代码实现,一步步带你跑通整个流程。

浙公网安备 33010602011771号