news 2026/7/12 11:57:12

一文搞懂 RAG(检索增强生成):从 LLM 幻觉到智能检索,手把手带你理解核心原理与代码实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
一文搞懂 RAG(检索增强生成):从 LLM 幻觉到智能检索,手把手带你理解核心原理与代码实现

引言

想象一下这个场景:你问 ChatGPT 一个关于你们公司内部制度的问题,它信誓旦旦地给出一段看似合理、实则完全编造的答案——这就是大模型的幻觉(Hallucination)。

大模型就像一个知识渊博但"与世隔绝"的学者,它的知识截止于训练数据的日期。之后发生的事情、你企业内部没有公开的文档,它全都不知道。但关键问题在于——它不会承认自己不知道,而是会一本正经地胡说八道。

那怎么解决呢?答案就是我们今天的主角——RAG(Retrieval-Augmented Generation,检索增强生成)


一、大模型的幻觉从何而来?

1.1 大模型的知识边界

LLM(大语言模型)的知识完全取决于训练时喂给它的数据集。训练数据里没有的东西,它就不可能"知道"。这带来了几个结构性的问题:

问题描述
📚知识有截止日期训练数据只覆盖到某一时间点,之后的新信息它无从得知
🔒无法访问私有数据企业内部文档、机密资料不会出现在公开训练数据中
💬不懂装懂面对不知道的问题,模型倾向于"编造"而非承认无知
1.2 幻觉的本质

所谓"幻觉",就是模型生成的内容与事实不符。这并非模型故意撒谎,而是因为:

  • 模型的输出本质上是概率性的——它只是在预测下一个最可能的 token
  • 当模型缺乏相关知识时,它依然会根据语言模式"推测"出一个答案
  • 这个推测在语言上可能通顺,但在事实上可能完全错误

核心矛盾:用户要查询的内容,模型不知道;模型却能生成一段看似合理的回答。


二、解决幻觉的两条路:Fine-tuning vs RAG

想一下,怎么让大模型知道它不知道的东西?

2.1 微调(Fine-tuning)

把新知识直接训练进模型参数里。

  • 优点:知识融入模型本身,推理时无需额外检索
  • 缺点:成本高昂,需要大量标注数据和 GPU 算力,而且知识更新就要重新训练
2.2 RAG(检索增强生成)

不给模型"植入记忆",而是在提问前先去知识库里查资料,把查到的内容塞进 Prompt 里再让模型回答。

  • 优点:成本低,知识库随时更新,可解释性强
  • 缺点:依赖检索质量,检索不到就回答不了

类比理解:

  • Fine-tuning= 让一个人去上全日制大学(时间长、成本高、知识固化)
  • RAG= 给一个人配了搜索引擎和百科全书(随时查、成本低、知识实时更新)

对于大多数企业场景来说,RAG 是现阶段性价比最高的方案。


三、什么是 RAG?

3.1 名词拆解
单词含义
Retrieval(检索)去知识库里检索与用户问题相关的文档片段
Augmented(增强)把检索到的内容作为背景知识,增强到 Prompt 里
Generation(生成)让大模型基于增强后的 Prompt 生成回答
3.2 RAG 的工作流程
用户提问 → 检索知识库(找到相关文档片段)→ 拼接到 Prompt 中 → 大模型生成回答

具体来说:

  1. 用户提出一个问题
  2. 去知识库中检索—— 找到与问题语义最相关的文档片段(分片:按章节/按页/按段落切分的自然语义段落)
  3. 拼接到 Prompt 中—— 把检索到的文档片段作为背景知识,加入原始 Prompt
  4. 大模型回答—— 基于这些背景知识生成准确、可靠的回答

这就是 RAG 的整个流程:先检索,再增强,最后生成

四、核心技术:从关键词到向量语义搜索

4.1 关键词搜索为什么不太行?

传统搜索依赖文本匹配

  • 你搜"苹果好吃吗" → 匹配到包含"苹果"的文档
  • 但如果你搜"那种红色的、咬起来嘎嘣脆的水果怎么样?" → 关键词匹配可能完全找不到"苹果"相关内容

问题所在:语言表达千变万化,同一个意思可以有无数种说法。关键词搜索无法理解语义。

4.2 向量语义搜索

这就是 RAG 的第一个技术突破:向量(Vector)语义搜索

核心思想:把文字转换成一个多维空间中的坐标(向量),语义相近的文字在空间中离得近。

用一个直观的例子理解:

假设我们定义两个维度来描述食物:

  • 维度一(食用性):0 = 不可食用,1 = 高度可食用
  • 维度二(硬度):0 = 液体状,1 = 非常坚硬

那么:

食物向量坐标 [食用性, 硬度]
🍎 苹果[0.9, 0.3]
🍌 香蕉[0.9, 0.1]
🍓 水果(抽象概念)[0.9, 0.3]
🪨 石头[0.1, 0.9]

向量空间中:

  • 苹果水果的距离很近([0.9, 0.3] ≈ [0.9, 0.3])→ 语义高度相关 ✅
  • 苹果香蕉的距离也较近([0.9, 0.3] vs [0.9, 0.1])→ 水果之间语义相关 ✅
  • 苹果石头的距离很远([0.9, 0.3] vs [0.1, 0.9])→ 语义无关 ❌

这只是一个 2 维的简化示例。在实际应用中,向量通常有几百到上千个维度,可以表达极其丰富的语义信息。

4.3 相似度计算

两个向量的相似度通常用**余弦相似度(Cosine Similarity)**来衡量:

  • 夹角越小 → 余弦值越接近 1 → 语义越相似
  • 夹角越大 → 余弦值越接近 -1 → 语义越不相似

通过这种方式,即使用户的提问用词完全不同,只要能映射到相近的向量空间位置,就能找到语义相关的文档。


五、嵌入模型(Embedding Model)

要把文字变成向量,就需要一个专门的模型——嵌入模型(Embedding Model)

5.1 Embedding Model vs Generative Model
类型用途成本
Embedding Model将文本转换为向量表示💰 相对便宜
Generative Model(如 GPT、Claude)生成文本、对话、推理💰💰💰 昂贵

RAG 中两种模型配合使用:

  • Embedding Model:负责把知识库文档和用户问题都向量化
  • Generative Model:负责根据检索结果生成最终回答
5.2 能处理多种数据格式

Embedding 技术不仅限于文字,还可以处理:

  • 📝 文本(txt、markdown、pdf)
  • 🖼️ 图片(通过多模态 embedding 模型)
  • 🎤 语音(先转文字再 embedding)
  • 📊 各种格式的文档

所有内容向量化后,就都能进行语义搜索了。


六、RAG 的两个关键突破

6.1 文档怎么切分(Chunking)

知识库里的文档往往很长,不可能一次性全部放入 Prompt(有上下文长度限制)。需要把文档切分成一个个有独立语义的片段(Chunk)。

切分策略可以按:

策略适用场景示例
📖 按章节结构化文档、书籍第一章、第二章...
📄 按页PDF 等固定版式文档第1页、第2页...
📝 按段落一般文章、文档每个自然段落一个 chunk
✂️ 按固定大小通用策略每 512 tokens 一个 chunk(可重叠)

好的切分策略是 RAG 效果的关键之一。切得太大 → 检索不精准;切得太小 → 丢失上下文语义。

6.2 文档怎么查(向量检索)

第二个突破:向量数据库(Vector Database)

传统数据库(MySQL、PostgreSQL 等)无法高效处理向量的相似度搜索。向量数据库专为此而生:

  • 📊存储向量:将切割后的文档片段通过 embedding 模型转换成向量存储起来
  • 🔍相似度搜索:查询时,把用户问题也向量化,在数据库中找最相似的向量
  • 高性能:支持海量向量的快速检索(通过 ANN / 近似最近邻算法)
  • 💾持久化存储:数据不丢失,可反复使用

常见向量数据库:Milvus、Pinecone、Weaviate、Qdrant、Chroma 等。


七、RAG 完整架构图

把整个流程串起来,RAG 的完整架构如下:

┌─────────────────────────────────────────────────────────────────┐ │ RAG 系统架构 │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ ┌──────────┐ ┌──────────────┐ ┌──────────────────┐ │ │ │ 知识库文档 │ ──► │ 文档切分 │ ──► │ Embedding Model │ │ │ │ (txt/pdf/ │ │ (Chunking) │ │ (文本 → 向量) │ │ │ │ md/...) │ │ │ │ │ │ │ └──────────┘ └──────────────┘ └────────┬─────────┘ │ │ │ │ │ ▼ │ │ ┌──────────────────┐ │ │ │ 向量数据库 │ │ │ │ (存储+索引) │ │ │ └────────┬─────────┘ │ │ │ │ │ ┌──────────┐ ┌──────────────┐ │ │ │ │ 用户问题 │ ──► │ Embedding │ ────────────┘ │ │ │ │ │ (问题→向量) │ 相似度搜索 │ │ └──────────┘ └──────────────┘ │ │ │ ▼ │ │ ┌──────────────────┐ │ │ │ 相关文档片段 │ │ │ │ (检索结果Top-K) │ │ │ └────────┬─────────┘ │ │ │ │ │ ▼ │ │ ┌──────────────────────────────────────────────────────┐ │ │ │ 增强后的 Prompt = 原始问题 + 检索到的背景文档片段 │ │ │ └──────────────────────────┬───────────────────────────┘ │ │ │ │ │ ▼ │ │ ┌──────────────────┐ │ │ │ Generative Model │ │ │ │ (生成最终回答) │ │ │ └──────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────┘

一句话总结:

在原始 Prompt 给到大模型之前,先查询知识库,把相关的文档片段作为背景知识加入到 Prompt 里,再让大模型回答。这就是 RAG。


八、代码实战:用 LangChain 构建 RAG 系统

光说不练假把式,我们来看一个基于 LangChain 的 RAG 实现示例。

8.1 环境准备
{ "name": "rag-test", "dependencies": { "@langchain/core": "^1.2.2", "@langchain/openai": "^1.5.5", "dotenv": "^17.4.2" } }

三个核心依赖:

  • @langchain/openai:统一封装 OpenAI 兼容的 LLM 和 Embedding 接口
  • @langchain/core:LangChain 核心库,提供 Document、Tool 等抽象
  • dotenv:环境变量管理
8.2 初始化模型
import 'dotenv/config' import { ChatOpenAI, OpenAIEmbeddings } from 'langchain/openai' import { Document } from 'langchain/core/documents' // 初始化 Chat 模型(用于最终生成回答) const model = new ChatOpenAI({ temperature: 0, // 温度设为 0,确保回答稳定 model: process.env.MODEL_NAME, // 例如:gpt-4o / deepseek-chat apiKey: process.env.OPENAI_API_KEY, configuration: { baseURL: process.env.OPENAI_BASE_URL, } }) // 初始化 Embedding 模型(用于文本向量化) const embeddings = new OpenAIEmbeddings({ apiKey: process.env.OPENAI_API_KEY, model: process.env.EMBEDDINGS_MODEL_NAME, // 例如:text-embedding-3-small configuration: { baseURL: process.env.OPENAI_BASE_URL, } })

关键点

  • temperature: 0→ 确保回答的确定性和一致性(RAG 场景不需要创造性)
  • Embedding 模型和 Chat 模型是两个独立的模型,各司其职
8.3 构建知识库文档

我们用一个关于"光光和东东"的儿童故事作为知识库:

const documents = [ new Document({ pageContent: `光光是一个活泼开朗的小男孩,他有一双明亮的大眼睛, 总是带着灿烂的笑容。光光最喜欢的事情就是和朋友们一起玩耍,他特别 擅长踢足球,每次在球场上奔跑时,就像一道阳光一样充满活力。`, metadata: { chapter: 1, character: "光光", type: "角色介绍", mood: "活泼" }, }), new Document({ pageContent: `东东是光光最好的朋友,他是一个安静而聪明的男孩。 东东喜欢读书和画画,他的画总是充满了想象力。虽然性格不同,但东东 和光光从幼儿园就认识了,他们一起度过了无数个快乐的时光。`, metadata: { chapter: 2, character: "东东", type: "角色介绍", mood: "温馨" }, }), new Document({ pageContent: `有一天,学校要举办一场足球比赛,光光非常兴奋, 他邀请东东一起参加。但是东东从来没有踢过足球,他担心自己会拖累 光光。光光看出了东东的担忧,他拍着东东的肩膀说:"没关系,我们 一起练习,我相信你一定能行的!"`, metadata: { chapter: 3, character: "光光和东东", type: "友情情节", mood: "鼓励", }, }), // ... 更多文档片段 ]

Document 的两个核心字段:

字段作用是否参与向量化
pageContent文档正文内容,是检索匹配的核心✅ 是
metadata元信息(章节、角色、类型、情感等),用于后续过滤和溯源❌ 否

metadata不参与向量化计算,但它非常重要——可以帮助你在检索后做元数据过滤来源标注分类展示等。

提问:

const question = '光光和东东怎么成为朋友的?'
8.4 RAG 检索流程(核心逻辑扩展)

虽然原始代码在此处结束了,但完整的 RAG 流程应该是这样的:

// Step 1: 将知识库文档向量化并存入向量数据库 const vectorStore = await MemoryVectorStore.fromDocuments( documents, embeddings ) // Step 2: 将用户问题向量化,并在向量数据库中检索 const relevantDocs = await vectorStore.similaritySearch(question, 3) // 返回与问题语义最相似的前 3 个文档片段 // Step 3: 构建增强后的 Prompt const context = relevantDocs.map(doc => doc.pageContent).join('\n\n') const augmentedPrompt = ` 请基于以下背景知识回答问题。如果背景知识中没有相关信息,请明确说明。 【背景知识】 ${context} 【用户问题】 ${question} 【回答】 ` // Step 4: 调用大模型生成回答 const response = await model.invoke(augmentedPrompt) console.log(response.content)

预期的大模型回答(基于检索到的文档):

光光和东东从幼儿园就认识了。虽然性格不同——光光活泼开朗、擅长踢足球,东东安静聪明、喜欢读书画画——但他们从幼儿园开始就是最好的朋友。光光邀请东东一起参加足球比赛,并耐心地教东东踢球;东东也为光光画画作为回报。在足球比赛中,东东传出一个漂亮的球,光光射门得分,他们的友谊变得更加深厚了。

这样的回答完全基于知识库中检索到的真实内容,不会产生幻觉


九、RAG 在 Agent 生态系统中的定位

RAG 不是一个孤立的技术,它是构建AI Agent的核心模块之一。

9.1 Agent 的公式
Agent = LLM + Memory + Tool + RAG + MCP + Skills
模块解决的问题说明
LLM基础推理能力大模型的"大脑"
Memory无状态问题记住上下文、用户偏好、项目规范
Tool无法操作外部世界调用 API、操作文件、执行命令
RAG知识盲区检索内部知识库获取私有信息
MCP跨进程/跨语言工具调用标准化 Tool 通信协议
Skills复杂任务编排可复用的"技能包"
9.2 RAG vs MCP:两种上下文扩展方式
  • RAG:先检索,再增强 —— 解决"知识不在训练数据中"的问题
  • MCP:跨进程提供 Tool + Resource —— 解决"工具跨语言/跨项目复用"的问题

两者并不互斥,可以结合使用。例如:通过 MCP 连接一个远程的知识库服务,然后在 Agent 内部用 RAG 的方式检索其中的文档。


十、RAG 的进阶挑战与优化方向

掌握 RAG 的基本概念只是第一步,在实际落地中你还会遇到这些挑战:

挑战描述优化方向
🔪文档切分策略chunk 太大检索不精准,太小丢失语义语义切分、滑动窗口、层级索引
🔍检索精度召回率 vs 准确率的平衡混合检索(向量+关键词)、ReRank 重排序
📊知识更新文档变更后如何同步增量索引、版本管理
🎯多轮对话后续问题可能指代之前的上下文Query 改写、对话历史向量化
🖼️多模态 RAG图片、表格、代码等非文本内容多模态 Embedding + 结构化解析

十一、总结

RAG(检索增强生成)的精髓可以用三句话概括:

  1. 大模型不知道的东西,它不会承认不知道,而是会胡说(幻觉)
  2. RAG 的核心思路:问之前先去知识库查一下,查到的东西塞进 Prompt 再让模型回答
  3. 向量 + 语义搜索是 RAG 实现的技术基石,嵌入模型把文字变成向量,向量数据库做相似度检索

从更大的视角看,RAG 是Harness Engineering(挽具工程)的典型代表之一。LLM 就像一个强大的引擎,但引擎再牛,没有好的变速箱、刹车和仪表盘,这辆车就没法上路。RAG 就是给模型装上了一个"知识检索系统",让它的能力可以被稳定、可靠地驾驭。

引擎是模型,Harness 就是装着引擎的车。RAG 是这辆车上最关键的零件之一。

学习资源推荐

如果你想更深入地学习大模型,以下是一些非常有价值的学习资源,这些资源将帮助你从不同角度学习大模型,提升你的实践能力。

一、全套AGI大模型学习路线

AI大模型时代的学习之旅:从基础到前沿,掌握人工智能的核心技能!​

因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获取

二、640套AI大模型报告合集

这套包含640份报告的合集,涵盖了AI大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师,还是对AI大模型感兴趣的爱好者,这套报告合集都将为您提供宝贵的信息和启示

​因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获取

三、AI大模型经典PDF籍

随着人工智能技术的飞速发展,AI大模型已经成为了当今科技领域的一大热点。这些大型预训练模型,如GPT-3、BERT、XLNet等,以其强大的语言理解和生成能力,正在改变我们对人工智能的认识。 那以下这些PDF籍就是非常不错的学习资源。

因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获取

四、AI大模型商业化落地方案

作为普通人,入局大模型时代需要持续学习和实践,不断提高自己的技能和认知水平,同时也需要有责任感和伦理意识,为人工智能的健康发展贡献力量。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/12 11:52:16

AUTOSAR SWC设计实战:基于DaVinci Developer的3个端口配置案例与ARXML生成

AUTOSAR SWC设计实战:基于DaVinci Developer的3个端口配置案例与ARXML生成 在汽车电子软件开发领域,AUTOSAR标准已经成为行业通用框架,而Vector的DaVinci Developer工具链则是实现这一标准的关键工程平台。对于刚接触AUTOSAR的工程师而言&…

作者头像 李华
网站建设 2026/7/12 11:50:52

QMK Toolbox:解锁机械键盘无限可能的魔法钥匙

QMK Toolbox:解锁机械键盘无限可能的魔法钥匙 【免费下载链接】qmk_toolbox A Toolbox companion for QMK Firmware 项目地址: https://gitcode.com/gh_mirrors/qm/qmk_toolbox 你是否曾经对键盘上的按键布局感到不满意?是否羡慕别人键盘上那些炫…

作者头像 李华
网站建设 2026/7/12 11:50:52

VC6.0环境下可直接编译的OpenGL雷达扫描演示程序(带动态余晖拖尾)

本文还有配套的精品资源,点击获取 简介:这是一个基于VC6.0和OpenGL开发的雷达界面可视化示例,核心功能包括:实时旋转的扫描线、扫描区域渐变衰减的余晖效果(通过帧缓冲叠加Alpha透明度逐帧衰减实现)、探…

作者头像 李华
网站建设 2026/7/12 11:50:34

3DMigoto皮肤MOD管理的终极解决方案:从混乱到秩序的技术演进

3DMigoto皮肤MOD管理的终极解决方案:从混乱到秩序的技术演进 【免费下载链接】d3dxSkinManage 3dmigoto skin mods manage tool 项目地址: https://gitcode.com/gh_mirrors/d3/d3dxSkinManage 在当今的游戏MOD管理领域,3DMigoto皮肤MOD的复杂性和…

作者头像 李华
网站建设 2026/7/12 11:50:22

子网掩码 /24 实战:3步计算网络、广播、主机地址(附Python脚本)

子网掩码 /24 实战:3步计算网络、广播、主机地址(附Python脚本)在局域网配置和网络故障排查中,快速计算网络地址、广播地址和可用主机范围是每个运维人员的基本功。本文将以最常见的/24子网掩码为例,通过三个标准化步骤…

作者头像 李华