RAG 是什么
RAG ( Retrieval Augmented Generation 检索增强生成 ) 是一种增强 LLM 能力的技术,通过从外部知识库中检索相关信息,并将其融入内容生成过程,使模型能够生成更准确、可靠的回答,有效的减少幻觉
因为 LLM 存在哪些问题,我们才需要用到 RAG 技术?
- 知识更新滞后:LLM 依赖训练数据,比如训练数据截止到某个时间点,之后的新信息便无法获取
- 易产生幻觉:可能生成看似合理但事实错误的内容
- 领域知识局限:通用模型对专业领域深度理解不足,比如医疗或法律
- 外部数据源访问受限:无法直接访问私有或动态更新的外部知识库
RAG 和微调的区别?
微调 ( Fine-tuning ) 是在预训练大模型基础上,用特定领域数据调整模型参数,使其适应具体任务
可见两者的区别是:
- RAG:通过检索外部实时信息辅助生成,不修改模型参数,适合动态知识需求
- 微调:直接修改模型内部参数,依赖训练数据,擅长固定领域优化(如法律、医疗),但无法实时更新知识
简易 RAG 实现
简易 RAG 的实现可概括为三步:
- 数据准备:读取文档内容后分块并向量化
- 检索:用户提问时,用相似度检索匹配相关的文本块
- 生成:将检索内容与问题拼接,输入大模型中生成最终回答
数据准备
数据准备阶段大致有以下流程:
Loader -> 数据清洗 -> 元数据提取 -> Chunking -> Embedding
Loader
首先是 Loader 的工作,如何从不同的媒介中加载数据,如:文本文件、PDF、网站、数据库、API 等
处理不同文件类型的数据涉及诸多技术挑战,这里不做详细探讨
值得注意的是,RAG 不仅仅面向文本,其应用场景可延伸至语音、视频、图像等多模态领域。原则上,只要能够进行有效向量化(embedding)的数据形态,都可以纳入 RAG 的技术框架
数据清洗
为什么数据清洗是必要的?
因为如果检索的数据质量不高,比如有噪音、重复或者错误信息,会导致检索效果差,进而影响生成的答案质量。比如,如果数据库里有重复的内容,检索时可能返回冗余的信息,生成模型可能重复回答或者混淆。另外,如果数据格式不统一,比如有 HTML 标签或者乱码,可能影响检索模型的处理,无法正确理解内容。
数据清洗的常见方法
- 去重:删除完全重复或高度相似的文本,避免冗余干扰
- 格式清理:去除 HTML 标签、乱码、特殊符号等非文本内容
- 标准化:统一文本格式(如全角转半角、小写化)、分段分句
- 去噪:过滤广告、无关符号、停用词(如“的”“是”)等干扰信息
- 纠错补全:修正拼写错误,填补缺失的关键信息(如日期、术语)
- 结构化处理:将非结构化文本(如长段落)切分为带标签的段落或问答对,便于检索
通常通过自动化工具(如正则表达式、NLP库)和人工审核结合实现,确保数据简洁、一致且与任务目标匹配
元数据提取
元数据提取是指从原始数据中抽取出描述性信息的过程,这些信息用于解释数据的属性、结构、来源或上下文
如:文件名、时间、章节 title、关键词列表等
举例说明:
- 学术论文库:提取标题、作者、发表日期、关键词、引用文献作为元数据
- 企业文档:提取部门、项目名称、版本号、审批状态等
- 新闻文章:提取事件类型、地点、涉及人物、时间线等
为什么需要提取元数据?
-
提升检索效率:元数据(如文档标题、作者、日期、关键词等)可以作为索引的补充,帮助系统快速定位相关文本片段,减少无关内容的搜索范围
-
增强内容过滤能力:元数据允许按特定条件(如时间范围、领域类别)筛选数据,确保检索结果更精准。例如,过滤掉过时的法律条款或指定某类学术论文
-
优化语义理解:提取元数据能为模型提供结构化的上下文,有助于模型的语义理解,生成更高质量的回答
如何提取元数据?
-
结构化数据直接提取
若数据本身是结构化格式(如数据库、表格),可直接提取字段(如作者、日期、标签)
-
非结构化数据解析
对文本、PDF、网页等非结构化数据,可通过规则匹配、NLP 技术、模型分析等手段提取
-
人工标注辅助
对复杂或模糊的元数据(如情感倾向、领域类别),结合人工标注确保准确性
🤔 元数据提取是针对特定业务场景,还是针对普适性场景?
元数据提取的颗粒度和方向,确实需要结合场景灵活调整——但即使面对「普适性文件」,元数据提取依然有意义,只是策略不同
例如:
-
通过提取文件格式(PDF、Word、网页等)、创建时间等基础元数据,可初步分类和快速筛选诸如“最近 3 个月的 PDF 文件”这样的场景
-
通过提取内容的关键词列表,可辅助判断和筛选内容主题
Chunking
为什么需要分块?
分块后能提高检索效率,确保模型精准定位并利用最相关的信息片段
如果直接使用大文本作为输入,会带入大量无关冗余的信息。由于模型都有最大输入长度的限制,如果包含这些冗余内容,我们就无法同时放入其他相关的有用上下文了。因此,将每个段落的文本拆分成较小的片段。直观上,较小的文本片段通常只涵盖了单一或少数概念,相比较大的片段来说,会包含更少的无关杂讯
分块策略的选取将直接影响检索和 RAG 的整体效果,但这也是一个复杂的问题,此处暂不展开讨论
Embedding
Embedding 是将文本、图像、音频和视频等信息转化为一串数值向量的过程
通过 Embedding,数据被转换为向量后,计算机能快速计算向量之间的相似度(比如余弦相似度),找到与用户问题语义最匹配的文本块
例如,用户问“养猫要注意什么”,即使文本块中没出现“注意”这个词,Embedding 也能匹配到相关语义的段落
Embedding 模型的好坏也会直接影响后续检索的质量,如何选择不同的 Embedding 模型这里也暂不讨论
检索
检索的最核心目的就是:找出最相关的文本块
keyword + KNN 结合关键词精准匹配和 KNN 相似度匹配
以下介绍一些常用的检索优化手段:
元数据过滤
先通过元数据精准过滤可大幅提升检索的效率和相关性
假设一个系统存储了 10 万篇文档,用户问:
❓ “2023 年新能源汽车的行业报告有哪些?”
无元数据过滤:
系统需要遍历所有 10 万篇文档,用复杂的语义匹配模型逐一分析内容,耗时且可能包含无关结果(比如 2020 年的报告)
用元数据过滤(年份+类型):
- 先用元数据筛选出
年份=2023
+类型=行业报告
的文档,可能只剩 100 篇 - 再对这 100 篇做语义检索,找出与“新能源汽车”相关的内容
效率提升原因:
- 计算量骤减:语义模型只需处理 100 篇而非 10 万篇,速度提升百倍
- 干扰减少:避免了因内容关键词模糊匹配导致的误判(例如旧文档提到“新能源”但年份不符)
类似场景:电商平台搜索“红色连衣裙”,先按「颜色」「品类」筛选商品,再根据关键词排序,远比全库搜索更快更准
重排序(Rerank)
初次检索后召回大量相关的文档,但是简单的相似度搜索(如关键词匹配或向量检索)可能返回冗余、噪声或不完全相关的文档。Rerank(重排序)能基于更精细的语义理解,对召回结果重新打分排序,筛选出最相关的少量文档交给生成模型,从而提升最终答案的准确性和针对性
简单的 Rerank 实现:用 GPT 等模型直接评估文档相关性(如输出打分或生成解释)
举个栗子🌰
问题:「如何预防感冒?」
向量检索可能返回10篇文档,包含「感冒症状」「药物治疗」等无关内容
Rerank 模型会识别出「增强免疫力」「勤洗手」「接种疫苗」等段落,优先保留这些内容,让生成的答案更聚焦
优化总结:用较小的计算成本(仅对少量文档重排序),显著提升生成答案的质量和可靠性
生成
说到底,前面所有环节的核心任务就一个:为生成环节准备高质量的数据输入(即优化 Prompt 内容)
至于如何设计 Prompt 来高效利用这些数据、激发大模型能力,这属于 Prompt 工程的范畴,暂不展开讨论
总结
虽然实现一个简易的 RAG 系统看似简单,但要达到一个不错的效果并最终在企业应用场景中落地,每一步都涉及诸多的技术挑战,也面临着质量、成本、效率等各方面因素的取舍