RAG(检索增强生成)

#2025/12/31 #ai

目录

一、什么是RAG?为什么需要它?

核心定义

RAG = Retrieval-Augmented Generation(检索增强生成)

简单理解

传统LLM:直接回答问题(可能瞎编)  
RAG系统:先搜索资料 → 再基于资料回答(有据可依)  

问题场景:LLM的“幻觉“

用户问:"2023年世界杯冠军是谁?"  
纯LLM回答:"我认为是巴西队。" # ❌ 自信但错误!  

RAG系统:  
1. 先搜索2023年世界杯结果  
2. 找到真实资料  
3. 基于资料回答:"根据搜索结果[1],2023年世界杯冠军是..."  

LLM的三大问题

  • ❌ 训练数据有时效性(可能过时)
  • ❌ 会编造听起来合理但错误的答案(幻觉)
  • ❌ 无法访问实时信息或专有数据

二、RAG的工作原理

基础架构图解

{%}

**图:基础 RAG 流程包含检索与生成两个核心环节。LLM 接收用户问题时,检索模块获取的信息将作为提示词被输入 LLM,进而生成基于事实的答案

RAG包含两个核心步骤:

用户问题:"MacBook Pro多少钱?"  
    ↓  
① [步骤1:检索]  
搜索相关文档  
    ↓  
找到Top 3相关文档:  
- 文档1:"MacBook Pro价格$2,249"  
- 文档2:"M3芯片版本配置"  
- 文档3:"官网优惠信息"  
    ↓  
[步骤2:生成]  
② 把问题+文档一起输入LLM  
    ↓  
LLM生成答案:  
"根据搜索结果[1],MacBook Pro目前价格是 $2,249。  
官方渠道[3]可能有优惠活动。"  

更详细的流程图

{%}|624

图 :生成式搜索在搜索流程的末端生成答案和摘要,同时引用其来源(由搜索系统的前序步骤返回)

用户问题  
    ↓  
1) 检索阶段  
   - 搜索文档库  
   - 使用稠密检索/重排序  
   - 获取最相关的Top K文档  
    ↓  
2) 生成阶段  
   - 将问题+检索结果作为上下文  
   - 输入LLM  
   - 生成带引用的答案  
    ↓  
输出:  
"This is one possible answer to your question [1],   
although others have also pointed out this other   
possible answer. [2][3]"  

关键特点

  • ✅ 答案基于真实文档
  • ✅ 标注信息来源
  • ✅ 减少幻觉现象

三、从搜索到RAG:核心升级

传统搜索 vs RAG

维度传统搜索RAG
输出文档链接列表完整的答案
用户体验需要自己阅读多篇文档直接得到答案
引用标注来源
准确性取决于文档质量由LLM整合多源信息

升级的本质

{%}

图:通过比较嵌入向量之间的相似度,找到与输入提示词相关性最高的信息。在将提示词提供给 LLM 之前,将其添加到提示词中

在搜索流程末端接入LLM

原始搜索系统:  
查询 → 检索 → 返回文档列表 ✓  

RAG系统:  
查询 → 检索 → 返回文档列表 → LLM生成答案 ✓✓  

四、使用LLM API实现RAG

实战案例:用Cohere API 构建 RAG

import cohere  
co = cohere.Client("YOUR_API_KEY")  

# 用户查询  
query = "income generated"  

# 步骤1:检索  
# 使用嵌入式搜索获取相关文档  
results = search(query)  # 假设这是之前实现的搜索函数  

# 步骤2:基于知识的生成  
# 将文档转换为Cohere要求的格式  
docs_dict = [{'text': text} for text in results['texts']]  

# 调用Cohere的chat端点  
response = co.chat(  
    message=query,  
    documents=docs_dict  # 关键:传入检索到的文档  
)  

print(response.text)  

输出示例

输出:  
The film generated a worldwide gross of over $677 million,   
or $773 million with subsequent re-releases.  

神奇之处

  • LLM自动识别文档来源
  • 自动提取关键信息
  • 生成简洁的答案

查看引用信息

# Cohere会标注哪些文本来自哪个文档  
print(response.citations)  

输出

citations=[  
    ChatCitation(start=21, end=36, text='worldwide gross',   
                 document_ids=['doc_0']),  
    ChatCitation(start=40, end=57, text='over $677 million',   
                 document_ids=['doc_0']),  
    ...  
]  

价值:用户可以追溯信息来源,验证准确性!


五、 使用本地模型实现RAG

为什么需要本地模型?

API方案:  
✅ 简单易用  
❌ 需要付费  
❌ 数据上传到外部  
❌ 网络依赖  

本地模型方案:  
✅ 完全免费  
✅ 数据私密  
✅ 无网络依赖  
❌ 需要自己搭建  

完整实现步骤

步骤1:加载生成模型

from langchain import LlamaCpp  

# 加载量化的Phi-3模型  
llm = LlamaCpp(  
    model_path="Phi-3-mini-4k-instruct-q4.gguf",  
    n_gpu_layers=-1,      # 使用GPU加速  
    max_tokens=500,  
    n_ctx=2048,           # 上下文长度  
    seed=42,  
    verbose=False  
)  

步骤2:加载嵌入模型

from langchain.embeddings.huggingface import HuggingFaceEmbeddings  

# 用于生成文档向量  
embedding_model = HuggingFaceEmbeddings(  
    model_name='BAAI/bge-small-en-v1.5'  # 小而强的嵌入模型  
)  

步骤3:创建向量数据库

from langchain.vectorstores import FAISS  

# 假设我们有一些文本数据  
texts = [  
    "The film had a worldwide gross over $677 million...",  
    "It became the tenth-highest grossing film of 2014...",  
    # ... 更多文档  
]  

# 创建本地向量数据库  
db = FAISS.from_texts(texts, embedding_model)  

步骤4:设计RAG提示词模板

这是关键! 需要告诉LLM如何使用检索到的信息:

from langchain import PromptTemplate  

template = """<|user|>   
Relevant information:  
{context}  

Provide a concise answer to the following question   
using the relevant information provided above:  
{question}<|end|>  
<|assistant|>"""  

prompt = PromptTemplate(  
    template=template,  
    input_variables=["context", "question"]  # 两个变量  
)  

模板说明

  • {context}:检索到的相关文档
  • {question}:用户的问题

步骤5:组装完整的RAG链

from langchain.chains import RetrievalQA  

# 创建RAG流程  
rag = RetrievalQA.from_chain_type(  
    llm=llm,                          # 生成模型  
    chain_type='stuff',               # 简单拼接方式  
    retriever=db.as_retriever(),      # 检索器  
    chain_type_kwargs={  
        "prompt": prompt              # 提示词模板  
    },  
    verbose=True  
)  

步骤6:测试RAG系统

# 提问  
response = rag.invoke('Income generated')  

print(response)  

输出

The Income generated by the film in 2014 was over $677 million   
worldwide. This made it the tenth-highest grossing film of that   
year. It should be noted, however, this figure includes both   
initial ticket sales as well as any subsequent re-releases.   
With these additional releases, total earnings surged to   
approximately $773 million. ...  

成功! 系统能够:

  • ✅ 检索相关文档
  • ✅ 基于文档生成答案
  • ✅ 提供详细信息

六、高级RAG技术

掌握基础RAG后,以下技术可以进一步提升系统性能:


技术1:查询改写

问题场景

# 用户的原始问题又长又啰嗦  
用户问:"我们明天有一篇关于动物的作文要交。我喜欢企鹅,  
可以写关于企鹅的。但我也可以写海豚。它们是动物吗?  
也许是吧。我们写海豚吧。比如,它们生活在哪里?"  

# 这样的问题搜索效果很差!  

解决方案

# 步骤1:用LLM改写查询  
改写后的查询:"海豚生活在哪里"  

# 步骤2:用改写后的查询进行检索  
results = search("海豚生活在哪里")  

# 步骤3:生成答案  

实现方式

  • 使用特定提示词
  • 使用API(如Cohere的co.chat有内置改写

技术2:多查询RAG

问题场景

用户问:"比较NVIDIA 2020年与2023年的财报。"  

# 问题:需要对比两年的数据  
# 解决:生成多个独立查询  

处理流程

# 步骤1:拆分为多个查询  
查询1 = "NVIDIA 2020年财报"  
查询2 = "NVIDIA 2023年财报"  

# 步骤2:分别检索  
results_2020 = search(查询1)  
results_2023 = search(查询2)  

# 步骤3:合并结果后生成答案  
combined_context = results_2020 + results_2023  
answer = llm.generate(问题, combined_context)  

优势:能够处理需要多源信息的复杂问题!


技术3:多跳 RAG

针对需要分步推理的复杂问题,系统需执行连续检索。

问题场景

用户问:"2023年排名最靠前的汽车制造商有哪几个?  
它们是否都生产电动汽车?"  

# 需要分步推理  

处理流程

# 第1跳  
查询1 = "2023年排名最靠前的汽车制造商"  
results1 = search(查询1)  
制造商列表 = ["丰田", "大众", "现代"]  # 从结果中提取  

# 第2跳:为每个制造商生成后续查询  
查询2a = "丰田是否生产电动汽车"  
查询2b = "大众是否生产电动汽车"  
查询2c = "现代是否生产电动汽车"  

results2 = [search(q) for q in [查询2a, 查询2b, 查询2c]]  

# 综合所有结果生成最终答案  

核心思想:像人类一样,一步步推理解决复杂问题!


技术4:路由RAG

问题场景

企业有多个数据源:  
- 人力资源系统(Notion)  
- 客户管理系统(Salesforce)  
- 内部文档(SharePoint)  

如何根据问题自动选择正确的数据源?  

解决方案

# 步骤1:LLM判断问题类型  
if 问题涉及人力资源:  
    数据源 = "Notion知识库"  
elif 问题涉及客户数据:  
    数据源 = "Salesforce CRM"  
else:  
    数据源 = "SharePoint文档"  

# 步骤2:从对应数据源检索  
results = search(问题, 数据源)  

# 步骤3:生成答案  

技术5:智能体RAG

核心思想

把数据源抽象为“工具“,让智能体自主决定:

  • 是否需要检索
  • 检索哪个数据源
  • 是否需要多次检索
  • 何时给出最终答案
用户问:"帮我在Notion发布本周工作总结"  

智能体推理:  
思考:这需要两个步骤  
行动1:从Notion检索工作记录  
观察1:获取到本周任务列表  
思考:现在可以总结了  
行动2:调用Notion API发布内容  
观察2:发布成功  
最终答案:"已发布本周工作总结到Notion"  

七、RAG效果评估

为什么需要评估?

问题:  
如何判断你的RAG系统是好是坏?  
如何对比两个不同的RAG系统?  

解决:  
需要标准化的评估指标  

四大核心评估维度

如论文“Evaluating Verifiability in Generative Search Engines“(2023)所述:

1. 流畅性(Fluency)

定义:生成文本的语言流畅度与逻辑连贯性

评估示例

# 好的输出  
"MacBook Pro价格是$2,249,采用M3芯片,性能强劲。"  
✅ 语言流畅,逻辑清晰  

# 差的输出  
"MacBook Pro $2,249 M3芯片 性能 强劲"  
❌ 不流畅,像关键词堆砌  

2. 感知效用(Perceived Utility)

定义:回答内容的信息价值与实用价值

评估示例

用户问:"如何提升网站SEO?"  

# 高效用答案  
"提升SEO的三个关键步骤:  
1. 优化关键词密度  
2. 提升页面加载速度  
3. 增加高质量外链"  
✅ 实用、可操作  

# 低效用答案  
"SEO很重要,你应该优化它。"  
❌ 空泛,没有实用信息  

3. 引用召回率(Citation Recall)

定义:生成答案中引用的信息占检索文档的比例

计算方式

# 检索到3个相关文档  
文档1:价格信息  
文档2:配置信息  
文档3:优惠信息  

# 生成的答案  
"MacBook Pro价格$2,249[1],采用M3芯片[2]。"  

引用召回率 = 引用文档数 / 相关文档总数  
           = 2 / 3  
           = 0.67  

意义:衡量是否充分利用了检索到的信息

4. 答案相关性(Answer Relevance)

定义:答案与提问主题的契合度

评估示例

用户问:"MacBook Pro价格"  

# 高相关性  
"MacBook Pro价格是$2,249"  
✅ 直接回答问题  

# 低相关性  
"MacBook Pro是苹果公司推出的笔记本电脑系列..."  
❌ 没有回答价格问题  

自动化评估工具

Ragas 框架

from ragas import evaluate  
from ragas.metrics import (  
    faithfulness,  
    answer_relevancy,  
    context_recall,  
    context_precision,  
)  

# 准备评估数据  
evaluation_data = {  
    "question": ["MacBook Pro多少钱?"],  
    "answer": ["价格是$2,249"],  
    "contexts": ["MacBook Pro价格$2,249..."](/post/94z1807pj5.html#"MacBook-Pro价格$2,249"),  
    "ground_truth": ["$2,249"]  
}  

# 运行评估  
results = evaluate(  
    evaluation_data,  
    metrics=[  
        faithfulness,        # 忠实度  
        answer_relevancy,    # 答案相关性  
        context_recall,      # 上下文召回  
        context_precision,   # 上下文精度  
    ]  
)  

print(results)  

八、RAG的实际应用场景

场景1:企业知识库问答

传统方式:  
员工:"公司的请假政策是什么?"  
→ 打开300页PDF员工手册  
→ 搜索"请假"关键词  
→ 阅读多个章节  
→ 自己总结政策 😓  

RAG方式:  
员工:"公司的请假政策是什么?"  
→ RAG系统自动检索相关章节  
→ LLM总结并回答  
→ 附上原文页码引用  
→ 1秒得到答案!😊  

场景2:生成式搜索引擎

代表产品:Perplexity、Microsoft Copilot、Google Gemini

传统搜索引擎:  
查询:"Python如何读取CSV文件?"  
返回:10个网页链接  
用户:需要点开多个链接,自己找答案  

RAG搜索引擎:  
查询:"Python如何读取CSV文件?"  
返回:  
"使用pandas库读取CSV的方法[1]:  
import pandas as pd  
df = pd.read_csv('file.csv')  
[来源:pandas官方文档]"  
用户:直接得到答案和代码!  

场景3:“与我的数据对话”

场景:CEO想了解销售情况  

传统方式:  
1. 联系数据分析师  
2. 等待报表制作  
3. 开会讨论  
时间:几天  

RAG方式:  
CEO:"上季度哪个产品卖得最好?"  
RAG系统:  
→ 检索销售数据库  
→ 分析数据  
→ 生成回答  
时间:几秒钟  

九、RAG的优势与局限

核心优势

维度纯LLMRAG
事实准确性❌ 容易幻觉✅ 基于真实文档
信息时效性❌ 训练数据过时✅ 实时检索最新信息
可解释性❌ 无法追溯来源✅ 标注信息来源
专有数据❌ 无法访问✅ 可接入企业数据
可信度

注意事项

1. 检索质量影响生成质量

# 如果检索到的文档不相关  
→ LLM生成的答案也会不准确  

解决方案: 
- 提升检索精度(使用重排序)  
- 增加查询改写  
- 优化嵌入模型  

2. 需要验证机制

问题:RAG系统是自动的,如何保证答案质量?  

建议:  
✅ 要求返回信息来源URL  
✅ 添加置信度评分  
✅ 关键决策加人工确认  
✅ 定期人工抽查  

3. 成本考虑

成本项说明
计算检索+生成需要两次计算
存储向量数据库需要存储空间
API使用托管API需要付费

十、核心要点总结

1. RAG的本质

RAG = 搜索系统的智能升级  

传统搜索:问题 → 文档列表  
RAG系统:问题 → 文档 → 智能答案  

2. 两大核心步骤

步骤1:检索(Retrieval)  
- 使用语义搜索找相关文档  
- 可用稠密检索、重排序等技术  

步骤2:生成(Generation)  
- 把问题+文档输入LLM  
- 生成带引用的准确答案  

3. 关键技术栈

# 基础RAG  
嵌入模型 → 向量数据库 → 检索器 → LLM → 答案  

# 高级RAG  
查询改写 → 多查询 → 多跳推理 → 路由 → 智能体  

4. 评估指标

流畅性:语言是否自然  
感知效用:信息是否有用  
引用召回率:是否充分利用检索结果  
答案相关性:是否回答了问题  

5. 实现方式对比

方式优点缺点适用场景
API方案简单快速付费、数据外传快速原型
本地模型免费、私密需要搭建生产环境
混合方案灵活复杂度高企业级应用

核心启示

RAG的革命性意义

  1. 解决了LLM的致命缺陷
    • 不再瞎编答案
    • 能够获取最新信息
    • 可以访问专有数据
  2. 提升了搜索体验
    • 从“找文档“到“得答案“
    • 从“自己阅读“到“智能总结“
    • 从“无据可查“到“标注来源“
  3. 开启了新的可能
    • 企业知识库智能化
    • 客服机器人精准化
    • 研究助手专业化

RAG不是让LLM更聪明,而是让LLM有据可依!

就像给学生配上了图书馆——既能独立思考,又能查阅资料,还能标注引用!

现在你已经掌握了RAG的核心原理和实现方法,下一章我们将学习如何让LLM“看懂“图片——多模态LLM技术!