Implémenter des composants personnalisés

Pour implémenter des composants personnalisés, utilisez le kit SDK Node.js Oracle Digital Assistant afin d'établir une interface avec le service de composants personnalisé de Digital Assistant.

Pour implémenter des composants personnalisés que vous pouvez déployer vers le conteneur imbriqué de Digital Assistant, Oracle Cloud Infrastructure Functions, un back-end Mobile Hub ou un serveur Node.js, procédez comme suit :

  1. Installez le logiciel pour créer des composants personnalisés.

  2. Créez le package de composants personnalisés.

  3. Créez un composant personnalisé.

Remarque

Si vous prévoyez de déployer le package de composants personnalisé vers un service de composant personnalisé imbriqué, chaque brique à laquelle vous ajoutez le package est comptée comme un service distinct. Le nombre de services de composant personnalisés imbriqués d'une instance est limité. Si vous ne connaissez pas cette limite, demandez à l'administrateur de service d'obtenir pour vous la valeur embedded-custom-component-service-count comme décrit dans Affichage des limites de service dans la console Infrastructure. Envisagez de réunir plusieurs composants par package afin de diminuer le nombre de services de composant imbriqués que vous utilisez. Si vous essayez d'ajouter un service de composant après avoir atteint cette limite, la création du service échoue.

Etape 1 : installation du logiciel pour créer des composants personnalisés

Pour créer un package de composants personnalisé, vous avez besoin de Node.js, de Node Package Manager et du kit SDK Node.js Oracle Digital Assistant Bots.

Remarque

Sous Windows, le kit SDK Bots Node ne fonctionne pas sous Windows si l'installation du noeud est de version 20.12.2 ou supérieure en raison d'une modification incompatible en amont dans Node.js. Si la version 20.12.2 ou supérieure du noeud est déjà installée, vous devez la désinstaller, puis installer la version 20.12.1 ou une version antérieure pour que le kit SDK Bots Node fonctionne.
  1. Si vous ne l'avez pas déjà fait, téléchargez Node.js à partir de la page https://nodejs.org et installez-le pour un accès global. Node Package Manager (npm) est distribué avec Node.js.

    Pour vérifier si Node.js et npm sont installés, ouvrez une fenêtre de terminal et saisissez ces commandes :

    node –v 
    npm –v
  2. Afin d'installer le kit SDK Node.js Bots Oracle Digital Assistant pour l'accès global, saisissez la commande suivante dans une fenêtre de terminal :
    npm install -g @oracle/bots-node-sdk

    Sur un Mac, utilisez la commande sudo :

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

    Lorsque vous utilisez l'option -g (global), vous avez un accès direct à l'interface de ligne de commande bots-node-sdk. Sinon, utilisez npx @oracle/bots-node-sdk.

  3. Pour vérifier votre installation du kit SDK Node.js Bots Oracle Digital Assistant, saisissez la commande suivante :
    bots-node-sdk -v
    La commande doit imprimer la version du kit SDK Node.js Bots Oracle Digital Assistant.

Etape 2 : création du package de composants personnalisés

Pour démarrer un projet, utilisez la commande bots-node-sdk init dans l'interface de ligne de commande (CLI) du kit SDK afin de créer les fichiers et la structure de répertoire nécessaires pour la structure de votre composant.

La commande init comprend quelques options, telles que l'utilisation de JavaScript (valeur par défaut) ou de TypeScript, et le nom du fichier JavaScript du composant initial. Ces options sont décrites dans Outils de développement de CLI. Voici la commande de base pour démarrer un projet JavaScript :

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

Cette commande effectue les actions suivantes pour un package JavaScript :

  • Créer le dossier de niveau supérieur.

  • Créer un dossier components et ajoute un fichier JavaScript de composant d'échantillon nommé hello.world.js. Il s'agit de l'emplacement où vous placerez vos fichiers JavaScript de composant.

  • Ajouter un fichier package.json, qui indique main.js en tant que point d'entrée principal et répertorie @oracle/bots-node-sdk en tant que devDependency. Le fichier de package pointe également vers des scripts 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"
      }
    }
  • Ajouter un fichier main.js, qui exporte les paramètres du package et pointe vers le dossier des composants pour l'emplacement des composants, vers le dossier de niveau supérieur.

  • Ajouter un fichier .npmignore au dossier de niveau supérieur. Ce fichier est utilisé lors de l'export du package de composants. Il doit exclure du package les fichiers .tgz. Par exemple : *.tgz.

  • Pour certaines versions de npm, crée un fichier package-lock.json.

  • Installe toutes les dépendances du package dans le sous-dossier node_modules.
Remarque

Si vous n'utilisez pas la commande bots-node-sdk init pour créer le dossier du package, assurez-vous que le dossier de niveau supérieur contient un fichier .npmignore contenant lui-même une entrée *.tgz. Par exemple :
*.tgz
spec
service-*

Sinon, chaque fois que vous packagerez les fichiers dans un fichier TGZ, vous inclurez le fichier TGZ qui existe déjà dans le dossier de niveau supérieur et la taille de votre fichier TGZ continuera de doubler.

Si vous prévoyez un déploiement vers le conteneur imbriqué, votre package doit être compatible avec le noeud 14.17.0.

Etape 3 : création d'un composant personnalisé

Création du fichier de composant

Utilisez la commande init component de l'interface de ligne de commande du kit SDK afin de créer un fichier JavaScript ou TypeScript avec la structure permettant d'utiliser le kit SDK Node.js Oracle Digital Assistant pour écrire un composant personnalisé. Le langage indiqué lors de l'exécution de la commande init pour créer le package de composants détermine si un fichier JavaScript ou TypeScript est créé.

Par exemple, afin de créer un fichier pour le composant personnalisé, à partir d'une fenêtre de terminal, utilisez la commande CD (Change Directory) pour passer au dossier de niveau supérieur du package et saisissez la commande suivante, en remplaçant <component name> par le nom du composant :

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

Pour JavaScript, cette commande ajoute <component name>.js au dossier components. Pour TypeScript, le fichier est ajouté au dossier src/components. L'argument c indique que le fichier est destiné à un composant personnalisé.

Le nom de composant ne doit pas dépasser 100 caractères. Vous pouvez utiliser uniquement des caractères alphanumériques et des traits de soulignement dans le nom. Vous ne pouvez pas utiliser de traits d'union. Le nom ne peut pas non plus comporter le préfixe System.. Oracle Digital Assistant ne vous permet pas d'ajouter un service de composant personnalisé dont les noms de composant ne sont pas valides.

Pour plus d'informations, reportez-vous à https://github.com/oracle/bots-node-sdk/blob/master/bin/CLI.md.

Ajout de code aux fonctions metadata et invoke

Votre composant personnalisé doit exporter deux objets :

  • metadata : fournit à la brique les informations suivantes sur le composant.
    • Nom de composant
    • Propriétés prises en charge
    • Actions de transition prises en charge

    Pour les flux de dialogue basés sur YAML, le composant personnalisé prend en charge les propriétés suivantes par défaut. Ces propriétés ne sont pas disponibles pour les briques conçues en mode de dialogue Visual.

    • autoNumberPostbackActions : booléen. Non obligatoire. Lorsque la valeur true est définie, les boutons et les options de liste sont numérotés automatiquement. La valeur par défaut est false. Reportez-vous à Numérotation automatique pour les canaux de texte uniquement dans les flux de dialogue YAML.
    • insightsEndConversation : booléen. Non obligatoire. Lorsque la valeur true est définie, la session arrête l'enregistrement de la conversation pour la génération de rapports d'analyse. La valeur par défaut est false. Reportez-vous à Modélisation du flux de dialogue.
    • insightsInclude : booléen. Non obligatoire. Lorsque la valeur true est définie, l'état est inclus dans la génération de rapports d'analyse. La valeur par défaut est true. Reportez-vous à Modélisation du flux de dialogue.
    • translate : booléen. Non obligatoire. Lorsque la valeur true est définie, la traduction automatique est activée pour ce composant. La valeur par défaut est celle de la variable de contexte autotranslation. Reportez-vous à Services de traduction dans les briques.
  • invoke : contient la logique à exécuter. Avec cette méthode, vous pouvez lire et écrire des variables de contexte de brique, créer des messages de conversation, définir des transitions d'état, effectuer des appels REST, etc. En général, vous utilisez le mot-clé async avec cette fonction pour gérer les promesses. La fonction invoke accepte l'argument suivant :
    • context, qui nomme la référence à l'objet CustomComponentContext dans le kit SDK Node.js Digital Assistant. Cette classe est décrite dans la documentation du kit SDK disponible à l'adresse https://oracle.github.io/bots-node-sdk/. Dans les versions antérieures du kit SDK, son nom était conversation. Vous pouvez utiliser l'un ou l'autre des noms.
    Remarque

    Si vous utilisez une bibliothèque JavaScript qui ne prend pas en charge les promesses (et n'utilise donc pas le mot-clé async), il est également possible d'ajouter un argument done en tant que rappel que le composant appelle une fois le traitement terminé.

Voici un exemple :

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

Pour en savoir plus et découvrir quelques exemples de code, reportez-vous à Ecriture de composants personnalisés dans la documentation du kit SDK Bots Node.

Contrôle du flux avec keepTurn et transition

Utilisez différentes combinaisons des fonctions keepTurn et transition du kit SDK Bots Node pour définir comment le composant personnalisé interagit avec l'utilisateur et comment la conversation se poursuit après que le composant renvoie le contrôle du flux vers la brique.

  • keepTurn(boolean) indique si la conversation doit passer à un autre état sans inviter d'abord l'utilisateur à entrer du texte.

    Si vous voulez définir keepTurn sur True, vous devez appeler keepTurn après avoir appelé reply car reply définit implicitement keepTurn sur false.

  • transition(action) fait passer le dialogue à l'état suivant une fois que toutes les réponses, le cas échéant, ont été envoyées. L'argument action facultatif nomme l'action (résultat) renvoyée par le composant.

    Si vous n'appelez pas transition(), la réponse est envoyée mais la boîte de dialogue reste dans l'état et l'entrée utilisateur suivante revient à ce composant. Autrement dit, invoke() est appelé à nouveau.

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

Voici quelques cas d'emploi courants dans lesquels vous pouvez utiliser keepTurn et transition pour contrôler le flux de dialogue :

Cas d'emploi Valeurs définies pour keepTurn et transition

Composant personnalisé qui passe à un autre état sans inviter d'abord l'utilisateur à entrer du texte.

  1. Le cas échéant, utilisez context.reply(<reply>) pour envoyer une réponse.

  2. Définissez context.keepTurn(true).

  3. Définissez context.transition avec une chaîne supportedActions (par exemple, context.transition("success")) ou sans argument (par exemple, context.transition()).

Par exemple, ce composant personnalisé met à jour une variable avec la liste des valeurs à afficher immédiatement dans l'état suivant du flux de dialogue.
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();
 }

Composant personnalisé qui permet à la brique d'attendre une saisie après le retour du contrôle à la brique et avant le passage de la brique à un autre état.

  1. Le cas échéant, utilisez context.reply(<reply>) pour envoyer une réponse.

  2. Définissez context.keepTurn(false).

  3. Définissez context.transition avec une chaîne supportedActions (context.transition("success")) ou sans argument (context.transition()).

Par exemple :
context.keepTurn(false);
context.transition("success");
Composant personnalisé qui obtient l'entrée utilisateur sans renvoyer le contrôle de flux à la brique. Par exemple :
  • Un composant transmet la saisie utilisateur pour interroger un moteur de recherche back-end. Si la brique ne gère qu'un seul résultat, mais que la requête en renvoie plusieurs, le composant invite l'utilisateur à fournir davantage d'informations pour filtrer les résultats. Dans ce cas, le composant personnalisé continue à gérer la saisie utilisateur : il conserve la conversation jusqu'à ce que le moteur de recherche renvoie un seul résultat. Lorsqu'il obtient un seul résultat, le composant appelle context.transition() pour passer à un autre état, tel qu'établi dans la définition de flux de dialogue.

  • Un composant traite un questionnaire et passe uniquement à l'état suivant lorsqu'une réponse a été apportée à toutes les questions.

  1. N'appelez pas transition.

  2. Définissez keepTurn(false).

Par exemple, ce composant personnalisé génère un devis, puis affiche les boutons Yes et No pour demander un autre devis. Il revient à la brique lorsque l'utilisateur clique sur 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);
    };
  }

Si un composant ne passe pas à un autre état, il doit suivre son propre état, comme le montre l'exemple ci-dessus.

Pour une gestion d'état plus complexe, par exemple pour donner à l'utilisateur la possibilité d'annuler l'opération si une extraction de données prend trop de temps, vous pouvez créer et utiliser une variable de contexte. Par exemple : context.variable("InternalComponentWaitTime", time). Si vous utilisez une variable de contexte, n'oubliez pas de la réinitialiser ou de la définir sur NULL avant d'appeler context.transition.

Tant que vous n'avez pas de modification d'état, toutes les valeurs transmises en tant que propriétés de composant sont disponibles.

L'appel de composant se répète sans entrée utilisateur. Par exemple :

  • Un composant envoie une commande ping à un service distant pour obtenir le statut d'une commande jusqu'à ce que le statut soit renvoyé comme accepted ou que le composant expire. Si le statut accepted n'est pas renvoyé après la cinquième commande ping, le composant change d'état avec le statut failedOrder.

  • Le composant personnalisé transfère l'utilisateur à un agent physique. Dans ce cas, la saisie utilisateur et les réponses sont envoyées à l'agent. Le composant passe à un autre état lorsque l'utilisateur ou l'agent met fin à sa session.

  • N'appelez pas transition.

  • Définissez context.keepTurn(true).

Voici un exemple conçu spécialement pour vous montrer comment répéter l'appel sans attendre l'entrée utilisateur, puis comment réaliser la transition ensuite :
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);
  }
}

Accès au back-end

Vous constaterez que plusieurs bibliothèques Node.js ont été créées pour faciliter les demandes HTTP et que la liste change fréquemment. Examinez les avantages et les inconvénients des bibliothèques actuellement disponibles, et déterminez lesquelles fonctionnent le mieux pour vous. Nous vous recommandons d'utiliser une bibliothèque qui prend en charge les promesses afin de tirer parti de la version async de la méthode invoke, introduite dans la version 2.5.1, et d'utiliser le mot-clé await pour écrire vos appels REST de façon synchrone.

Vous avez la possibilité d'utiliser l'API node-fetch préinstallée avec le kit SDK Bots Node. Vous trouverez des exemples de code dans Accès au back-end à l'aide d'appels REST HTTP dans la documentation du kit SDK Bots Node.

Utilisation du kit SDK pour accéder à la charge utile de demande et de réponse

Les méthodes d'instance CustomComponentContext permettent d'obtenir le contexte de l'appel, de modifier les variables et d'y accéder, et de renvoyer les résultats au moteur de dialogue.

Vous trouverez plusieurs exemples de code pour l'utilisation de ces méthodes dans Ecriture de composants personnalisés et Messagerie de conversation dans la documentation du kit SDK Bots Node.

La documentation de référence du kit SDK est disponible à l'adresse suivante : https://github.com/oracle/bots-node-sdk.

Composants personnalisés pour les briques multilingues

Lorsque vous concevez un composant personnalisé, vous devez déterminer si ce composant sera utilisé par une brique qui prend en charge plusieurs langues.

Si le composant personnalisé doit prendre en charge les briques multilingues, vous devez savoir si les briques sont configurées pour la prise en charge des langues natives ou le service de traduction.

Lorsque vous utilisez un service de traduction, vous pouvez traduire le texte de la brique. Vous disposez des options suivantes :

Pour les compétences en langue maternelle, vous avez les options suivantes :

  • Transmettez les données à la brique dans des variables, puis générez le texte à partir d'un composant système en transmettant les valeurs des variables à une clé de groupe de ressources, comme décrit dans Utilisation d'un composant système pour référencer un groupe de ressources. Avec cette option, le composant personnalisé doit avoir des propriétés de métadonnées pour que la brique transmette les noms des variables dans lesquelles stocker les données.

  • Utilisez le groupe de ressources du composant personnalisé pour composer la réponse du composant personnalisé, comme décrit dans Groupes de ressources de référence à partir du composant personnalisé. Utilisez la méthode conversation.translate() pour obtenir la chaîne de groupe de ressources à utiliser pour votre appel vers context.reply(). Cette option n'est valide que pour les définitions de groupe de ressources qui utilisent des paramètres positionnels (numérotés). Elle ne fonctionne pas pour les paramètres nommés. Avec cette option, le composant personnalisé doit avoir une propriété de métadonnées pour le nom de la clé de groupe de ressources, et les paramètres de la clé de groupe de ressources nommée doivent correspondre à ceux utilisés dans l'appel de context.reply().

Voici un exemple d'utilisation du regroupement de ressources à partir du composant personnalisé. Dans cet exemple, fmTemplate serait défini sur quelque chose comme ${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();  
  }
};

Vérification du fonctionnement du composant dans les assistants numériques

Dans une conversation avec assistant numérique, l'utilisateur peut interrompre un flux de conversation en modifiant le sujet. Par exemple, si un utilisateur lance un flux pour effectuer un achat, il peut interrompre ce flux afin de demander le montant des crédits dont il dispose sur une carte-cadeau. Nous appelons ce phénomène non sequitur. Pour permettre à l'assistant numérique d'identifier et de gérer des non sequiturs, appelez la méthode context.invalidInput(payload) lorsqu'une réponse de variation utilisateur n'est pas comprise dans le contexte du composant.

Dans une conversation numérique, l'exécution détermine si une entrée non valide est un non sequitur en recherchant les correspondances de réponse dans toutes les briques. Si des correspondances sont trouvées, le flux est réacheminé. Dans le cas contraire, un message s'affiche, s'il est fourni, pour inviter l'utilisateur à saisir des données, puis le composant est exécuté de nouveau. La nouvelle entrée est transmise au composant dans la propriété text.

Dans une conversation de brique autonome, l'exécution affiche le message, s'il est fourni, qui invite l'utilisateur à effectuer une saisie, puis exécute à nouveau le composant. La nouvelle entrée est transmise au composant dans la propriété text.

Cet exemple de code appelle context.invalidInput(payload) lorsque l'entrée n'est pas convertie en nombre.

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

Voici un exemple de la façon dont un assistant numérique gère les entrées non valides au moment de l'exécution. Pour la première réponse relative à l'âge (twentyfive), il n'y a aucune correspondance dans les briques inscrites auprès de l'assistant numérique, donc la conversation affiche le message context.invalidUserInput indiqué. Dans la deuxième réponse relative à l'âge (send money), l'assistant numérique trouve une correspondance ; il demande ainsi s'il doit réacheminer vers ce flux.


Description de l'image components-nonsequitur-conversation.png ci-après
Description de l'illustration components-nonsequitur-conversation.png

Vous devez appeler context.invalidInput() ou context.transition(). Si vous appelez les deux opérations, assurez-vous que la variable system.invalidUserInput est toujours définie si un message supplémentaire est envoyé. Notez également que les composants d'entrée utilisateur (tels que les composants Réponse commune et Résoudre les entités) réinitialisent system.invalidUserInput.

Par exemple, supposons que vous modifiez le composant AgeChecker comme indiqué ci-dessous, et que vous appelez context.transition() après 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;
}

Dans ce cas, le flux de données doit revenir à askage pour que l'utilisateur obtienne deux messages de sortie : "Age input not understood. Please try again", suivi de "How old are you?". Voici comment cela peut être géré dans un flux de dialogue en mode 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"

Exécution du service de composant dans un environnement de développement

Pendant la phase de développement, vous pouvez démarrer un service local pour afficher le package de composants personnalisé.

  1. Dans le dossier de niveau supérieur, ouvrez une fenêtre de terminal et exécutez les commandes suivantes pour démarrer le service :
    npm install
    npm start
  2. Pour vérifier que le service est en cours d'exécution, entrez l'URL suivante dans un navigateur :
    localhost:3000/components

    Le navigateur affiche les métadonnées de composant.

  3. Si vous disposez d'un accès Internet direct, vous pouvez accéder à l'environnement de développement à partir d'une brique :
    1. Installez un tunnel, tel que ngrok ou Localtunnel.
    2. Si vous passez par un proxy, accédez à http://www.whatismyproxy.com/ pour obtenir l'adresse IP externe de votre proxy, puis, dans la fenêtre de terminal que vous utiliserez pour démarrer le tunnel, entrez les commandes suivantes :
      export https_proxy=http://<external ip>:80
      export http_proxy=http://<external ip>:80
    3. Démarrez le tunnel et configurez-le pour afficher le port 3000.
    4. Dans Oracle Digital Assistant, accédez à l'onglet Composants Icône Composants de la brique et ajoutez un service de composant externe avec l'URL de métadonnées définie sur https://<tunnel-url>/components.
      Vous pouvez utiliser n'importe quelle valeur pour le nom utilisateur et le mot de passe.
Vous pouvez à présent ajouter des états pour les composants du service au flux de dialogue et les tester à partir la page Aperçu de la brique.