RAG(检索增强生成)基础

1. 背景

大模型应用开发的三种模式,在选择使用哪种模式时,需要考虑 知识实时性专业深度 以及 模型幻觉控制

  1. Prompt(提示词工程) – 问题没问清楚
    • 通过精心设计提示词,引导大模型生成期望输出。
  2. RAG(Retrieval-Augmented Generation) – 缺乏背景知识
    • 结合信息检索与文本生成,实时检索外部知识增强生成能力。
  3. Fine-tuning(微调) – 模型能力不足
    • 用特定领域数据微调预训练模型,使其更适配任务。

快速搭建本地知识库:

  • 无代码轻量平台:difycoze
  • 有技术团队:LangChain + Llama-Index

2. RAG 技术概览

RAG(Retrieval-Augmented Generation)是一种结合了信息检索+文本生成的技术,它通过实时检索相关文档或信息,并将其作为上下文输入到大模型中,从而提升生成内容的时效性和准确性。

2.1 RAG 的优势

  • 解决知识时效性问题:大模型的训练数据通常是静态的,无法涵盖最新信息,而RAG可以实时检索外部知识库,确保信息是最新、最准确的。
  • 减少模型幻觉:通过引入外部知识,RAG能有效减少模型生成虚假或不准确内容的可能性。
  • 提升专业领域回答质量:RAG能够结合垂直领域的专业知识库,生成更具深度和专业性的回答。
  • 支持内容溯源:RAG生成的内容可以追溯到原始文档,增强了答案的可信度(即可解释性)。

2.2 核心原理和流程

Step 1:数据预处理,构建索引库

  1. 知识库构建:收集和整理来自文档、网页、数据库等多种来源的数据。
  2. 文档分块:将文档切分成大小适中的文本片段(chunks)。分块策略需要在语义完整性与检索效率之间取得平衡。
  3. 向量化处理:使用嵌入模型(如 BGE, M3E, Chinese-Alpaca-2 等)将文本块转换为向量,并存储在向量数据库中。
  • 收集多源数据 → 切分文档 chunk → 嵌入向量 → 写入向量库

Step 2:检索阶段

  1. 查询处理:将用户输入的问题转换为向量,然后在向量数据库中进行相似度检索,找到与问题最相关的文本片段。
  2. 重排序:对检索到的结果进行相关性排序,选出最相关的片段作为生成阶段的输入。
  • 将用户 Query 嵌入向量 → 相似度检索 → 重排序

Step 3:生成阶段

  1. 上下文组装:将检索到的文本片段与用户问题结合,构建成一个增强的上下文输入。
  2. 生成回答:大模型基于这个增强的上下文生成最终的回答。
  • 组装检索片段 + Query → LLM 生成回答

划重点:RAG 本质就是构造了一个更强大的 Prompt!

3. Native RAG 三步曲

阶段 关键问题 难点
Indexing 如何更好地把知识存起来 分块策略、向量化模型
Retrieval 如何精准检索少量有用知识 相似度计算、重排序
Generation 如何让模型用好检索结果 Prompt 构建、模型优化

4. LangChain快速搭建本地知识库检索

4.1. 环境准备

  1. 本地安装好 Conda 环境
  2. 推荐使用 ChatGPT 或者 阿里百炼
  3. 百炼平台使用
    • 注册登录
    • 申请api key

依赖安装:pip下面这些包到conda,pypdf2dashscopelangchainlangchain-openailangchain-communityfaiss-cpu,推荐Python 3.10

4.2. 搭建流程

  1. 文档加载,并按一定条件切割成片段
  2. 将切割的文本片段灌入检索引擎
  3. 封装检索接口
  4. 构建调用流程:Query -> 检索 -> Prompt -> LLM -> 回复

4.3 RAG 代码实现流程

  1. 加载 PDF 文件并提取文本与页码PyPDF2.PdfReaderextract_text_with_page_numbers(pdf)

    • 作用: 读取 PDF 文件,从每一页中提取文本内容,并记录每行文本的原始页码,便于后续结果溯源。
  2. 处理文本并创建向量存储process_text_with_splitter(text, page_numbers, save_path)

    • 文本分块RecursiveCharacterTextSplitter(separators=["\n\n", "\n", ".", " ", ""], chunk_size=512, chunk_overlap=128)
      • 作用: 将长文本分割成小块(chunks),便于后续向量化和检索,同时设置重叠保证上下文连续性。
    • 创建嵌入模型DashScopeEmbeddings(model="text-embedding-v2") (或 OpenAIEmbeddings())
      • 作用: 初始化文本嵌入模型,将文本块转为向量表示。
    • 向量化存储FAISS.from_texts(chunks, embeddings)
      • 作用: 使用 FAISS 向量数据库存储文本向量,支持高效相似度检索。
    • 存储页码信息knowledgeBase.page_info = page_infopickle.dump(page_info, f)
      • 作用: 将每个文本块对应的页码信息存储在 knowledgeBase 对象中,并可选地保存到本地文件系统,实现查询结果的溯源。
  3. 加载本地知识库load_knowledge_base(load_path, embeddings)

    • 作用: 从本地路径加载已保存的 FAISS 向量数据库及相关页码信息。
  4. 检索增强生成 (RAG)

    • 相似度搜索docs = knowledgeBase.similarity_search(query)
      • 作用: 根据用户输入的查询 query,在向量数据库中查找语义最相似的文档片段 docs
    • 初始化大语言模型ChatOpenAI(...) (或 Tongyi(...))
      • 作用: 初始化对话型大模型,用于后续生成回答。
    • 加载问答链chain = load_qa_chain(chatLLM, chain_type="stuff")
      • 作用: 构建一个问答链,将检索到的文档作为上下文与用户问题结合,引导大语言模型生成回答。
    • 执行问答链response = chain.invoke(input={"input_documents": docs, "question": query})
      • 作用: 运行问答链,生成基于检索结果的答案。
    • 成本跟踪with get_openai_callback() as cost:
      • 作用: 监控 API 调用的成本。
  5. 结果溯源

    • 显示来源页码source_page = knowledgeBase.page_info.get(text_content.strip(), "未知")
    • 作用: 从 knowledgeBase 中获取每个检索到的文档片段对应的原始页码,并打印出来,实现答案的溯源。

pdf 文本分块,向量化存储,保存+加载向量数据库及页码信息,测试输出

1
百度文库  - 好好学习,天天向上  \n-1 上海浦东发展银行西安分行  \n个金客户经理管理考核暂行办法  \n \n \n第一章  总   则 \n第一条   为保证我分行个金客户经理制的顺利实施,有效调动个\n金客户经理的积极性,促进个金业务快速、稳定地发展,根据总行《上\n海浦东发展银行个人金融营销体系建设方案(试行)》要求,特制定\n《上海浦东发展银行西安分行个金客户经理管理考核暂行办法(试\n行)》(以下简称本办法)。  \n第二条   个金客户经理系指各支行(营业部)从事个人金融产品\n营销与市场开拓,为我行个人客户提供综合银行服务的我行市场人\n员。 \n第三条   考核内容分为二大类,....

处理文本并创建知识库,同时保存到磁盘,测试输出

1
2
3
4
5
6
7
8
提取的文本长度: 3881 个字符。
文本被分割成 10 个块。
已从文本块创建知识库...
向量数据库已保存到: ./vector_db
页码信息已保存到: ./vector_db\page_info.pkl
文本被分割成 10 个块。
已从文本块创建知识库...
<langchain_community.vectorstores.faiss.FAISS at 0x1d0ffedb220>

设置查询问题,检索增强生成(RAG),测试输出:

1
2
3
4
5
6
7
8
9
10
查询已处理。成本: Tokens Used: 1289
Prompt Tokens: 1240
Prompt Tokens Cached: 0
Completion Tokens: 49
Reasoning Tokens: 0
Successful Requests: 1
Total Cost (USD): $0.0
根据第十一条的规定,客户经理每年评聘的申报时间是每年的1月份。由分行人力资源部和个人业务部在每年的2月份组织统一的资格考试。考试合格者由分行颁发个金客户经理资格证书,其有效期为一年。
来源:
文本块页码: 1

通过Tongyi做结果溯源(显示来源页码),测试输出:

1
2
3
4
5
6
7
8
9
10
11
12
向量数据库已从 ./vector_db 加载。
页码信息已加载。
查询已处理。成本: Tokens Used: 0
Prompt Tokens: 0
Prompt Tokens Cached: 0
Completion Tokens: 0
Reasoning Tokens: 0
Successful Requests: 1
Total Cost (USD): $0.0
客户经理每年的评聘申报时间是每年一月份。由分行人力资源部、个人业务部每年二月份组织统一的资格考试。考试合格者由分行颁发个金客户经理资格证书,其有效期为一年。
来源:
文本块页码: 1

5. 三大阶段有效提升RAG质量方法

5.1 数据准备阶段

常见问题

  • 数据质量差:企业数据(尤其是非结构化数据)缺乏治理,未标记/评估的数据可能包含敏感、过时、矛盾或错误的信息。
  • 多模态信息挑战:难以准确提取+理解文档中的标题、配色、图像、标签等不同元素。
  • 复杂PDF提取:PDF格式为人类阅读设计,机器解析难度大。

如何提升数据准备阶段的质量?

  1. 构建完整的数据准备流程(数据部门做,提升数据质量)

    1. 数据评估与分类
      • 数据审计:全面审查现有数据,识别敏感、过时、矛盾或不准确的信息。
      • 数据分类:按类型、来源、敏感性和重要性来分类
    2. 数据清洗
      • 去重:删除重复数据
      • 纠错:修正格式错误、拼写错误等
      • 更新:替换过时信息,确保数据时效性
      • 一致性检查:解决数据矛盾,确保逻辑一致
    3. 敏感信息处理
      • 识别敏感数据:使用工具或正则表达式识别敏感信息,如个人身份信息
      • 脱敏或加密:对敏感数据进行脱敏处理,确保合规。
    4. 数据标记与标注
      • 元数据标记:为数据添加元数据,如来源、创建时间等
      • 内容标注:对非结构化数据进行标注,便于后续检索和分析
    5. 数据治理框架
      • 制定政策:明确数据管理、访问控制和更新流程
      • 责任分配:指定数据治理负责人,确保政策执行
      • 监控与审计:定期监控数据质量,进行审计
  2. 智能文档技术(针对复杂的pdf )

    • 利用智能文档技术提升多模态和复杂结构文档的数据处理效率
    • 利用多模态文档识别+理解引擎,然后文档解析成doc tree,txt。
    • RagFlow底层使用OCR技术对pdf识别很好

5.2. 知识检索阶段

常见问题

  • 内容缺失:检索过程未覆盖关键内容,导致系统提供的答案不完整或碎片化,直接拉低 RAG 质量。
  • 错过排名靠前的文档
    • 检索时相关文档虽被找到,但排名过低或未被选中(只召回 top k),导致高相关内容未被利用,最终答案无法满足需求。
    • 由于 top k 设置依赖经验,理论上应排序全量文档,但实际只用少数文档,增加了漏查风险。
  • 不在上下文中
    • 检索到了包含答案的文档,但这些内容未被纳入最终上下文,导致生成答案时遗漏关键信息。
    • 常发生在召回文档过多、上下文窗口有限时,需进一步筛选和整合相关片段。

如何提升知识检索阶段的质量?

  1. 通过查询转换澄清用户意图:明确用户意图,提高检索准确性。

    • 场景:用户询问 “如何申请信用卡?”
    • 问题:用户意图可能模糊,例如不清楚是申请流程、所需材料还是资格条件。
    • 解决方法:通过查询转换明确用户意图。
    • 实现步骤:
      • 意图识别:使用自然语言处理技术识别用户意图。例如,识别用户是想了解流程、材料还是资格。
      • 查询扩展:根据识别结果扩展查询。例如:
        • 如果用户想了解流程,查询扩展为“信用卡申请的具体步骤”
        • 如果用户想了解材料,查询扩展为“申请信用卡需要哪些材料”
        • 如果用户想了解资格,查询扩展为“申请信用卡的资格条件”
      • 检索:使用扩展后的查询检索相关文档
    • 示例:
      1. 用户输入:“如何申请信用卡?”
      2. 系统识别意图为 流程,扩展查询为 信用卡申请的具体步骤
      3. 检索结果包含详细的申请步骤文档,系统生成准确答案
  2. 采用混合检索和重排策略:确保最相关的文档被优先处理,生成更准确的答案。

    • 场景:用户询问“信用卡年费是多少?”
    • 问题:直接检索可能返回大量文档,部分相关但排名低,导致答案不准确。
    • 解决方法:采用混合检索和重排策略。
    • 步骤:
      1. 混合检索:结合关键词检索和语义检索。比如:关键词检索:“信用卡年费”。
      2. 语义检索:使用嵌入模型检索与“信用卡年费”语义相近的文档。
      3. 重排:对检索结果进行重排。
      4. 生成答案:从重排后的文档中生成答案。
    • 示例:
      1. 用户输入:“信用卡年费是多少?”
      2. 系统进行混合检索,结合关键词和语义检索。
      3. 重排后,最相关的文档(如“信用卡年费政策”)排名靠前。
      4. 系统生成准确答案:“信用卡年费根据卡类型不同,普通卡年费为100元,金卡为300元,白金卡为1000元。”

5.3. 答案生成阶段

常见问题

  • 未提取:答案与所提供的上下文相符,但大语言模型却无法准确提取。这种情况通常发生在上下文中存在过多噪音或相互冲突的信息时。
  • 不完整:尽管能够利用上下文生成答案,但信息缺失会导致对用户查询的答复不完整。格式错误:当prompt中的附加指令格式不正确时,大语言模型可能误解或曲解这些指令,从而导致错误的答案。
  • 幻觉:大模型可能会产生误导性或虚假性信息。

如何提升答案生成阶段的质量?

  • 改进提示词模板
  • 实施动态防护栏
  1. 改进提示词模板
    • 如何对原有的提示词进行优化?
    • 可以通过 DeepSeek-R1QWQ 的推理链,对提示词进行优化:
      • 信息提取:从原始提示词中提取关键信息。
      • 需求分析:分析用户的需求,明确用户希望获取的具体信息。
      • 提示词优化:根据需求分析的结果,优化提示词,使其更具体、更符合用户的需求。
场景 原始提示词 改进后的提示词
用户询问“如何申请信用卡?” “根据以下上下文回答问题:如何申请信用卡?” “根据以下上下文,提取与申请信用卡相关的具体步骤和所需材料:如何申请信用卡?”
用户询问“信用卡的年费是多少?” “根据以下上下文回答问题:信用卡的年费是多少?” “根据以下上下文,详细列出不同信用卡的年费信息,并说明是否有减免政策:信用卡的年费是多少?”
用户询问“什么是零存整取?” “根据以下上下文回答问题:什么是零存整取?” “根据以下上下文,准确解释零存整取的定义、特点和适用人群,确保信息真实可靠:什么是零存整取?”
  1. 实施动态防护栏
    • 动态防护栏(Dynamic Guardrails)是一种在生成式AI系统中用于实时监控和调整模型输出的机制,旨在确保生成的内容符合预期、准确且安全。它通过设置规则、约束和反馈机制,动态地干预模型的生成过程,避免生成错误、不完整、不符合格式要求或含有虚假信息(幻觉)的内容。
    • 在RAG系统中,动态防护栏的作用尤为重要,因为它可以帮助解决以下问题:
      • 未提取:确保模型从上下文中提取了正确的信息。
      • 不完整:确保生成的答案覆盖了所有必要的信息。
      • 格式错误:确保生成的答案符合指定的格式要求。
      • 幻觉:防止模型生成与上下文无关或虚假的信息。
  • 场景1:防止未提取

    • 用户问题:“如何申请信用卡?”
    • 上下文:包含申请信用卡的步骤和所需材料。
    • 动态防护栏规则:检查生成的答案是否包含“步骤”和“材料”。如果缺失,提示模型重新生成。
    • 示例:
      • 错误输出:“申请信用卡需要提供一些材料。”
      • 防护栏触发:检测到未提取具体步骤,提示模型补充。
  • 场景2:防止不完整

    • 用户问题:“信用卡的年费是多少?”
    • 上下文:包含不同信用卡的年费信息。
    • 动态防护栏规则:检查生成的答案是否列出所有信用卡的年费。如果缺失,提示模型补充。
    • 示例:
      • 错误输出:“信用卡A的年费是100元。”
      • 防护栏触发:检测到未列出所有信用卡的年费,提示模型补充。
  • 场景3:防止幻觉

    • 用户问题:“什么是零存整取?”
    • 上下文:包含零存整取的定义和特点。
    • 动态防护栏规则:检查生成的答案是否与上下文一致。如果不一致,提示模型重新生成。
    • 示例:
      • 错误输出:“零存整取是一种贷款产品。
      • 防护栏触发:检测到与上下文不一致,提示模型重新生成。

如何实现动态防护栏技术? 事实性校验规则,在生成阶段,设置规则验证生成内容是否与检索到的知识片段一致。例如,可以使用参考文献验证机制,确保生成内容有可靠来源支持,避免输出矛盾或不合理的回答。

如何制定事实性校验规则?(后置处理)

  • 当业务逻辑明确且规则较为固定时,可以人为定义一组规则,比如:
    • 规则1:生成的答案必须包含检索到的知识片段中的关键实体(如“年费”、“利率”)。
    • 规则2:生成的答案必须符合指定的格式(如步骤列表、表格等)。
    • 实施方法:
      • 使用正则表达式或关键词匹配来检查生成内容是否符合规则。
      • 例如,检查生成内容是否包含“年费”这一关键词,或者是否符合步骤格式(如“1. 登录;2. 设置”)。

6. RAG在不同阶段提升质量的实践

  • 数据准备环节,阿里云考虑到文档具有多层标题属性且不同标题之间存在关联性,提出多粒度知识提取方案,按照不同标题级别对文档进行拆分,然后基于 Qwen14B 模型和 RefGPT 训练了一个面向知识提取任务的专属模型,对各个粒度的 chunk 进行知识提取和组合,并通过去重和降噪的过程保证知识不丢失、不冗余。最终将文档知识提取成多个事实型对话,提升检索效果;
  • 知识检索环节,哈啰出行采用多路召回的方式,主要是向量召回和搜索召回。其中,向量召回使用了两类,一类是大模型的向量、另一类是传统深度模型向量;搜索召回也是多链路的,包括关键词、ngram等。通过多路召回的方式,可以达到较高的召回查全率。
  • 答案生成环节,中国移动为了解决事实性不足或逻辑缺失,采用 FoRAG 两阶段生成策略,首先生成大纲,然后基于大纲扩展生成最终答案。

7. QA

如果LLM可以处理无限上下文了,RAG还有意义吗?

  • 效率与成本:LLM处理长上下文时计算资源消耗大,响应时间增加。RAG通过检索相关片段,减少输入长度。
  • 知识更新:LLM的知识截止于训练数据,无法实时更新。RAG可以连接外部知识库,增强时效性。
  • 可解释性:RAG的检索过程透明,用户可查看来源,增强信任。LLM的生成过程则较难追溯。
  • 定制化:RAG可针对特定领域定制检索系统,提供更精准的结果,而LLM的通用性可能无法满足特定需求。
  • 数据隐私:RAG允许在本地或私有数据源上检索,避免敏感数据上传云端,适合隐私要求高的场景。
  • 结合LLM的生成能力和RAG的检索能力,可以提升整体性能,提供更全面、准确的回答。

“觉得不错的话,给点打赏吧 ୧(๑•̀⌄•́๑)૭”

微信二维码

微信支付

支付宝二维码

支付宝支付

RAG(检索增强生成)基础
http://neurowave.tech/2025/06/29/2-14-LLM-RAG基础/
作者
Artin Tan
发布于
2025年6月29日
更新于
2025年8月16日