基于关键词/TF-IDF/SimCSE召回和ERNIE-Gram排序的政务问答(FAQ)系统搭建

一、引言

1.1 政务问答系统的重要性

在数字化转型的大潮中,政务问答系统作为政府与民众之间沟通的重要桥梁,其重要性日益凸显。这类系统不仅能够迅速响应民众的需求,还能有效提升政务服务的效率与质量,进一步推动政府的透明化、高效化和智能化建设。

提高政务服务效率:政务问答系统通过自动化处理民众的问题,显著减少了人工客服的工作量,从而加快了问题解决的速度。同时,系统还能对常见问题进行智能识别与快速回复,有效缩短了民众等待的时间。

提升公众满意度:政务问答系统能够提供24小时不间断的服务,满足民众随时随地的咨询需求。此外,系统还能根据民众的历史问题和偏好,提供个性化的服务建议,从而增强民众的获得感和满意度。

1.2 政务问答系统的核心要素

构建一个高效、智能的政务问答系统,离不开以下三个核心要素:

数据源:数据源是政务问答系统的基石。系统需要从政府网站、政策文件、公告通知等多个渠道收集并整合信息,以确保回答的准确性和权威性。

召回与排序算法:召回算法负责从庞大的数据源中快速找到与民众问题相关的候选答案。而排序算法则根据答案的相关性、准确性等因素,对候选答案进行排序,以呈现给民众最优质的回复。

系统架构:系统架构决定了政务问答系统的稳定性和可扩展性。一个优秀的系统架构应该能够支持高并发访问、快速响应和灵活迭代,以满足不断变化的服务需求。

1.3 博客目的

本博客旨在详细介绍基于关键词、TF-IDF、SimCSE召回和ERNIE-Gram排序的政务问答系统搭建过程。通过深入剖析这些技术的原理与应用,我们将展示如何构建一个高效、智能且易于维护的政务问答系统,以期为相关领域的从业者提供有益的参考和启示。下图是保险领域的问答示例:

二、技术背景

2.1 关键词匹配技术

基本原理:关键词匹配技术是一种基于字符串匹配的算法,它通过将用户输入的问题与数据库中的问题进行逐一比对,找到最相似的答案进行回复。这种技术简单直观,但容易受到同义词、近义词等语言现象的影响,导致匹配精度不高。

优缺点分析:关键词匹配技术的优点在于实现简单、速度快,适用于处理大规模文本数据。然而,其缺点也显而易见,即对于语义层面的理解较为有限,难以处理复杂或模糊的问题。

2.2 TF-IDF算法

定义与计算方式:TF-IDF(Term Frequency-Inverse Document Frequency)是一种用于评估一个词语对于一个文件集或一个语料库中的其中一份文件的重要程度的统计方法。其中,TF(词频)表示某个词语在文档中出现的频率;IDF(逆文档频率)则用于衡量该词语在文档集中的普遍程度。通过计算每个词语的TF-IDF值,我们可以筛选出对文档最具代表性的词语。

在文本处理中的应用:TF-IDF算法在文本分类、信息检索等领域有着广泛的应用。在政务问答系统中,我们可以利用TF-IDF算法对问题进行特征提取,然后基于这些特征进行答案的召回与排序。

2.3 SimCSE模型

简介与原理:SimCSE是一种基于对比学习的语义匹配模型,它通过对输入文本进行微小的扰动(如删除、替换或插入词语等),生成多个正样本对,并利用这些正样本对进行模型训练。通过这种方式,SimCSE能够学习到文本的深层语义表示,从而实现对文本之间语义相似度的准确评估。

在语义匹配中的应用:在政务问答系统中,SimCSE模型可以用于评估用户输入的问题与候选答案之间的语义相似度,从而帮助系统更准确地召回相关答案。

2.4 ERNIE-Gram模型

ERNIE系列介绍:ERNIE(Enhanced Representation through kNowledge IntEgration)是百度开发的一系列预训练语言模型,旨在通过引入丰富的知识信息来提升模型的语义理解能力。ERNIE系列模型在多个自然语言处理任务上取得了显著的性能提升。

ERNIE-Gram的特点与优势:ERNIE-Gram作为ERNIE系列的一个变种,特别注重于捕捉文本中的n-gram特征(即连续出现的n个词语组成的短语)。这种设计使得ERNIE-Gram在处理复杂或模糊的文本时表现出色,能够更准确地理解文本的语义信息。在政务问答系统中,ERNIE-Gram模型可以用于对候选答案进行排序,以确保呈现给民众最优质的回复。

三、系统设计与实现

3.1 系统整体架构

政务问答系统的整体架构由多个模块组成,包括数据预处理模块、召回模块、排序模块、输出与交互模块。这些模块协同工作,共同实现用户问题的智能回答。

问答的流程分为两部分,第一部分是管理员/工程师流程,第二部分就是用户使用流程,在模型的层面,需要离线的准备数据集,训练模型,然后把训练好的模型部署上线。另外,就是线上搭建问答检索引擎,第一步把收集好的语料数据,利用训练好的模型抽取问题的向量,然后把向量插入到近似向量检索引擎中,构建语义索引库,这部分做完了之后,就可以使用这个问答服务了,但是用户输入了Query之后,发生了什么呢?第一步就是线上服务会接收Query后,对数据进行处理,并抽取用户Query的向量,然后在ANN查询模块进行检索匹配相近的问题,最终选取Top10条数据,返回给线上服务,线上服务经过一定的处理,把最终的答案呈现给用户。

本次模型的优化流程如下:

3.2 数据预处理模块

数据采集与清洗

  • 从政府网站、政策文件、公告通知等渠道收集数据。
  • 对数据进行清洗,去除重复、无效或格式不正确的信息。

文本分词与去停用词

  • 使用分词工具对文本进行分词处理。
  • 去除文本中的停用词,如"的"、"了"等常见但无实际意义的词语。

得到的问答对数据如下:

宁夏针对哪些人员开通工伤保障绿色通道?
四川金堂税务网上申报率为多少?
普陀如何实时跟踪返沪人员健康信息?
闽政通上的跨省异地就医业务可办理哪些业务子项?
国家卫健委要求什么人员禁止乘坐交通工具?
中国科学院上海有机化学研究所与广西中医药大学联合哪些机构结合中医药特点研发抗新型冠状病毒的药剂?
河北省的单位想要审批投资项目,可以在哪里办理呢?
重庆市使用财政性资金采购进口疫情防控物资如何审批?

评估集是问题对,示例如下:

南昌市出台了哪些企业稳岗就业政策?	南昌市政府出台了哪些企业的稳岗就业政策?
上海宣布什么时间开始开展中小学在线教育,学生不到校?	中小学在线教育什么时候开始,上海开始开始的?
北京市对于中小微企业经贸交流平台展会项目的支持标准是怎样的?	中小微企业经贸交流平台的发展目标
在疫情防控期间怎样灵活安排工作时间?	怎样在防控期间灵活安排工作时间?
湖北省为什么鼓励缴费人通过线上缴费渠道缴费?	为什么要鼓励缴费人通过线上缴费渠道缴费

特征提取与存储

  • 提取文本中的关键词、短语等特征信息。
  • 将特征信息存储到数据库中,以便后续召回和排序模块使用。 进行数据库中的问题进行特征编码的代码片段如下:

3.3 召回模块实现

基于关键词的召回

  • 根据用户输入的问题,提取关键词。
  • 在数据库中搜索包含这些关键词的文本,作为候选答案。

核心代码片段如下:

基于TF-IDF的召回

  • 计算用户输入问题与数据库中文本的TF-IDF值。
  • 根据TF-IDF值的相似度,选择最相关的文本作为候选答案。

核心代码片段如下:

基于SimCSE的召回策略与实现: 首先政务问答场景的数据只有问题和答案对,再没有其他的数据了。如果使用有监督方法,需要问题-问题对,还需要收集一些问题进行人工标注。因此可以考虑使用无监督语义索引技术SimCSE模型。

总体上无监督技术没有有监督技术效果好,所以为了提升SimCSE的性能,我们使用了开放问答领域的预训练语言模型RocketQA,并且在SimCSE的基础上利用WR策略进行优化。

整个方案无需人工参与数据标注,所以是一个无监督的解决方案。

上图是SimCSE的原理图,SimCSE主要是通过dropout来把同一个句子变成正样本(做两次前向,但是dropout有随机因素,所以产生的向量不一样,但是本质上还是表示的是同一句话),把一个batch里面其他的句子变成负样本的。

SimCSE网络结构搭建,搭建代码如下:

加载模型的核心代码片段如下:

排序模块实现

ERNIE-Gram模型训练与调优

  • 使用政务领域的数据对ERNIE-Gram模型进行预训练。
  • 根据实验结果调整模型参数,以提高排序精度。

ERNIE-Gram模型的代码如下:

ini 复制代码
class Predictor(object):
    def __init__(self,
                 model_dir,
                 device="gpu",
                 max_seq_length=128,
                 batch_size=32,
                 use_tensorrt=False,
                 precision="fp32",
                 cpu_threads=10,
                 enable_mkldnn=False):
        self.max_seq_length = max_seq_length
        self.batch_size = batch_size

        model_file = model_dir + "/inference.get_pooled_embedding.pdmodel"
        params_file = model_dir + "/inference.get_pooled_embedding.pdiparams"
        if not os.path.exists(model_file):
            raise ValueError("not find model factivateile path {}".format(model_file))
        if not os.path.exists(params_file):
            raise ValueError("not find params file path {}".format(params_file))
        config = paddle.inference.Config(model_file, params_file)

        if device == "gpu":
            # set GPU configs accordingly
            # such as intialize the gpu memory, enable tensorrt
            config.enable_use_gpu(100, 0)
            precision_map = {
                "fp16": inference.PrecisionType.Half,
                "fp32": inference.PrecisionType.Float32,
                "int8": inference.PrecisionType.Int8
            }
            precision_mode = precision_map[precision]

            if use_tensorrt:
                config.enable_tensorrt_engine(
                    max_batch_size=batch_size,
                    min_subgraph_size=30,
                    precision_mode=precision_mode)
        elif device == "cpu":
            # set CPU configs accordingly,
            # such as enable_mkldnn, set_cpu_math_library_num_threads
            config.disable_gpu()
            if enable_mkldnn:
                # cache 10 different shapes for mkldnn to avoid memory leak
                config.set_mkldnn_cache_capacity(10)
                config.enable_mkldnn()
            config.set_cpu_math_library_num_threads(cpu_threads)
        elif device == "xpu":
            # set XPU configs accordingly
            config.enable_xpu(100)

        config.switch_use_feed_fetch_ops(False)
        self.predictor = paddle.inference.create_predictor(config)
        self.input_handles = [
            self.predictor.get_input_handle(name)
            for name in self.predictor.get_input_names()
        ]
        self.output_handle = self.predictor.get_output_handle(
            self.predictor.get_output_names()[0])

     

    def predict(self, data, tokenizer):
        
        examples = []
        for text in data:
            input_ids, segment_ids = convert_example_ranking(
                text,
                tokenizer,
                max_seq_length=self.max_seq_length,
                is_test=True)
            examples.append((input_ids, segment_ids))

        batchify_fn = lambda samples, fn=Tuple(
            Pad(axis=0, pad_val=tokenizer.pad_token_id, dtype='int64'),  # input
            Pad(axis=0, pad_val=tokenizer.pad_token_id, dtype='int64'),  # segment
        ): fn(samples)


        input_ids, segment_ids = batchify_fn(examples)
        self.input_handles[0].copy_from_cpu(input_ids)
        self.input_handles[1].copy_from_cpu(segment_ids)
        self.predictor.run()
        sim_score = self.output_handle.copy_to_cpu()

        sim_score = expit(sim_score)

        return sim_score

加载训练好的模型核心代码如下:

四、模型的应用

4.1 语义召回模型的调用

调用测试的代码片段如下:

4.2 问答功能使用fastapi进行接口化

词语联想接口如下:

问答接口如下:

五、系统应用与效果

5.1 政务问答系统的实际应用场景

政务服务大厅

  • 在政务服务大厅中设置问答系统,方便市民咨询和办理业务。
  • 通过系统提供的信息,减少市民等待时间,提高服务效率。

在线政务平台

  • 在线政务平台上集成问答系统,为市民提供24小时不间断的服务。
  • 通过系统回答市民的问题,减轻人工客服的工作压力。

微信公众号端的应用截图:

网页端的应用截图:

5.2 系统应用效果展示

用户反馈与满意度调查

  • 收集用户对系统的反馈意见,了解系统的优缺点。
  • 进行满意度调查,评估系统对用户需求的满足程度。

政务服务效率提升数据

  • 统计系统上线前后的政务服务效率数据,如办理时间、用户满意度等。
  • 分析系统对政务服务效率的提升效果。

系统的后台数据显示:

5.3 系统优化与迭代

根据用户反馈进行功能调整

  • 根据用户的反馈意见,对系统的功能进行调整和优化。
  • 增加用户需要的功能,改进用户不满意的地方。

引入新技术提升系统性能

  • 关注自然语言处理领域的新技术和发展趋势。
  • 将新技术引入到系统中,提升系统的性能和智能化水平。

六、结论与展望

6.1 博客内容总结

本博客详细介绍了政务问答系统的搭建过程与关键技术。通过数据预处理、召回模块、排序模块和输出与交互模块的设计和实现,构建了一个高效、智能的政务问答系统。实验结果和系统应用效果表明,该系统能够显著提高政务服务的效率和用户的满意度。

6.2 未来研究方向

深度学习技术在政务问答系统中的应用

  • 探索更先进的深度学习模型和技术在政务问答系统中的应用。
  • 提高系统的语义理解能力和智能化水平。

多模态数据融合与跨语言问答系统

  • 研究多模态数据(如文本、图像、语音等)在政务问答系统中的融合方法。
  • 开发跨语言问答系统,满足不同语言用户的需求。

6.3 对政务服务的启示

提升政务服务智能化水平

  • 通过引入智能问答系统等技术手段,提升政务服务的智能化水平。
  • 为市民提供更加便捷、高效的服务体验。

加强政府与公众的互动与沟通

  • 利用智能问答系统加强与市民的互动和沟通。
  • 及时回应市民的关切和需求,提高政府的公信力和满意度。
相关推荐
小禾家的2 分钟前
.NET AI 开发人员库 --AI Dev Gallery简单示例--问答机器人
人工智能·c#·.net
生信碱移3 分钟前
万字长文:机器学习的数学基础(易读)
大数据·人工智能·深度学习·线性代数·算法·数学建模·数据分析
疯狂小料5 分钟前
Python3刷算法来呀,贪心系列题单
开发语言·python·算法
Cosmoshhhyyy6 分钟前
LeetCode:2274. 不含特殊楼层的最大连续楼层数(排序 Java)
java·算法·leetcode
KeyPan6 分钟前
【机器学习:四、多输入变量的回归问题】
人工智能·数码相机·算法·机器学习·计算机视觉·数据挖掘·回归
码力全開8 分钟前
C 语言奇幻之旅 - 第14篇:C 语言高级主题
服务器·c语言·开发语言·人工智能·算法
人工智能技术咨询.9 分钟前
人工智能未来会如何改变人们的生活?
人工智能·深度学习·计算机视觉·语言模型·aigc·生活
矮油0_o14 分钟前
30天开发操作系统 第 12 天 -- 定时器
c语言·汇编·算法·操作系统
Milk夜雨14 分钟前
C++ 数据结构与算法——寻找最大素数因子的整数
数据结构·c++·算法
MicrosoftReactor23 分钟前
技术速递|探索 Microsoft.Extensions.VectorData 与 Qdrant 和 Azure AI 搜索的结合使用
人工智能·microsoft·.net·azure