首先我们看一下完整的对话流程,如上图所述,共分为8个环节。
技能平台主要负责其中右边3、4、5、6 的4个环节,而其中如何做到有效的数据流转、低成本能力建设就是我们所需要解决的核心问题。当然,其中也面临着不少的挑战。
对话系统 (Dialog System) 是“让机器理解并处理人类对话的系统”,核心是模仿及抽象人与人之间沟通的方式,将对话抽象成具体的任务模块:TTS(倾听)、NLU(理解)、Policy(记忆、见人说人话)、Action(组织语言)。
为了保证对话系统主体链路的稳定性及灵活性,小布的整体思路是“轻中控,重模块化”。目前的算法工作主要围绕NLU、Policy两个模块展开,其中 Policy 目前主要以规则及产品策略为主,因此下面重点介绍语义理解部分的一些算法事件经验。
语义理解主要是将Query 映射到具体的动作空间,并且提取动作执行所能识别的标准值,具体算法建模为意图理解和槽位解析。
小布技能平台覆盖了分类、语义匹配、文本匹配等三类意图理解方式,以及若干槽位解析能力,下面将展开详解。
文本分类:通过文本分类的方式进行意图理解,能够在有限域内完成更精细化的意图理解。其准召的天花板较高,业内及小布技能平均准召在反复迭代优化后普遍能够做到90%以上。
意图理解的文本分类,其本质是一个N+1 分类的多分类任务。
N:指域内需要理解的用户意图,如音乐领域包含:点播歌手的歌曲、随机播放歌曲、查询信息、点播类型音乐等等。
1:是指的域外的other意图,所有非该领域意图的query 都需要分类模型能够拒绝,避免无论用户说什么问题都会一定分类到域内意图。
由于“other”意图近乎无穷,因此意图理解分类同时也是一个严重样本不均衡任务。
在意图分类任务中,尤其在泛娱乐等资源相关领域存在实体知识决定意图分类的例子,如:
同时为了保证嵌入特征及文本分类的效果,进一步降低模型训练成本。
围绕数据对抗做了一系列的特征及数据增强:
预训练模型蒸馏会很大程度上提升小模型的泛化能力。
但是在实际工作中发现,现有大规模预训练模型在实体相关性上存在偏差。尤其在泛娱乐相关领域对于资源实体无法很好的区分。
因此,现有做法是,通过大规模预训练语言模型进行离线数据挖掘及数据增强。通过数据蒸馏的方式引入大规模预训练语言模型的相关泛化能力。
分类的方式适用于语料充分、准召要求高的场景。但是分类算法需要掌握较多的算法及调优知识。
为了满足非算法人员无成本的研发语音相关技能,同时覆盖开发域、低数据量的部分意图理解场景,因此需要提供意图匹配相关算法能力。
业内语义匹配算法主要分为语义表征及交互匹配两种技术方案。
前者可以通过ANN等算法大量降低Query-Query 匹配的计算量及匹配次数,缺点是需要在query -> model -> embedding的过程中将不相似query 在embedding 层面进行区分,embedding learning 的难度较高。
后者则能同时捕捉交互信息,因此在准确性上会明显优于语义表征的方式,但是计算代价较高。因此往往配合方案为:语义表征(召回)+ 语义交互(精排)。
但是由于技能平台的特殊性:面向场景不定、领域数众多。无法针对每一个技能都单独训练一个交互匹配模型。因此技能平台在语义匹配方案主要以语义表征为主。
在语义表征领域,近年来以无监督预训练相关任务发展最为迅速。
在实际业务使用过程中,我们发现仅通过700w左右的数据预训练已经能达到80%左右的准召,也证实了无监督预训练任务的确能过为语义表征带来一定的收益。但是无监督预训练任务的天花板也较为明显。
上图分别列举了word2vec与PTM 两种方式的部分case 及优缺点。
为了进一步提升语义表征的效果,我们采用了metric learning 相关的做法对已有无监督模型进一步finetuning。两者叠加构建技能平台的语义表针算法能力。
常规语义匹配及分类虽然已经能够满足大部分应用场景,但是在新闻、客服等领域存在许多不含有上下文、或上下文与标准主体相差很大的匹配问题。因此,我们同样利用ES构建了基于文本主体的匹配算法。
对query 、template都分别进行分词、筛词、滤词。保留文本主体后在进行文本pattern层面的匹配。同语义表征匹配一同解决意图匹配的问题。
在槽位解析方面,技能平台共研发了标准时间解析、地点、人名等数十种通用槽位解析能力。
以及基于DAG+DP、AC双数组匹配等多种的词典匹配算法能力。
同时为了解决部分任意槽位的抽取,基于bilstm+CRF 构建了一整套模板数据生成、特征增强的算法解决方案。
通过上述解析器、模型、词典等槽位解析共同构建了整套算法槽位解析能力。同时为了针对多槽位、歧义槽位等问题,构建了槽位消解、槽位映射以及上图所示的语义槽功能。
技能平台通过抽象现有语义理解及槽位解析能力,提供了一整套的技能研发算法解决方案,使得非算法人员也能够通过有限的培训后,自主的完成技能的创建、迭代及上线。
以上就是技能平台在语义理解相关领域的算法简介。
整体采用分层架构设计,整体架构具有可伸缩性,支持通用化能力的任意组合满足多种业务需求。
并行流水线设计,支持业务水平扩展。充分利用底层组件,结合实际业务需求进行业务逻辑编排。每一条业务流水线代表一个业务单元。实现平台通用语义理解可配置化接入。新业务逻辑快速接入。
具体收益:代码复用率达到70%,新业务接入提效超过100%(原来需要二周左右开发,现在3-4天可以完成)。性能从平响20ms提升到不到10ms,整体性能提升100%。
业务单元模块化设计,将原子化组件能力加上业务逻辑组合为一个个业务单元,经过统一的编排层实现通用的dm能力。支持多重条件判断,支持多种格式的协议转换。用户可以配置化实现多种回复类型,可以通过简单的配置实现多轮对话流。
具体收益:多种dm通用能力沉淀为组件,代码服用率提高40%,实现dm能力可配置化实现。简化协议解析流程,通过简单的公式配置就可以实现协议转化,节约90%的协议转化逻辑。整体稳定性提升,半年内故障数为0。
算法模型作为语义理解核心组成部分,其生命周期的管理在技能平台完成自动化流转。模型的生命周期分为几个部分 数据准备——模型训练——模型测试——模型上线——模型下线。
在技能平台完成数据准备,触发机器学习平台部署的训练脚本完成模型训练,生成算法模型。通过发布系统将模型推送到在线模型serving服务,加载最新模型,对外提供分类服务。
技能平台将小布助手的全部基础数据进行统一管理,隔离数据源操作,保证数据的安全性。隔离离线数据和在线数据,用户在平台管理端产生离线数据,通过发布流程将数据发布到在线环境,影响在线服务。数据隔离保证在线数据的稳定性,所有在线服务加载的基础数据都是经过验证的快照数据。同时发布系统通过文件发布打通了线上线下各个环境,保证数据上线过程经过各个环境进行了严格的验证。
数据在技能平台具有一个完整的生命周期,每一个阶段都分别对应一个环境。
技能平台为技能上线提供了一套标准流程,完整流程中的各个节点都可以根据实现需要进行一定的调整。
技能上线主要分为三个步骤:
召回方案分类两类:
文本分类:需要训练算法模型,适合语料较多,高精准召回场景
文本匹配:采用通用语言模型进行句向量转换,利用检索方案进行召回。适合少语料,召回要求不高的场景
默认的other意图做拒绝使用,其他意图可以手动任意添加,每一个意图即表示一个召回节点。
槽位提取主要支持两种方式
自建词典:用户可以在词典管理界面新增和上传自建词典
通用提槽:平台提供通用的槽位提取能力
设置为纯实体的槽位,具有纯实体召回能力
平台支持三种召回语料
规则:用户可以输入正则表达式,平台的规则引擎将会加载这些规则语料实现召回。规则适用于确定场景的召回,编写正则表达式的时候需要注意对范围的限制防止对其他意图的误召回。
训练语料:用户可以新增或者导入需要召回的语料。如果训练方案选择的是文本分类,这里的语料将会用于模型训练,适用语料较多的场景。如果训练方案选择的是文本匹配,这里的语料将会用于建立向量空间,后续召回通过检索的方式实现,该方式适用于语料较少的场景。用户可以根据实际情况按需选择。
关键词增强:增加召回能力,通过关键词的添加可以增加召回的准确度
在完成召回语料的创建后,用户可以上传测试语料,用于对语义部分的测试使用。
在完成各种语料的创建之后,就可以进入到模型训练阶段。
这一阶段根据训练方案的不同将会产生不同的行为:
文本分类:触发部署在机器学习平台的训练脚本进行模型训练,训练完成后上传模型文件到指定目录,推送数据到对话测试环境,通知对话测试环境的在线模型服务更新模型。
文本匹配:推送数据到对话测试环境,通知该环境的检索服务进行向量空间的构建。
模型训练完成后,用户就可以通过批量测试验证语义理解部分,测试完成后将会生成测试报告用户下载报告进行查看。根据测试报告可以持续对语义部分进行调校。
在完成语义部分后就可以进入对话部分,首先创建新的技能。然后进入技能选择该技能需要订阅的意图。
这一步用户可以根据自己的实际需求进行回复配置,每一条回复都可以增加各类限制条件,只有当全部限制条件都满足的情况下才会出对应的回复。目前平台主要之处文字卡片和payload两种回复形式,后续平台还会支持更多的回复形式,敬请期待。
在完成了语义和对话数据的创建和测试后,就可以进入到发布阶段。首先进行发布单的创建,当前发布可以通过三种维度进行。
打包发布:以技能为主,将关联的领域数据进行打包发布
领域发布:只发布领域相关数据,包括领域,意图,槽位,词典等。
对话发布:只发布技能相关数据,包括技能,回复,映射关系等。
发布流程需要按照标准流程在每一个环境进行验证工作,只有验证通过后才能进入到下一个阶段。
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby
在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has
我的主要目标是能够完全理解我正在使用的库/gem。我尝试在Github上从头到尾阅读源代码,但这真的很难。我认为更有趣、更温和的踏脚石就是在使用时阅读每个库/gem方法的源代码。例如,我想知道RubyonRails中的redirect_to方法是如何工作的:如何查找redirect_to方法的源代码?我知道在pry中我可以执行类似show-methodmethod的操作,但我如何才能对Rails框架中的方法执行此操作?您对我如何更好地理解Gem及其API有什么建议吗?仅仅阅读源代码似乎真的很难,尤其是对于框架。谢谢! 最佳答案 Ru
我的假设是moduleAmoduleBendend和moduleA::Bend是一样的。我能够从thisblog找到解决方案,thisSOthread和andthisSOthread.为什么以及什么时候应该更喜欢紧凑语法A::B而不是另一个,因为它显然有一个缺点?我有一种直觉,它可能与性能有关,因为在更多命名空间中查找常量需要更多计算。但是我无法通过对普通类进行基准测试来验证这一点。 最佳答案 这两种写作方法经常被混淆。首先要说的是,据我所知,没有可衡量的性能差异。(在下面的书面示例中不断查找)最明显的区别,可能也是最著名的,是你的
几个月前,我读了一篇关于rubygem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:
我目前正在使用以下方法获取页面的源代码:Net::HTTP.get(URI.parse(page.url))我还想获取HTTP状态,而无需发出第二个请求。有没有办法用另一种方法做到这一点?我一直在查看文档,但似乎找不到我要找的东西。 最佳答案 在我看来,除非您需要一些真正的低级访问或控制,否则最好使用Ruby的内置Open::URI模块:require'open-uri'io=open('http://www.example.org/')#=>#body=io.read[0,50]#=>"["200","OK"]io.base_ur
前言作为一名程序员,自己的本质工作就是做程序开发,那么程序开发的时候最直接的体现就是代码,检验一个程序员技术水平的一个核心环节就是开发时候的代码能力。众所周知,程序开发的水平提升是一个循序渐进的过程,每一位程序员都是从“菜鸟”变成“大神”的,所以程序员在程序开发过程中的代码能力也是根据平时开发中的业务实践来积累和提升的。提高代码能力核心要素程序员要想提高自身代码能力,尤其是新晋程序员的代码能力有很大的提升空间的时候,需要针对性的去提高自己的代码能力。提高代码能力其实有几个比较关键的点,只要把握住这些方面,就能很好的、快速的提高自己的一部分代码能力。1、多去阅读开源项目,如有机会可以亲自参与开源
导读:随着叮咚买菜业务的发展,不同的业务场景对数据分析提出了不同的需求,他们希望引入一款实时OLAP数据库,构建一个灵活的多维实时查询和分析的平台,统一数据的接入和查询方案,解决各业务线对数据高效实时查询和精细化运营的需求。经过调研选型,最终引入ApacheDoris作为最终的OLAP分析引擎,Doris作为核心的OLAP引擎支持复杂地分析操作、提供多维的数据视图,在叮咚买菜数十个业务场景中广泛应用。作者|叮咚买菜资深数据工程师韩青叮咚买菜创立于2017年5月,是一家专注美好食物的创业公司。叮咚买菜专注吃的事业,为满足更多人“想吃什么”而努力,通过美好食材的供应、美好滋味的开发以及美食品牌的孵
嗨~大家好,这里是可莉!今天给大家带来的是7个C语言的经典基础代码~那一起往下看下去把【程序一】打印100到200之间的素数#includeintmain(){ inti; for(i=100;i 【程序二】输出乘法口诀表#includeintmain(){inti;for(i=1;i 【程序三】判断1000年---2000年之间的闰年#includeintmain(){intyear;for(year=1000;year 【程序四】给定两个整形变量的值,将两个值的内容进行交换。这里提供两种方法来进行交换,第一种为创建临时变量来进行交换,第二种是不创建临时变量而直接进行交换。1.创建临时变量来