如何最大化利用UNIT的特性进行开发 Impulse干货系列:3. C#接入UNIT&使用词槽作为参数来执行函数
goJhou 发布于2017-08 浏览:4317 回复:14
6
收藏

那欢迎各位看我的贴子,我是Impulse. 大家好

本干货系列教程,所有最终的目的是与C#进行交互,而不是单纯使用UNIT,所以在以后的帖子中,可能会涉及到除UNIT以外的服务。

我在UNIT的摸索学习中,有一些小经验可以分享给大家

之后可能会时不时写干货给大家,如果能帮助到大家开发了,我也会感到很愉快

话不多说,我们开始吧


在这一篇,我会给各位看到我自己写的一部分封装代码,旨在传递一种思维,希望能和大家共勉(程序小白,大牛勿喷)




首先是发送给UNIT

  如何发送在官方文档中都有写到,我就不再多述,直接上核心方法封装代码

  以下为发送给UNIT并获取返回JSON对象的命令

  大致分为3个方向,意图成功完成,将返回完整的json对象。意图未完成会将澄清话语进行打印。未知意图将走第3条路(可能是因为少配了对话集,做这条路为了方便完善意图)

  这里使用到了以下几个第三方类库 可以在NuGet中下载到

  Newtonsoft.Json;

  Newtonsoft.Json.Linq;


这里提供意图完成与意图未完成的两种结果json对象样本,供大家代入代码进行学习

部分有备注


意图完成:

{

    "log_id": 150237316846815,

    "result": {

        "action_list": [

            {

                "action_id": "open_satisfy",

                "action_type": {

                    "act_target": "",

                    "act_target_detail": "",

                    "act_type": "satisfy",     satisfy表示意图完成

                    "act_type_detail": ""

                },

                "arg_list": [],

                "code_actions": {},

                "confidence": 1,

                "exe_status": [],

                "hint_list": [],

                "main_exe": "open",     该执行函数的名字

                "say": ""

            },

            {

                "action_id": "open_guide",

                "action_type": {

                    "act_target": "",

                    "act_target_detail": "",

                    "act_type": "guide",

                    "act_type_detail": ""

                },

                "arg_list": [],

                "code_actions": {},

                "confidence": 1,

                "exe_status": [],

                "hint_list": [               这里是引导的内容

                    {

                        "hint_query": "关闭"

                    },

                    {

                        "hint_query": "调整"

                    }

                ],

                "main_exe": "",

                "say": "好的"            这里是UNIT bot说的话

            }

        ],

        "qu_res": {

            "intent_candidates": [

                {

                    "extra_info": null,

                    "from_who": "ml_qu",

                    "func_slot": "",

                    "intent": "OPEN",

                    "intent_confidence": 99.60952758789062,

                    "intent_need_clarify": false,

                    "match_info": "",

                    "slots": [

                        {

                            "confidence": 99.77851104736328,

                            "length": 4,

                            "need_clarify": false,

                            "normalized_word": "灯光",           

                            "offset": 6,

                            "original_word": "灯光",        

                            "type": "user_target",      

                            "word_type": ""

                        }

                    ]

                }

            ],

            "log_id": "openapi_150237316846815_9161",

            "raw_query": ",打开灯光,",             用户进入时的完整句子,因为我接入了百度的语音识别,所以会有两个逗号

            "status": 0,

            "timestamp": 1

        },

        "schema": {

            "bot_merged_slots": [

                {

                    "begin": 0,

                    "confidence": 0,

                    "length": 0,

                    "merge_method": "update",

                    "normalized_word": "灯光",         这里是归一后的词

                    "original_word": "灯光",               这里是用户进入的词

                    "session_offset": 0,

                    "type": "user_target",              词槽名称

                    "word_type": ""

                }

            ],

            "current_qu_intent": "OPEN",

            "intent_confidence": 99.60952758789062

        },

        "session_id": "a47fba40a0cf4dfb900466d4e91d84551"     多轮会话需要把这个暂时写入static变量,以方便下次调用

    }

}


意图未完成:

{

    "log_id": 150237384639821,

    "result": {

        "action_list": [

            {

                "action_id": "open_user_target_clarify",

                "action_type": {

                    "act_target": "slot",

                    "act_target_detail": "user_target",

                    "act_type": "clarify",           clarify表示意图未完成

                    "act_type_detail": ""

                },

                "arg_list": [],

                "code_actions": {},

                "confidence": 1,

                "exe_status": [],

                "hint_list": [],

                "main_exe": "",

                "say": "打开什么?"             缺词槽会返回澄清话语

            }

        ],

        "qu_res": {

            "intent_candidates": [

                {

                    "extra_info": null,

                    "from_who": "ml_qu",

                    "func_slot": "",

                    "intent": "OPEN",

                    "intent_confidence": 99.08135223388672,

                    "intent_need_clarify": false,

                    "match_info": "",

                    "slots": []

                }

            ],

            "log_id": "openapi_150237384639821_9161",

            "raw_query": ",打开,",          用户说的话

            "status": 0,

            "timestamp": 1

        },

        "schema": {

            "bot_merged_slots": [],

            "current_qu_intent": "OPEN",

            "intent_confidence": 99.08135223388672

        },

        "session_id": "4215dc84ec1240b0a4fd7773b012daaf1"       补充词槽需要重复调用这个sessionID

    }

}



那到上一步我们只是完成了意图分析,有后续的补充词槽和意图错误的可能。请各位根据自己的环境去定义之后的路该怎么走


  在获取到了完整的json对象后,我将它的返回值抛给了DoSth函数进行所谓的   

    意图执行

使用json对象可以很方便的去foreach,然后匹配它们的词槽,填入我相应的变量中。 这里我就是以归一化设计去写的

各位请先判断一下这个normalized_word是否为空,我这里忘写了


最后是获取对象,我在c#中暂时使用了枚举,如果归一做的好的话,完全不需要枚举,可以将设备类型定义在设备的实体类中使用linq抓取。

 这里代码有用到Linq知识,不过多作讲解,如果有需要可自行百度了解



这里是意图执行的核心代码。包含了如何查找对象,如何查找函数,及执行函数

由于函数签名千变万化,我觉得各位可能有更好的办法解决这种问题。这里我使用了泛型和根据函数签名走不同指向的方式来解决。

MethodInfo为Reflection下的类型。请引入System.Reflection

反射可通过函数名定位函数,并传参执行

如果使用得当,MethodInfo将获取到确切的函数对象

那针对这一块根据函数名找函数执行,我觉得各门语言大同小异,理解一下思路总是好的。

那上头的代码是我根据我自己的系统进行定制化开发的。


关于C#中如何根据函数名执行函数,详情请参考:http://blog.csdn.net/u011045710/article/details/9102775


那通过我三个章节的介绍,相信你对UNIT的用途、开发过程、接入过程有了一个进阶的了解。

我也非常感谢各位可以坚持看完我所有的UNIT干货系列


希望对各位有所帮助和启发。如果有更好的建议,随时欢迎跟贴喔!!!

收藏
点赞
6
个赞
共14条回复 最后由卡农LLLL回复于2017-11
#15卡农LLLL回复于2017-11

你们又开始刷屏了的感觉.

0
#14goJhou回复于2017-11
#13 笔墨哥回复
授人以鱼不如授人以渔~哈哈~

嗯嗯,就这道理

0
#13笔墨哥回复于2017-11
#12 goJhou回复
其实我是想教思想的。代码直接给你们,可能会因为环境的问题跑不起来的

授人以鱼不如授人以渔~哈哈~

0
#12goJhou回复于2017-11
#11 卡农LLLL回复
论坛支持代码块就好了...现在能把代码放git上面大家好伸手吗...大神.
展开

其实我是想教思想的。代码直接给你们,可能会因为环境的问题跑不起来的

0
#11卡农LLLL回复于2017-11

论坛支持代码块就好了...现在能把代码放git上面大家好伸手吗...大神.

0
#10笔墨哥回复于2017-11
#9 卡农LLLL回复
干货越来越多...好神奇

嗯,关注楼主,有好多不错的分享~

0
#9卡农LLLL回复于2017-11

干货越来越多...好神奇

0
#8笔墨哥回复于2017-11
#7 ZYuXinz回复
大神,帮帮我!

没有说问题,goJhou也不好帮呀~

0
#7ZYuXinz回复于2017-11

大神,帮帮我!

0
#6goJhou回复于2017-11
#5 一个秂的黑聿白回复
谢谢分享,大佬

不客气

0
#5一个秂的黑聿白回复于2017-11

谢谢分享,大佬

0
#4笔墨哥回复于2017-10

慢慢的都是干货呀,进来学习啦~

0
#3月光下的眼泪4回复于2017-10

谢谢分享

0
#2月光下的眼泪4回复于2017-10

好人

0
TOP
切换版块