Implementa componenti personalizzati

Per implementare i componenti personalizzati, utilizzare l'SDK Node.js di Oracle Digital Assistant per interfacciarsi con il servizio di componenti personalizzati di Digital Assistant.

Di seguito viene descritto come implementare i componenti personalizzati che è possibile distribuire nel contenitore incorporato Digital Assistant, in Oracle Cloud Infrastructure Functions, in un backend Mobile Hub o in un server Node.js.

  1. Installare il software per la creazione di componenti personalizzati.

  2. Creare il package di componenti personalizzati.

  3. Creare e creare un componente personalizzato.

Nota

Se si prevede di distribuire il package di componenti personalizzati in un servizio di componenti personalizzati incorporato, ogni skill a cui si aggiunge il package viene conteggiato come servizio separato. È previsto un limite al numero di servizi di componenti personalizzati incorporati che un'istanza può avere. Se non si conosce il limite, chiedere all'amministratore del servizio di ottenere automaticamente embedded-custom-component-service-count come descritto in Visualizza limiti del servizio nella console dell'infrastruttura. Prendere in considerazione l'inserimento di più componenti per pacchetto per ridurre al minimo il numero di servizi dei componenti incorporati che si utilizzano. Se si tenta di aggiungere un servizio componente dopo aver raggiunto tale limite, la creazione del servizio non riesce.

Passo 1: Installare il software per la creazione di componenti personalizzati

Per creare un pacchetto di componenti personalizzato, sono necessari Node.js, Node Package Manager e l'SDK Node.js dei bot di Oracle Digital Assistant.

Nota

In Windows, l'SDK del nodo bot non funziona in Windows se l'installazione del nodo è la versione 20.12.2 o successiva a causa di una modifica non compatibile con le versioni precedenti in Node.js. Se hai già installato Node versione 20.12.2 o successiva, devi disinstallarlo e quindi installare la versione 20.12.1 o precedente per consentire il funzionamento dell'SDK del nodo bot.
  1. Se non lo si è già fatto, scaricare Node.js da https://nodejs.org e installarlo per l'accesso globale. Node Package Manager (npm) viene distribuito con Node.js.

    Per verificare se sono installati Node.js e npm, aprire una finestra del terminale e digitare i comandi seguenti:

    node –v 
    npm –v
  2. Per installare l'SDK Node.js dei bot di Oracle Digital Assistant per l'accesso globale, immettere questo comando in una finestra del terminale:
    npm install -g @oracle/bots-node-sdk

    Su un Mac, si utilizza il comando sudo:

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

    Quando si utilizza l'opzione -g (globale), è possibile accedere direttamente all'interfaccia della riga di comando bots-node-sdk. In caso contrario, utilizzare npx @oracle/bots-node-sdk.

  3. Per verificare l'installazione dell'SDK Node.js dei bot di Oracle Digital Assistant, digitare il comando seguente:
    bots-node-sdk -v
    Il comando deve stampare la versione dell'SDK Node.js dei bot di Oracle Digital Assistant.

Passo 2: Creare il pacchetto di componenti personalizzati

Per avviare un progetto, utilizzare il comando bots-node-sdk init dell'interfaccia della riga di comando (CLI) dell'SDK per creare i file e la struttura di directory necessari per la struttura del componente.

Il comando init include alcune opzioni, ad esempio l'uso di JavaScript (impostazione predefinita) o TypeScript e il nome del file JavaScript del componente iniziale. Queste opzioni sono descritte in Strumenti per sviluppatori CLI. Di seguito è riportato il comando di base per l'avvio di un progetto JavaScript.

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

Questo comando completa le seguenti azioni per un pacchetto JavaScript:

  • Crea la cartella di livello superiore.

  • Crea una cartella components e aggiunge un file del componente di esempio JavaScript denominato hello.world.js. Qui è dove mettere i file del componente JavaScript.

  • Aggiunge un file package.json, che specifica main.js come punto di ingresso principale ed elenca @oracle/bots-node-sdk come devDependency. Il file del pacchetto punta anche ad alcuni script bots-node-sdk.

    {
      "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"
      }
    }
  • Aggiunge alla cartella di livello superiore un file main.js che esporta le impostazioni del package e punta alla cartella dei componenti per la posizione dei componenti.

  • Aggiunge un file .npmignore alla cartella di livello superiore. Questo file viene utilizzato quando si esporta il package di componenti. Deve escludere i file .tgz dal pacchetto. Ad esempio: *.tgz.

  • Per alcune versioni di npm, crea un file package-lock.json.

  • Installa tutte le dipendenze del pacchetto nella sottocartella node_modules.
Nota

Se non si utilizza il comando bots-node-sdk init per creare la cartella del pacchetto, assicurarsi che la cartella di livello superiore contenga un file .npmignore contenente una voce *.tgz. Ad esempio:
*.tgz
spec
service-*

In caso contrario, ogni volta che si inseriscono i file in un file TGZ, si include il file TGZ già esistente nella cartella di livello superiore e il file TGZ continuerà a raddoppiare le dimensioni.

Se si prevede di eseguire la distribuzione nel contenitore incorporato, il pacchetto deve essere compatibile con il nodo 14.17.0.

Passo 3: Creare e creare un componente personalizzato

Creazione del file del componente

Utilizzare il comando init component dell'interfaccia CLI dell'SDK per creare un file JavaScript o TypeScript con la struttura per utilizzare l'SDK Node.js di Oracle Digital Assistant per scrivere un componente personalizzato. La lingua specificata al momento dell'esecuzione del comando init per creare il pacchetto del componente determina se viene creato un file JavaScript o TypeScript.

Ad esempio, per creare un file per il componente personalizzato, da una finestra di terminale, dal CD alla cartella di livello superiore del pacchetto e digitare il comando seguente, sostituendo <component name> con il nome del componente:

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

Per JavaScript, questo comando aggiunge <component name>.js a components folder. Per TypeScript, il file viene aggiunto alla cartella src/components. L'argomento c indica che il file si riferisce a un componente personalizzato.

Il nome del componente non può superare i 100 caratteri. Nel nome è possibile utilizzare solo caratteri alfanumerici e caratteri di sottolineatura. Non è possibile utilizzare trattini. Né il nome può avere un prefisso System.. Oracle Digital Assistant non consentirà di aggiungere un servizio componente personalizzato con nomi componente non validi.

Per ulteriori dettagli, vedere https://github.com/oracle/bots-node-sdk/blob/master/bin/CLI.md.

Aggiungi codice ai metadati e richiama funzioni

Il componente personalizzato deve esportare due oggetti:

  • metadata: fornisce allo skill le informazioni sui componenti riportate di seguito.
    • Nome componente
    • Proprietà supportate
    • Azioni di transizione supportate

    Per i flussi di dialogo basati su YAML, il componente personalizzato supporta per impostazione predefinita le seguenti proprietà. Queste proprietà non sono disponibili per gli skill progettati in modalità finestra di dialogo Visual.

  • invoke: contiene la logica da eseguire. In questo metodo è possibile leggere e scrivere variabili di contesto delle competenze, creare messaggi di conversazione, impostare transizioni di stato, effettuare chiamate REST e altro ancora. In genere, questa funzione consente di utilizzare la parola chiave async per gestire le promesse. La funzione invoke accetta il seguente argomento:
    • context, che assegna un nome al riferimento all'oggetto CustomComponentContext nell'SDK Node.js di Digital Assistant. Questa classe è descritta nella documentazione dell'SDK all'indirizzo https://oracle.github.io/bots-node-sdk/. Nelle versioni precedenti dell'SDK, il nome era conversation. È possibile utilizzare uno dei due nomi.
    Nota

    Se si utilizza una libreria JavaScript che non supporta le promesse, quindi non si utilizza la parola chiave async, è anche possibile aggiungere un argomento done come callback richiamato dal componente al termine dell'elaborazione.

Esempio:

'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');   
  }
}

Per ulteriori informazioni ed esplorare alcuni esempi di codice, consulta la sezione relativa alla scrittura di componenti personalizzati nella documentazione relativa all'SDK del nodo bot.

Controllare il flusso con keepTurn e la transizione

È possibile utilizzare diverse combinazioni delle funzioni keepTurn e transition del kit SDK nodo bot per definire il modo in cui il componente personalizzato interagisce con un utente e il modo in cui la conversazione continua dopo che il componente restituisce il controllo del flusso alla competenza.

  • keepTurn(boolean) specifica se la conversazione deve passare a un altro stato senza prima richiedere l'input dell'utente.

    Tenere presente che se si desidera impostare keepTurn su true, è necessario chiamare keepTurn dopo aver chiamato reply perché reply imposta in modo implicito keepTurn su false.

  • transition(action) fa sì che la finestra di dialogo passi allo stato successivo dopo l'invio di tutte le eventuali risposte. L'argomento facoltativo action indica l'azione (risultato) restituita dal componente.

    Se non si chiama transition(), la risposta viene inviata, ma la finestra di dialogo rimane nello stato e il successivo input utente torna a questo componente. Cioè, invoke() viene chiamato di nuovo.

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

Di seguito sono riportati alcuni casi d'uso comuni in cui utilizzare keepTurn e transition per controllare il flusso della finestra di dialogo.

caso d'uso Insieme di valori per keepTurn e transizione

Componente personalizzato che passa a un altro stato senza prima richiedere l'input all'utente.

  1. Se applicabile, utilizzare context.reply(<reply>) per inviare una risposta.

  2. Impostare context.keepTurn(true).

  3. Impostare context.transition con una stringa supportedActions (e.g., context.transition("success") o senza alcun argomento (ad esempio, context.transition()).

Ad esempio, questo componente personalizzato aggiorna una variabile con un elenco di valori da visualizzare immediatamente in base allo stato successivo nel flusso della finestra di dialogo.
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();
 }

Componente personalizzato che consente allo skill di attendere l'input dopo che il controllo torna allo skill e prima che lo skill passi a un altro stato.

  1. Se applicabile, utilizzare context.reply(<reply>) per inviare una risposta.

  2. Impostare context.keepTurn(false) .

  3. Impostare context.transition con una stringa supportedActions(context.transition("success") o senza argomenti (context.transition()).

Ad esempio:
context.keepTurn(false);
context.transition("success");
Componente personalizzato che recupera l'input dell'utente senza restituire il controllo del flusso allo skill. Ad esempio:
  • Un componente passa l'input utente per eseguire una query su un motore di ricerca backend. Se la competenza può contenere solo un singolo risultato, ma la query restituisce invece più risultati, il componente richiede all'utente un input maggiore per filtrare i risultati. In questo caso, il componente personalizzato continua a gestire l'input dell'utente; tiene la conversazione fino a quando il motore di ricerca non restituisce un singolo colpo. Quando ottiene un singolo risultato, il componente chiama context.transition() per passare a un altro stato, come definito nella definizione del flusso della finestra di dialogo.

  • Un componente elabora un questionario e passa a un altro stato successivo solo quando viene fornita una risposta a tutte le domande.

  1. Non chiamare transition.

  2. Impostare keepTurn(false).

Ad esempio, questo componente personalizzato restituisce un preventivo, quindi visualizza i pulsanti Yes e No per richiedere un altro preventivo. Esegue la transizione allo skill quando l'utente fa clic su No.
  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);
    };
  }

Se un componente non passa a un altro stato, deve tenere traccia del proprio stato, come mostrato nell'esempio precedente.

Per una gestione dello stato più complessa, ad esempio per consentire all'utente di annullare se il recupero dei dati richiede troppo tempo, è possibile creare e utilizzare una variabile di contesto. Ad esempio: context.variable("InternalComponentWaitTime", time). Se si utilizza una variabile di contesto, non dimenticare di reimpostarla o impostarla su null prima di chiamare context.transition.

Tenere presente che, finché non si esegue la transizione, sono disponibili tutti i valori passati come proprietà del componente.

Il richiamo del componente si ripete senza l'input dell'utente. Ad esempio:

  • Un componente esegue il ping di un servizio remoto per lo stato di un ordine fino a quando lo stato non viene restituito come accepted o il timeout del componente. Se lo stato accepted non viene restituito dopo il quinto ping, il componente esegue la transizione con lo stato failedOrder.

  • Il componente personalizzato trasferisce l'utente a un agente reale. In questo caso, l'input e le risposte dell'utente vengono inviati all'agente. Il componente passa a un altro stato quando l'utente o l'agente termina la sessione.

  • Non chiamare transition.

  • Impostare context.keepTurn(true).

Di seguito è riportato un esempio in qualche modo elaborato che mostra come ripetere il richiamo senza attendere l'input dell'utente e quindi come eseguire la transizione al termine:
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);
  }
}

Accedi al backend

Verranno trovate diverse librerie Node.js create per semplificare le richieste HTTP e l'elenco cambia frequentemente. Dovresti rivedere i pro e i contro delle librerie attualmente disponibili e decidere quale funziona meglio per te. Si consiglia di utilizzare una libreria che supporti le promesse in modo da poter utilizzare la versione async del metodo invoke, introdotta nella versione 2.5.1, e la parola chiave await per scrivere le chiamate REST in modo sincrono.

Un'opzione è l'API node fetch preinstallata con l'SDK del nodo bot. Accedere al backend mediante chiamate REST HTTP nella documentazione relativa all'SDK del nodo bot contiene alcuni esempi di codice.

Utilizzare l'SDK per accedere ai payload delle richieste e delle risposte

I metodi di istanza CustomComponentContext consentono di ottenere il contesto per le variabili di richiamo, accesso e modifica e di inviare nuovamente i risultati al motore della finestra di dialogo.

È possibile trovare diversi esempi di codice per l'uso di questi metodi in Scrittura di componenti personalizzati e Messaggistica di conversazione nella documentazione dell'SDK del nodo bot.

La documentazione di riferimento sull'SDK è disponibile all'indirizzo https://github.com/oracle/bots-node-sdk.

Componenti personalizzati per skill multilingua

Quando si progetta un componente personalizzato, è necessario valutare se il componente verrà utilizzato da uno skill che supporta più lingue.

Se il componente personalizzato deve supportare competenze multilingue, è necessario sapere se le competenze sono configurate per il supporto della lingua nativa o il servizio di traduzione.

Quando si utilizza un servizio di traduzione, è possibile tradurre il testo dalla competenza. Sono disponibili le opzioni seguenti:

Per le competenze linguistiche native, sono disponibili le seguenti opzioni:

  • Trasmettere i dati alla competenza nelle variabili e quindi eseguire l'output del testo da un componente di sistema passando i valori delle variabili a una chiave bundle di risorse, come descritto in Utilizzare un componente di sistema per fare riferimento a un bundle di risorse. Con questa opzione, il componente personalizzato deve avere proprietà di metadati per consentire allo skill di passare i nomi delle variabili in cui memorizzare i dati.

  • Utilizzare il bundle di risorse del componente personalizzato per comporre la risposta del componente personalizzato, come descritto in Bundle di risorse di riferimento del componente personalizzato. Utilizzare il metodo conversation.translate() per ottenere la stringa del bundle delle risorse da utilizzare per la chiamata a context.reply(). Questa opzione è valida solo per le definizioni di bundle di risorse che utilizzano parametri posizionali (numerati). Non funziona per i parametri denominati. Con questa opzione, il componente personalizzato deve avere una proprietà di metadati per il nome della chiave del bundle di risorse e i parametri della chiave del bundle di risorse denominato devono corrispondere a quelli utilizzati nella chiamata a context.reply().

Di seguito è riportato un esempio di utilizzo del bundle di risorse dal componente personalizzato. In questo esempio, fmTemplate verrà impostato su un valore simile a ${rb('date.dayOfWeekMessage', 'lundi', '19 juillet 2021')}.

'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();  
  }
};

Assicurarsi che il componente funzioni negli assistenti digitali

In una conversazione dell'assistente digitale, un utente può interrompere un flusso di conversazione modificando l'oggetto. Ad esempio, se un utente avvia un flusso per effettuare un acquisto, potrebbe interrompere tale flusso per chiedere quanto credito ha su una carta regalo. Lo chiamiamo non sequitur. Per consentire all'assistente digitale di identificare e gestire i non sequiturs, chiamare il metodo context.invalidInput(payload) quando una risposta di espressione utente non è compresa nel contesto del componente.

In una conversazione digitale, il runtime determina se un input non valido è un non sequitur mediante la ricerca di corrispondenze di risposta in tutte le competenze. Se trova corrispondenze, reindirizza il flusso. In caso contrario, viene visualizzato il messaggio, se fornito, che richiede all'utente l'input, quindi esegue di nuovo il componente. Il nuovo input viene passato al componente nella proprietà text.

In una conversazione di skill standalone, il runtime visualizza il messaggio, se fornito, che richiede all'utente l'input, quindi esegue di nuovo il componente. Il nuovo input viene passato al componente nella proprietà text.

Questo codice di esempio chiama context.invalidInput(payload) ogni volta che l'input non viene convertito in un numero.

"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();
    }
};

Di seguito è riportato un esempio di come un assistente digitale gestisce l'input non valido in runtime. Per la prima risposta età (twentyfive), non ci sono corrispondenze in alcuna competenza registrata con l'assistente digitale in modo che la conversazione visualizzi il messaggio context.invalidUserInput specificato. Nella risposta alla seconda età (send money), l'assistente digitale trova una corrispondenza in modo da chiedere se deve reindirizzare a tale flusso.


Descrizione dei componenti-nonsequitur-conversation.png:
Descrizione dell'immagine components-nonsequitur-conversation.png

È necessario chiamare context.invalidInput() o context.transition(). Se si richiamano entrambe le operazioni, assicurarsi che la variabile system.invalidUserInput sia ancora impostata se viene inviato un messaggio aggiuntivo. Tenere inoltre presente che i componenti di input dell'utente, ad esempio i componenti delle entità di risposta comune e di risoluzione, reimpostano system.invalidUserInput.

Si supponga, ad esempio, di modificare il componente AgeChecker come illustrato di seguito e di chiamare context.transition() dopo context.invalidInput().

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

In questo caso, il flusso di dati deve tornare a askage in modo che l'utente riceva due messaggi di output: "Input età non compreso. Si prega di riprovare" seguito da "Quanti anni hai?". Ecco come potrebbe essere gestito in un flusso di dialogo in modalità YAML.

  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"

Eseguire il servizio del componente in un ambiente di sviluppo

Durante la fase di sviluppo, è possibile avviare un servizio locale per esporre il package di componenti personalizzati.

  1. Dalla cartella di livello superiore, aprire una finestra di terminale ed eseguire i comandi seguenti per avviare il servizio:
    npm install
    npm start
  2. Per verificare che il servizio sia in esecuzione, immettere il seguente URL in un browser:
    localhost:3000/components

    Il browser visualizza i metadati del componente.

  3. Se si dispone di accesso diretto a Internet, è possibile accedere all'ambiente di sviluppo da una competenza:
    1. Installare un tunnel, ad esempio ngrok o Localtunnel.
    2. Se si è dietro un proxy, andare a http://www.whatismyproxy.com/ per ottenere l'indirizzo IP esterno del proxy e quindi, nella finestra del terminale che si utilizzerà per avviare il tunnel, immettere i comandi seguenti:
      export https_proxy=http://<external ip>:80
      export http_proxy=http://<external ip>:80
    3. Avviare il tunnel e configurarlo per esporre la porta 3000.
    4. In Oracle Digital Assistant, andare alla scheda Componenti della competenza Icona Componenti e aggiungere un servizio componente Esterno con l'URL dei metadati impostato su https://<tunnel-url>/components.
      È possibile utilizzare qualsiasi valore per il nome utente e la password.
È ora possibile aggiungere stati per i componenti del servizio al flusso della finestra di dialogo e testarli dalla pagina Anteprima dello skill.