Accéder à un agent API.AI depuis une application Ionic

API.AI est une plate-forme permettant de développer des agents comprenant le langage naturel.
Parmi les kits de développement proposés par API.AI, le plugin Apache Cordova cordova-plugin-apiai est celui qui vous permettra d'accéder à l'un de vos agents depuis une application Ionic.

Voici quelques indications pour intégrer cordova-plugin-apiai dans une application Ionic développée en langage TypeScript.

Le point de départ est donc une application Ionic, créée avec l'outil en ligne de commande Ionic CLI, version 3.

Pour installer le plugin Cordova, utilisez la commande suivante :

ionic cordova plugin add cordova-plugin-apiai

L'étape suivante consiste à intervenir sur le fichier TypeScript src/app/app.component.ts, dans la méthode initializeApp(), en ajoutant l'appel à ApiAIPlugin.init() :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
initializeApp() {
  this.platform.ready().then(() => {
    // Okay, so the platform is ready and our plugins are available.
    // Here you can do any higher level native things you might need.
    this.statusBar.styleDefault();
    this.splashScreen.hide();

    ApiAIPlugin.init(
      {
          clientAccessToken: "<your client access key here>", 
          lang: "fr" // set lang tag from list of supported languages 
      }, 
      function(result) { /* success processing */ },
      function(error) { /* error processing */ }
    );
  });
}

Si vous utilisez un éditeur de code comme Visual Studio Code, la référence ApiAIPlugin sera signalée en erreur ; cette référence est apportée par le plugin cordova-plugin-apiai, et pour corriger l'erreur, il suffit d'ajouter la déclaration suivante en début de fichier.

1
declare var ApiAIPlugin: any;

A condition d'utiliser la déclaration ci-dessus dans un fichier source .ts, on peut dès lors utiliser la méthode ApiAIPlugin.requestVoice() dans un composant de l'application Ionic.
Voici un exemple d'appel de cette méthode, dans une méthode de composant :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
ask() {
  let self: any = this;
  self.speech = '';    

  try {     
    ApiAIPlugin.requestVoice(
      {}, // empty for simple requests, some optional parameters can be here 
      (response) => {
          self.speech = response.result.fulfillment.speech;
          console.log(self.speech);
          self.ref.detectChanges();
      },
      (error) => {
          // place your error processing here 
          self.speech = error.message;
      });                
  } catch (e) {
      alert(e);
  }
}

Cet exemple montre en plus une solution permettant d'accéder au membre speech du composant, depuis les fonctions callbacks passées dans l'appel ApiAIPlugin.requestVoice().
Le but est ici d'afficher le contenu du membre speech dans la vue du composant, avec la réponse de l'agent, ou bien un message d'erreur.

Notez que l'on passe par une variable intermédiaire, self, pour y accéder : en effet, étant dans du code JavaScript, l'utilisation directe de this dans les callbacks aurait un autre sens.

Par ailleurs, affecter une nouvelle valeur à speech ne permet pas que la vue qui l'utilise soit rafraîchie automatiquement.
Pour pallier à ce problème, on a recours à la classe Angular ChangeDetectorRef, dont une instance est injectée par le constructeur du composant (avec déclaration du membre ref) :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import { Component, ChangeDetectorRef } from '@angular/core';

declare var ApiAIPlugin: any;

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {
  speech: string;

  constructor(private ref: ChangeDetectorRef) {
  }

  ask() {
    // ...
  }
}