List Slot - Append instead of override

Hello!

When I started working on our bot, the List Slot could only store one entry, now I’m trying to change my code to use a List Slot instead of multiple slots with true/false values.

I got the following code to test the behavior of the List-Slot.

Domain:

intents:
  - start
  - greet
  - goodbye
  - affirm
  - deny
  - mood_great
  - mood_unhappy

actions:
- utter_greet
- utter_cheer_up
- utter_did_that_help
- utter_happy
- utter_goodbye
- action_show_list

slots:
   cats:
      type: list

entities:
  - cats

templates:
  utter_greet:
  - text: "Gib mir Keywords!"

  utter_cheer_up:
  - text: "Here is something to cheer you up:"
    image: "https://i.imgur.com/nGF1K8f.jpg"

  utter_did_that_help:
  - text: "Did that help you?"

  utter_happy:
  - text: "Great carry on!"

  utter_goodbye:
  - text: "Bye"

Story:

happy path

* start
  - utter_greet
* mood_great
  - action_show_list


## happy path
* start
  - utter_greet
* mood_great
  - action_show_list
* mood_great
  - action_show_list
* mood_great
  - action_show_list

## happy path
* start
  - utter_greet
* mood_great
  - action_show_list
* mood_great
  - action_show_list

NLU:

## intent:mood_great
- Wir Fünf wollen uns ersteinmal [Kennenlernen](cats:kat_kennenlernen)
- Unser Projekt benötigt [Geld](cats:kat_finanzierungsideen) um zu starten.
- Es gibt [neue](cats:kat_neue_integrieren) Mitglieder in der Gruppe, die wir erst noch [kennenlernen](cats:kat_kennenlernen) müssen.
- Unser [Bürgermeister](cats:kat_beziehung_politik) stellt sich uns in den Weg.
- Wie können wir unser [Vorhaben](cats:kat_vision) [nachhaltig](cats:kat_nachhaltigkeit) gestalten?
- Wie können wir unser [Vorhaben](cats:kat_vision) im Einklang mit der [Umwelt](cats:kat_nachhaltigkeit) umsetzen?
- Es gibt so [viel zu tun](cats:kat_aufgabenverteilung), wie sollen wir wissen, [welches Problem](cats:kat_themenauswahl) wir zu erst angehen sollen?
- Wie sollen wir die [Aufgaben](cats:kat_aufgabenverteilung) verteilen?
- Wie sollen wir die [Aufgaben verteilen](cats:kat_aufgabenverteilung) ?
- [Welchen](cats:kat_entscheidungen_optionen) Weg sollen wir gehen?
- Wie finde ich [neue](cats:kat_neue_integrieren) Unterstützer für unser Projekt?
- Wie finde ich [neue Unterstützer](cats:kat_neue_integrieren) in unserer [Gemeinde](cats:kat_beziehung_politik)?
- Wie finde ich [neue Unterstützer](cats:kat_neue_integrieren) für unser Projekt?
- Wie finde ich neue [Unterstützer](cats:kat_beziehung_politik) für unser Projekt?
- Die Strukturen in der [Gemeindeverwaltung](cats:kat_beziehung_politik) machen es uns schwer, [Konsensentscheidungen](cats:kat_entscheidungen_optionen) zu finden
- Wir brauchen [Ideen](cats:kat_vision) um unsere [Gemeindevertreter](cats:kat_beziehung_politik) zu überzeugen.
- Wie ziehen wir [Entscheidungsträger](cats:kat_beziehung_politik) auf unsere Seite?
- Wie gewinnen wir die [Politik](cats:kat_beziehung_politik) Politik für unser Anliegen?
- Wie gewinnen wir den [Gemeinderat](cats:kat_beziehung_politik) Politik für unser Anliegen?
- Wir brauchen Hilfe bei der [Ideenfindung](cats:kat_vision)
- Wie kommen wir zu einer [Entscheidung](cats:kat_entscheidungen_optionen)
- Wie können wir unsere [Abstimmung](cats:kat_entscheidungen_optionen) optimal vorbereiten?
- [Verein](cats:kat_beziehung_politik)
- Wie lassen sich Stärken und [Ideen](cats:kat_vision) aller [Gemeindevertreter](cats:kat_beziehung_politik) bündeln
- Wie kann ich [Mitstreiter](cats:kat_kennenlernen) gewinnen?
- Wie können wir [Konflikte](cats:kat_entscheidungen_optionen) bewältigen?
- Wie bekommen wir [Geld](cats:kat_finanzierungsideen) für unser [Vorhaben](cats:kat_vision)?
- Wie können wir [Geld erwirtschaften](cats:kat_finanzierungsideen) ?
- Wie können wir [Geld](cats:kat_finanzierungsideen) erwirtschaften?
- Wie können wir Geld [erwirtschaften](cats:kat_finanzierungsideen) ?
- wie können wir neue [Businesspläne](cats:kat_finanzierungsideen) entwickeln?
- Wir wollen die [Umwelt](cats:kat_nachhaltigkeit) retten
- unsere [Dorfgemeinschaft](cats:kat_themenauswahl) braucht Hilfe
- wir wollen [Feste](cats:kat_aufgabenverteilung) feiern
- Wie können wir [Veranstaltungen](cats:kat_aufgabenverteilung) organisieren
- Wie können wir Veranstaltungen [organisieren](cats:kat_aufgabenverteilung)
- Wie [strukturieren](cats:kat_themenauswahl) wir die [Versammlung](cats:kat_aufgabenverteilung)?

Custom Action:

from typing import Any, Text, Dict, List
from rasa_sdk import Action, Tracker
from rasa_sdk.executor import CollectingDispatcher
import pprint
# This files contains your custom actions which can be used to run
# custom Python code.
#
# See this guide on how to implement these action:
# https://rasa.com/docs/rasa/core/actions/#custom-actions/


# This is a simple example for a custom action which utters "Hello World!"

class ActionShowList(Action):
    def name(self) -> Text:
        return "action_show_list"

    def run(self, dispatcher: CollectingDispatcher,
                     tracker: Tracker,
                      domain: Dict[Text, Any]) -> List[Dict[Text, Any]]:
         dispatcher.utter_message(pprint.pformat(tracker.get_slot("cats"), indent=4))

         return []

I started the bot and had following conversation:

My Questions are:

  • is it right, that the List Slot only represents entities extracted from the last user message?
  • is there a way to change the behavior, to append the entities instead of overriding?

Slots in general get filled with only the latest user message. If you want to append entities to your slot, then you should do this in a custom action by naming your slot differently to your entities

Hi, I am having the same problem, is there another way to do that now?

no, you still have to do this in a custom action atm i believe

Has this been changed in recent updates?

Has anybody implemented the custom action solution and willing to share code?

3 Likes

@akelad may you share the action code for appending slots ?

I had a similar problem where inside a form if a had the same intent that triggered the form without any entity it override my slot with an empty list. I fixed this with a custom mapping and two slots:

async def extract_slotform(self, dispatcher, tracker, domain):
    val = tracker.get_slot("slotform")
    nval = tracker.get_slot("slotentity")
    if val is None:
        val = []
    for n in nval:
        if n not in val:
            val.append(n)
    if not val:
        return {'slotform': None}
    return {'slotform': val}