So I am developing a rasa calm chatbot for interacting with a simulated robot of sorts. I ask it to move objects and once it has all the required slots, it will trigger a custom action. However, if I interrupt a ongoing flow, it behaves weirdly and sets slots automatically.
Here is an example:
user : move the brush
robot: Where would you like me to move the brush to?
user: move the can from the kitchen to the dining room
robot: Moving brush from bedroom table to dining room table
Let’s continue with move object no location.
Ok, I am updating object to can respectively.
Where would you like me to move the can to?
Here move object no location is the name of the flow when the user does not specify the source location of the object. For something like “move the cup to the kitchen” and I have a custom action that determines the location of the cup and all that. In the above example, the brush location is determined to be bedroom table which is correct, but nowhere did I set a destination to dining room table
Here’s the end2end from the inspector:
- user: move the brush
- utter: utter_ask_destination_location
- user: move the can from the kitchen to the dining room
- utter: Moving brush from bedroomtable to diningroomtable
- utter: utter_flow_continue_interrupted
- utter: utter_corrected_previous_input
- utter: utter_ask_destination_location
this is for when the user does not specify the source location
move_object_no_location:
description: This flow is triggered when the user requests the robot to move an object to a destination without specifying its source location.
steps:
- collect: object
description: Extract and store the name of the object the user wants the robot to move. Ensure the input is a valid string representing an object, rejecting any empty strings.
- action: action_check_if_object_in_kb
next:
- if: slots.object_in_kb
then: "collect_destination_location_to_move_object_to"
- else:
- action: utter_object_not_in_kb
next: END
- id: "collect_destination_location_to_move_object_to"
collect: destination_location
description: Extract and store the specific location to where the user wants the robot to move the object. Ensure the input is a valid location, rejecting any empty strings.
- action: action_check_if_destination_location_in_kb
next:
- if: slots.location_in_kb
then:
- action: action_set_params_move_object
- action: action_send_move_object_goal
- set_slots:
- object_in_kb: False
- location_in_kb: False
- source_location: null
- destination_location: null
next: END
- else:
- action: utter_destination_location_not_in_kb
- set_slots:
- destination_location: null
next: "collect_destination_location_to_move_object_to"
and here is the one for when the user gives both source and destination
move_object_from_location:
description: This flow is triggered when the user requests the robot to move an object from one location to another.
steps:
- collect: object
description: Extract and store the name of the object the user wants the robot to move. Ensure the input is a valid string representing an object, rejecting any empty strings.
- action: action_check_if_object_in_kb
next:
- if: slots.object_in_kb
then: "collect_location_to_move_object_from"
- else:
- action: utter_object_not_in_kb
next: END
- id: "collect_location_to_move_object_from"
collect: source_location
description: Extract and store the specific location from where the user wants the robot to move the object. Ensure the input is a valid location, rejecting any empty strings.
- call: "verify_or_update_source_location"
next:
- if: slots.location_in_kb
then:
- set_slots:
- location_in_kb: False
next: "collect_destination_location_to_move_object_to"
- else:
- action: utter_source_location_not_in_kb
- set_slots:
- source_location: null
- location_in_kb: False
next: "collect_location_to_move_object_from"
- id: "collect_destination_location_to_move_object_to"
collect: destination_location
description: Extract and store the specific location to where the user wants the robot to move the object. Ensure the input is a valid location, rejecting any empty strings.
- action: action_check_if_destination_location_in_kb
next:
- if: slots.location_in_kb
then:
- action: action_set_params_move_object
- action: action_send_move_object_goal
- set_slots:
- object_in_kb: False
- location_in_kb: False
- source_location: null
- destination_location: null
next: END
- else:
- action: utter_destination_location_not_in_kb
- set_slots:
- destination_location: null
- location_in_kb: False
next: "collect_destination_location_to_move_object_to"
I can understand it confusing these two and asking for a source location, but it straight up assumed a location
These two flows are likely too similar for the LLM to distinguish between them.
I recommend that you have just one flow: move_object
In that flow, you always first collect the object and the destination_location.
But for the source_location, I would build a conditional statement. If the source_location slot is already filled, your done. If the source_location slot is not filled, you could first ask a question: do you know the current location of the object?
If the answer is yes, you ask for it, if the answer is no, you leave it null.
Then, in the remainder of the flow, you can handle the behavior based on the source_location slot being null or having a value.
yes these two flows are two similar, and I would understand it if the LLM made a mistake in choosing between one of these. But what happened is that it assigned a value to the slot without asking anything. There was no mention of a bedroom in that conversation, and yet it assigned that in the source location slot. I was looking for a way to deal with that.
You might need to implement session management or context resetting to handle interruptions more effectively, ensuring correct slot filling and responses.