Skip to content

Commit

Permalink
route_alternative moved from slots to a special state variable
Browse files Browse the repository at this point in the history
The `dialogue_state` variable is now a member variable of the state,
(same as `conn_info` and `directions`), not a slot.

This reflects the actual usage of the variable – it is always integer,
never a probability distribution. Now wo don't need to use `isinstance`
to test whether a route has been found, we can use `is not None`, which
is nicer.

This fixes the problem reported in #165.
  • Loading branch information
tuetschek committed May 29, 2015
1 parent 86de4ba commit fe0b991
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 43 deletions.
7 changes: 3 additions & 4 deletions alex/applications/PublicTransportInfoCS/data/ontology.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,10 +216,6 @@
'system_informs',
'absolute_time',
],
'route_alternative': [
# this is necessary to be defined as it is a state variable used by the policy and automatically added to
# the dialogue state
],

'lta_task': [],
'lta_bye': [],
Expand All @@ -246,6 +242,9 @@
]
},

# additional variables that relate to the state but are not used as slots (initialized to None)
'variables': ['route_alternative', 'conn_info', 'directions'],

'context_resolution': {
# it is used DM belief tracking context that
# if the systems asks (request) about "from_city" and user responds (inform) "city" then it means (inform)
Expand Down
72 changes: 34 additions & 38 deletions alex/applications/PublicTransportInfoCS/hdc_policy.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

from datetime import timedelta
from .directions import GoogleDirectionsFinder, Travel, NotSupported
from .platform_info import PlatformInfo
from .platform_info import PlatformInfo
from datetime import datetime
from datetime import time as dttime
from collections import defaultdict
Expand Down Expand Up @@ -125,7 +125,6 @@ def get_da(self, dialogue_state):
:param dialogue_state: the belief state provided by the tracker
:return: a dialogue act - the system action
"""

ludait_prob, last_user_dai_type = dialogue_state["ludait"].mph()
if ludait_prob < self.policy_cfg['accept_prob_ludait']:
last_user_dai_type = 'none'
Expand Down Expand Up @@ -317,7 +316,6 @@ def get_connection_res_da(self, ds, ludait, slots_being_requested, slots_being_c
:param slots_being_requested: The slots currently requested by the user
:rtype: DialogueAct
"""

# output DA
res_da = None

Expand Down Expand Up @@ -514,11 +512,11 @@ def get_an_alternative(self, ds):
:param ds: The current dialogue state
:rtype: DialogueAct
"""
if 'route_alternative' not in ds:
if ds.route_alternative is not None:
return DialogueAct('request(from_stop)')
else:
ds['route_alternative'] += 1
ds['route_alternative'] %= len(ds.directions) if ds.directions is not None else 1
ds.route_alternative += 1
ds.route_alternative %= len(ds.directions) if ds.directions is not None else 1
return self.get_directions(ds)

def get_requested_alternative(self, ds):
Expand All @@ -529,31 +527,31 @@ def get_requested_alternative(self, ds):
"""
res_da = DialogueAct()

if 'route_alternative' in ds:
if ds.route_alternative is not None:
ds_alternative = ds["alternative"].mpv()

if ds_alternative == "last":
res_da.extend(self.get_directions(ds, "last"))
elif ds_alternative == "next":
ds["route_alternative"] += 1
ds.route_alternative += 1
try:
ds.directions[ds['route_alternative']]
ds.directions[ds.route_alternative]
res_da.extend(self.get_directions(ds, "next"))
except:
ds["route_alternative"] -= 1
ds.route_alternative -= 1
res_da.append(DialogueActItem("inform", "found_directions", "no_next"))

elif ds_alternative == "prev":
ds["route_alternative"] -= 1
ds.route_alternative -= 1

if ds["route_alternative"] == -1:
ds["route_alternative"] += 1
if ds.route_alternative == -1:
ds.route_alternative += 1
res_da.append(DialogueActItem("inform", "found_directions", "no_prev"))
else:
res_da.extend(self.get_directions(ds, "prev"))

else:
ds["route_alternative"] = int(ds_alternative) - 1
ds.route_alternative = int(ds_alternative) - 1
res_da.extend(self.get_directions(ds))

else:
Expand Down Expand Up @@ -584,25 +582,25 @@ def get_requested_info(self, requested_slots, ds, accepted_slots):
continue

# try to find a route if we don't know it yet
if not isinstance(ds['route_alternative'], int):
if ds.route_alternative is None:
req_da, iconfirm_da, conn_info = self.gather_connection_info(ds, accepted_slots)
# we have all information we need, start searching
if len(req_da) == 0:
ds.conn_info = conn_info
res_da = iconfirm_da
# the search will change ds['route_alternative'] if a route is found
# the search will change ds.route_alternative if a route is found
dir_da = self.get_directions(ds, check_conflict=True)
# only return the output DAs if no route is found (i.e., the error message),
# otherwise we go on to return the specific information requested
if not isinstance(ds['route_alternative'], int):
if ds.route_alternative is None:
res_da.extend(dir_da)
# we don't know enough, ask about the rest
else:
res_da = req_da

# we have a route, so return information about it
# NB: ds['route_alternative'] might have changed in the meantime if a route has been found
if isinstance(ds['route_alternative'], int):
# NB: ds.route_alternative might have changed in the meantime if a route has been found
if ds.route_alternative is not None:
if slot == 'from_stop':
res_da.extend(self.req_from_stop(ds))
elif slot == 'to_stop':
Expand Down Expand Up @@ -852,7 +850,6 @@ def gather_connection_info(self, ds, accepted_slots):
to_city=to_city_val, to_stop=to_stop_val,
vehicle=vehicle_val, max_transfers=max_transfers_val)


def gather_platform_info(self, ds, accepted_slots):
"""Return a DA requesting further information for the platform search.
Expand Down Expand Up @@ -889,7 +886,6 @@ def gather_platform_info(self, ds, accepted_slots):
train_name=train_name_val)
return req_da, iconfirm_da, pi


def req_current_time(self):
"""Generates a dialogue act informing about the current time.
:rtype: DialogueAct
Expand All @@ -907,7 +903,7 @@ def req_from_stop(self, ds):
:rtype : DialogueAct
"""
route = ds.directions[ds['route_alternative']]
route = ds.directions[ds.route_alternative]
leg = route.legs[0]
da = DialogueAct()
for step in leg.steps:
Expand All @@ -923,7 +919,7 @@ def req_to_stop(self, ds):
"""Return a DA informing about the destination stop of the last
recommended connection.
"""
route = ds.directions[ds['route_alternative']]
route = ds.directions[ds.route_alternative]
leg = route.legs[0]
da = DialogueAct()
for step in reversed(leg.steps):
Expand All @@ -938,7 +934,7 @@ def req_departure_time(self, dialogue_state):
:rtype : DialogueAct
"""
route = dialogue_state.directions[dialogue_state['route_alternative']]
route = dialogue_state.directions[dialogue_state.route_alternative]
leg = route.legs[0]
da = DialogueAct()
for step in leg.steps:
Expand All @@ -952,7 +948,7 @@ def req_departure_time_rel(self, dialogue_state):
"""Return a DA informing the user about the relative time until the
last recommended connection departs.
"""
route = dialogue_state.directions[dialogue_state['route_alternative']]
route = dialogue_state.directions[dialogue_state.route_alternative]
leg = route.legs[0]
da = DialogueAct()
for step in leg.steps:
Expand Down Expand Up @@ -984,7 +980,7 @@ def req_arrival_time(self, dialogue_state):
"""Return a DA informing about the arrival time the destination stop of the last
recommended connection.
"""
route = dialogue_state.directions[dialogue_state['route_alternative']]
route = dialogue_state.directions[dialogue_state.route_alternative]
leg = route.legs[0]
da = DialogueAct()
for step in reversed(leg.steps):
Expand All @@ -998,7 +994,7 @@ def req_arrival_time_rel(self, dialogue_state):
"""Return a DA informing about the relative arrival time the destination stop of the last
recommended connection.
"""
route = dialogue_state.directions[dialogue_state['route_alternative']]
route = dialogue_state.directions[dialogue_state.route_alternative]
leg = route.legs[0]
da = DialogueAct()
for step in reversed(leg.steps):
Expand All @@ -1016,7 +1012,7 @@ def req_duration(self, dialogue_state):
"""Return a DA informing about journey time to the destination stop of the last
recommended connection.
"""
route = dialogue_state.directions[dialogue_state['route_alternative']]
route = dialogue_state.directions[dialogue_state.route_alternative]
leg = route.legs[0]
da = DialogueAct()
for step in leg.steps:
Expand All @@ -1042,7 +1038,7 @@ def req_num_transfers(self, dialogue_state):
"""Return a DA informing the user about the number of transfers in the
last recommended connection.
"""
route = dialogue_state.directions[dialogue_state['route_alternative']]
route = dialogue_state.directions[dialogue_state.route_alternative]
leg = route.legs[0]
n = sum([1 for step in leg.steps if step.travel_mode == step.MODE_TRANSIT]) - 1
da = DialogueAct('inform(num_transfers="%d")' % n)
Expand All @@ -1052,7 +1048,7 @@ def req_time_transfers(self, dialogue_state):
"""Return a DA informing the user about transfer places and time needed for the trasfer in the
last recommended connection.
"""
route = dialogue_state.directions[dialogue_state['route_alternative']]
route = dialogue_state.directions[dialogue_state.route_alternative]
leg = route.legs[0]
# get only transit with some means of transport
transits = [step for step in route.legs[0].steps if step.travel_mode == step.MODE_TRANSIT ]
Expand Down Expand Up @@ -1113,9 +1109,9 @@ def get_directions(self, ds, route_type='true', check_conflict=False):
if check_conflict:
apology_da = self.check_directions_conflict(conn_info)
if apology_da is not None:
if 'route_alternative' in ds:
if ds.route_alternative is not None:
ds.directions = None
del ds['route_alternative']
ds.route_alternative = None
return apology_da

# get dialogue state values
Expand Down Expand Up @@ -1159,27 +1155,27 @@ def process_directions_for_output(self, dialogue_state, route_type):
:param route_type: the route type requested by the user ("last", "next" etc.)
:rtype: DialogueAct
"""
if not isinstance(dialogue_state['route_alternative'], int):
dialogue_state['route_alternative'] = 0
if dialogue_state.route_alternative is None:
dialogue_state.route_alternative = 0

try:
# get the alternative we want to say now
route = dialogue_state.directions[dialogue_state['route_alternative']]
route = dialogue_state.directions[dialogue_state.route_alternative]
# only 1 leg should be present in case we have no waypoints
steps = route.legs[0].steps
except IndexError:
# this will lead to apology that no route has been found
steps = []
#dialogue_state.directions = None
del dialogue_state['route_alternative']
dialogue_state.route_alternative = None

res = []

# introduction
if len(dialogue_state.directions) > 1:
res.append('inform(found_directions="%s")' % route_type)
if route_type != "last":
res.append("inform(alternative=%d)" % (dialogue_state['route_alternative'] + 1))
res.append("inform(alternative=%d)" % (dialogue_state.route_alternative + 1))

# route description
prev_arrive_stop = self.ORIGIN # remember previous arrival stop
Expand Down Expand Up @@ -1312,7 +1308,7 @@ def get_limited_context_help(self, dialogue_state):
res_da = DialogueAct()

# if we do not understand the input then provide the context sensitive help
if not 'route_alternative' in dialogue_state:
if dialogue_state.route_alternative is None:
# before something is offered
if randbool(10):
res_da.append(DialogueActItem("help", "task", "weather"))
Expand Down
6 changes: 5 additions & 1 deletion alex/components/dm/dddstate.py
Original file line number Diff line number Diff line change
Expand Up @@ -270,8 +270,12 @@ def restart(self):
Nevertheless, remember the turn history.
"""

# initialize slots
self.slots = defaultdict(D3DiscreteValue)
# initialize other variables
if 'variables' in self.ontology:
for var_name in self.ontology['variables']:
setattr(self, var_name, None)

def update(self, user_da, system_da):
"""Interface for the dialogue act update.
Expand Down

0 comments on commit fe0b991

Please sign in to comment.