全文共2951字,预计学习时长6分钟
你有没有在大冬天里的深夜里,为了关灯睡觉而不得不离开温暖被窝的经历?
本文将介绍如何为普通家庭照明开关构建自然语言接口,以便用户可以使用如“请打开所有灯”或者“打开孩子房间里的灯”等简单命令来控制灯光。
本文主要介绍自然语言接口(NLI)部分,不涵盖语音识别与实际灯光操作部分。你可以使用WebSpeech轻易实现语音转换,如有所需,也可使用Arduino/Homekit提供的简化API(应用程序编程接口)控制家中灯光。
我们所使用的工具是NLPCraft和Scala语言(NLPCraft也适用于Java、Groovy和Kotlin等基于JVM的语言)。NLPCraft是一个免费开源项目,它可以帮助你为任何设备或软件快速构建领域特定自然语言接口。
NLPCraft使用现代语义建模和基于确定性意图的用户输入匹配,而非传统的计算语言学(即神经网络),因此,它不需要任何已有的域语料库,也不需要冗长的模型训练与开发。
使用NLPCraft时,大多数工作都围绕着为特定领域构建语义模型展开。一种模型定义一组应当在用户中检测到的命名实体(由用户定义或源于spaCy, OpenNLP, Stanford CoreNLP或者 Google Natural Language等第三方)。NLPCraft还包含一种高级意图匹配工具,稍后会在示例中用到。
目前的任务是为一个普通灯光开关设计一个自由格式的自然语言接口。以下是设计指令示例:
- 关闭屋子里所有灯
- 打开主卧室壁橱的照明灯
- 打开灯
- 请将楼上的灯光关掉
- 打开屋子里所有灯
- 关闭客卧的灯
- 你能把所有的灯都关掉吗?
- 关掉二楼的照明灯
- 请熄灯!
- 立刻关掉所有灯光!
- 请关掉卧室灯
图片来源:unsplash.com/@thevisualiza
在这些示例中,很快发现以下三个在用户输入中必须被检测到的不同实体(在稍后的意图中将会用到用户输入):
- 打开灯的操作
- 关闭灯的操作
- 灯的位置
以下是定义这三个实体的YAML中NLPCraft语义模型的声明性编程部分:
id: "nlpcraft.lightswitch.ex" name: "Light Switch Example Model" version: "1.0" description: "NLI-powered light switch example model."macros:- name: "" macro: "{turn|switch|dial|control|let|set|get|put}" - name: " " macro: "{entire|full|whole|total|*}" - name: " " macro: "{all|*} {it|them|light|illumination|lamp|lamplight}"enabledTokens: [] # Don't use any built-in tokens.elements: - id: "ls:loc" description: "Location of lights." synonyms: - " {upstairs|downstairs|*} {kitchen|library|closet|garage|office|playroom|{dinning|laundry|play} room}" - " {upstairs|downstairs|*} {master|kid|children|child|guest|*} {bedroom|bathroom|washroom|storage} {closet|*}" - " {house|home|building|{1st|first} floor|{2nd|second} floor}" - id: "ls:on" groups: - "act" description: "Light switch ON action." synonyms: - " on" - " on " - id: "ls:off" groups: - "act" description: "Light switch OFF action." synonyms: - " {off|out}" - "{ |shut|kill|stop|eliminate} {off|out} " - "no "
除了句法上存在一些特殊性,这个模型的定义非常清晰易懂:
· 第14行,第21行和第29行定义了三个元素(即命名实体):ls:loc, ls:on, 和ls:off。每个实体都是通过一组宏扩展的同义词集定义的。
· 第5行列出了稍后会在实体定义中使用到的宏。
这个模型的出色之处在于,仅仅几十行YAML代码就可产生很高的生产效率和经济效益:
当通过NLPCraft加载时,这个模型将每个实体转换为十万多个不同的同义词———在传统方法中,这必须通过手动创建才能实现。
NLPCraft擅长同义词处理:除了基本的规范化、标记化、词干化、停用词去除等,还可执行高级洗牌程序和加权选择算法。你也可以使用PoS标记、正则表达式或用户自定义谓词,为更高级的检测用例定义语义元素。
现在有了模型配置的声明性编程部分,接下来就可以通过提供意图匹配逻辑来完成模型定义的剩余部分。从技术层面上说,NLPCraft模型只是NCMODEL Java接口的一种实现形式。使用便捷的NCModelFileAdapter适配器,以利用上述基于YAML的配置来建构模型:
class LightSwitchModel extends NCModelFileAdapter ("org/nlpcraft/examples/lightswitch/lightswitch_model.yaml") { @NCIntent("id=act conv=false term(act)={groups @@ 'act'} term(loc)={id == 'ls:loc'}*") def onMatch( @NCIntentTerm("act") actTok: NCToken, @NCIntentTerm("loc") locToks: List[NCToken] ): NCQueryResult = { val status = if (actTok.getId == "ls:on") "on" else "off" val locations = if (locToks.isEmpty) "entire house" else locToks.map(getOriginalText).mkString(", ") // Add HomeKit, Arduino or other integration here.// By default - just return a descriptive action string. NCQueryResult.text(s"Lights '$status' in '${locations.toLowerCase}'.") }}
注释:
· 第1行中,从外部基于YAML的配置(上文已讨论过)将模型初始化。
· 第2行中,将意图附加到onMatch(…)回调中。请注意,使用的是Nlpcraft支持的NCIntent Java注解和基于文本的意图领域专用语言(DSL)。此意图将匹配具有以下实体的任何用户输入:-恰好只有一个操作(即属于组"act"的任何实体)和-零个或多个灯的位置。
· 当意图匹配成功并且调用回调时,检测到的实体将通过NCIntentTerm注解映射到回调方法参数中。
· 回调只是返回灯的状态(见第13行)。此时可以添加Arduino、HomeKit等集成。
现在,大功告成
图片来源:unsplash.com/@rohanmakhecha
将模型编译并部署到data probe中,启动REST服务器,然后就可以让模型接受REST调用并开始使用自然语言控制灯光了。
虽然可以使用任何REST工具将输入发送到模型中,但我们将用到的是内置的JUnit5兼容测试框架,这可以实现更多的自动化操作。
使用此代码创建LightSwitchTest.java文件并运行:
package org.nlpcraft.examples.lightswitch;import org.junit.jupiter.api.*;import org.nlpcraft.common. *;import org.nlpcraft.model.test.*;import java.io. *;import static org.junit.jupiter.api.Assertions. *;class LightSwitchTest { private NCTestClient cli; @BeforeEach void setUp() throws NCException, IOException { cli = new NCTestClientBuilder().newBuilder().build(); cli.open("nlpcraft.lightswitch.ex"); } @AfterEach void tearDown() throws NCException, IOException { cli.close(); } @Test void test() throws NCException, IOException { assertTrue(cli.ask("Turn the lights off in the entire house.").isOk()); assertTrue(cli.ask("Switch on the illumination in the master bedroom closet.").isOk()); assertTrue(cli.ask("Get the lights on.").isOk()); assertTrue(cli.ask("Please, put the light out in the upstairs bedroom.").isOk()); assertTrue(cli.ask("Set the lights on in the entire house.").isOk()); assertTrue(cli.ask("Turn the lights off in the guest bedroom.").isOk()); assertTrue(cli.ask("Could you please switch off all the lights?").isOk()); assertTrue(cli.ask("Dial off illumination on the 2nd floor.").isOk()); assertTrue(cli.ask("Please, no lights!").isOk()); assertTrue(cli.ask("Kill off all the lights now!").isOk()); assertTrue(cli.ask("No lights in the bedroom, please.").isOk()); }}
请注意,在测试中使用了最初想要支持的原始语句。查看测试输出并验证所有工作是否按预期进行。
有了自动化测试,就可以在不破坏进程内容的前提下,快速地使用模型、进行更改或迭代修改。
继续拓展这一模式:可以添加Arduino集成或者将模型ls:loc 实体应用到家庭配置中;也可以添加一些流行语,或者用一些独特的方式来控制灯光。
· NLPCraft可在GitHub上获得:https://github.com/vic64/nlpcraft?source=post_page---------------------------
· Apache 2.0 许可(https://www.apache.org/licenses/LICENSE-2.0?source=post_page---------------------------),通用条款(https://commonsclause.com/?source=post_page---------------------------)。
· 在https://nlpcraft.org/download.html下载NLPCraft。
· 有关此示例的更多说明:https://nlpcraft.org/setting-up.html?source=post_page---------------------------
· 进入Github查看此示例及其他示例:https://github.com/vic64/nlpcraft/tree/master/src/main/scala/org/nlpcraft/examples/lightswitch?source=post_page---------------------------
留言 点赞 关注
我们一起分享AI学习与发展的干货
欢迎关注全平台AI垂类自媒体 “读芯术”
(添加小编微信:dxsxbb,加入读者圈,一起讨论最新鲜的人工智能科技哦~)