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