rasa2.0学习笔记

2.0横空出世,之前写的项目需要升级,趁此机会边用边整理下rasa一些技术细节,自己看的,不要纠结格式。(内容可能包含原1.x部分)

(1)story和rule

新加了一个rule,与story区别:

rule用于单轮对话的固定规则,core部分训练会校验是否只有一个user_uttered

rule是固定规则(整合了原来的trigger intent),如果需要根据前文灵活设置对话线,还是要用story

 

(2)State

代表tracker的状态,键值对表示,由tracker转换而来,key和value如下,rulepolicy和memorypolicy时(self.lookup)作为获取cation的key(后者将key压缩并base64转码,前者原值存储)

# State is a dictionary with keys (USER, PREVIOUS_ACTION, SLOTS, ACTIVE_LOOP)
# representing the origin of a SubState;
# the values are SubStates, that contain the information needed for featurization
SubState = Dict[Text, Union[Text, Tuple[Union[float, Text]]]]
State = Dict[Text, SubState]


state = {
            rasa.shared.core.constants.USER: self._get_user_sub_state(tracker),
            rasa.shared.core.constants.SLOTS: self._get_slots_sub_state(tracker),
            rasa.shared.core.constants.PREVIOUS_ACTION: self._get_prev_action_sub_state(
                tracker
            ),
            rasa.shared.core.constants.ACTIVE_LOOP: self._get_active_loop_sub_state(
                tracker
            ),
        }

样例
<class 'dict'>: {'prev_action': {'action_name': 'form_search_person_by_car_no'}, 'active_loop': {'name': 'form_search_person_by_car_no'}, 'user': {'intent': 'stop'}}

(3)trackers_as_states和trackers_as_actions的获取

tracker->states->取每个ActionExecuted(因为预测的就是action)的前max_history个states->sliced_states->需要的话通过hash去重->sliced_states添加到trackers_as_states、当前event.action添加到trackers_as_actions

trackers_as_states :List[List[State]]

trackers_as_actions : List[List[Text]]

(4)form rejected

源码逻辑:form启动之后(2.0表示为activate_loop),追问过程中用户没有提供任何有用的slot,则进入一轮rejected,由其他policy预测下一步动作。如果在故事或rules中又显式启动当前form,在执行form动作之后update ActionExecuted event时会重置form的validate状态为true、rejected状态为false。(继续当前form)

(5)关于story和rules中的active_loop:xxxx

从1.x开始这里就不是很明白,最近重新研究下,可能不一定准确,仅供参考

- action: form_xxx             # 启动form
- active_loop: form_xxx        # 在故事或rules中增加ActiveLoop event,表示启动
- active_loop: null            # 在故事或rules中增加ActiveLoop event,表示停止
- action: action_submit        # form获取信息后,完成后续动作

官网解释是说训练过程中不会调用action server,所以action返回的event需要手动填写到story或rules中。

实测:

a 训练时如果故事如上例,form中间没有其他流程时(仅有form自身的追问过程,且happy path),后面两个active_loop写与不写,对话时流程都会走到最后的submit。因为memony和rule policy在训练时生成的trackers_as_states不会有{'active_loop':xxxx}状态(form从开始到结束没有被中断,在生成states时是一步完成),对话的tracker同样不会产生这一状态,故可匹配。

b 当训练过程中form中间包含unhappy path时,如

- action: form_xxx             # 启动form     
- active_loop: form_xxx        # step1
- intent: stop                 # unhappy path
- action: utter_stop           # 
- action: form_xxx             # 重新回到form
- active_loop: form_xxx        # step2
- active_loop: null            # step3
- action: action_submit        # form获取信息后,完成后续动作

若step1注调,则无法匹配后面的unhappy path,因为实际对话tracker此时会产生含有{'active_loop':xxxx}的状态(因为form没有连续一次性完成),与训练的states无法匹配。

step2和3注调任何一个均会产生故事冲突,无法通过验证(此处逻辑尚未明确确定,初步结果是rule预测的action为listen而story预测结果为action_submit)

总之:设置slot和启动/停止form两种event会形成对应states,在写故事和rule时,需要在对应action后面添加到step中

(6)rule中的lookup

和memony policy中的lookup类似,lookup['rule']是rule训练数据中的step逻辑

而lookup['rules_for_loop_unhappy_path']则是处理loop过程中的unhappy path的情况,有do_not_validate_loop和do_not_predict_loop_action两个类型,分别在特定状态下跳过validate和predict当前loop环节(因为loop过程中需要处理story中的其他action和intent,不需要遵从当前form的loop)。

注意,loop在activate状态下,如果没有rejected,下一轮对话rule policy会优先预测当前form的action。

(7)loop中的unhappy_lookup

rule policy训练部分一段代码

        for states, actions in zip(trackers_as_states, trackers_as_actions):
            action = actions[0]
            active_loop = get_active_loop_name(states[-1])
            # even if there are two identical feature keys
            # their loop will be the same
            if not active_loop:
                continue

            states = self._states_for_unhappy_loop_predictions(states)
            feature_key = self._create_feature_key(states)
            if not feature_key:
                continue

            # Since rule snippets and stories inside the loop contain
            # only unhappy paths, notify the loop that
            # it was predicted after an answer to a different question and
            # therefore it should not validate user input
            if (
                # loop is predicted after action_listen in unhappy path,
                # therefore no validation is needed
                is_prev_action_listen_in_state(states[-1])
                and action == active_loop
            ):
                lookup[feature_key] = DO_NOT_VALIDATE_LOOP
            elif (
                # some action other than active_loop is predicted in unhappy path,
                # therefore active_loop shouldn't be predicted by the rule
                not is_prev_action_listen_in_state(states[-1])
                and action != active_loop
            ):
                lookup[feature_key] = DO_NOT_PREDICT_LOOP_ACTION

unhappy代表循环中间有其他步骤,当循环已经是启动状态,从其他步骤回到form不用重新validate(最后一个状态前面动作是listen,说明form是被打断过的,最近这次用户输入也是对其他问题的回答,比如是否继续,用户说是,因此不用验证);最后一个状态前面动作不是listen,且预测动作不是当前循环,说明是当前路径的连续其他动作,不预测当前loop,注意,reject只是从当前form跳过一次,上面是policy层面不再进入当前form 

(8)form中间追问是否影响memory policy

当form过程没有触发reject exception时(正常追问过程或重写form的validate方法),整个从form启动到结束的过程在memory策略的predict_action_probabilities(featurizer.prediction_states)中被忽略,也就是都归为正常追问(happy path)合并为一步。注意,实际tracker中依然记录的全部的每个交互步骤。

如果form被rejected或检测到接下来执行的并不是当前form(例如rule中增加的chichat/退出部分),则会被判定为unhappy路径,因此此前步骤不会忽略(featurizer.prediction_states),从而影响memory相关策略判定。

总结,happy path会忽略中间步骤,unhappy path不会忽略,reject状态很重要,如果非reject状态,rule policy会优先走happy path,编写的unhappy rule因此也不会起作用

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值