任务说明:
https://wiki.deepin.org 上有900多条deepin系统相关的中文教程和词条,请编写能根据这些内容回答问题的中文聊天机器人。使用者通过命令行界面输入问题,机器人输出回答和参考的wiki文档的链接。
聊天机器人要能根据 deepin wiki 内容回答问题;且回答和问题有80%以上概率的相关性;对于每个问题,机器人要给出3个可能的回答;编写博客,记录开发过程的心得与体会。
代码仓库在此自提,欢迎star:
ArkShin / project225 · GitLab (eduxiji.net)
题目分析与设计思路:
这道题的本质是制作一个问答系统,属于NLP任务。传统上问答系统有3条技术路线,一是利用知识图谱构建deepin系统各概念之间的关系并以此回答;二是将问题和参考文档一起放进BERT等语言模型,预测答案所在文章位置;三是利用生成式语言模型直接输出结果,但这可能存在“幻觉”问题,即模型输出错误。前两个技术路线更成熟,但实现步骤繁琐,需要大量数据集,回答不够自然流畅。
这里最终采用sBERT+生成式模型的路线来完成该问答机器人。首先就输入问题和所有教程文档比对语义,匹配出相似度高的文档;再将文档和问题作为prompt输入生成式LLM(large language model),让它参考文档内容生成回答。这克服了传统问答系统回答不够自然的问题和LLM的“幻觉”问题,保证了输出的流畅与准确。
1、利用sBERT完成文档匹配,它是双塔模型(Deep Structured Semantic Model,DSSM)的一种:
(1)双塔模型包括user塔和item塔;item塔负责对所有文档进行词嵌入得到词向量,对词向量进行处理得到文档的向量表示。user塔负责对输入的问题进行词嵌入,同样处理得到问题语句的句向量。
(2)计算向量间的余弦距离,返回最相近的k个作为参考文档。题目要求给出3个参考回答,取k=3。
(3)sBERT使用BERT对文档进行嵌入,通过pooling得到句向量编码;并衡量他们的余弦距离。
双塔模型就是这样子的;当然这是最原始的,我们使用的sBERT后面会提到。
2、问答利用LLM进行:
我们将匹配的文档内容和用户问题一起作为LLM的prompt。LLM会在给定参考文档内寻找答案并输出结果,这样的“阅读题”保证了答案的可靠性;生成式QA让机器人回答更自然流畅。另外即使参考文档不准确LLM也会根据自己知识进行补充。这里我们使用gpt-3.5-turbo模型作为LLM。
系统框架:
系统由三个部分组成。
1、输入模块:用户需要配置选择的模型类型、文档位置、GPT-API密钥等信息,并选择自己的问题所属类型并输入问题。
2、匹配模块:将输入文字用向量表示并通过sBERT得到和问题匹配度高的文档。
3、回答模块:将问题和文档一起作为prompt传给gpt-3.5并使之回答问题。计算文本间的相似度:对于测试集中的问答衡量所给答案和测试集标准答案的相似度;对于测试集外的问答衡量问题和答案所在文档间的相似度。
实现重点描述:
1、由于deepin wiki网站设置了反爬虫,无法通过爬虫获得文档信息;只能手工复制粘贴的方式将网站的文档信息全部转移到本地,存储在data.zip中;每个.txt文档均包含了页面的文字信息和其URL链接。
2、词嵌入(word-embedding)即对词语进行向量化表示,使向量能反映语义。比对多种嵌入方式,我们最终使用BERT模型对文档进行词嵌入,得到了词向量的合理表示。在这里我们试验了不同的预训练BERT,根据表现最后选择Chinese-BERT-wwm预训练模型。 这个模型是由哈工大讯飞联合实验室训练的,效果比Google的中文BERT要好,模型链接放在这里了:hfl/chinese-bert-wwm-ext · Hugging Face
3、BERT只是对每个词进行了嵌入,之后还需要通过pooling(mean-pooling或max-pooling)得到整个文档或句子的句向量,这里我们使用mean-pooling完成池化。将用户问题的嵌入向量(user塔)和所有文档的嵌入向量(item塔)逐一比较余弦距离,距离最小的相似度最高。
4、调用gpt-3.5-turbo的API过程中,传送给GPT的prompt定义为:
prompt="参考资料:"+sBERT匹配出的document+"请据此回答问题:"+question
对GPT的提示角色内容是:
"role": "system", "content": "你是一个自动问答系统;请回答问题,你可以参考提供的资料作答."
如果文档过长超过了GPT的tooken限制,会放弃这一文档并依序用下一个文档内容进行提问;直到输出3个回答。
每个回答之后系统会输出该文档中记录的网页地址作为参考链接,并给出二者的余弦相似度。
系统测试情况:
1、开发过程中针对每个函数体均进行了单元测试;针对文档匹配、GPT提问等模块均单独进行了构件测试,确保项目各构件之间的交互没有问题。
2、为衡量问题回答的效果,我们从deepin文档中抽取信息构建了30个问-答对序列作为数据集存储在dataset.json中。运行时每个问题系统都会给出最可能的3个答案,比较这些答案和数据集标准答案之间的余弦相似度;这样一共得到了90个结果。余弦相似度的公式为:
3、对90个答案分别求取余弦相似度,本系统可以保证输出的回答与正确答案语义上90+%的相似度,且从匹配度越高的文档中得到的回答相似度越高。
系统效果:
可以看出基本上还是能给出比较靠谱的回答的~
机器人给的链接都是可以点开的,不是GPT编出来的~
收获&后记:
这个项目是大学生操作系统大赛的一道题,要求制作一个国产操作系统的问答机器人;这篇博客也投放到了deepin社区中,算是为国产操作系统做出了一点微不足道的贡献吧。
该项目的核心还是NLP,我们考察了很多比较传统的模型包括知识图谱等,最后还是决定借着大模型的风口,做一些GPT的应用吧。GPT的出现的确改变了NLP的很多,但感觉还是需要调教;像这里是通过类似阅读题的方式让它不要胡说八道。
最后整个项目都是模块化的,你可以轻易组装;比如用Word2Vec或者别的encoding方式替换我们的BERT;我们也希望将来有一天能用文心一言等国产大模型替换GPT来生成回答。
参考文献:
1、Deepin Wiki - 深度百科 | DeepinWiki
2、Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks arXiv:1908.10084 [cs.CL]
3、Revisiting Pre-Trained Models for Chinese Natural Language Processing arXiv:2004.13922 [cs.CL]