Filling and custom validating slots from button payloads inside a form action

Issue. I’m very new to coding and Rasa, so please forgive me if I use imprecise or incorrect terminology. I have been facing an issue when trying to fill and custom validate slots from button payloads inside a form action (I’ve had no issues with typed input). It seems that the button payloads are being passed literally to the slot. This in turns causes the validation action to treat it as invalid input. See below excerpts of 1) the form action in the domain file, 2) the slot definition in the domain file, 3) the relevant utterance and buttons in the domain file, 4) the custom validation action in the actions file and, 5) the debug log.

I have been able to work around the issue (see the end of this post), however I’m not sure if the workaround is sustainable, so would welcome any thoughts on getting button payloads right inside form actions.

  1. Domain (forms):
forms:
  compare_price_form:
    required_slots:
      product:
      - type: from_text
  1. Domain (slots):
slots:
  product:
    type: any
    influence_conversation: false
  1. Domain (responses):
responses:
  utter_ask_compare_price_form_product:
  - text: Queres saber o preço mais baixo de qual produto da cesta básica?
    buttons:
    - title: Arroz
      payload: /ask_price_product{{"product":"arroz"}}
    - title: Feijão
      payload: /ask_price_product{{"product":"feijao"}}
  1. Actions:
class ValidateComparePriceForm(FormValidationAction):
    
    def name(self) -> Text:
        return "validate_compare_price_form"

    def validate_product(
        self,
        slot_value: Any,
        dispatcher: CollectingDispatcher,
        tracker: Tracker,
        domain: DomainDict,
    ) -> Dict[Text, Any]:

        listed_product = ['arroz', 'feijao']

        if slot_value not in listed_product:
        	dispatcher.utter_message(text = f"Por enquanto só procuro o melhor preço de %s e %s . Mas vou ver se um dia adiciono isto!" % tuple(listed_product))
        	return {"product": None}
        else:
        	return {"product": slot_value}
  1. Debug log:

Workaround. I have been able to get around the issue for now by stripping the button payloads down to the literal desired text input, however I can’t find any support for this approach in the documentation and am worried that it will cause unexpected issues down the line. Is this a valid approach or should I be trying something else? Any thoughts greatly appreciated! See below the workaround in the utterance and buttons in the domain file, which for now seems to work

Domain:

responses:
  utter_ask_compare_price_form_product:
  - text: Queres saber o preço mais baixo de qual produto da cesta básica?
    buttons:
    - title: Arroz
      payload: arroz
    - title: Feijão
      payload: feijao

In this particular case, the intent is ask_price_product and the entity is arroz. Since arroz is the entity of interest, wouldn’t it be better to base the slot value on that?

I think this change in domain.yml ought to do it.

forms:
  compare_price_form:
    required_slots:
      product:
      - type: from_entity
1 Like

Thanks. I had previously mapped the slot from_entity and had still experienced the same issue (but other details of the setup were different so I can’t isolate it to the slot mapping). I might be muddying the water here, but have also started upgrading to Rasa 3x, and will subsequently try your suggestion as so:

slots:
  product:
    type: text
    mappings:
    - type: from_entity
      entity: product

On the apparent issue of the button payload being passed literally to the slot when a form is active, do you think that mapping the slot from_entity will change that behaviour?

It’s hard to say for sure, but I’d imagine that no longer using from_text should fix most of it.

Thanks. I’ll try it and report back.

Hi @koaning, doing as you suggested worked, after updating and migrating to Rasa v3.

After updating, I made the following changes to domain (slots, forms):

  1. Domain (slots):
slots:
  product:
    type: text
    influence_conversation: false
    mappings:
    - type: from_entity
      entity: product
  1. Domain (forms):
forms:
  price_info_form:
    required_slots:
    - product

Interestingly, either of the following payloads now works inside an active form:

responses:
  utter_ask_compare_price_form_product:
  - text: Queres saber o preço mais baixo de qual produto da cesta básica?
    buttons:
    - title: Arroz 
      payload: /ask_price{{"product":"arroz"}}
    - title: Feijão 
      payload: /ask_price{{"product":"feijao"}}

OR

responses:
  utter_ask_compare_price_form_product:
  - text: Queres saber o preço mais baixo de qual produto da cesta básica?
    buttons:
    - title: Arroz
      payload: arroz
    - title: Feijão
      payload: feijao