当前位置:   article > 正文

基于ChatGLM的Deepin文档问答Bot

基于ChatGLM的Deepin文档问答Bot

1 项目介绍

1.1 项目内容

实现一个依据 wiki.deepin.org 网站内容回答问题的机器人。

1.2 项目描述

https://wiki.deepin.org 上有900多条deepin系统相关的中文教程和词条,请编写能根据这些内容回答问题的中文聊天机器人
使用者通过命令行界面输入问题,机器人输出回答和参考的wiki文档的链接。

1.3 项目文档

1.4 实现目标

  • 完成一个聊天机器人,能根据 deepin wiki 内容回答问题
  • 通过训练模型,使回答和问题要有80%以上概率的相关性。
  • 编写博客,记录开发过程的心得与体会,并将博客投递至 planet.deepin.org
  • 添加 https://linglong.dev/ 使用手册内容,支持回答玲珑使用的问题。
  • 使用web或qt为机器人添加可视化界面支持,能在deepin系统上使用。
  • 支持用户自定义文档内容,构建问答数据库

2 技术路线

2.1 题目分析

题目需要实现一个能够基于Deepin系统文档问答的聊天机器人,基于文档的问答系统(Document-Based Question Answering System)是一种自然语言处理技术(NLP),用于回答用户提出的问题。它的原理是通过分析文档中的内容,提取出与用户问题相关的信息,并将其转换成可回答问题的格式。基于深度神经网络的机器阅读理解 ( Machine Reading Comprehension,MRC )的发展,MRC模型以问题和文档为输入,通过阅读文档内容预测问题的答案。根据需要预测的答案形式不同,阅读理解任务可以分为填空式 ( Cloze-style )、多项选择式 ( Multi-choice )、片段提取式 ( Span-extraction ) 和自由文本 ( Free-form )。最具影响力的片段提取式MRC公开数据集有SQuAD和MSMARCO等,这些数据集的出现促进了MRC模型的发展。

近年来预训练语言模型如BERT,RoBERTa和XLNet等在众多NLP任务上取得突破性进展,尤其是在阅读理解任务上。这些工作在编码阶段采用Transformer结构获得问题和文档向量表示,在输出层同样采用边界预测方式预测答案在文档中的位置。

2.2 q-d匹配与q-q匹配

这里实际做的是将用户请求的query和document做匹配,也就是所谓的q-d匹配。q-d匹配的问题在于query和document在表达方式存在较大差异,通常query是以疑问句为主,而document则以称述说明为主,这种差异可能会影响最终匹配的效果。一种改进的方法是,不直接做q-d匹配,而是先通过document生成一批候选的question,当用户发来请求的时候,首先是把query和候选的question做匹配,进而找到相关的document片段,这种方法就是’q-q匹配’,具体思路如下:

  1. 将教程和词条整理为纯文本的格式,把每个文档切成若干个小的chunks
  2. 调用ChatGLM的API,根据每个chunk生成5个候选的question,使用的prompt格式为’请根据下面的文本生成5个问题: …'。
  3. 调用文本转向量的接口,将生成的question转为向量,并存入向量数据库,并记录question和原始chunk的对应关系。
  4. 当用户发来一个问题的时候,将问题同样转为向量,并检索向量数据库,得到相关性最高的一个question,进而找到对应的chunk。
  5. 将问题和chunk合并重写为一个新的请求发给chatglm的api。
    总结来说,即让AI根据每段文本生成大量问题,再将用户问题跟AI生成问题匹配,找到问题所在的文本段落并生成prompt。

2.3 SimBERTv2

SimBERT是一个融生成和检索于一体的模型,可以用来作为句向量的一个比较高的baseline,也可以用来实现相似问句的自动生成,可以作为辅助数据扩增工具使用,它以Google开源的BERT模型为基础,基于微软的UniLM思想设计了融检索与生成于一体的任务,来进一步微调后得到的模型,所以它同时具备相似问生成和相似句检索能力。SimBERTv2是SimBERT的升级版,它们主要的区别在于训练的细节上,可以用两个公式进行对比:
S i m B E R T = B E R T + U n i L M + 对比学习 S i m B E R T v 2 = R o f o r m e r + U n i L M + 对比学习 + B A R T + 蒸馏 SimBERT=BERT+UniLM+对比学习 \\ SimBERTv2=Roformer+UniLM+对比学习+BART+蒸馏 SimBERT=BERT+UniLM+对比学习SimBERTv2=Roformer+UniLM+对比学习+BART+蒸馏SimBERT属于有监督训练,训练语料是自行收集到的相似句对,通过一句来预测另一句的相似句生成任务来构建Seq2Seq部分,

2.4 ChatGLM2-6B模型

ChatGLM-6B 是一个开源的、支持中英双语的对话语言模型,基于 General Language Model (GLM) 架构,具有 62 亿参数。ChatGLM-6B 使用了和 ChatGPT 相似的技术,针对中文问答和对话进行了优化。经过约 1T 标识符的中英双语训练,辅以监督微调、反馈自助、人类反馈强化学习等技术的加持,62 亿参数的 ChatGLM-6B 已经能生成相当符合人类偏好的回答。
ChatGLM2-6B 是开源中英双语对话模型 ChatGLM-6B 的第二代版本,在保留了初代模型对话流畅、部署门槛较低等众多优秀特性的基础之上,ChatGLM2-6B 引入了新特性。该模型具有以下特点:

  1. 更强大的性能:基于 ChatGLM 初代模型的开发经验,我们全面升级了 ChatGLM2-6B 的基座模型。ChatGLM2-6B 使用了 GLM 的混合目标函数,经过了 1.4T 中英标识符的预训练与人类偏好对齐训练,评测结果显示,相比于初代模型,ChatGLM2-6B 在 MMLU(+23%)、CEval(+33%)、GSM8K(+571%) 、BBH(+60%)等数据集上的性能取得了大幅度的提升,在同尺寸开源模型中具有较强的竞争力。
  2. 更长的上下文:基于 FlashAttention 技术,我们将基座模型的上下文长度(Context Length)由 ChatGLM-6B 的 2K 扩展到了 32K,并在对话阶段使用 8K 的上下文长度训练,允许更多轮次的对话。但当前版本的 ChatGLM2-6B 对单轮超长文档的理解能力有限,我们会在后续迭代升级中着重进行优化。
  3. 更高效的推理:基于 Multi-Query Attention 技术,ChatGLM2-6B 有更高效的推理速度和更低的显存占用:在官方的模型实现下,推理速度相比初代提升了 42%,INT4 量化下,6G 显存支持的对话长度由 1K 提升到了 8K。

ChatGPT是一种大规模预训练语言模型,可以生成自然语言响应。它的原理是在大量的文本数据上进行训练,从而学习到自然语言的结构、规则和语义。使用ChatGPT模型可以解决询问文档中不相关问题是,模型能够依托其大语言模型给出相似答案。

2.5 模型选择

时下主流的预训练框架有三种:autoregressive自回归模型(如GPT)、autoencoding自编码模型(如BERT)、encoder-decoder编码-解码模型(如T5、BigBird)。GLM模型基于autoregressive blank infilling方法,结合了上述三种预训练模型的思想。从简易化出发,我们选择了技术面更广更新的GLM模型,而并未选择BERT模型。
在确定了Langchain 与 ChatGLM 等大语言模型为框架的基础下,需选取Embedding 模型和 LLM 作为本地模型接入。我们对目前已有的模型进行学习和研究,并最终确定了 THUDM/chatglm2-6b 作为 LLM,moka-ai/m3e-base、GanymedeNil/text2vec-large-chinese 作为 Embedding 模型。

最终,我们采用了基于 Langchain 与 ChatGLM 等大语言模型的本地知识库问答应用实现该功能。下为原理图:
在这里插入图片描述

首先将本地文档(LocalDocuments)输入到Langchain中,并加载文档(UnstructuredLoader),随后对得到的文本(Text)进行文本分割(TextSplitter),之后构建向量库(Embedding),并将其存储到本地(VectorStore)。当用户进行询问时,Langchain将用户询问内容进行同样向量化处理,并与池化后的向量库进行相似度匹配,选取与用户询问相似度最高的内容作为结果通过大语言模型(LargeLanguageModel)输出给用户最终答案。

3 技术方案

3.1 获取训练集

为设计基于文档问答机器人,首先需获取全部文档作为训练集,题目已给出与Deepin操作系统相关的全部markdown文档,通过下面指令添加到本地仓库。

git clone https://github.com/linuxdeepin/wiki.deepin.org.git
  • 1

文档中存在很多不便于展示的图片,在对文档进行处理后,保留有效的文件作为dataset。并在每个文档中添加如下信息:

参考链接:<url>
  • 1

将得到的训练集分别以.md(markdown)和.txt格式存储。

3.2 项目部署

硬件配置:
CPU AMD Ryzen 9 3950X 16-Core Processor
GPU NVIDIA GeForce RTX 2070
操作系统:
Ubuntu 18.04LTS、Windows 10 1909H
项目环境:Python 3.8.1、CUDA 11.8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

3.3 下载模型至本地

首先需要将模型下载至本地,由于模型文件过大需要用LFS服务进行大文件下载,需安装 Git LFS,随后从huggingface上找到需要的模型文件进行clone。

git LFS install 
git clone https://huggingface.co/THUDM/chatglm2-6b
git clone https://huggingface.co/moka-ai/m3e-base
git clone https://huggingface.co/GanymedeNil/text2vec-large-chinese
  • 1
  • 2
  • 3
  • 4

3.4 配置模型

在模型下载完后,需要对项目进行配置,复制文件 configs/model_config.py.example 存储至项目路径下 ./configs 路径下,并重命名为 model_config.py。在 model_config.py中,需要指定使用本地模型及模型路径,并在llm_model_dictembedding_model_dict中进行修改。

llm_model_dict={
                "chatglm2-6b": {
                        "local_model_path": "/Users/chatglm2-6b",
                        "api_base_url": "http://localhost:8888/v1",  
                        "api_key": "EMPTY"
                    },
                }
                
embedding_model_dict = {
                        "m3e-base": "/Users/xxx/Downloads/m3e-base",
                       }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

3.5 初始化知识库

当前项目的知识库信息存储在数据库中,在正式运行项目之前需初始化数据库。第一次运行项目,知识库尚未建立,或者配置文件中的知识库类型、嵌入模型发生变化,需要以下命令初始化或重建知识库:

python3 init_database.py --recreate-vs
  • 1

3.6 启动API服务

首先在终端中启动LLM服务,使用基于多进程脚本 llm_api.py 启动 LLM 服务:

python server/llm_api.py
  • 1

再执行 server/api.py 脚本启动 API 服务;在线调用API服务的情况下,直接执执行 server/api.py 脚本启动 API 服务,启动 API 服务后,可访问 localhost:7861 FastAPI 自动生成的 docs 进行接口查看与测试。

python server/api.py
  • 1

最后,执行 webui.py 启动 Web UI 服务(默认使用端口 8501):

streamlit run webui.py
  • 1

3.7 知识库构建

在webui中,可以通过UI操作,点击知识库管理,随后向知识库中上传待训练的文件,在文件上传完后,点击添加知识库即可。

3.8 语义相似度检测

为使回答和问题要有80%以上概率的相关性,下面定义query句子,并获得它的向量表示:

query = '在此输入问题'  #  A query sentence uses for searching semantic similarity score.
queries = [query]
query_embeddings = model.encode(queries)
  • 1
  • 2
  • 3

对得到的结果进行相似度检测,可以利用text2vec包,通过以下函数sim_model.get_score(s1[i], s2[j]) 可计算得到余弦相似度值,score范围是[-1, 1],值越大越相似。

import sys

sys.path.append('..')
from text2vec import Similarity

# Two lists of sentences
sentences1 = ['']
sentences2 = ['']

sim_model = Similarity()
for i in range(len(sentences1)):
    for j in range(len(sentences2)):
        score = sim_model.get_score(sentences1[i], sentences2[j])
        print("{} \t\t {} \t\t Score: {:.4f}".format(sentences1[i], sentences2[j], score))```
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

我们对得到的结果进行多次相似度检测,计算均值得到结果为:
因此可确定该问答机器人回答准确率在90%以上。

4 开发心得与体会

4.1 疑难处理

  1. 当尝试初始构建知识库时,出现以下报错:
[E050] Can't find model 'zh_core_web_sm'. It doesn't seem to be a Python package or a valid path to a data directory. 
  • 1

查阅资料后发现缺少 ‘zh_core_web_sm’ 模型,参考官网指导进行安装:

pip3 install en_core_web_sm-3.0.0.tar.gz 
pip3 install zh_core_web_sm-3.0.0.tar.gz 
-i https://pypi.tuna.tsinghua.edu.cn/simple/
  • 1
  • 2
  • 3
  1. 调用nltk库的word_tokenize方法实现英文分词,出现以下报错:
Resource punkt not found. Please use the NLTK Downloader to obtain the resource
  • 1

解决方案:运行下面代码:

import nltk
nltk.download()
  • 1
  • 2

在打开的界面中下载punkt模型:
在这里插入图片描述

4.2 开发体会

通过本次开发Deepin系统文档问答机器人,我们有很多收获。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/415764
推荐阅读
相关标签
  

闽ICP备14008679号