ThinkSSL🔒 一键申购 5分钟快速签发 30天无理由退款 购买更放心 广告
# 智能应答 - [什么是上下文处理?](#_1) - [上下文工作方式](#_2) - [示例展示](#_3) - [上下文实现原理](#_4) #### 什么是上下文处理? 首先您先查看并了解了微擎的[消息响应流程](http://www.kancloud.cn/donknap/we7/134650),明白消息的响应是通过“关键字”进行响应的。 比如,管理员设定好一系列的回复规则,当用户输入:“今天天气是什么”,系统回复:“今天是晴天”。 此处的“今天天气是什么”就是一个关键字,并且这个关键字是有意义的,管理员完全可以揣测出来用户在输入这句话期望得到的结果是“今天是晴天”。 所以管理员可以通过设置关键字回复来达到人机交互。 但是好些时候用户输入的关键字是需要通过上下文的理解来确定用户的意图。 比如,用微信打印照片,用户先输入:“打印照片”,系统回复:“请发送一张照片”,用户发送一张照片,系统回复:“照片正在打印”。 如果没有这样的交互,用户直接发送一张照片过来,系统无法得知用户是要打印照片,还是要使用其它什么模块功能。 所以微擎提供了上下文锁定来处理此类需求 #### 上下文工作方式 - 上下文回复仅可以在 WeModuleProcessor 的继承类中使用。 - 当管理设置一条规则触发到该模块的Processor中,可以过通$this->beginContext();来锁定上下文会话。 - 锁定会话后,后面无论用户输入什么内容,均会被直接触发到该模块的Processor中。 - 模块进行一系列的交互与处理后,可以通过 this->endContext(); 来解锁上下文会话。 - 用户输入的关键字继续正常的被其它模块接收。 #### 示例展示 下面的示例将演示根据血型查性格的简单例子: ``` class BloodTestModuleProcessor extends WeModuleProcessor { //void: 所有处理程序必须实现虚函数 respond. 用以响应消息 public function respond() { if(!$this->inContext) { $reply = '请输入你的血型(A, B, O, AB), 来分析你今年的运程. '; $this->beginContext(); // 如果是按照规则触发到本模块, 那么先输出提示问题语句, 并启动上下文来锁定会话, 以保证下次回复依然执行到本模块 } else { $btypes = array('a', 'b', 'o', 'ab'); $b = strtolower($this->message['content']); // 如果当前会话在上下文中, 那么表示当前回复是用户回答提示问题的答案. if(in_array($b, $btypes)) { switch($b) { case 'a': $reply = 'A型血今年.....'; break; case 'b': $reply = 'B型血今年.....'; break; case 'o': $reply = 'O型血今年.....'; break; case 'ab': $reply = 'AB型血今年.....'; break; } $this->endContext(); // 如果当前回答符合答案格式, 那么进行保存并进行下一个问题. (可以保存至 SESSION 中) // 直到最后一个问题回答完成, 输出测试结果给用户, 并结束对话锁定. 以保证用户其他对话能正常路由. // 本示例只有一个问题, 因此不保存答案, 直接输出测试结果. // 如果对话默认的超时不够, 那么可以在每次提出下一个问题的时候重新调用 beginContext 来顺延超时. } else { $reply = '请输入正确的血型(A, B, O, AB). '; // 回答不符合答案格式, 那么重新显示当前问题. } } return $this->respText($reply); } } ``` #### 上下文实现原理 微擎的上下文操作使用 **$\_SESSION + DB** 来实现. 上下文数据保存在 **$\_SESSION\['context'\]** 变量中,并与 **sessions** 表中数据做一对一的映射,用户可通过操作 sessions 表中的数据进行上下文会话的基本管理. 要实现上下文操作主要使用 **Processor** 里的内定方法: - **public $inContext;** 本次对话是否为上下文响应对话, 如果当前对话是由上下文锁定而路由到的. 此值为 **true**, 否则为 **false** - **protected function beginContext($expire = 3600);** 请在模块处理程序中调用此函数已开始一个新的上下文对话. 附加的参数 $expire 说明本次会话的失效时间. 例如 $this->beginContext(1800) 就说明启动一次上下文会话锁定, 并且本次会话将会于30分钟后释放, 如果不固定超时的话, 请在每次请求时调用 beginContext - **protected function endContext();** 在模块处理程序中调用 **endContext** 来**结束**一次会话, 并 **销毁**会话中保存的所有数据(当前为 $\_SESSION) - **protected function refreshContext($expire = 0);** **在模块处理程序中调用** refreshContext\*\* 来刷新用户处于上下文的时限. 超过时限用户将会自动退出上文环境.