英文:
How to edit and confirm form slots in Rasa framework?
问题
I'm building a booking bot using Python and Rasa. I want to add a confirmation step when the user fills in all slots in my form. The requirements are:
- User may confirm the values.
- User may change the values.
- Bot must be expandable to handling other inputs and intents from the user.
I drew a flow-diagram which demonstrates more clearly the logic I want to implement:
flow-diagram
I have 2 questions:
- How do you usually implement the confirmation step?
- How would you implement the logic on the picture?
I'm using Rasa v3.5.13 and Rasa SDK v3.5.1.
I already tried the following:
-
Confirmation within the form: I added an additional slot
confirmation
to the form, implemented extraction and validation to handle user input, but I couldn't make Rasa call custom actions before or afterbook_form
is called. Inheriting fromFormAction
appeared to be impossible because it doesn't inheritAction
frominterfaces.py
. Rules conflict withaction_listen
that is invoked right afterbook_form
. Making a wrapper action aroundbook_form
and calling it instead of the original form works only in the first time, but then the active loop starts to callbook_form
instead of my wrapper. -
Confirmation after the form: passing a custom action in
active_loop
afterbook_form
is filled in seems to work, but I found out that Rasa only calls the lastFollowupAction
returned by my custom action, but I want to call multiple actions on each iteration. I also tried to create a custom action that only sets the categorical slotconfirmation_status
with values: "initialized," "confirmed," "rejected," or "fixed." The idea was that stories can handle my logic relying onconfirmation_status
, but they do it poorly or don't do it at all. Two stories were not enough even to just activateaction_extract_confirmation_status
afteractive_loop
was set tonull
, let alone handling all the logic.
So far, the second option seems to be okay if using rules instead of stories. But I need a lot of rules, and they may become a bottleneck in further development. Coding my logic in Python seems much more robust and easier to me, but I can't find a way to do this normally in Rasa.
UPD:
Tried out another approach:
- rule: Activate confirmation loop
steps:
- action: book_form
- slot_was_set:
- requested_slot: null
- active_loop: null
- action: action_extract_confirmation_status
- active_loop: action_extract_confirmation_status
wait_for_user_input: false
- rule: Ask for confirmation the first time
condition:
- active_loop: action_extract_confirmation_status
steps:
- action: action_extract_confirmation_status
- slot_was_set:
- confirmation_status: initialized
- action: utter_introduce_slots
- action: action_utter_slots
- action: utter_ask_for_confirmation
- rule: Ask for confirmation
condition:
- active_loop: action_extract_confirmation_status
steps:
- action: action_extract_confirmation_status
- slot_was_set:
- confirmation_status: fixed
- action: action_utter_slots
- action: utter_ask_for_confirmation
- rule: Ask for correction in the confirmation loop
condition:
- active_loop: action_extract_confirmation_status
steps:
- action: action_extract_confirmation_status
- slot_was_set:
- confirmation_status: rejected
- action: utter_ask_for_correction
- rule: Finish confirmation
condition:
- active_loop: action_extract_confirmation_status
steps:
- action: action_extract_confirmation_status
- slot_was_set:
- confirmation_status: confirmed
- active_loop: null
- action: utter_booking_completed
And got another conflict:
- the prediction of the action 'action_utter_slots' in rule 'Ask for confirmation' is contradicting with rule(s) 'handling active loops and forms - action_extract_confirmation_status - action_listen' which predicted action 'action_listen'.
- the prediction of the action 'utter_ask_for_correction' in rule 'Ask for correction in confirmation loop' is contradicting with rule(s) 'handling active loops and forms - action_extract_confirmation_status - action_listen' which predicted action 'action_listen'.
- the prediction of the action 'utter_introduce_slots' in rule 'Ask for confirmation the first time' is contradicting with rule(s) 'handling active loops and forms - action_extract_confirmation_status - action_listen' which predicted action 'action_listen'.
Please update your stories and rules so that they don't contradict each other.
This is so annoying.
英文:
I'm building a booking bot using Python and Rasa. I want to add a confirmation step when user fills in all slots in my form. The requirements are:
- User may confirm the values.
- User may change the values.
- Bot must be expandable to handling other inputs and intents from the user.
I drew a flow-diagram which demonstrates more clearly the logic I want to implement:
flow-diagram
I have 2 questions:
- How do you usually implement the confirmation step?
- How would you implement the logic on the picture?
I'm using Rasa v3.5.13 and Rasa SDK v3.5.1.
I already tried the following:
-
Confirmation within the form: I added an additional slot
confirmation
to the form, implemented extraction and validation to handle user input, but I couldn't make Rasa to call custom actions before or afterbook_foorm
is called. Inheriting fromFormAction
appeared to be impossible, because it doesn't inheritAction
frominterfaces.py
. Rules conflict withaction_listen
that is invoked right afterbook_foorm
. Making a wrapper action aroundbook_foorm
and calling it instead of the original form works only in the first time, but then active loop starts to callbook_foorm
instead of my wrapper. -
Confirmation after the form: passing a custom action in
active_loop
afterbook_form
is filled in seems to work, but I found out that Rasa only calls the lastFollowupAction
returned by my custom action, but I want to call multiple actions on each iteration. I also tried to create a custom action that only sets the categorical slotconfirmation_status
with values: "initialized", "confirmed", "rejected" or "fixed". The idea was that stories can handle my logic relying onconfirmation_status
, but they do it poorly or don't do it at all. Two stories were not enough even to just activateaction_extract_confirmation_status
afteractive_loop
was set tonull
, let alone handling all the logic.
So far, the second option seems to be OK if using rules instead of stories. But I need a lot of rules, and they may become a bottleneck in the further development. Coding my logic in python seems much more robust and easier to me, but I can't find a way to do this normally in Rasa.
UPD:
Tried out another approach:
- rule: Activate confirmation loop
steps:
- action: book_form
- slot_was_set:
- requested_slot: null
- active_loop: null
- action: action_extract_confirmation_status
- active_loop: action_extract_confirmation_status
wait_for_user_input: false
- rule: Ask for confirmation the first time
condition:
- active_loop: action_extract_confirmation_status
steps:
- action: action_extract_confirmation_status
- slot_was_set:
- confirmation_status: initialized
- action: utter_introduce_slots
- action: action_utter_slots
- action: utter_ask_for_confirmation
- rule: Ask for confirmation
condition:
- active_loop: action_extract_confirmation_status
steps:
- action: action_extract_confirmation_status
- slot_was_set:
- confirmation_status: fixed
- action: action_utter_slots
- action: utter_ask_for_confirmation
- rule: Ask for correction in confirmation loop
condition:
- active_loop: action_extract_confirmation_status
steps:
- action: action_extract_confirmation_status
- slot_was_set:
- confirmation_status: rejected
- action: utter_ask_for_correction
- rule: Finish confirmation
condition:
- active_loop: action_extract_confirmation_status
steps:
- action: action_extract_confirmation_status
- slot_was_set:
- confirmation_status: confirmed
- active_loop: null
- action: utter_booking_completed
And got another conflict:
- the prediction of the action 'action_utter_slots' in rule 'Ask for confirmation' is contradicting with rule(s) 'handling active loops and forms - action_extract_confirmation_status - action_listen' which predicted action 'action_listen'.
- the prediction of the action 'utter_ask_for_correction' in rule 'Ask for correction in confirmation loop' is contradicting with rule(s) 'handling active loops and forms - action_extract_confirmation_status - action_listen' which predicted action 'action_listen'.
- the prediction of the action 'utter_introduce_slots' in rule 'Ask for confirmation the first time' is contradicting with rule(s) 'handling active loops and forms - action_extract_confirmation_status - action_listen' which predicted action 'action_listen'.
Please update your stories and rules so that they don't contradict each other.
This is so annoying.
答案1
得分: 0
以下是翻译好的代码部分:
async def run(
self,
dispatcher: CollectingDispatcher,
tracker: Tracker,
domain: DomainDict
) -> List[EventType]:
latest_confirmation_status = tracker.get_slot('confirmation_status')
latest_intent = tracker.get_intent_of_latest_message()
latest_entities = tracker.latest_message.get('entities')
logging.debug(f'Latest confirmation status: {latest_confirmation_status}; '
f'Latest intent: {latest_intent}; '
f'Latest entities: {latest_entities}')
if latest_confirmation_status == INACTIVE:
dispatcher.utter_message(response='utter_introduce_slots')
dispatcher.utter_message(format_slot_values(tracker))
dispatcher.utter_message(response='utter_ask_for_confirmation')
return [ActiveLoop(ACTION_NAME), SlotSet("confirmation_status", RUNNING)]
elif latest_confirmation_status == RUNNING:
if latest_entities:
dispatcher.utter_message(format_slot_values(tracker))
dispatcher.utter_message(response='utter_ask_for_confirmation')
return []
elif latest_intent == 'affirm':
dispatcher.utter_message(response='utter_booking_completed')
return [ActiveLoop(None), SlotSet("confirmation_status", COMPLETED)]
elif latest_intent == 'deny':
dispatcher.utter_message(response='utter_ask_for_correction')
return []
else:
logging.warning('Aborted confirmation loop')
return [ActiveLoop(None), SlotSet("confirmation_status", ABORTED)]
else:
raise ValueError(f'Unexpected status: {repr(latest_confirmation_status)}')
- rule: 激活确认循环
steps:
- action: book_form
- slot_was_set:
- requested_slot: null
- active_loop: null
- action: action_confirm
- active_loop: action_confirm
- rule: 中止确认循环
steps:
- slot_was_set:
- confirmation_status: aborted
- active_loop: null
- rule: 完成确认循环
steps:
- slot_was_set:
- confirmation_status: completed
- active_loop: null
英文:
The only way I could do this is to implement everything in a single action, and set this action as an active loop.
async def run(
self,
dispatcher: CollectingDispatcher,
tracker: Tracker,
domain: DomainDict
) -> List[EventType]:
latest_confirmation_status = tracker.get_slot('confirmation_status')
latest_intent = tracker.get_intent_of_latest_message()
latest_entities = tracker.latest_message.get('entities')
logging.debug(f'Latest confirmation status: {latest_confirmation_status}; '
f'Latest intent: {latest_intent}; '
f'Latest entities: {latest_entities}')
if latest_confirmation_status == INACTIVE:
dispatcher.utter_message(response='utter_introduce_slots')
dispatcher.utter_message(format_slot_values(tracker))
dispatcher.utter_message(response='utter_ask_for_confirmation')
return [ActiveLoop(ACTION_NAME), SlotSet("confirmation_status", RUNNING)]
elif latest_confirmation_status == RUNNING:
if latest_entities:
dispatcher.utter_message(format_slot_values(tracker))
dispatcher.utter_message(response='utter_ask_for_confirmation')
return []
elif latest_intent == 'affirm':
dispatcher.utter_message(response='utter_booking_completed')
return [ActiveLoop(None), SlotSet("confirmation_status", COMPLETED)]
elif latest_intent == 'deny':
dispatcher.utter_message(response='utter_ask_for_correction')
return []
else:
logging.warning('Aborted confirmation loop')
return [ActiveLoop(None), SlotSet("confirmation_status", ABORTED)]
else:
raise ValueError(f'Unexpected status: {repr(latest_confirmation_status)}')
- rule: Activate confirmation loop
steps:
- action: book_form
- slot_was_set:
- requested_slot: null
- active_loop: null
- action: action_confirm
- active_loop: action_confirm
- rule: Abort confirmation loop
steps:
- slot_was_set:
- confirmation_status: aborted
- active_loop: null
- rule: Complete confirmation loop
steps:
- slot_was_set:
- confirmation_status: completed
- active_loop: null
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论