搭建一个简单的FAQ系统

现在的智能问答系统的应用是非常普遍的,比如说客服,前台机器人,讲解机器人等很多场景都可能会用到FAQ问答系统,所谓的FAQ就是 frequently asked questions,也就是说在某个场景下,比较常见的一些问题。
首先我们来看看整体的FAQ流程,我们需要对输入的问题进行预处理,比如去停,分词等;然后需要对预处理之后的语料进行向量化,这里向量化的方法很多,也不拘泥于一种,常见的向量化方法有词频向量化、word2vec、tf-idf 等方法;向量化之后,就可以进行文本相似度计算了然后我们可以选取相似度最高的问题答案输出就可以了。
整个处理的流程图如下所示:
flowchart
好了,明白了整个流程了之后,我们就可以开始搭建问答系统了。首先,是创建问答库,这里我们就创建一个十来个问题的问题库和答案库,顺序要一一对应起来:
问题库:
question
答案库:
answer
好了,问答库弄好了之后,我们要对问题库进行预处理操作,主要就是进行分词操作,代码如下所示:
segment

import jieba


def stopword_list():
    stopwords = [line.strip() for line in open('stopword.txt', encoding='utf-8').readlines()]
    return stopwords


def seg_with_stop(sentence):
    sentence_seg = jieba.cut(sentence.strip())
    stopwords = stopword_list()
    out_string = ''
    for word in sentence_seg:
        if word not in stopwords:
            if word != '\t':
                out_string += word
                out_string += " "
    return out_string


def segmentation(sentence):
    sentence_seg = jieba.cut(sentence.strip())
    out_string = ''
    for word in sentence_seg:
        out_string += word
        out_string += " "
    return out_string


inputQ = open('Question.txt', 'r', encoding='gbk')
outputQ = open('QuestionSeg.txt', 'w', encoding='gbk')
inputA = open('Answer.txt', 'r', encoding='gbk')
outputA = open('AnswerSeg.txt', 'w', encoding='gbk')

for line in inputQ:
    line_seg = segmentation(line)
    outputQ.write(line_seg + '\n')

outputQ.close()
inputQ.close()

for line in inputA:
    line_seg = segmentation(line)
    outputA.write(line_seg + '\n')

outputA.close()
inputA.close()

我们逐行对问题库进行了分词操作,然后输出。接下来我们就可以进行输入问题 query 进行向量化,然后和问题库中的问题向量进行相似度计算,这里我们用的是余弦相似度算法,然后取相似度最高的问题相对应的答案输出即可,其实流程是比较简单的。代码如下所示:
vector

from sklearn.feature_extraction.text import CountVectorizer
import math
from segmentation import segmentation

count_vec = CountVectorizer()


def count_cos_similarity(vec_1, vec_2):
    if len(vec_1) != len(vec_2):
        return 0

    s = sum(vec_1[i] * vec_2[i] for i in range(len(vec_2)))
    den1 = math.sqrt(sum([pow(number, 2) for number in vec_1]))
    den2 = math.sqrt(sum([pow(number, 2) for number in vec_2]))
    return s / (den1 * den2)


def cos_sim(sentence1, sentence2):
    sentences = [sentence1, sentence2]
    # print(count_vec.fit_transform(sentences).toarray())  # 输出特征向量化后的表示
    # print(count_vec.get_feature_names())  # 输出的是切分的词, 输出向量各个维度的特征含义

    vec_1 = count_vec.fit_transform(sentences).toarray()[0]
    vec_2 = count_vec.fit_transform(sentences).toarray()[1]
    # print(len(vec_1), len(vec_2))
    return count_cos_similarity(vec_1, vec_2)


def get_answer(sentence1):
    sentence1 = segmentation(sentence1)
    score = []
    for idx, sentence2 in enumerate(open('QuestionSeg.txt', 'r')):
        # print('idx: {}, sentence2: {}'.format(idx, sentence2))
        # print('idx: {}, cos_sim: {}'.format(idx, cos_sim(sentence1, sentence2)))
        score.append(cos_sim(sentence1, sentence2))
    if len(set(score)) == 1:
        print('暂时无法找到您想要的答案。')
    else:
        index = score.index(max(score))
        file = open('Answer.txt', 'r').readlines()
        print(file[index])


while True:
    sentence1 = input('请输入您需要问的问题(输入q退出):\n')
    if sentence1 == 'q':
        break
    else:
        get_answer(sentence1)

好了,我们可以试试效果如何:
result
仅仅通过余弦相似度匹配,我们就可以有一个不错的效果了,这就是一个简单的问答系统搭建。希望能让大家对QA系统有一个初步的了解,如有纰漏之处,也请大家不吝指教,代码详情请见 GitHub,谢谢。

  • 5
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值