在当今信息爆炸的时代,如何有效地组织和检索知识,提供准确的问答服务,是 intelligence 和 technology 领域面临的重大挑战。RAG(Retrieval Augmented Generation)技术,作为一种高效的 AI 问答方案,为我们提供了一种新的解决方案。本文将深入探讨 RAG 技术的工作原理和实现流程,帮助大家更好地理解和应用这一前沿技术。

RAG 技术概述

RAG 技术的全称是 Retrieval Augmented Generation,即 “检索增强生成”。它的核心思想是,当系统收到用户的问题时,首先从已有的知识库中检索与问题相关的信息,然后基于这些信息生成回答。这种方法的优势在于能够处理大量的文档数据,并且提供更准确、更快速的问答服务。

举例说明:

假如用户问:“量子计算的基本原理是什么?”
RAG 系统不会直接从记忆中生成答案,而是先检索知识库中与“量子计算”相关的权威资料(如教材片段、论文内容),再在此基础上进行内容生成。这样,回答既有来源支撑,也更准确。

关键优势:

  • 可处理大量文档数据

  • 提供更精准的答案

  • 减少幻觉(hallucination)

  • 适应性强,可更新知识库

RAG的基本流程

接下来,我会通过一张清晰的流程图,一步步解析RAG的核心工作流程

如图所示,整个RAG流程可以清晰地分为两个主要阶段:第一阶段(红色区域):回答前准备 - “养兵千日”​第二阶段(绿色区域):回答时的过程。

数据准备阶段:分片与索引

  • ​数据输入 (Data Input):​​ 这通常是您希望模型掌握的核心知识来源,比如公司文档、产品手册、百科全书、甚至网页内容等原始信息。

  • ​分片 (Chunking):​​ 原始文档通常太大,无法直接处理。这一步将它们​​切割成更小的、语义相对完整的片段 (Segment List)​​。比如按段落、小节或特定长度分割。

  • ​索引 (Indexing):​​ 这是构建可查询知识库的关键:

    • 先将文本片段通过 ​​Embedding 模型 (Embedding Model)​​ 进行处理。这个模型就像一台“翻译机”,​​将每个文本片段转化为高维空间中的一个数值向量 (Vector)​​。这些向量奇妙地捕捉了文本的​​语义信息​​(词句的意思和关系)。

    • 所有生成的向量​​存储到向量数据库 (Vector Database)​​ 中。这种数据库的专长就是​​高效存储和检索向量数据​​。

举例说明:

原始文档:人工智能教程,含 10 页内容
分片策略:每段为一个片段,共 120 个片段
优势:更精细的内容定位

回答阶段:召回、重排与生成

当用户提出问题,系统就开始运转这个“召回(查询)→重排→生成”的流程:

  • ​用户提问 (User):​​ 流程的起点是用户的自然语言问题 (如 “什么是RAG的最佳实践?”)。

  • ​问题向量化 (Embedding Model):​​ 用户的原始问题也要经过相同的 ​​Embedding 模型​​处理,转化为一个代表问题语义的​​向量 (Vector)​​。

  • ​召回/检索 (Retrieval):​​ 拿着用户问题的向量,系统在​​向量数据库 (Vector Database)​​ 中进行搜索。数据库的核心功能是比较向量的相似度。它找出那些与用户问题向量​​最相似的、代表文档片段的向量​​,从而快速​​召回 (Retrieve)​​ 一批与问题相关的文本片段。上一步到这一步通常叫​​“召回阶段”​​。

  • ​(可选) 重排 (Reranking - Cross-Encoder):​​ 初始召回的相关片段可能数量众多且质量不一。为了提高最终结果精度,系统可以使用更复杂但计算量也更大的 ​​Cross-Encoder 模型​​(图中未展示具体位置,但Cross-Encoder标签旁标注“相关的片段”表示其作用)对这些片段进行​精细化排序 (Reranking)​​。Cross-Encoder 直接比较问题和片段之间的关系细节,挑选出​​最精简、最相关的那几个关键片段 (Relevant Fragments / Top-K Documents)​​。这是​​“重排阶段”​​。

  • ​生成 (Generation):​​ ​​大语言模型 (Large Language Model)​​ 正式登场!它将用户的​​原始问题 (Query)​​ 和从上一步获得的​​最相关的文本片段 (Relevant Context)​​ ​​一起​​作为输入。模型利用自身的理解能力和生成能力,​​融合上下文知识​​,​​输出最终的、信息丰富且相关的回复 (Response)​​ 给用户。这步就是​​“生成阶段”​​。

RAG项目实操

现在,我来讲讲RAG用python怎么实现。

这里使用的工具是anaconda(管理环境)和jupyter notebook(分步骤运行比较直观,PyCharm+jupyter插件效果也是一样的),jupyter notebook不用另外下载,anaconda里会附带。

环境搭建

运行命令窗口cd到合适的路径,输入下面的命令行创建虚拟环境并激活虚拟环境:

    conda create -n RAG python=3.12

    conda activate RAG

接下来,运行下面的命令行安装依赖:

    pip install sentence_transformers chromadb google-genai python-dotenv

sentence_transformers​用于加载语义嵌入向量(Embeddings)模型和Cross-Encoder模型,生成句子、段落或图像的语义嵌入向量(Embeddings);

chromadb​轻量级开源向量数据库,专为存储和检索高维嵌入向量设计,支持快速语义搜索与元数据管理;

接下来,要把jupyter notebook的内核更改为虚拟环境内核

先退出已经激活的虚拟环境

    conda deactivate

然后,输入下面的命令行添加插件

   conda install nb_conda_kernels

准备文档

这里我准备了《诡秘之主》小说的前5章,格式是md格式,如果用langchaim中的document_loaders可以识别pdf、docs格式。

编写代码

在命令行输入jupyter notebook,打开jupyter notebook;注意要在虚拟环境内打开!!!

接着点击newPython[conda env:虚拟环境名]新建项目;

分片:

导入 List 这个对象用于标识函数返回结果的类型,然后我们创建一个函数用来处理分片的逻辑,函数名就叫做 split_into_chunks,其中的 chunk 就是片段的意思。

这个函数有一个参数叫做 doc_file,我们待会就把我们的文档名作为 doc_file 传入进来;这个函数的返回值是一个字符串列表(片段列表)。

在函数的内部,我们首先读取文件内容,把它放在 content 变量里面,然后按行来拆分,把这个 content 切分为多个 chunk,然后我们调用一下这个函数,并且循环遍历,拿到所有的片段,把片段的编号和对应的内容都打印出来,观察结果如何。

索引:

首先先引入 SentenceTransformer 对象,然后用它来加载一个 Embedding 模型,然后编写函数 embed_chunk获取片段的向量;

  • encode()方法​​:将文本输入(chunk)转换为固定维度的向量;

  • normalize_embeddings=True​:对生成的向量进行 ​​L2 归一化​​,使所有向量模长为 1,提升余弦相似度计算的准确性;

  • tolist()转换​​:将 NumPy 数组转为标准 Python 列表,便于序列化存储(如 JSON)或兼容非 NumPy 环境。

接下来,就把分片的List用循环一一调用函数 embed_chunk

片段转化为向量后,就需要把这些向量存入到向量数据库;

召回(检索):

编写检索召回的函数retrieve:用 embed_chunk 函数把用户问题转化为向量,查询与用户问题最为相似的前 k个结果,再把这些片段列表都返回回去。

重排:

首先引入 sentence_transformersCrossEncoder 包,然后写重排函数 rerank函数内部,我们首先创建一个 cross-encoder 模型,然后把用户问题 query 的召回片段添加进一个列表,然后我们把这个列表发给 cross-encoder 模型,让它给每一个片段打分,分值就代表了用户问题与召回片段内容的相似程度,然后排序(从高到低);

生成:

定义了一个函数 qwen_rag_generate,用于将用户的问题和相关文档片段(chunks)构造成提示词(prompt),通过调用 大语言模型(我这里是Qwen-32B),生成基于上下文的回答,并采用 HTTP POST 请求向 API 发送内容,设置合适的参数和请求头,接收并解析模型的回答结果