7-4 项目架构设计
前面我们介绍了检索增强生成(RAG)流程的主要环节,在这个实战中,我们把整个流程串起来。在总体设计中,RAG流程分为两个部分,一个是知识库的构建,一个是RAG问答的流程。
在知识库构建过程中,需要经过文档的解析、文档的分块,分块后经过嵌入模型转换为嵌入向量,然后最终存入向量数据库中。
我们先来了解一下这个知识库涉及的文档。我们要实现的RAG流程是企业员工制度问答助手,所以文档涉及跟公司制度相关的一些资料。作为演示,有以下文档:
- 考勤管理制度:涉及考勤、休假、加班等方面的规定,里面包含一些表格信息。
- 差旅费用标准文档:包括出差过程中涉及的交通费、住宿费、伙食补助费以及市内交通费的一些规定和说明,同样包含表格信息。
- 差旅文档中住宿费说明的附件(excel文档):规定了不同职级在不同地区的住宿费标准,还考虑了旺季和非旺季时间上的标准差异。
为了方便开发,我们做了模块化设计,主要有两个模块:
- 模型模块:把整个流程中使用的大语言模型和嵌入模型放在
model模块里。- 大语言模型:通过OpenAI的接口调用,使用欧拉玛部署的千问2 72B模型【还挺大的,我不打算部署了,而是采用阿里云百炼的平台,我们重点关注文档的处理,向量化】。推理使用与接口一样的数据格式,包括提示值、模型类型以及大语言模型的几个关键参数,如温度、top p、max tokens(最大输出token的限制),还有是否支持流式输出。将大语言模型的调用封装成
RAG_and_name类。 - 嵌入模型:采用
langchain中的hugging face embedding来调用嵌入模型,具体使用BGE-M3模型。
- 大语言模型:通过OpenAI的接口调用,使用欧拉玛部署的千问2 72B模型【还挺大的,我不打算部署了,而是采用阿里云百炼的平台,我们重点关注文档的处理,向量化】。推理使用与接口一样的数据格式,包括提示值、模型类型以及大语言模型的几个关键参数,如温度、top p、max tokens(最大输出token的限制),还有是否支持流式输出。将大语言模型的调用封装成
- 文档解析模块(DOC pass):把文档解析和分块的操作放在此模块。
- PDF文档解析:采用RAG flow的
deep DOC解决方案,之前用过这个类,主要用于解析PDF文档,包含OCR模块、布局分析模块、表格解析模块以及后续合并的一些模块。 - Excel文档解析:采用
openpyxl来加载excel文档。由于文档中有很多合并单元格,会影响程序可读性,为更好处理信息,我们将合并单元格进行拆分,并将拆分后的所有单元格填充同样的信息。具体操作是遍历所有合并单元格,记住其开始位置(左上角位置)跟结束位置(右下角位置),然后在左上角到右下角的所有单元格之间填充合并单元格中的内容信息,最后返回填充后的信息。
- PDF文档解析:采用RAG flow的
【可能是用来避免丢失上下文信息。】
了解了model跟DOC pass这两个重要模块后,就可以开始构建RAG的制度问答助手。
- 导入相关方法和包:导入
model跟DOC pass里面的相关内核方法,如嵌入模型、大语言模型,文档解析方面的PDF文档解析和分化,以及excel文档的读取和解析。因为使用chroma数据库,所以导入相关内核包。同时,把递归文本分块的类也引进来,用于对较长文本进行再次分块处理。 - 设置文档路径:设置PDF文档和excel文档的路径。
- 实例化递归文本分块对象:设定块大小为128块,块之间的重叠部分是30个字符,同时添加对中文语境的分隔符,如句号、顿号等。
- 解析PDF文档:
- 用
deep DOC方式加载并解析设定的2个PDF文档。
pdf文档的解析
- 遍历解析后的内容,若文本信息超过200个字符,调用实例化的递归文本分块对象,以
sleep test方式对文本再次分块;若为表格信息或小于200字符的文本信息,直接加入分块后的数据列表。 - 执行后查看解析分块后的数据,并打印其长度。
- 用
- 处理Excel文件:
- 使用
DOC pass里处理excel文件的函数读取并解析excel文件,同时处理合并单元格信息,将其拆开并做相同内容填充,得到excel中每一行的列表信息。 - 去除空列,仅取有效数据,通过
pandas转换成markdown格式,然后将处理后的表格信息放入数据列表。
- 使用
- 封装数据:数据列表里的数据都是文本数据,为符合
langchain中对文档的规定,需将这些数据封装成langchain中的document形式。遍历数据列表里的每个数据,把数据内容放在页面内容里,添加一个测试的元数据,封装成document类,再将document类放到一个列表里。 - 文档向量化及入库:
- 实例化一个嵌入模型类,
langchain对chroma向量数据库的操作做了封装,可直接支持文档的向量化和入库操作。 - 建立与
chroma向量数据库的连接,通过HTTP方式指定host跟端口。 - 使用
langchain中的chroma类对分块后的文档进行向量化处理,并添加到chroma向量数据库中。具体操作为chroma.from_documents,指定分块后的文档、嵌入函数、chroma向量数据库的连接以及入库的向量集合名称(如“制度DB”),以此在chroma向量数据库中创建一个向量集合。
- 实例化一个嵌入模型类,
类似 Chroma,LangChain 可以对 Milvus 向量数据库进行操作。 LangChain 是主流的大型语言模型应用开发框架,其模块化设计使得开发者能够灵活对接 Milvus 等主流向量数据库,实现文本嵌入存储与语义检索的无缝集成。通过安装langchain - milvus库,可使用 LangChain 对 Milvus 进行向量存储、相似性搜索、混合搜索等操作,还能结合 Milvus 的内置函数如 BM25 实现全文检索功能。具体操作可参考Milvus 官方文档。
- 向量检索测试:给定一个查询,通过向量集合中的相似性搜索函数进行向量检索。输入检索问题和返回检索的数量,查看检索后的信息。例如,检索到两个文档,其中第二个与问题语义更匹配。至此,完成企业知识库的构建。
构建完企业知识库后,进行RAG的问答流程:
- 实例化大语言模型:实例化一个大语言模型类,作为RAG中文本生成的工具,该类在
model模块中设计。 - 设计提示词模板:在提示词模板里,首先描述任务,要求大语言模型根据提供的上下文信息回答给定问题,若上下文信息中无相关信息,直接回答“不知道”。任务描述后,接着是具体的问题跟上下文。
- 构建RAG问题的pipeline:
- 输入参数:给定问题列表,以及每个问题列表可搜索的上下文数量。
- 遍历问题列表:通过向量集合的相似性搜索查找与每个问题最相似的K个上下文信息。
- 拼接上下文信息:将检索出的所有上下文信息(文档格式为
document,直接拼接文档的页面内容)拼接成一个大的上下文信息。 - 打印问题和上下文信息:把输入的问题和拼接后的上下文信息打印出来。
- 替换提示词模板:将所有问题和上下文信息替换到设计的提示词模板里,完成问题增强,即给问题增加相关上下文信息。
- 模型输出:将增强后的提示词放入大语言模型,设定为流式输出,遍历流式输出结果并打印。
我们可以结合RAG的整体流程与代码做一下对照。给定一个问题,到知识库中搜索相关上下文信息,将上下文信息与问题组合,输入大语言模型,大语言模型根据添加后的上下文信息回答问题。
进行问题测试:
- 问关于加班的规定,可见问题及相关的三个上下文信息,大语言模型根据上下文做出回答,且回答准确,能在上下文中找到依据。
- 问出差的问题,结果显示回答正确,符合上下文中提供的信息。
通过以上两个部分,我们构建了一个企业员工制度问答助手,后续可问更多问题来测试这个初始的问答助手。
简短修订说明
“RAG”(检索增强生成) “嵌入模型” “向量数据库”