From db9ddd461048779f6d19fb2ffec7be3abb2b7465 Mon Sep 17 00:00:00 2001 From: Shahin Shayandeh <shahins@microsoft.com> Date: Mon, 31 Aug 2020 17:17:57 -0700 Subject: [PATCH] Normalize string comparisons in multiwoz template nlg to be case insensitive (#87) * normalize template nlg keys to be lower case * fix slot comparison in multiwoz nlg to be case insensitive * use value_lower instead of calling .lower() on each comparison --- convlab2/nlg/template/multiwoz/nlg.py | 39 +++++++++++++++++---------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/convlab2/nlg/template/multiwoz/nlg.py b/convlab2/nlg/template/multiwoz/nlg.py index 96764ec..1329275 100755 --- a/convlab2/nlg/template/multiwoz/nlg.py +++ b/convlab2/nlg/template/multiwoz/nlg.py @@ -6,13 +6,21 @@ import collections from convlab2.nlg import NLG +def lower_keys(x): + if isinstance(x, list): + return [lower_keys(v) for v in x] + elif isinstance(x, dict): + return {k.lower(): lower_keys(v) for k, v in x.items()} + else: + return x + def read_json(filename): with open(filename, 'r') as f: - return json.load(f) + return lower_keys(json.load(f)) # supported slot -slot2word = { +Slot2word = { 'Fee': 'fee', 'Addr': 'address', 'Area': 'area', @@ -43,6 +51,7 @@ slot2word = { # 'TrainID': 'TrainID' } +slot2word = dict((k.lower(), v.lower()) for k,v in Slot2word.items()) class TemplateNLG(NLG): def __init__(self, is_user, mode="manual"): @@ -105,9 +114,9 @@ class TemplateNLG(NLG): dialog_acts = self.sorted_dialog_act(dialog_acts) action = collections.OrderedDict() for intent, domain, slot, value in dialog_acts: - k = '-'.join([domain, intent]) + k = '-'.join([domain.lower(), intent.lower()]) action.setdefault(k, []) - action[k].append([slot, value]) + action[k].append([slot.lower(), value]) dialog_acts = action mode = self.mode try: @@ -160,7 +169,7 @@ class TemplateNLG(NLG): sentences = '' for dialog_act, slot_value_pairs in dialog_acts.items(): intent = dialog_act.split('-') - if 'Select' == intent[1]: + if 'select' == intent[1]: slot2values = {} for slot, value in slot_value_pairs: slot2values.setdefault(slot, []) @@ -176,7 +185,7 @@ class TemplateNLG(NLG): sentence += ' , ' + value sentence += ' {} ? '.format(slot2word[slot]) sentences += sentence - elif 'Request' == intent[1]: + elif 'request' == intent[1]: for slot, value in slot_value_pairs: if dialog_act not in template or slot not in template[dialog_act]: sentence = 'What is the {} of {} ? '.format(slot.lower(), dialog_act.split('-')[0].lower()) @@ -191,31 +200,32 @@ class TemplateNLG(NLG): sentences += sentence else: for slot, value in slot_value_pairs: + value_lower = value.lower() if value in ["do nt care", "do n't care", "dontcare"]: - sentence = 'I don\'t care about the {} of the {}'.format(slot.lower(), dialog_act.split('-')[0].lower()) - elif self.is_user and dialog_act.split('-')[1] == 'Inform' and slot == 'Choice' and value == 'any': + sentence = 'I don\'t care about the {} of the {}'.format(slot, dialog_act.split('-')[0]) + elif self.is_user and dialog_act.split('-')[1] == 'inform' and slot == 'choice' and value_lower == 'any': # user have no preference, any choice is ok sentence = random.choice([ "Please pick one for me. ", "Anyone would be ok. ", "Just select one for me. " ]) - elif slot == 'Price' and 'same price range' in value: + elif slot == 'price' and 'same price range' in value_lower: sentence = random.choice([ "it just needs to be {} .".format(value), "Oh , I really need something {} .".format(value), "I would prefer something that is {} .".format(value), "it needs to be {} .".format(value) ]) - elif slot in ['Internet', 'Parking'] and value == 'no': + elif slot in ['internet', 'parking'] and value_lower == 'no': sentence = random.choice([ - "It does n't need to have {} .".format(slot.lower()), - "I do n't need free {} .".format(slot.lower()), + "It does n't need to have {} .".format(slot), + "I do n't need free {} .".format(slot), ]) elif dialog_act in template and slot in template[dialog_act]: sentence = random.choice(template[dialog_act][slot]) sentence = sentence.replace('#{}-{}#'.format(dialog_act.upper(), slot.upper()), str(value)) - elif slot == 'NotBook': + elif slot == 'notbook': sentence = random.choice([ "I do not need to book. ", "I 'm not looking to make a booking at the moment." @@ -237,7 +247,7 @@ class TemplateNLG(NLG): key += s + ';' if dialog_act in template and key in template[dialog_act]: sentence = random.choice(template[dialog_act][key]) - if 'Request' in dialog_act or 'general' in dialog_act: + if 'request' in dialog_act or 'general' in dialog_act: sentence = self._postprocess(sentence) sentences += sentence else: @@ -254,6 +264,7 @@ class TemplateNLG(NLG): def example(): # dialog act dialog_acts = [['Inform', 'Hotel', 'Area', 'east'],['Inform', 'Hotel', 'Internet', 'no'], ['welcome', 'general', 'none', 'none']] + #dialog_acts = [['Inform', 'Restaurant', 'NotBook', 'none']] print(dialog_acts) # system model for manual, auto, auto_manual -- GitLab