纯自己看的笔记,语言表达就不要纠结啦。。。
(1)data augmentation 策略不影响 Memoization相关的策略,Memoization相关策略训练时只根据最原始的story记录操作对儿信息。注意可能会存在相同操作序列但是后续action不同的情况,则会去掉该操作序列。
(2)相对于MemoizationPolicy,AugmentedMemoizationPolicy从tracker中提取历史操作(只提取action相关,去掉了slotset等事件),与训练时提取的[{意图,前一操作}。。。。设置的max_history参数个操作对儿]进行比较,匹配则返回后续的action作为推荐,不匹配则递归依次去掉最早的操作再次匹配。类似从前往后采用移动窗口的形式匹配训练时的操作对儿序列。直到最后一个
[None,。。。。 {}, {'prev_action_listen': 1.0, 'intent_x': 1.0}]
因为每个story最初都会有[None,。。。。 {}, {'prev_action_listen': 1.0, 'intent_x': 1.0}]这个操作对,故通过AugmentedMemoizationPolicy可最终实现不同story的切换。
在fallback action中返回UserUtteranceReverted event,可防止无效意图的影响。
注意:当某意图是A story的中间意图并且是B story的开始意图,则在A中走到对应意图位置且重复触发该意图,则会跳出A,准备进入B,因为history中最后几个意图已经变为[None,。。。。 {'INTENT_x': 1.0, 'intent_x': 1.0} {'INTENT_x': 1.0, 'intent_x': 1.0}],即由于重复intent的进入只能通过AugmentedMemoizationPolicy匹配到B开头。
(3)MemoizationPolicy策略下,story间切换一般通过KerasPolicy策略实现,在进行若干步之后会自动再次与Memoization策略的记录匹配从而回到Memoization。
(4)实体识别会影响对话状态(如果与story配置不同(如story中有识别,实际没有,反之亦然),则对话不会使用memoizationPolicy,但是一般会通过TED或keras policy选择下一个动作,进而回归story主线),可以使用
intents:
- greet:
use_entities: []
去掉特定intent中的实体影响,也可以通过设置
intents:
- greet:
use_entities:
- name
- first_name
ignore_entities:
- location
- age
取特定实体影响,注意,配置之后并不影响实体识别。
(5)policy优先级,先看置信度,而后比较policy等级,具体逻辑如下
for policy_name, prediction in predictions.items():
confidence = (max(prediction.probabilities), prediction.priority)
if self._is_form_policy(policy_name):
# store form prediction separately
form_confidence = confidence
form_policy_name = policy_name
elif confidence > best_confidence:
# pick the best policy
best_confidence = confidence
best_policy_name = policy_name
if form_confidence is not None and self._is_not_mapping_policy(
best_policy_name, best_confidence[0]
):
# if mapping didn't win, check form policy predictions
if form_confidence > best_confidence:
best_policy_name = form_policy_name
return predictions[best_policy_name].probabilities, best_policy_name
即如果mapping置信度最高则取mapping,而后判断form,再后取其他
(6)rasa提供了基于知识库的查询架构(试验功能)
简单说就是将知识库与列出所有、哪一个、实体属性等常用类型的查询规范化整理到一个action内部-ActionQueryKnowledgeBase,有一些基本slot的设定,知识库默认是从json文件读入到内存,支持重写(如改为从数据库读)。
(7)调用层次
processor->ensemble->policy
processor->action.run()
processor._predict_and_execute_next_action
while(需要继续预测下一步 且 对话没有暂停 且 没有达到最大预测步骤数)
调用predict_next_action获得置信度最高的action和policy
执行action.run()
(8)tracker stores 和event brokers
二者都是对对话的events进行记录,前者主要为rasa服务自身运行准备,后者方便将对话过程输出给外部服务进行分析,另外使用sql数据库时,二者记录信息基本差不多,但前者将意图名称、动作类型等提为单独字段,格式更适合结构化查询,后者只有sender_id提为单独字段,其余信息以json格式存为data字段,不适合查询。
使用sql存储时
tracker stores 需要创建表events(自动创建),序列events_seq(手动)
event brokers 官网未提示需要预先创建内容,实测会自动创建表events,与前者字段不同,使用oracle时,id字段为主键但源码中并未给值,可以借助序列和触发器默认给值。
(9)story不会验证不同story流程相同的情况
rasa data validate stories方法能够验证不同story前x个交互相同但接下来action不同的冲突情况,但实测模型依旧可用,会选择某个路径进行对话。
(10)确定story开始位置
rasa并未提供当前对话所属story位置功能,但可确定当前是否处于某个story开始位置(不同story开始不重复的情况下),将data augmentation设置为0(即不使用扩充story训练),使用AugmentedMemoizationPolicy策略,判断最终匹配story时,用的event对是[None,。。。。 {}, {'prev_action_listen': 1.0, 'intent_x': 1.0}]形式即可(story的第一个位置)。
(11)story中的slot{}和entity
## greet + goodbye
* greet
- utter_greet
* affirm
- action_test
- slot{"test_slot": "2"}
- utter_letmehelp
## greet + goodbye + affirm
* greet
- utter_greet
* affirm
- action_test
- slot{"test_slot": null}
- utter_affirm
- slot{"slot_name":"slot_value"},代表当前位置对特定slot的判断:slot为text时,只判断是否有值或null;为categorical或bool时,可判断是否是特定值,从而达到story分支的目的。
注意,只有Unfeaturized类型的slot不会影响对话(-slot{}也会失效)。slot{}不必接紧接在有slotset事件的动作之后。
intent后也可添加{"entity_name":"entity_value"},注意不是slot,代表当前位置位置的对话需要提取entity(如果没有该动作则不会匹配当前story)
## greet + goodbye
* greet
- utter_greet
* search_person_by_car_no{"car_no":"京B11111"}
- utter_letmehelp
## greet + goodbye + affirm
* greet
- utter_greet
* search_person_by_car_no
- utter_affirm
上面search_person_by_car_no意图下有无检测到实体同样会影响story走势。同样,story的实体值不代表实际对话的实体值
在tracker的event和memonypolicy的训练过程中,实体和-slot{}会形成对应的状态信息如下,从而影响到基于memonypolicy的匹配
{'intent_intent_2': 1.0, 'slot_theme_2': 1.0, 'entity_theme': 1.0, 'prev_action_listen': 1.0}
根据实测- slot{}在story的作用更类似于意图,即验证slot的状态和值,而非一个动作,另外官网和https://blog.rasa.com/designing-rasa-training-stories/博客对于
* greet
- utter_greet
* search_person_by_car_no{"car_no":"京B11111"}
- slot{"car_no": "2"}
- utter_letmehelp
样式的对话均有类似的描述,即slot{}在car_no的auto_fill为true时不用出现也行。但根据测试slot{]在此处为验证功能,及验证car_no此处是否有值,而car_no非自动填充时,验证失败,导致story不匹配(当将auto_fill设置为true时,下面故事匹配,因为slot有值)。同理测得,将其改为 - slot{"car_no":nulll}时,亦可匹配。
https://forum.rasa.com/t/usage-of-slots-in-stories/2309/2 上作者也有解释说-lost{} 既代表验证又代表有SlotSet 事件
但实测
## greet + goodbye
* greet
- utter_greet
* search_person_by_car_no
- slot{"car_no": "1"}
- utter_letmehelp
## greet + goodbye + affirm
* greet
- utter_greet
* search_person_by_car_no
- slot{"car_no": null}
- utter_affirm
search的意图并未设置slot也可匹配
不知道为何与官网说法不同,总之,暂且理解为- slot{}为验证slot值,提供分支功能,意图上的entity,也作为story匹配的条件之一。
(12)关于spacy和metie识别实体
spacy支持中文(官网有包),但是只支持预定义的一些实体类型,不支持自己二次训练,故无法支持自定义实体。
metie支持二次训练,训练数据需要所有nlu_data中的intent下的语料(包括与实体无关的,即没有实体标注的语料),若只提供实体本身作为训练数据,则在p,则在parse环节,输入语句的所有分词都会被识别为实体。
(13)form的退出
正常的form退出 需要使用Form(None)事件
form提供了临时暂停一轮的方式
raise ActionExecutionRejection
需要重写validate方法(其实在run()中流程写即可),自定义实现,第二轮过后还会回到之前form
之后下一轮输入如果不触发ActionExecutionRejection,则会根据在触发的action run 之后更新
一个ActionExecuted时间,从而让tracker的active_form["rejected"] = False,回归原form(action后返回UserUtteranceReverted事件亦可使rejected状态归位)
form不可嵌套,如果想中间进入另一个form最好先停掉当前form