正则实体的应用实践
使用正则可以灵活、可靠地实现匹配到已知范围的多种说法,并实现关注字段的抽取。
场景1-抽取用户表述中的条件
用户故事
用户与一个图书管理机器人对话,希望查找符合要求的图书。
用户输入:“找一本关于xxx的书”。
期望机器人可以抽出中间的xxx条件,并作为搜索的关键词。
搭建步骤
- 新建一个正则实体“查询图书”,正则表达式:
找一本关于(\w+)的书
- 创建词槽“图书查询条件”,选择角色填槽,角色名:
1
,可填槽实体:查询图书 - 新建意图“查询图书”,添加一个相似问:
[找一本关于历史的书]{"entity":"查询图书"}
- 新建一个对话流程技能
- 触发意图选择“查询图书”
- 进入画布,开始单元后接询问填槽单元,选择待填词槽为“图书查询条件”
- 后接消息发送单元,回复内容为:
查找图书的条件:{slot=图书查询条件}
- 技能状态改为已生效,点击训练机器人
- 用测试机器人中测试对话效果,可以看到机器人抽取出了图书的条件,并将其填入“图书查询条件”词槽中。
正则式的常用规则
在搭建示例中,我们将正则实体的表达式配置为:找一本关于(\w+)的书
,其中:
\w
表示任意汉字、英文字母、数字+
表示重复至少1次(1-N)
因此:
\w+
表示长度至少为1的连续汉字、英文字母或数字
提炼和扩展一些正则式的常用规则:
\d*
表示连续0-N个数字?
表示重复0或者1次*
表示重复任意次(0-N)(ab)+
:表示至少重复1次ab,例如:ab,abab,ababab
正则实体的角色填槽
在搭建示例中,括号中的内容
(\w+)
会被单独作为实体抽出,并带有角色名。角色名按照括号从左到右的顺序默认为1、2、3…
角色名支持通过使用
(?P<name>xxxx)
的写法自定义,例如:找一本关于(?P<book>\w+)的书
。对应的,词槽中的角色名需要修改为book。
如果不希望机器人将某些括号中的内容抽出,需要把括号原内容
(xxx)
改写成(?:xxx)
,这样括号里面的内容,就不会被单独抽出实体以及角色。
尝试支持更多的说法
用户的表述不会只有
找一本关于xxx的书
这一种,用户还可能会说:- 我想找一本关于xxx的书
- 找关于xxx的书
- 搜xxx的书
- 找一本xxxx的书
用户可能不说“一本”或者“关于”,因此这两部分重复0或1次,同时无需被抽取出来。将正则表达式优化为:
找(?:一本)?(?:关于)?(?P<book>\w+)的书
。可以识别到的说法扩展为:- 找一本关于chatbot的书
- 找chatbot的书
- 找一本chatbot的书
- 找关于chatbot的书
用户对“查找”的表述有很多,如“搜索”、“找”等,因此可以用“|”将这些表述拼接起来,表达或关系。将正则表达式优化为:
(?:搜|查找|找)(?:一本)?(?:关于)?(?P<book>\w+))的书
。可以识别到的说法扩展为:- 搜一本关于chatbot的书
- 查找一本关于chatbot的书
- 找一本关于chatbot的书
- 搜一本chatbot的书
- 查找一本chatbot的书
- 搜chatbot的书
场景2-填入多个词槽
用户故事
某ASR项目中,用户说IP地址时,ASR结果样式为:10.12点2.245。
期望机器人可以将其转换成正确的书写格式10.12.2.245
搭建步骤
- 新建一个正则实体“IP地址”,正则表达式:
(\d+)\.(\d+)点(\d+)\.(\d+)
- 创建4个词槽“IP1”至“IP4”,将
角色名@填槽实体
一次配置为为1@IP地址
,2@IP地址
,3@IP地址
,4@IP地址
, - 新建对话流程技能
- 新建触发意图“抽取IP”,添加一个相似问:
[10.12点2.245]{"entity":"IP地址"}
- 新建对话流程技能,触发意图选择“抽取IP”
- 进入画布,开始单元后配置四个询问填槽单元,待填词槽依次为“IP1”至“IP4”
- 后接消息发送单元,回复内容为:
{slot=IP1}.{slot=IP2}.{slot=IP3}.{slot=IP4}
- 新建触发意图“抽取IP”,添加一个相似问:
- 技能状态改为已生效,点击训练机器人
- 用测试机器人中测试对话效果,可以看到机器人抽取出了IP地址,并将其转换为正确的格式打印出来。
更完善的正则表达式
正则匹配很容易出错,需要考虑各种可能的情况
以IP地址为例,考虑以下的bad cases:
- 1111.1.2.3
- 333.1.2.3
- 256.1.2.3
- 1.2.3.2555
- 1.2.3333.4
IP地址的数字范围,每一段为0-255之前,因此应该为1-3位数字,可以用{1,3}限制数字的范围:
(\d{1,3})\.(\d{1,3})点(\d{1,3})\.(\d{1,3})
每个字段范围是0-255,需要考虑数字的取值范围,例如当数字为3位时,最高位只能是1或者2
([012]?[0-9]{1,2})\.([012]?[0-9]{1,2})点([012]?[0-9]{1,2})\.([012]?[0-9]{1,2})