【多轮对话】从微软源码看用户模拟器构建

2022-09-06 20:12:59 浏览数 (2)

用户模拟器是在任务型多轮对话场景中,用于模拟用户在指定目标下多轮对话过程,可以用于生成对话数据,以及通过强化的方式训练系统决策。在具体的任务型场景需要定义有哪些用户行为、用户意图、用户可能说的槽位等,而之后用户模拟器是怎么来推进对话过程的呢?

论文:A User Simulator for Task-Completion Dialogues

代码地址: https://github.com/MiuLab/TC-Bot

本文首先简单介绍用户模拟器方法,再从源码细节分析具体多轮对话中的用户模拟器应该如何构建。

用户模拟器

用户行为user action

首先第一步就是确定用户会有哪些action,以及action对应的意图、槽位有哪些,这个与具体的任务有关。但是很对最近的论文都是复用剑桥提出的DSTC2/3(餐馆预订)中对用户action的定义,那么他们定义了哪些呢:

act

包含的slot

描述

inform

槽值(s, v), ...

用户告知系统的值,例如:饭店是xx,厂家是xxx

request

槽位名s

用户询问系统的槽位,例如:xx药的厂家有哪些?

ack

None

肯定(这里和确认很像,但是这里是会话的肯定,肯定的返回结果),例如:Okay, what’s the phone number of that place?”

affirm

None

认可/是的

negate

None

否定/不是

reqalts

None

其他、以上都不是

confirm

one slot (s, v)

s是可以告知的槽位,v是对应的值,例如:这个药品是同仁堂生产的吗?

deny

one slot (s, v)

s是可以告知的槽位,v是对应的值,例如:不要国产的格列卫

null

None

空、非当前域、未理解

reqmore

None

还有哪些、还有更多的剂型吗

thankyou

致谢

help

None

你有什么功能、你可以做什么、我可以问什么

repeat

None

重复一下、你说什么

bye

None

Hello

None

例子:

代码语言:txt复制
[{"act":"confirm", "slots":[["area", "centre"]]},
 {"act":"request", "slots":[["slot", "phone"]]},
 {"act":"deny", "slots":[["area","north"]]},
 {"act":"hello", "slots":[]},]

其实affirm和confirm和合并,negate和deny也可以合并

确定了user action,以及任务的槽位和意图之后,就可以开始构建基于Agenda-Based的用户模拟器了。

Agenda-Based的用户模拟方法

Agenda-Based主要通过生成用户目标,然后将其通过出栈的形式来生成对话流,主要包含以下模块:

  • 用户目标生成:这部分可以基于数据库随机生成,目标也包含inform_slots、request_slots。生成用户目标之后,
  • 用户行为(action)产生:
    • 首轮:会有一些条件,比如必须要有餐馆名字等。
    • 非首轮:结合系统的问询说出目标中的某一个或多个槽位
  • 会话状态:这个是模拟器内部的会话状态:
    • 历史信息:用户保存说了哪些槽位,哪些槽位没有说。
    • 会话状态:失败、成功、还没结束
  • NLG模块:将用户action转化为自然语言。

主函数run.py

通过主函数中DM(run.py)来完成agent和user之间的对话,state_tracker记录并结合KB结果给agent作为其infrom。两者交互通过action(包含request,infrom,diaact等),并非自然语言。agent、user、act_set、slot_set、state_tracker、user_action、reward、episode_over。

也可以利用user bot在线训练agent,然后agent与真实用户交互来继续在线训练。

state_tracker

state_tracker.py中的state_tracker类包含:

  • Current_slots:
    • Agent_request_slots: agent必须要知道value的slots;
    • Infrom_slot: 当前获得的inform_slots;
    • Request_slots: 需要向用户提问的slots;
  • history_dictionaries: 当前对话每轮记录。
  • kb_helper:类,可以返回可用的movie list。
  • movie_dictionaries: 电影数据库。
  • turn_count: 轮次计数。

本文主要介绍模拟器,state_tracker这块感兴趣可以自行细读。

user smilator代码

用户模拟器代码:usersim_rule.py,其中有一个RuleSimulator类,对于其输入、输出为:

输入

首次对话,调用initialize_episode(),直接会输出,无需输入。

对话过程中调用next(),需要输入system_action, map形式,key包含:

  1. diaact: action,例如 request, infrom
  2. infrom_slots: 包含imform的slot-value
  3. request_slots: 包含slot-‘UNK’
  4. turn: 当前对话轮次

举例子:system_action: {'request_slots': {'date': 'UNK'}, 'turn': 3, 'speaker': 'agent', 'inform_slots': {}, 'diaact': 'request'}

输出

自然语言。例如:which restaurant and what is the address for breaskfast for 10 people on tomorrow morning

输出是自然语言还是结构化的字段(user action),可以按需更改,因为按照M2M对话产生对话的outline也可以是user action。

构造函数

  • 域字典:包含域的字典和对应项;如movie_dict,包含key有actor,city,date等,value是其对应的取值。(语料,kb)
  • act_set:user的action type,如closing,inform,等。
  • slot_set:域对应的slot type,如actor,date等。
  • start_set:根据语料生成的usr goal sample。包含inform_slots、request_slots。包含test,train,valid等。
  • params:参数,包含
    • max_turn最大轮次、
    • slot_err_probability:(s d i/c s d)槽位错误概率
    • slot_err_mode:错误模式
    • intent_err_probability:意图错误概率
    • simulator_run_mode、(0 for dia-act; 1 for NL; 2 for no output)
    • simulator_act_level:0 for dia_act level; 1 for NL level
    • learning_phase(all, train, test)
    • NLG模板。

params举例:{'max_turn': 20, 'slot_err_mode': 0, 'slot_err_probability': 0.05, 'intent_err_probability': 0.05, 'simulator_act_level': 0, 'learning_phase': 'all', 'simulator_run_mode': 0}

初始化initialize_episode

记录状态的数据结构: history_slots, insorm_slots, request_slot, rest_slot都为空, turn(int)=0

Episode_over、dialog_status。

goal产生(_sample_goal):从start_set随机选一条记录。其中ticket设为UNK

_sample_action:初始action选择,包含以下:

  • diaact: 从配置文件的start_dia_acts中随机选一个(只有request)。
  • Infrom_slot: 如果有moviename,则第一轮必出现,再选一个其他的infrom。
  • agenda:将其他slot和request slot加入到rest_slot中。
  • Request_slot: ticket在最后请求,优先随机选其他request,

根据action调用NLG生成自然语言,加入到action'nl'中。方法:模板,对于agent和usr每类request和infrom都有相应模板。lstm_decoder。

很多逻辑冗余,例如state'request_slots'刚添加,就判空。以及一些不可能出现的情况(上层已经判断过)。

输出:user_action,包含diaact、infrom_slots、request_slots、turn、nl。

Next User action(next函数)

输入:DM输入system_action, 包含request_slot, inform_slots等信息。

输出:response_action

更新信息:state'turn'加2,dialog_status。turn超过最大次数,则state'diaact'='closing'。更新history_slots,清空inform_slots。

对于不同的sys_act,回应不同:

  • system request:从sys_action的request中选取第一个slot。如果request为空,则在rest_slot中随机选一个slot。
  • 如果在infrom_slot中,将其对应键值保存到state'infrom_slot'中,state'diaact'='infrom', 并从rest_slots中移除,清空state'request_slots',(因为其代表本次request值)
  • 如果在request_slot中,state'diaact'='request', 并将slot填入到state'request_slot'。
    • 待修改:并且发送如果还有infrom,则全部取出到state'infrom_slot',并将这些infrom从rest_slot中移除。这样做是防止user infrom没说完,系统就返回了结果。
  • 否则为donot care,(既不在infrom也不再request)
  • Response_inform: 回应系统的inform action.
  • System_action中包含键taskcomplete,则转换下一个diaact=thanks,如果其值为no_value_match,则将ticket的value设为no_value;否则检查system_action的slot-value和goal中是否一致,不一致则constraint_check为0,diaact=deny。
  • 如果不包含taskcomplete,将infrom加入到state'history_slots',并比对infrom与goal中slot-value是否一致。一致则更新state。
    • 如果value不一致,可以选择再说一遍不一致的slot-value,或者直接state'diaact'=deny,结束会话。
    • 如果slot不在goal中,是donot care的slot,不管,发起state'request_slots'中请求,如果其为空的则在rest_slots中选一个,如果rest_slots也为空的,则请求ticket。
  • multiple_choice:回应系统提供slot的可选择value,user diaact变为inform。将slot从rest_slot移除。
    • system inform_slot在user inform slot中,返回inform中的值。
    • 如果在user request slot中,那么随机选择一个答案。并将其从request_slot中移除。
    • 如果都不在,返回i do not care。
  • Response_confirm:
    • 如果rest_slot不为空,则随机选取一个slot。
    • 否则返回state'diaact' = "thanks"
  • thanks:轮次结束,决定对话状态,返回相应奖励,对话成功条件:
  • rest_slot中无剩余、
  • history_slot无空值并且和goal中一致。
  • system_action返回的ticket不为空。

加入噪声corrupt

  1. 以slot_err_probability概率产生错误的slot-value,slot_err_mode=0,则替换value;mode=1则以1/3概率替换value,1/3概率替换slot和value,1/3删除slot-value;mode=2, 替换slot和value; mode=3, 删除slot和value。
  2. 以intent_err_probability随机改变user_action'diaact'。

模拟agent SLU识别错误、交互噪声的情况,增加鲁棒性,数据集也会扩充。

经过NLG。

奖励:(DM)

  1. Status = sucess, R=2*max_turn;
  2. status= Failed, R= -max_turn;
  3. Else: R=-1;

名词解释

S = (A,G) , goal G, G=(c, r),c是要求,r是用户请求获得什么。还需要加入intent信息。agenda A堆栈类型(未完成),对话系统解决一个出栈一个。

User goal

  1. inform_slot: 用户的限制的slot-value;其中又分为Require slots和Optional slots;
  2. request_slot: 用户请求的slot。

数据生成方式:

  1. 从语料中用户第一轮的数对话提取槽位。
  2. 所有用户的所有回合的槽位。

将user goal生成database,然后对话开始时候从中随机采样生成user goal。

User action

首轮:会有特殊限制,如一般都会包含request,至少一个infrom slot,movie名如果知道首轮会出现。

对话过程中,包含一个类堆的agenda,过程中会出栈和入栈(agenda出现没有的slot)。

Dialogue Status

no_outcome_yet, success(回答所有requestable slots,通过NLU来识别,并给出正确的票), failure。还会限制对话轮次,超出算失败。并决定返回奖励。

NLU

intent和slots联合训练,使用Seq2Seq方法,数据为全部对话action和utterance,IOB的slot标签和intent标签

NLG

  1. 模板。
  2. 模型:Seq2Seq,输入是dialog action,生成类模板的句子。

对于dialog act,如果找到了规则模板,则输出模板,否则使用模型的输出。

扩展

最近也有很多使用模型来做用户模拟器的,这里简单提一下,后续有机会细说。主要还是通过数据驱动的模型方法来自动学习用户,通过对话历史、user profile、task schema作为输入,预测下一轮应该说什么,主要有:

  • 基于统计建模
    • Collaboration-based User Simulation for Goal-oriented Dialog Systems
    • A stochastic model of human machine interaction for learning dialog strategies
  • 有监督:
    • Neural User Simulation for Corpus-based Policy Optimization for Spoken Dialogue Systems
    • A Sequence-to-Sequence Model for User Simulation in Spoken Dialogue Systems
  • 强化:Iterative Policy Learning in End-to-End Trainable Task-Oriented Neural Dialog Models
  • 逆强化:User Simulation in Dialogue Systems using Inverse Reinforcement Learning

另外看了一篇感觉比较合理google AI: USER MODELING FOR TASK ORIENTED DIALOGUES,可以简单看下他的模型图

Reference

  • A User Simulator for Task-Completion Dialogues
  • Agenda-Based User Simulation for Bootstrapping a POMDP Dialogue System
  • A Sequence-to-Sequence Model for User Simulation in Spoken Dialogue Systems(

0 人点赞