一、私有化知识中心整体介绍
在对chatglm2-6的环境搭建完成之后,我们便可以开始使用langchain与chatglm搭建一个私有的知识中心(别问为什么要搭建知识中心,因为这是我最初的想法,后面的AIGC应用会在知识中心的基础上构建,作为素材库)对于怎么搭建chatglm环境或者什么素材库不清楚的朋友,请看我上一篇文章:chatglm2-2b+sdxl1.0+langchain打造私有AIGC(一)
langchain是什么这里就不做具体介绍了,不懂的家人们请移步langchain中文网
基于上图,我简单介绍一下:
1.1、Local Document线路
1、本地的文件服务器,或者你电脑磁盘里面的各种文本文件,使用langchain的组件,PyPDFLoader(针对PDF文件),DocxtxtLoader(针对word文件),TextLoader(针对txt文件)加载出来(读出文件内容)【对应上图中的1,2步】
2、使用langchain的文档分割器splitter对内容进行分割(因为一般情况下文档内容太长,需要分段处理)形成一个一个的小段文档【对应上图中的3,4步】
3、将分割好了的小文档进行向量化(langchain会加载一个向量化模型,对文档进行向量化处理,后面会讲如何使用向量化模型),存入向量数据库【对应上图中的5,6步】
1.2、Query线路
1、用户输入信息,langchain用向量模型将信息向量化,然后传入到向量数据库【对应上图中的8,9步】
2、向量数据库会用输入的向量与库里已有向量进行距离计算,然后返回对应最匹配的前面N条数据(Local Document线路里面存入进去的文档内容,返回的数据不是向量哈,是原始内容,向量只是用于做计算)【对应上图中的10,11步】
3、langchain接收到向量数据库返回的文本信息后,将这些文本信息和用户输入的信息整合在一起构成prompt(提示词)【对应上图中的12,13步】
4、langchain将构造好的prompt传入到LLM(语言大模型,这里指的就是chatglm),LLM根据prompt回答用户的问题【对应上图中的14,15步】
为什么不直接问直接答,还要这么麻烦呢?通俗的讲,因为大模型不是什么都知道,我们需要先告诉大模型一些前驱知识,他才能回答我们对应的问题,在这种场景下大模型只是一个免得我们去到处翻阅资料或者百度搜索才能知道答案的工具
二、chatglm与langchain集成
现在已经理清楚了流程关系,我们变可以开始进行实际开发了,首先我们按照先后顺序梳理出我们需要用到的langchain组件
2.1、组件引用准备:
1)文档加载组件
from langchain.document_loaders import DocxtxtLoader , PyPDFLoader, TextLoader
2)文档分割组件
from langchain.text_splitter import RecursiveCharacterTextSplitter,CharacterTextSplitter
3)向量模型加载器
from langchain.embeddings import HuggingFaceEmbeddings
4)向量数据库
from langchain.vectorstores import Chroma
向量数据库有很多,这里不做一一介绍,但是都大同小异,这里我们就以Chroma为例
5)构造提示词组件
from langchain.prompts import PromptTemplate
6)大模型
# langchain封装的一个大模型客户端类from transformers
from langchian.llms.base import LLM
# 加载chatglm使用
import AutoModel,AutoTokenizer
7)链组件(用于将构造好的prompts传递给LLM)
from langchain.chains.llm import LLMChain
2.2、单步骤方法实现
现在该引用的都已经引用了,我们接下来就需要把这些组件串起来,如下:
1)加载载文档:
# 加载文档 目前我只需要PDF WORD TXT这三种格式的文档
def loadfile(cls, filePath: str):
if filePath.find(".docx") != -1:
loader = Docx2txtLoader(filePath)
pages = loader.load()
return pages
elif filePath.find(".pdf") != -1:
loader = PyPDFLoader(filePath)
pages = loader.load()
return pages
else:
loader = TextLoader(filePath)
pages = loader.load()
return pages
2)文档切分
# 文档切分 chunk_size表示切分长度, overlap 表示上下段重复长度
# 比如有一句话:今天天很好,适合写文章 chunk_size=3 overlap=1 那么切分出来的结果就是
# ["今天天","天很好","好,适","适合写","写文章"]
def splitDocs(cls, data, chunk_size: int = 200, overlap: int = 50):
if not data:
raise ImportError("没有传入相应的文档数据")
else:
text_splitter = RecursiveCharacterTextSplitter(
separators=["\n\n", "。", "......", "!", "?", "?", "!"