In dieser mehrteiligen Blog-Serie wird ein KI gesteuerter Chatbot auf Basis von RASA erstellt, welcher mit einer Matrix42 ESM Instanz verbunden ist.
Der Bot soll dabei in einer ersten Version folgende Anforderungen erfüllen:
- Eröffnen von Tickets direkt über den Bot
- Hilfestellung mittels Abfrage der M42 KB
- Bestellen von Services aus dem Service-Katalog
- MS Teams Integration
- WhatsApp / SMS Integration
Rasa
Bei Rasa handelt es sich um ein OpenSource Bot Framework.
Rasa verwendet dabei maschinelles Lernen, um:
- zu erkennen, was der Benutzer erreichen möchte (Intent-Erkennung, Natural Language Understanding NLU)
- die dazu passende Aktion oder Antwort auszuwählen (Dialogmanagement)
Durch das maschinelle Lernen kann ein mit Rasa erstellter Chatbot auch mit neuen, bisher unbekannten Benutzereingaben zurechtkommen.
Mehr Informationen zu Rasa gibt es direkt auf der Rasa Website
Setting up your environment (rasa.com)
Rasa Konfiguration
Nach der Initialisierung von Rasa werden automatisch alle benötigten Dateien angelegt. Folgende Dateien sind nun relevant für das Trainieren des Chatbots:
| File | Zweck |
| data\nlu.yml | Beispiele für mögliche Benutzereingaben (intents, entities) |
| data\rules.yml | feste Regeln für Dialogverläufe |
| data\stories.yml | Beispiele für Dialogverläufe |
| domain.yml | Enthält die Sprachäusserungen (responses, utterances), die der Chatbot produzieren kann, und listet die Aktionen auf, welche der Chat auslösen kann. |
| credentials.yml | Zugangsdaten für externe Provider (Slack, Teams etc.) |
| endpoints.yml | Schnittstellen, auf welche der Chatbot im Betrieb zugreifen kann |
| actions/actions.py | Aktionen welche ausgeführt werden können |
Use Cases – Ticket eröffnen & FAQ abrufen
Das Vorgehen für das Abbilden der Use Cases ist prinzipiell immer dasselbe:
Trainingsdaten erfassen in der nlu.yml:

domain.yml anpassen, sowie entsprechende Stories oder Rules erstellen. In diesem Fall möchten wir den Bot dazu bringen, für das Erstellen der Tickets ein sogenanntes «Form» abzufüllen – dabei müssen definierte entities innerhalb der Konversation mit Daten gefüllt werden. Im Falle des Tickets sind dies in diesem Beispiel eine Kurz-Beschreibung, eine detailliertere Beschreibung sowie eine Bestätigung. In der domain.yml werden auch die responses definiert, welche wir in den Stories oder Rules benutzen können. Rasa kennt dabei verschiedene Typen, wie Text, Buttons oder Bilder. Zuletzt werden in der Domain.yml auch die Actions definiert, welche beliebig programmiert werden können.
version: '3.1'
intents:
- affirm
- bot_challenge
- greet
- ich_habe_ein_problem
- mood_great
- nlu_fallback
- open_ticket:
use_entities: []
- out_of_scope
- help
- deny
- goodbye
entities:
- ticket_title
- ticket_description
- confirm
slots:
ticket_title:
type: text
influence_conversation: false
mappings:
- type: from_text
conditions:
- active_loop: open_ticket_form
requested_slot: ticket_title
ticket_description:
type: text
influence_conversation: false
mappings:
- type: from_text
conditions:
- active_loop: open_ticket_form
requested_slot: ticket_description
confirm:
type: bool
influence_conversation: false
mappings:
- type: from_intent
intent: affirm
value: true
conditions:
- active_loop: open_ticket_form
requested_slot: confirm
- type: from_intent
intent: deny
value: false
conditions:
- active_loop: open_ticket_form
requested_slot: confirm
forms:
open_ticket_form:
required_slots:
- ticket_title
- ticket_description
- confirm
responses:
utter_out_of_scope:
- text: Sorry, dabei kann ich dir leider nicht weiterhelfen..
utter_greet:
- text: Hey! Wie kann ich Dir helfen?
buttons:
- title: Technical Support
payload: /open_ticket
- title: Status open Requests
payload: /help_status_open
- title: Order Something
payload: /help_order
utter_did_that_help:
- text: |-
Hatt dir das weitergeholfen?
buttons:
- title: Ja
payload: /affirm
- title: Nein
payload: /deny
utter_happy:
- text: Super - mach weiter so!
- text: Freut mich zu hören!
utter_goodbye:
- text: Tschüss
utter_iamabot:
- text: Ich bin MrAnderson.
utter_ask_rephrase:
- text: Sorry, ich habe dich nicht verstanden. Kannst du das bitte umformulieren?
utter_ask_confirm:
- text: |-
Soll ich ein Ticket mit folgenden Angaben erstellen?
Betreff: {ticket_title}
Details: {ticket_description}
buttons:
- title: Ja
payload: /affirm
- title: Nein, Abbrechen
payload: /deny
utter_ticket_creation_canceled:
- text: Alles klar - die Anfrage wurde abgebrochen.
utter_ask_whatelse:
- text: Kann ich dir sonst noch irgendwie helfen?
utter_ask_ticket_title:
- text: Bitte beschreibe kurz um was es geht
utter_ask_ticket_description:
- text: Bitte beschreibe deine Anfrage detailiert
utter_no_email:
- text: Sorry, deine Email wurde nicht im System gefunden.
actions:
- action_open_incident
- action_query_faq
Damit der Bot nun weiss, was er bei einem bestimmten Intent zu tun hat, müssen entsprechende Stories erfasst werden. Für die beiden Use Cases, könnten diese z. B. so aussehen:
- story: open ticket interactive story 1
steps:
- intent: greet
- action: utter_greet
- intent: open_ticket
- action: open_ticket_form
- active_loop: open_ticket_form
- slot_was_set:
- requested_slot: ticket_title
- slot_was_set:
- ticket_title: Mein Drucker geht nicht mehr
- slot_was_set:
- requested_slot: ticket_description
- slot_was_set:
- ticket_description: Seit gestern ist mein Drucker nicht mehr nutzbar, bitte um Hilfe
- slot_was_set:
- requested_slot: null
- active_loop: null
- action: action_open_incident
- story: FAQ
steps:
- intent: ich_habe_ein_problem
- action: action_query_faq
- action: utter_did_that_help
- intent: affirm
Der Bot ist nun so weit vorbereitet, dass er trainiert werden kann

Nach erfolgreichem Training kann er im API Modus gestartet werden

Actions
RASA hat bereits einen Action-Server integriert, welcher es ermöglicht, eigene Logik z. B. um externe APIs abzurufen einzubinden. Es gäbe auch die Möglichkeit, andere Endpoints als Action Server zu nutzen, beispielsweise Node-Red welches ein sehr mächtiges Open-Source No-Code-Tool für die Erstellung von Schnittstellen anbietet (Kann z. B. auch als API-Gateway und Field-Mapper benutzt werden. Dazu mehr in einem anderen Post).
Der Standard Action Server von Rasa kann mittels Python erweitert werden. Für den Fall für die Verbindung mit Matrix42 habe ich angefangen, eine eigene M42-Python Klasse zu bauen. Wer die Arbeit mit der M42 API kennt weiss, dass diese doch einige Eigenheiten mit sich bringt.
Die Authentifizierung an M42 bzw. Erkennung des Users wird in diesem Beispiel direkt anhand der von Teams mitgegebenen Credentials (E-Mail) durchgeführt. Das System prüft also, ob die E-Mail des Users, welcher aus Teams heraus mit dem Bot kommuniziert, im Matrix42 hinterlegt ist und holt sich die entsprechende userid für weitere Aktionen im Namen des users ab.

Der Action Aufruf für das Erstellen eines Incidents würde so aussehen – dabei wird die Logik für das Erstellen des Tickets von der zuvor erwähnten M42-Python Klasse übernommen.
#Auszug aus Action.py
class ActionOpenIncident(Action):
def name(self) -> Text:
return "action_open_incident"
def run(
self,
dispatcher: CollectingDispatcher,
tracker: Tracker,
domain: Dict[Text, Any],
) -> List[Dict]:
"""Create an incident and return TicketNumber.
"""
try:
user_information_str = tracker.sender_id
user_information_str_dict = eval(user_information_str)
email = user_information_str_dict.get("email")
except:
dispatcher.utter_message(f"Sorry - du scheinst nicht in Teams angemeldet zu sein. Bitte melde dich an und versuche es erneut.")
logger.debug("Error: No Teams user information found")
return [AllSlotsReset()]
ticket_description = tracker.get_slot("ticket_description")
ticket_title = tracker.get_slot("ticket_title")
confirm = tracker.get_slot("confirm")
if not confirm:
dispatcher.utter_message(
response="utter_incident_creation_canceled"
)
return [AllSlotsReset()]
response = m42.create_ticket(
description=ticket_description,
short_description=ticket_title,
email=email,
)
ticket_number = response
if ticket_number:
message = (
f"Ticket mit der Nummer {ticket_number} "
f"wurde erfolgriech erstellt. Es wird sich so schnell wie möglich jemand um dein Anliegen kümmern."
)
else:
message = (
f"Bei erstellen des Tickets ist ein Fehler aufgetreten. "
f"{response.get('error')}"
)
dispatcher.utter_message(message)
return [AllSlotsReset()]
#Auszug aus M42Api - Klasse
def create_ticket(
self, description, short_description, email
) -> Dict[Text, Any]:
result = self.email_to_userid(email)
user_id = result.get("user_id")
if user_id:
ticket_url = f"{self.base_api_url}/ticket/Create?activityType=5"
data = {
"JournalEntry": {
"Publish": 1,
"Comments": description,
"EntryType": 0,
"Creator": user_id,
"VisibleInPortal": 1,
"SkipRaiseCoRuEvent": 1,
},
"Subject": short_description,
"Description": description,
"User": user_id,
"Creator": user_id,
}
token = self.get_accesstoken()
headers = {
"Authorization": "Bearer " + token,
"Content-Type": "application/json"
}
request_args = {
"url": ticket_url,
"headers": headers,
"data": json.dumps(data),
}
result = self.handle_request(requests.post, request_args)
ticket_number = self.get_ticketNumber(result["content"])
return ticket_number
Teams Integration
Damit ein Bot mit Teams kommunizieren kann, muss auf das MS-Botframework zurückgegriffen werden. Dabei muss in einem ersten Schritt eine neue Teams-App erstellt werden (Developer Portal (microsoft.com))

Die App benötigt einige Basisinformationen wie Name, Beschreibung etc.
Unter «App Features» kann nun ein Bot hinzugefügt werden:

Wichtig ist es, hier dem Bot die entsprechende Endpoint-Adresse anzugeben – dies ist die URL, unter welcher der Rasa Bot von aussen erreichbar ist (Falls es sich um eine lokale Testinstallation handelt, hilft hier ngrok weiter). In meinem Fall wäre dies z.B. https://XXXX.eu.ngrok.io/webhooks/botframework/webhook.
Nun müssen nur noch in der Rasa Credentials.yml das botframework mit entsprechender app_id und Passwort hinterlegt werden:

Ergebnis
In einer ersten Iteration kann der Bot nun mittels MS Teams kommunizieren, sowie erkennen, ob ein User ein Ticket erstellen möchte oder ein FAQ Artikel anbieten. (Bitte Schreibfehler ignorieren 🥸)
Damit ein Chatbot auch wirklich gut wird, muss er von normalen Anfragen von Usern stetig lernen. Rasa bietet dafür eine Enterprise Version an, welche mit einem entsprechenden UI die Analyse sowie das weitere Training des Bots stark vereinfacht.
Der gesamte Code ist unter Github einsehbar.
Weitere Schritte
Optimierung Teams Integration
Integration Whatsapp/SMS
Optimierung/Erweiterung Stories
Abfrage offene Tickets
Service Bestellung