最近小马在搞AI,目标是实现一个智能问答系统来支撑业务。经过了之前一段时间的基础AI技术学习后,小马开始NLP并调研智能问答系统。本文介绍如何5分钟快速搭建一个智能问答系统。亲测效果良好。
典型的QA 系统包括在线客户服务系统、QA 聊天机器人等。大多数问答系统可以分为:生成式或检索式、单轮或多轮、开放域或特定问答系统。
传统的问答机器人大都是基于规则的知识图谱方式实现,这种方式需要对大量的语料进行分类整理。
而基于深度学习模型的实现方式可以彻底摆脱对语料的预处理,只需提供问题和答案的对应关系,通过自然语言处理的语义分析模型对问题库提取语义特征向量存入Milvus中,然后对提问的问题也进行语义特征向量提取,通过对向量特征的匹配就可以实现自动回复,轻松实现智能客服等应用。
一、理论准备
如何5分钟快速搭建一个智能问答系统,小马最初受到启发的是这个视频教程《5分钟搭建智能问答系统》,文章《快速搭建对话机器人,就用这一招!》--文章里有比较清晰的原理描述,但是发现教程中的项目版本已经过旧,而且资源已经被下架,所以视频仅供参考。于是顺藤摸瓜,找到最新相关教程的开源github地址(如果开源地址打不开了,来这里找或者找到文末源码下载链接并找到下图所示目录中的教程文件),跟着这个教程走。(附:加载中文模型的参考文章《bootcamp问答系统部署》)
教程文件
我们先来看看这个项目的描述。
This project combines Milvus and BERT to build a question and answer system. This aims to provide a solution to achieve semantic similarity matching with Milvus combined with AI models.
直译为:
本项目结合 Milvus 和 BERT 构建问答系统。旨在提供一种解决方案,通过 Milvus 结合 AI 模型实现语义相似度匹配。
Milvus是什么?
Milvus是一款全球领先的开源向量数据库,赋能 AI 应用和向量相似度搜索,加速非结构化数据检索。
Milvus is the most advanced open-source vector database built for AI applications and supports nearest neighbor embedding search across tens of millions of entries, and Towhee is a framework that provides ETL for unstructured data using SoTA machine learning models.
芝麻街
BERT 是什么?
BERT是Google开发的一种基于Transformer的机器学习技术,用于自然语言处理(NLP) 预训练。
BERT 是一个算法模型,它的出现打破了大量的自然语言处理任务的记录。在 BERT 的论文发布不久后,Google 的研发团队还开放了该模型的代码,并提供了一些在大量数据集上预训练好的算法模型下载方式。Goole 开源这个模型,并提供预训练好的模型,这使得所有人都可以通过它来构建一个涉及NLP 的算法模型,节约了大量训练语言模型所需的时间,精力,知识和资源。BERT模型的全称是:BERT(Bidirectional Encoder Representations from Transformers)。从名字中可以看出,BERT模型的目标是利用大规模无标注语料训练、获得文本的包含丰富语义信息的Representation。
BERT模型简介
BERT BASE: 与OpenAI Transformer 的尺寸相当,以便比较性能。
BERT LARGE: 一个非常庞大的模型,是原文介绍的最先进的结果。
BERT的基础集成单元是Transformer的Encoder。
这里有一个BERT相关视频教程《BERT从零详细解读,看不懂来打我》,涉及AE输入形式 mask模型,其使用到概率学,所以无监督学习依赖于训练数据,需要从训练数据中计算概率。
BERT是一个多任务模型,它的任务是由两个自监督任务组成,即MLM和NSP。
所谓MLM是指在训练的时候随即从输入预料上mask掉一些单词,然后通过的上下文预测该单词,该任务非常像我们在中学时期经常做的完形填空。正如传统的语言模型算法和RNN匹配那样,MLM的这个性质和Transformer的结构是非常匹配的。
Next Sentence Prediction(NSP)的任务是判断句子B是否是句子A的下文。相关还有教程1,2。
BERT其中的一个重要作用是可以生成词向量,它可以解决word2vec中无法解决的一词多义问题。获取完BERT词向量后还可以结合CNN、RNN等模型来实现自己的任务。
图片来自互联网
我们现在可以来看下系统的架构原理图。
Question Answering Engine
该系统可以将新的用户问题与先前存储在向量数据库中的大量答案联系起来。要构建这样的聊天机器人,请准备您自己的问题数据集和相应的答案。将问题和答案存储在关系数据库 MySQL中。然后使用用于自然语言处理 (NLP) 的机器学习 (ML) 模型BERT将问题转换为向量。这些问题向量在 Milvus 中存储和索引。当用户输入一个新问题时,BERT 模型也会将其转换为一个向量,Milvus 会搜索与这个新向量最相似的问题向量。问答系统对最相似的问题返回相应的答案。
系统会使用 Milvus 存储和搜索特征向量数据,Mysql 用于存储 Milvus 返回的 id 与问题数据集的对应关系,此时需要先启动 Milvus 和 Mysql。
二、快速部署
根据教程,我们需要安装 Milvus and MySQL。(注意参考视频中用的不是mysql来支持,是PostgreSQL)
小马的操作系统是ubuntu,并已安装了docker。
- Start Milvus and MySQL
Start Milvus v2.0
基于docker直接安装好Milvus,Install Milvus Standalone这一步相对比较简单照着教程敲就可以跑起来。
如果以上链接打不开,可以参考这个官方英文版教程。
wget https: //github.com/milvus-io/milvus/releases/download/v2.2.0/milvus-standalone-docker-compose.yml -O docker-compose.yml
Start MySQL
照着命令敲就可以跑起来。
- Start Server
现在我们需要起服务,教程提供了两种方式:通过运行docker、运行源码。如果是前者,需要注意参照教程设置好环境变量,而且需要注意跑起来的时候可能需要下依赖,其中报错不好排查。为了更清晰直观地学习,小马采用后者的方式运行服务。
Install the Python packages
先将代码拉取到本地,如果遇到git clone 等命令报错等问题,请先解决git问题,不是本文重点不再赘述。
我们进去源码的server目录,cd server,进行pythone依赖包的安装pip install -r requirements.txt。可以看一眼依赖文件。
这一步命令的运行可能会遇到各种报错,请自行寻找解决方案。
比如,pymilvus只支持python >= 3.4,在3.4、3.5、3.6、3.7下进行了全面测试。所以如果系统默认的python命名运行的是python2.7版本的,就会报错,需要更改命令执行的默认版本或者更新pip到3版本等等。pip3 install -r requirements.txt,如果不行还可以尝试更换源pip3 install -r requirements.txt -i https: //pypi.douban.com/simple,或者直接指定命令版本python3 -m pip install -r requirements.txt来运行。总之,这里要特别注意以py版本和源导致的报错为解决方向。
wget the model
安装完python依赖包之后,我们需要到cd server/src/model目录下进行模型下载(注意如果是docker运行的server指定的模型文件解压后目录是server/src/models,这取决于配置文件的配置)。教程里指定的地址是英文的模型https: //public.ukp.informatik.tu-darmstadt.de/reimers/sentence-transformers/v0.2/paraphrase-mpnet-base-v2.zip,这个模型将句子和段落映射到768维的密集向量空间,可用于聚类或语义搜索等任务。号称是支持中英文的,小马亲测,中文效果不佳。于是很多教程是建议换成中文模型的(即:要更换为中文训练模型,项目bootcamp默认是支持西文的。 bootcamp中text_search_engine默认使用的是paraphrase-mpnet-base-v2预训练模型的,通过上面的修改也能对中文进行搜索,但其主要针对的是西文,如果要使用中文进行NLP检索的话最好更换预训练模型)。于是小马就着手把这里的模型文件进行更换。
sentence-transformers框架包(如paraphrase-multilingual-MiniLM-L12-v2模型可以支持NLP文本相似度的计算),SBERT的作者发布了他们预训练的SBERT模型。所有预训练的模型可以在这里找到(也是教程默认的模型包含目录),可惜没有中文版的。sentence-transformers开源地址。
《Sentence-BERT实战》通过SBERT查找相似句子,假设我们有一个电子商务网站,假设在我们的数据库中有很多订单相关的问题,比如How to cancel my order?, Do you provide a refund?等等。现在当新问题进来时,我们的目标是找到与新问题最相似的问题。
SBERT模型是基于pytorch和transformers来实现的。
我们根据网络推荐将模型文件换成这个训练好的BERT中文模型:https: //storage.googleapis.com/bert_models/2018_11_03/chinese_L-12_H-768_A-12.zip
chinese_L-12_H-768_A-12是谷歌google发布的唯一一个中文模型。
类似的有:
chinese_wwm_ext_pytorch是哈工大讯飞联合实验室发布的中文预训练bert模型。
google-research bert训练好的模型。
Set configuration
同时按照参数表修改quick_deploy/server/src/config.py文件,修改MODEL_PATH地址为我们中文模型的路径(需要特别注意,这里只是模型文件目录的设置,具体目录里面是什么模型文件内容可能还得通过复查确认并修改encode.py代码来支持(可参考这里修改),即MODEL_PATH目录下的文件应该要是直接为模型的几个支撑文件):
插播一下:我们看到如果按照上文直接将上文提到的中文模型解压到模型文件目录,运行报错:
检查了下模型的目录,chinese_L-12_H-768_A-12中文的有两层上级目录,目录处理后与默认的英文模型来对比文件,确实模型文件中的内容不太相同(如上图默认必须要有modules.json)。其实,谷歌官方发布的中文版chinese_L-12_H-768_A-12文件是基于TensorFlow的,TensorFlow可是谷歌旗下的宝贝,使用pytorch无法运行。不过据说有可以将其转化为pytorch版本的脚本,可以自己搜一下。
Towhee is a machine learning framework that allows the creation of data processing pipelines, and it also provides predefined operators for implementing insert and query operations in Milvus.
于是我们到这里(即上文提到的Sentence-BERT(简称SBERT)作者提供的官方模块)下面找到另外两个支持中文的模型paraphrase-multilingual-mpnet-base-v2,paraphrase-multilingual-MiniLM-L12-v2尝试下效果(注意上文的chinese_L-12_H-768_A-12其实并不在目录中),更改加载模型的方法与chinese_L-12_H-768_A-12类似:
我们知道不同的模型向量维度是不一样的,如果直接这样使用会碰到报错,会提示你设置的向量维度和当前的向量维度不同。于是我们打开模型文件中的训练脚本看到向量维度为512,所以应该修改配置文件中的768为VECTOR_DIMENSION = int(os.getenv("VECTOR_DIMENSION", "512")):注意这是个坑,看下文。
导入数据集时还是报错: ERROR | milvus_helpers.py | insert | 66 | Failed to insert data into Milvus: Collection field dim is 512, but entities field dim is 768。
数据维度和表不符合,要重建一个collection?其实这个报错的意思是,Collection也就是相当于表是512的,但是数据是768的。呃,我们瞅一眼源码如下,于是决定还是改回VECTOR_DIMENSION = int(os.getenv("VECTOR_DIMENSION", "768")):于是导入正常了。
在导入csv文件时,若为中文问答集,为了避免csv文件导入时因编码问题的报错:UnicodeDecodeError: 'utf-8' codec can't decode byte 0xc4 in position 0: invalid continuation byte 或 Error with extracting feature from question 'gb2312' codec can't decode byte 0xa9 in position 71459: illegal multibyte sequence,我们需要相应得修改quick_deploy/server/src/opertio ns/load.py中读取csv文件部分代码为:
另外由于mysql建表编码格式的问题,可能导致后续导入数据出错,为了预防,修改quick_deploy/server/src/mysql_helper.py中创建mysql表部分代码为:
Run the code
到此我们的准备工作已经好了,回到教程,Then start the server with Fastapi.
我们看到服务已经启动。可以到api页面127.0.0.1:8000/docs调试接口了,127.0.0.1可换成机器的具体ip。至此,问答系统已经搭建好了,只需要按照CSV文档格式导入自己QA数据集(旧版教程中的项目一次最多只支持10MB数据集上传),就可以支持问答了。
需要体验客户端的话按照教程的命令即可(要注意把机器人服务的ip改为实际机器的ip),官方效果体验地址这里。
小马的界面
我们再来参观一下导入中文QA后DB的存储。
小馬親測,中文模型的效果還是不錯的。
相关资料:
bert-as-service
zilliz
中文语料/数据集
各领域公开数据集下载
文章关键字提取(基于BERT的关键词抽取)
bert中文使用
知乎-如何搭建基于文本语义的智能问答系统?
Milvus 智能问答系统
sbert模型准确率如何查看