Benutzerdefinierte Komponenten implementieren

Um benutzerdefinierte Komponenten zu implementieren, verwenden Sie das Oracle Digital Assistant Node.js-SDK für die Schnittstelle mit dem benutzerdefinierten Komponentenservice von Digital Assistant.

So implementieren Sie benutzerdefinierte Komponenten, die Sie im eingebetteten Container von Digital Assistant, in Oracle Cloud Infrastructure Functions, in einem Mobile Hub-Backend oder auf einem Node.js-Server bereitstellen können:

  1. Installieren Sie die Software zum Erstellen benutzerdefinierter Komponenten.

  2. Erstellen Sie das benutzerdefinierte Komponentenpackage.

  3. Erstellen Sie eine benutzerdefinierte Komponente.

Hinweis

Wenn Sie das benutzerdefinierte Komponentenpackage in einem eingebetteten benutzerdefinierten Komponentenservice bereitstellen möchten, zählt jeder Skill, dem Sie das Package hinzufügen, als separater Service. Die zulässige Anzahl eingebetteter benutzerdefinierter Komponentenservices einer Instanz ist begrenzt. Wenn Sie das Limit nicht kennen, bitten Sie den Serviceadministrator, den Parameter embedded-custom-component-service-count für Sie abzurufen, wie unter Servicelimits in der Infrastructure-Konsole anzeigen beschrieben. Ziehen Sie in Erwägung, mehrere Komponenten pro Package zu verpacken, um die Anzahl der von Ihnen verwendeten eingebetteten Komponentenservices zu minimieren. Wenn Sie versuchen, einen Komponentenservice hinzuzufügen, nachdem Sie dieses Limit erreicht haben, verläuft das Erstellen des Service nicht erfolgreich.

Schritt 1: Software für das Erstellen von benutzerdefinierten Komponenten installieren

Zur Erstellung eines benutzerdefinierten Komponentenpackages benötigen Sie Node.js, Node Package Manager und das Oracle Digital Assistant Bots-Node.js-SDK.

Hinweis

Unter Windows funktioniert das Bots-Knoten-SDK nicht unter Windows, wenn die Knoteninstallation Version 20.12.2 oder höher ist, da eine abwärtsinkompatible Änderung in Node.js vorliegt. Wenn die Node-Version 20.12.2 oder höher bereits installiert ist, müssen Sie sie deinstallieren und dann Version 20.12.1 oder eine frühere Version installieren, damit das Bots Node SDK funktioniert.
  1. Wenn Sie Node.js noch nicht heruntergeladen haben, laden Sie es von https://nodejs.org herunter, und installieren Sie es für den globalen Zugriff. Node Package Manager (npm) wird mit Node.js bereitgestellt.

    Um zu testen, ob Node.js und npm installiert sind, öffnen Sie ein Terminalfenster, und geben Sie die folgenden Befehle ein:

    node –v 
    npm –v
  2. Um das Oracle Digital Assistant Bots-Node.js-SDK für den globalen Zugriff zu installieren, geben Sie diesen Befehl in einem Terminalfenster ein:
    npm install -g @oracle/bots-node-sdk

    Verwenden Sie auf einem Mac den sudo-Befehl:

    sudo npm install -g @oracle/bots-node-sdk

    Wenn Sie die Option -g (global) verwenden, haben Sie direkten Zugriff auf die bots-node-sdk-Befehlszeilenschnittstelle. Verwenden Sie andernfalls npx @oracle/bots-node-sdk.

  3. Um Ihre Oracle Digital Assistant Bots-Node.js-SDK-Installation zu prüfen, geben Sie den folgenden Befehl ein:
    bots-node-sdk -v
    Der Befehl gibt die Version des Oracle Digital Assistant Bots-Node.js-SDK aus.

Schritt 2: Benutzerdefiniertes Komponentenpackage erstellen

Um ein Projekt zu starten, verwenden Sie den Befehl bots-node-sdk init über die Befehlszeilenschnittstelle (CLI) des SDK, um die erforderlichen Dateien und die Verzeichnisstruktur für die Komponentenstruktur zu erstellen.

Der Befehl init bietet einige Optionen, z.B. zur Verwendung von JavaScript (Standard) oder TypeScript sowie zur Angabe des Namens der JavaScript-Datei der anfänglichen Komponente. Diese Optionen werden unter CLI-Entwicklertools beschrieben. Nachfolgend finden Sie den Basisbefehl zum Starten eines JavaScript-Projekts:

bots-node-sdk init <top-level folder path> --name <component service name>

Dieser Befehl führt die folgenden Aktionen für ein JavaScript-Package aus:

  • Erstellt den Ordner der obersten Ebene.

  • Erstellt einen components-Ordner und fügt eine JavaScript-Beispielkomponentendatei mit dem Namen hello.world.js hinzu. Hier speichern Sie Ihre JavaScript-Komponentendateien.

  • Fügt eine package.json-Datei hinzu, die main.js als Haupteinstiegspunkt angibt und @oracle/bots-node-sdk als devDependency auflistet. Die Packagedatei verweist auch auf einige bots-node-sdk-Skripte.

    {
      "name": "myCustomComponentService",
      "version": "1.0.0",
      "description": "Oracle Bots Custom Component Package",
      "main": "main.js",
      "scripts": {
        "bots-node-sdk": "bots-node-sdk",
        "help": "npm run bots-node-sdk -- --help",
        "prepack": "npm run bots-node-sdk -- pack --dry-run",
        "start": "npm run bots-node-sdk -- service ."
      },
      "repository": {},
      "dependencies": {},
      "devDependencies": {
        "@oracle/bots-node-sdk": "^2.2.2",
        "express": "^4.16.3"
      }
    }
  • Fügt eine main.js-Datei hinzu, die die Packageeinstellungen exportiert und auf den Komponentenordner für den Speicherort der Komponenten und den Ordner der obersten Ebene verweist.

  • Fügt dem Ordner der obersten Ebene eine .npmignore-Datei hinzu. Diese Datei wird verwendet, wenn Sie das Komponentenpackage exportieren. Sie muss .tgz-Dateien aus dem Package ausschließen. Beispiel: *.tgz.

  • Bei einigen Versionen von npm wird eine package-lock.json-Datei erstellt.

  • Installiert alle Packageabhängigkeiten im Unterordner node_modules.
Hinweis

Wenn Sie den Packageordner nicht mit dem Befehl bots-node-sdk init erstellen, stellen Sie sicher, dass der Ordner der obersten Ebene eine .npmignore-Datei mit einem *.tgz-Eintrag enthält. Beispiel:
*.tgz
spec
service-*

Andernfalls fügen Sie jedes Mal, wenn Sie die Dateien in eine TGZ-Datei verpacken, die TGZ-Datei ein, die bereits im Ordner der obersten Ebene vorhanden ist, sodass Ihre TGZ-Datei kontinuierlich ihre Größe verdoppelt.

Wenn Sie das Deployment im eingebetteten Container planen, muss das Package mit Knoten 14.17.0 kompatibel sein.

Schritt 3: Benutzerdefinierte Komponente erstellen

Komponentendatei erstellen

Mit dem CLI-Befehl init component des SDK können Sie eine JavaScript- oder TypeScript-Datei mit dem Framework erstellen. Dann können Sie mit dem Node.js-SDK von Oracle Digital Assistant eine benutzerdefinierte Komponente schreiben. Die Sprache, die Sie beim Ausführen des init-Befehls zum Erstellen des Komponentenpackages angegeben haben, bestimmt, ob eine JavaScript- oder TypeScript-Datei erstellt wird.

Beispiel: Um eine Datei für die benutzerdefinierte Komponente zu erstellen, wechseln Sie in einem Terminalfenster mit CD zum Ordner der obersten Ebene des Packages, und geben Sie den folgenden Befehl ein. Ersetzen Sie dabei <component name> durch den Namen der Komponente:

bots-node-sdk init component <component name> c components

Bei JavaScript fügt dieser Befehl <component name>.js zum components-Ordner hinzu. Bei TypeScript wird die Datei dem Ordner src/components hinzugefügt. Das Argument c gibt an, dass die Datei für eine benutzerdefinierte Komponente gilt.

Beachten Sie, dass der Komponentenname nicht länger als 100 Zeichen sein darf. Sie können nur alphanumerische Zeichen und Unterstriche im Namen verwenden. Bindestriche sind nicht zulässig. Der Name darf auch nicht das Präfix System. aufweisen. Oracle Digital Assistant lässt nicht zu, dass Sie einen benutzerdefinierten Komponentenservice mit ungültigen Komponentennamen hinzufügen.

Weitere Details finden Sie unter https://github.com/oracle/bots-node-sdk/blob/master/bin/CLI.md.

Code zu Metadaten hinzufügen und Funktionen aufrufen

Die benutzerdefinierte Komponente muss zwei Objekte exportieren:

  • metadata: Gibt die folgenden Komponenteninformationen für den Skill an.
    • Komponentenname
    • Unterstützte Eigenschaften
    • Unterstützte Übergangsaktionen

    Bei YAML-basierten Dialogabläufen unterstützt die benutzerdefinierte Komponente standardmäßig die folgenden Eigenschaften. Diese Eigenschaften sind für Skills, die im visuellen Dialogmodus entworfen wurden, nicht verfügbar.

    • autoNumberPostbackActions: Boolescher Wert. Nicht erforderlich. Bei true werden Schaltflächen und Listenoptionen automatisch nummeriert. Der Standardwert ist false. Siehe Automatische Nummerierung von Nur-Text-Kanälen in YAML-Dialogabläufen.
    • insightsEndConversation: Boolescher Wert. Nicht erforderlich. Bei true wird die Aufzeichnung der Unterhaltung für Insight-Berichte gestoppt. Der Standardwert ist false. Siehe Dialogablauf modellieren.
    • insightsInclude: Boolescher Wert. Nicht erforderlich. Bei true wird der Status in Insight-Berichte einbezogen. Der Standardwert ist true. Siehe Dialogablauf modellieren.
    • translate: Boolescher Wert. Nicht erforderlich. Bei true ist die automatische Übersetzung für diese Komponente aktiviert. Der Standardwert ist der Wert der Kontextvariablen autotranslation. Siehe Übersetzungsservices in Skills.
  • invoke: Enthält die auszuführende Logik. Bei dieser Methode können Sie Skillkontextvariablen lesen und schreiben, Unterhaltungsnachrichten erstellen, Statusübergänge festlegen, REST-Aufrufe tätigen usw. Normalerweise würden Sie das Schlüsselwort async mit dieser Funktion verwenden, um Promises zu verarbeiten. Die Funktion invoke akzeptiert das folgende Argument:
    • context mit Angabe der Referenz zum Objekt CustomComponentContext im Node.js-SDK von Digital Assistant. Diese Klasse wird in der SDK-Dokumentation unter https://oracle.github.io/bots-node-sdk/ beschrieben. In früheren Versionen des SDK lautete der Name conversation. Sie können einen der beiden Namen verwenden.
    Hinweis

    Wenn Sie eine JavaScript-Bibliothek verwenden, die keine Promises unterstützt (und daher nicht das Schlüsselwort async verwendet), können Sie auch ein done-Argument als Callback hinzufügen, das die Komponente aufruft, wenn die Verarbeitung abgeschlossen ist.

Beispiel:

'use strict';

module.exports = {

  metadata: {
    name: 'helloWorld',
    properties: {
      human: { required: true, type: 'string' }
    },
    supportedActions: ['weekday', 'weekend']
  },

  invoke: async(context) => {
    // Retrieve the value of the 'human' component property.
    const { human } = context.properties();
    // determine date
    const now = new Date();
    const dayOfWeek = now.toLocaleDateString('en-US', { weekday: 'long' });
    const isWeekend = [0, 6].indexOf(now.getDay()) > -1;
    // Send two messages, and transition based on the day of the week
    context.reply(`Greetings ${human}`)
      .reply(`Today is ${now.toLocaleDateString()}, a ${dayOfWeek}`)
      .transition(isWeekend ? 'weekend' : 'weekday');   
  }
}

Weitere Informationen und einige Codebeispiele finden Sie unter Benutzerdefinierte Komponenten schreiben in der Dokumentation zum Bots Node-SDK.

Ablauf mit "keepTurn" und "transition" steuern

Sie verwenden verschiedene Kombinationen der Bots Node SDK-Funktionen keepTurn und transition, um zu definieren, wie die benutzerdefinierte Komponente mit einem Benutzer interagiert und wie die Unterhaltung fortgesetzt wird, nachdem die Komponente die Ablaufsteuerung wieder an den Skill übergeben hat.

  • keepTurn(boolean) gibt an, ob die Unterhaltung in einen anderen Status übergehen soll, ohne den Benutzer zuerst zur Eingabe aufzufordern.

    Wenn Sie keepTurn auf "true" setzen möchten, sollten Sie keepTurn nach reply aufrufen, weil reply die keepTurn-Funktion implizit auf false setzt.

  • transition(action) bewirkt, dass der Dialog nach dem Senden aller etwaiger Antworten in den nächsten Status übergeht. Das optionale action-Argument benennt die jeweilige von der Komponente zurückgegebene Aktion (Ergebnis).

    Wenn Sie transition() nicht aufrufen, wird die Antwort gesendet, der Dialog bleibt jedoch im Status, und die nachfolgende Benutzereingabe kehrt zu dieser Komponente zurück. Das bedeutet, dass invoke() erneut aufgerufen wird.

invoke: async (context) ==> {
   ...
   context.reply(payload);
   context.keepTurn(true);
   context.transition ("success"); 
}

Im Folgenden finden Sie einige häufige Anwendungsfälle, in denen Sie den Dialogablauf mit keepTurn und transition steuern können:

Anwendungsfall Für keepTurn und transition festgelegte Werte

Eine benutzerdefinierte Komponente, die in einen anderen Status übergeht, ohne den Benutzer zuerst zur Eingabe aufzufordern.

  1. Verwenden Sie gegebenenfalls context.reply(<reply>), um eine Antwort zu senden.

  2. Legen Sie context.keepTurn(true) fest.

  3. Legen Sie context.transition mit einer supportedActions-Zeichenfolge (Beispiel: context.transition("success")) fest, oder verwenden Sie kein Argument (Beispiel: context.transition()).

Beispiel: Diese benutzerdefinierte Komponente aktualisiert eine Variable mit einer Werteliste, die sofort im nächsten Status im Dialogablauf angezeigt werden soll.
invoke: async (context) => {
    const listVariableName = context.properties().variableName;
    ...
    // Write list of options to a context variable
    context.variable(listVariableName, list);
   // Navigate to next state without 
   // first prompting for user interaction.
   context.keepTurn(true);
   context.transition();
 }

Eine benutzerdefinierte Komponente, mit der der Skill auf die Eingabe warten kann, nachdem die Steuerung an ihn zurückgegeben wurde und bevor er in einen anderen Status übergeht.

  1. Verwenden Sie gegebenenfalls context.reply(<reply>), um eine Antwort zu senden.

  2. Legen Sie context.keepTurn(false) fest.

  3. Legen Sie context.transition mit einer supportedActions-Zeichenfolge (context.transition("success")) fest, oder verwenden Sie keine Argumente (context.transition()).

Beispiel:
context.keepTurn(false);
context.transition("success");
Eine benutzerdefinierte Komponente, die Benutzereingaben abruft, ohne die Ablaufsteuerung wieder an den Skill zurückzugeben. Beispiel:
  • Eine Komponente leitet die Benutzereingabe für eine Abfrage an eine Backend-Suchmaschine weiter. Wenn der Skill nur ein einzelnes Ergebnis aufnehmen kann, die Abfrage aber mehrere Treffer zurückgibt, fordert die Komponente den Benutzer zur Eingabe weiterer Werte für die Filterung der Ergebnisse auf. In diesem Fall wird die benutzerdefinierte Komponente weiterhin die Benutzereingabe verarbeiten. Die Unterhaltung wird angehalten, bis die Suchmaschine einen einzelnen Treffer zurückgibt. Wenn ein einzelnes Ergebnis zurückgegeben wird, ruft die Komponente context.transition() auf, um zu einem anderen Status zu wechseln, wie in der Dialogablaufdefinition definiert.

  • Eine Komponente verarbeitet einen Fragebogen und wechselt nur dann in einen anderen Folgestatus, wenn alle Fragen beantwortet wurden.

  1. Rufen Sie nicht transition auf.

  2. Legen Sie keepTurn(false) fest.

Beispiel: Diese benutzerdefinierte Komponente gibt ein Angebot aus und zeigt dann die Schaltflächen Yes und No an, um ein anderes Angebot anzufordern. Wenn der Benutzer auf No klickt, kehrt die Komponente zum Skill zurück.
  invoke: async (context) => {
    // Perform conversation tasks.
    const tracking_token = "a2VlcHR1cm4gZXhhbXBsZQ==";    
    const quotes = require("./json/Quotes.json");
    const quote = quotes[Math.floor(Math.random() * quotes.length)];
    
    // Check if postback action is issued. If postback action is issued, 
    // check if postback is from this component rendering. This ensures
    // that the component only responds to its own postback actions.     
    if (context.postback() && context.postback().token == tracking_token && context.postback().isNo) {
      context.keepTurn(true);
      context.transition();
    } else {
      // Show the quote of the day.
      context.reply("'" + quote.quote + "'");
      context.reply(" Quote by: " + quote.origin);
      // Create a single message with two buttons to 
      // request another quote or not.
      const mf = context.getMessageFactory();
      const message = mf.createTextMessage('Do you want another quote?')
        .addAction(mf.createPostbackAction('Yes', { isNo: false, token: tracking_token }))
        .addAction(mf.createPostbackAction('No', { isNo: true, token: tracking_token })); 
      context.reply(message);
      // Although reply() automatically sets keepTurn to false, 
      // it's good practice to explicitly set it so that it's
      // easier to see how you intend the component to behave.
      context.keepTurn(false);
    };
  }

Wenn eine Komponente nicht in einen anderen Status übergeht, muss sie ihren eigenen Status verfolgen, wie im obigen Beispiel gezeigt.

Für eine komplexere Statusverarbeitung, damit der Benutzer beispielsweise die Möglichkeit erhält, einen Datenabruf abzubrechen, wenn dieser zu lange dauert, können Sie eine Kontextvariable erstellen und verwenden. Beispiel: context.variable("InternalComponentWaitTime", time). Wenn Sie eine Kontextvariable verwenden, vergessen Sie nicht, diese zurückzusetzen oder auf Null zu setzen, bevor Sie context.transition aufrufen.

Hinweis: Solange kein Übergang stattfindet, sind alle Werte verfügbar, die als Komponenteneigenschaften übergeben werden.

Der Komponentenaufruf wird ohne Benutzereingabe wiederholt. Beispiel:

  • Eine Komponente pingt einen Remoteservice für den Status einer Bestellung, bis der Status accepted zurückgegeben wird oder bis die Komponente wegen Timeout abgebrochen wird. Wenn der Status accepted nach dem fünften Ping nicht zurückgegeben wird, führt die Komponente einen Übergang mit dem Status failedOrder aus.

  • Die benutzerdefinierte Komponente übergibt den Benutzer an einen Live-Agent. In diesem Fall werden die Benutzereingaben und die Antworten an den Agent weitergeleitet. Die Komponente wechselt in einen anderen Status, wenn der Benutzer oder der Agent die Session beendet.

  • Rufen Sie nicht transition auf.

  • Legen Sie context.keepTurn(true) fest.

Nachfolgend finden Sie ein etwas gekünsteltes Beispiel, das zeigt, wie der Aufruf wiederholt wird, ohne auf Benutzereingaben zu warten, und wie anschließend der Übergang erfolgt:
invoke: async (context) => {

  const quotes = require("./json/Quotes.json");
  const quote = quotes[Math.floor(Math.random() * quotes.length)];
  
  // Check if postback action is issued and postback is from this component rendering. 
  // This ensures that the component only responds to its own postback actions.     
  const um = context.getUserMessage()
  if (um instanceof PostbackMessage && um.getPostback() && um.getPostback()['system.state'] === context.getRequest().state && um.getPostback().isNo) {
    context.keepTurn(true);
    context.transition();
  } else {
    // Show the quote of the day.
    context.reply(`'${quote.quote}'`);
    context.reply(`Quote by: ${quote.origin}`);
    // Create a single message with two buttons to request another quote or not.
    let actions = [];

    const mf = context.getMessageFactory();
    const message = mf.createTextMessage('Do you want another quote?')
      .addAction(mf.createPostbackAction('Yes', { isNo: false }))
      .addAction(mf.createPostbackAction('No', { isNo: true }));
    context.reply(message);
    // Although reply() automatically sets keepTurn to false, it's good practice to explicitly set it so that it's
    // easier to see how you intend the component to behave.
    context.keepTurn(false);
  }
}

Auf das Backend zugreifen

Es gibt mehrere Node.js-Librarys, die erstellt wurden, um HTTP-Anforderungen einfach zu machen, und die Liste wird häufig geändert. Sie sollten die Vor- und Nachteile der aktuell verfügbaren Librarys überprüfen und entscheiden, welche für Sie am besten geeignet ist. Wir empfehlen, eine Library zu verwenden, die Promises unterstützt, damit Sie die async-Version der invoke-Methode, die in Version 2.5.1 eingeführt wurde, nutzen und mit dem await-Schlüsselwort synchron REST-Aufrufe schreiben können.

Eine Option ist die node fetch-API, die mit dem Bots Node-SDK vorinstalliert ist. Unter Zugriff auf das Backend mit HTTP-REST-Aufrufen in der Dokumentation für das Bots Node-SDK finden Sie einige Codebeispiele.

SDK für den Zugriff auf Anforderungs- und Antwort-Payloads verwenden

Mit CustomComponentContext-Instanzmethoden können Sie den Kontext für den Aufruf abrufen, Variablen anzeigen und ändern und Ergebnisse an die Dialog-Engine zurücksenden.

Codebeispiele zur Verwendung dieser Methoden finden Sie unter Benutzerdefinierte Komponenten schreiben und Unterhaltungsmessaging in der Dokumentation des Bots Node-SDK.

Die SDK-Referenzdokumentation finden Sie unter https://github.com/oracle/bots-node-sdk.

Benutzerdefinierte Komponenten für mehrsprachige Skills

Wenn Sie eine benutzerdefinierte Komponente entwerfen, sollten Sie überlegen, ob die Komponente von einem Skill verwendet wird, der mehrere Sprachen unterstützt.

Wenn die benutzerdefinierte Komponente mehrsprachige Skills unterstützen muss, müssen Sie wissen, ob die Skills für die native Sprachunterstützung oder den Übersetzungsservice konfiguriert sind.

Wenn Sie einen Übersetzungsservice verwenden, können Sie den Text aus dem Skill übersetzen. Sie haben folgende Optionen:

Für Sprachkenntnisse in Muttersprache stehen Ihnen folgende Optionen zur Verfügung:

  • Übergeben Sie die Daten an den Skill in Variablen, und geben Sie dann den Text aus einer Systemkomponente aus, indem Sie die Werte der Variablen an einen Resource Bundle-Schlüssel übergeben, wie unter Systemkomponente zum Referenzieren eines Resource Bundles verwenden beschrieben. Mit dieser Option muss die benutzerdefinierte Komponente Metadateneigenschaften aufweisen, damit der Skill die Namen der Variablen zum Speichern der Daten übergeben kann.

  • Verwenden Sie das Resource Bundle aus der benutzerdefinierten Komponente, um die Antwort der benutzerdefinierten Komponente zu verfassen, wie unter Resource Bundles aus der benutzerdefinierten Komponente referenzieren beschrieben. Mit der Methode conversation.translate() rufen Sie die Resource Bundle-Zeichenfolge ab, die für Ihren Aufruf von context.reply() verwendet werden soll. Diese Option ist nur für Resource Bundle-Definitionen gültig, die positionale (nummerierte) Parameter verwenden. Es funktioniert nicht für benannte Parameter. Bei dieser Option muss die benutzerdefinierte Komponente eine Metadateneigenschaft für den Namen des Resource Bundle-Schlüssels aufweisen, und die Parameter des benannten Resource Bundle-Schlüssels müssen mit denen übereinstimmen, die beim Aufruf von context.reply() verwendet werden.

Im Folgenden finden Sie ein Beispiel für die Verwendung des Resource Bundles aus der benutzerdefinierten Komponente. In diesem Beispiel würde fmTemplate auf ${rb('date.dayOfWeekMessage', 'lundi', '19 juillet 2021')} gesetzt.

'use strict';

var IntlPolyfill    = require('intl');
Intl.DateTimeFormat = IntlPolyfill.DateTimeFormat;

module.exports = {
  metadata: () => ({
    name: 'Date.DayOfWeek',
    properties: {
      rbKey:   { required: true,  type: 'string'    }
    },
    supportedActions: []
  }),
  invoke: (context, done) => {
    const { rbKey } = context.properties();
    if (!rbKey || rbKey.startsWith('${')){
      context.transition();
            done(new Error('The state is missing the rbKey property or it uses an invalid expression to pass the value.'));
    }
    //detect user locale. If not set, define a default
    const locale  = context.getVariable('profile.locale') ? 
      context.getVariable('profile.locale') : 'en-AU';  
    const jsLocale     = locale.replace('_','-');
    //when profile languageTag is set, use it. If not, use profile.locale
    const languageTag = context.getVariable('profile.languageTag')?
                      context.getVariable('profile.languageTag') : jslocale;
   /* =============================================================
      Determine the current date in local format and 
      the day name for the locale
      ============================================================= */
    var now          = new Date();
    var dayTemplate  = new Intl.DateTimeFormat(languageTag,
      { weekday: 'long' });
    var dayOfWeek    = dayTemplate.format(now);
    var dateTemplate = new Intl.DateTimeFormat(languageTag, 
      { year: 'numeric', month: 'long', day: 'numeric'});
    var dateToday    = dateTemplate.format(now);

   /* =============================================================
      Use the context.translate() method to create the ${Freemarker} 
      template that's evaluated when the reply() is flushed to the 
      client.
      ============================================================= */
    const fmTemplate = context.translate(rbKey, dateToday, dayOfWeek );

    context.reply(fmTemplate)
                .transition()
                .logger().info('INFO : Generated FreeMarker => ' 
                + fmTemplate);
    done();  
  }
};

Sicherstellen, dass die Komponente in digitalen Assistenten funktioniert

In einer Unterhaltung über den digitalen Assistenten kann ein Benutzer den Unterhaltungsablauf unterbrechen, indem er den Betreff ändert. Beispiel: Wenn ein Benutzer einen Ablauf zum Kauf startet, kann er diesen Ablauf unterbrechen, um abzufragen, wie viel Guthaben er noch auf einer Geschenkkarte hat. Wir bezeichnen dies als nicht sequenzielle Abfolge. Damit der digitale Assistent nicht folgerichtige Abfolgen identifizieren und verarbeiten kann, rufen Sie die context.invalidInput(payload)-Methode auf, wenn eine Benutzeräußerungsantwort im Kontext der Komponente nicht verstanden wird.

In einer digitalen Unterhaltung bestimmt die Laufzeit, ob eine ungültige Eingabe eine nicht sequenzielle Abfolge ist, indem in allen Skills nach Antwortübereinstimmungen gesucht wird. Wenn sie Übereinstimmungen findet, wird der Ablauf umgeleitet. Andernfalls wird die Meldung angezeigt (sofern vorhanden), der Benutzer wird zur Eingabe aufgefordert, und die Komponente wird erneut ausgeführt. Die neue Eingabe wird an die Komponente in der Eigenschaft text übergeben.

In einer Unterhaltung mit einem Standalone-Skill zeigt die Laufzeit die Nachricht an (sofern vorhanden), fordert den Benutzer zur Eingabe auf und führt die Komponente erneut aus. Die neue Eingabe wird an die Komponente in der Eigenschaft text übergeben.

Dieser Beispielcode ruft context.invalidInput(payload) auf, wenn die Eingabe keine Zahl ist.

"use strict"
 
module.exports = {
 
    metadata: () => ({
        "name": "AgeChecker",
        "properties": {
            "minAge": { "type": "integer", "required": true }
        },
        "supportedActions": [
            "allow",
            "block",
            "unsupportedPayload"
        ]
    }),
 
    invoke: (context, done) => {
        // Parse a number out of the incoming message
        const text = context.text();
        var age = 0;
        if (text){
          const matches = text.match(/\d+/);
          if (matches) {
              age = matches[0];
          } else {
              context.invalidUserInput("Age input not understood. Please try again");
              done();
              return;
          }
        } else {
          context.transition('unsupportedPayload");
          done();
          return;
        }
 
        context.logger().info('AgeChecker: using age=' + age);
 
        // Set action based on age check
        let minAge = context.properties().minAge || 18;
        context.transition( age >= minAge ? 'allow' : 'block' );
 
        done();
    }
};

Nachfolgend finden Sie ein Beispiel dafür, wie ein digitaler Assistent ungültige Eingaben zur Laufzeit verarbeitet. Für die erste Altersantwort (twentyfive) gibt es keine Übereinstimmungen in den Skills, die beim digitalen Assistenten registriert sind. Die Unterhaltung zeigt also die angegebene Nachricht context.invalidUserInput an. In der zweiten Altersantwort (Geld senden) findet der digitale Assistent eine Übereinstimmung, sodass er fragt, ob an diesen Ablauf umgeleitet werden soll.


Eine Beschreibung von components-nonsequitur-conversation.png folgt.
Beschreibung der Abbildung Components-nonsequitur-conversation.png

Rufen Sie entweder context.invalidInput() oder context.transition() auf. Wenn Sie beide Vorgänge aufrufen, stellen Sie sicher, dass die Variable system.invalidUserInput noch festgelegt ist, wenn zusätzliche Nachrichten gesendet werden. Beachten Sie auch, dass Benutzereingabekomponenten (wie Common Response- und Resolve-Entity-Komponenten) system.invalidUserInput zurücksetzen.

Beispiel: Die AgeChecker-Komponente wird wie unten dargestellt geändert, und context.transition() wird nach context.invalidInput() aufgerufen.

if (matches) {  age = matches[0]; } else { 
      context.invalidUserInput("Age input not understood. Please try again"); 
      context.transition("invalid"); 
      context.keepTurn(true);
      done();
      return;
}

In diesem Fall muss der Datenfluss wieder zu askage übergehen, sodass der Benutzer zwei Ausgabenachrichten erhält: "Altersangabe nicht verstanden. Bitte versuchen Sie es erneut", gefolgt von "Wie alt sind Sie?". So kann das in einem Dialogablauf im YAML-Modus behandelt werden.

  askage:
    component: "System.Output"
    properties:
      text: "How old are you?"
    transitions:
      next: "checkage"
  checkage:
    component: "AgeChecker"
    properties:
      minAge: 18
    transitions:
      actions:
        allow: "crust"
        block: "underage"
        invalid: "askage"

Komponentenservice in einer Entwicklungsumgebung ausführen

Während der Entwicklungsphase können Sie einen lokalen Service starten, um das benutzerdefinierte Komponentenpackage verfügbar zu machen.

  1. Öffnen Sie im Ordner der obersten Ebene ein Terminalfenster, und führen Sie die folgenden Befehle aus, um den Service zu starten:
    npm install
    npm start
  2. Um zu prüfen, ob der Service ausgeführt wird, geben Sie die folgende URL in einem Browser ein:
    localhost:3000/components

    Der Browser zeigt die Komponentenmetadaten an.

  3. Wenn Sie direkten Internetzugriff haben, können Sie von einem Skill aus auf die Entwicklungsumgebung zugreifen:
    1. Installieren Sie einen Tunnel wie ngrok oder Localtunnel.
    2. Wenn Sie sich hinter einem Proxyserver befinden, gehen Sie auf http://www.whatismyproxy.com/, um die externe IP-Adresse des Proxys abzurufen, und geben Sie dann im Terminalfenster, in dem Sie den Tunnel starten möchten, die folgenden Befehle ein:
      export https_proxy=http://<external ip>:80
      export http_proxy=http://<external ip>:80
    3. Starten Sie den Tunnel, und konfigurieren Sie ihn so, dass Port 3000 verfügbar ist.
    4. Gehen Sie in Oracle Digital Assistant zur Registerkarte "Komponenten" Symbol "Komponenten" des Skills, und fügen Sie einen Komponentenservice des Typs Extern hinzu, bei dem die Metadaten-URL auf https://<Tunnel-URL>/components gesetzt ist.
      Sie können einen beliebigen Wert für den Benutzernamen und das Kennwort verwenden.
Nun können Sie dem Dialogablauf Statusangaben für die Servicekomponenten hinzufügen und diese auf der Seite Vorschau des Skills testen.