Office Graph API et Cortana - Chapitre 3 : Intégration avec Cortana

 English version / Version anglaise

Preface

 

Bienvenue dans le troisième et dernier chapitre de cet article dédié à l’intégration de l’Office Graph API au sein d’une application .Net Windows Phone 8.1 et Cortana. Dans les chapitres précédents, nous avons vu comment interroger en C# / XML l’Office Graph pour retrouver des éléments de son réseau, tout en se connectant de façon sécurisée à Azure Active Directory grâce à la librairie ADAL. Nous avons pu retrouver des éléments du graphe et les afficher pour les parcourir.

Vous pouvez TELECHARGER LE CODE SOURCE complet de cette App dans le fichier ZIP tout en bas de chaque chapitre.

Cet article est publié en vue des TechDays 2015, qui auront lieux du 10 au 12 Janvier 2015 au Palais des Congrés de Paris. Cette année j'aurais la chance de coanimer la session dédiée à Office Graph au côté d'Alexandre Cipriani et Stéphane Palluet. Venez nombreux à notre session pour découvrir cet exemple et bien plus encore. 

Pour ce chapitre, je tiens à remercier particulièrement Steve Peschka. Je vous recommande vivement de lire son billet de blog, appelé CloudTopia qui présente comment intégrer Cortana, ce chapitre est grandement inspiré de son travail. Je vous recommande d'ailleurs de lire son blog, qui est une source d'information incroyable. Merci Steve !

 

Chapitre 1 : Introduction à L’Office Graph

Chapitre 2 : Comment faire des requêtes par code à l’Office Graph ?

Chapitre 3 : Intégration avec Cortana (cet article)

 

A propos des API de Cortana

 

Dans ce dernier article, nous allons maintenant nous intéresser à comment piloter nos recherches sur le graph grâce à des commandes vocales. Sur Windows Phone 8.1 et depuis quelques semaines en France, il est maintenant possible de piloter son téléphone à la voix, grâce à l’assistant Cortana. Cortana est une vraie interface de reconnaissance de la voix, permettant de parler avec son téléphone pour piloter ses demandes.

Dans cet exemple, nous allons utiliser le kit de développement de Cortana pour permettre de réaliser des commandes qui vont savoir interroger naturellement notre graphe d’entreprise, comme l’illustre le schéma suivant :

Lorsque l’on développe une application pour Cortana, on peut utiliser deux types de composants :

  • Le kit de reconnaissance vocale (dit SpeechRecognition) : permet d’écouter l’utilisateur, comprendre les phrases et mots qu’il prononce ;
  • Le kit de parole (dit SpeechSynthesis) : permet de faire parler Cortana, pour permettre par exemple à notre application de répondre aux commandes de l’utilisateur ;

En plus de l’intégration de ces deux composants, nous verrons que nous pouvons également indiquer à Cortana comment automatiquement lancer notre application, tout en interprétant la commande à ouvrir en même temps. 

 

A propos des commandes vocales

 

Pour interroger vocalement l’Office Graph, nous pourrions par exemple demander à l’application d’afficher des documents selon des axes de son graphe social. Ces axes pourrait être des personnes de son entourage, son manager, les éléments populaire autour de soi, les documents que nous avons lus, etc. etc.

Dans cet exemple, nous allons nous baser sur des formes d’instruction vocales, qui vont nous permettre de comprendre quel est l’axe que souhaite voir l’utilisateur. Nous pouvons par exemple interroger le graphe avec des commandes détaillées dans le tableau ci-dessous. Il est important de comprendre que chacune de ces commandes possède un ou plusieurs mots qui vont être détectés dans une phrase pour lancer la commande :

Exemple de commande

Requête Office Graph

«  Documents populaires »

Equivalent à la page d’accueil de Delve

« Mes travaux »

Eléments modifiés récemment par l’utilisateur sur ses différents espaces collaboratifs

«  Mes documents lus »

Eléments récemment lus par l’utilisateur

«  Documents partagés avec moi  »

Eléments qui ont été partagés récemment avec l’utilisateur

« Autour de moi »

Eléments  partagés récemment autour de l’utilisateur (réseau proche)

«  Documents de mon manager »

Eléments partagés récemment par le manager de l’utilisateur

«  Documents de mon équipe »

Eléments partagés récemment par les personnes de l’équipe de l’utilisateur

«  Documents de 'Pierre Dupont'  »

Eléments modifiés récemment par Pierre Dupont. Pour cette requête on peut utiliser n’importe quel terme après « de » pour rechercher des documents d’une personne. La recherche va bien fonctionner pour les prénoms. Pour les noms de famille, l’interprétation sera en fonction de la capacité de Cortana à comprendre et orthographié un nom propre.

«  Documents à propos de 'Office'  »

Eléments modifiés récemment à propos d’une thématique ou d’un mot clé. On peut par exemple utiliser le mot clé « à propos de » pour rechercher avec les mots prononcés après le mot clé. On peut ainsi rechercher à partir d’une thématique, un terme utilisé récemment, le nom d’un produit, d’un service, etc.

 

 

Voyons maintenant comment implémenter ces commandes avec Cortana et les API vocales de Windows Phone.

 

Les classes de Cortana

 

Pour utiliser Cortana, il faut inclure les deux namespaces correspondant aux librairies de reconnaissance vocale et de diction:

 using Windows.Media.SpeechRecognition;
using Windows.Media.SpeechSynthesis;

 

Comment faire parler Cortana ?

 

Nous allons commencer par la partie SpeechSynthesis, afin de faire parler Cortana et lui permettre de nous répondre lors de commandes vocales.

Pour cela, nous allons d’abord initialiser un objet de type SpeechSynthesizer. Lors de cette initialisation, on peut préciser quelle est le type de voix et la langue utilisée par le moteur de parole. Dans notre exemple nous allons par exemple choisir d’utiliser la voix féminine et la langue française, avec le code suivant :

 SpeechSynthesizer Synthesizer = new SpeechSynthesizer();
foreach (var voice in SpeechSynthesizer.AllVoices)
{
    if (voice.Gender == VoiceGender.Female && voice.Language.ToLowerInvariant().Equals("fr-fr"))
    {
        Synthesizer.Voice = voice;
    }
}

 

Avec l’objet synthétiseur, nous allons pouvoir lui faire dire des phrases en Français. Nous pouvons utiliser deux types de phrases :

  • Des phrases sous forme de chaînes de caractères simples, sans aucune forme de formattage grâce à la méthode SynthesizeTextToStreamAsync ;
  • Des phrases formatées au format SSML (format XML) grâce à la méthode SynthesizeSsmlToStreamAsync. L’avantage de ce format est que l’on peut par exemple contrôler le niveau d’intonation de la voix sur tel ou tel mot ;

Prenons l’exemple suivant pour faire dire à Cortana « Désolé, je n’ai pas compris » lorsque nous n’arrivons pas à comprendre la commande lancée par l’utilisateur.

En SSML, on peut représenter la phrase de la façon suivante pour accentuer l’intonation du mot « désolé » :

 <speak version='1.0' xmlns='https://www.w3.org/2001/10/synthesis' xml:lang="fr-FR">
  <prosody pitch='+35%' rate='-10%'> Désolé</prosody>
  <prosody pitch='-15%'> je n'ai pas compris.</prosody>
</speak>

Pour que Cortana prononce cette page, il suffit d’écrire la méthode code suivant en donnant en argument la chaine contenant le texte au format SSML :

 public async void StartSpeakingSsml(string ssmlToSpeak)
{
    // Generate the audio stream from plain text.
    SpeechSynthesisStream stream = await this.Synthesizer.SynthesizeSsmlToStreamAsync(ssmlToSpeak);
    // Send the stream to the media object.
    var mediaElement = new MediaElement();
    mediaElement.SetSource(stream, stream.ContentType);
    mediaElement.Play();
}

 

Comment faire écouter Cortana ?

 

Maintenant que nous avons vu commencer faire parler Cortana, intéressons-nous à comment faire en sorte que Cortana écoute les paroles et comment les interpréter par code.

La première étape est d’initialiser l’objet SpeechRecognizer, qui va nous servir pour lancer l’écoute de la commande. Avec cet objet, nous pourrons également définir une méthode qui sera exécutée lorsque l’opération d’écoute est terminée.

Le statut de l’écoute est renvoyé via l’argument de type AsyncStatus qui indique le résultat (Completed ou Error). Le texte sous forme de string est renvoyé via la méthode GetResults qui nous renvoie un objet de type SpeechRecognitionResult.

Dans l’exemple ci-dessous, nous allons par exemple initialiser le SpeechRecognizer, puis définir le code qui va être exécuté lors de la réception de la commande vocale. Si le statut est bon, nous récupérons le contenu du texte et on va regarder sur le texte contient le mot clé « travaux ». Si c’est le cas, nous déclencherons une méthode (LoadMyWork) qui appellera l’Office Graph sur les travaux en cours de l’utilisateur. Dans le cas contraire nous appellerons une méthode qui fera parler Cortana pour lui indiquer que la commande n’a pas été comprise.

 private async void InitializeRecognizer()
{
    this.Recognizer = new SpeechRecognizer();
    SpeechRecognitionTopicConstraint topicConstraint
        = new SpeechRecognitionTopicConstraint(SpeechRecognitionScenario.Dictation, "Travaux");

    this.Recognizer.Constraints.Add(topicConstraint);
    await this.Recognizer.CompileConstraintsAsync(); // Required

    recoCompletedAction = new AsyncOperationCompletedHandler<SpeechRecognitionResult>((operation, asyncStatus) =>
    {
        Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
        {
            this.CurrentRecognizerOperation = null;
            this.SearchTextBox.Text = "dictez votre commande";

            switch (asyncStatus)
            {
                case AsyncStatus.Completed:
                    SpeechRecognitionResult result = operation.GetResults();
                    if (!String.IsNullOrEmpty(result.Text))
                    {
                        string res = result.Text.ToLower();
                                     
                        if (res.Contains("mes travaux"))
                            LoadMyWork();
                        else
                            speechHelper.WrongCommand();
                    }
                    break;
                case AsyncStatus.Error:
                    speechHelper.WrongCommand();
                    break;
                default:
                    break;
            }
        }).AsTask().Wait();
    });
}

 

Nous allons maintenant regarder comment lancer une écoute de Cortana dans l’application. Au clic sur un bouton (le micro dans notre cas), nous allons lancer l’écoute active de Cortana. Pour cela, nous utilisons la méthode RecognizeAsync, en indiquant la méthode qui va être appelée lorsque l’opération d’écoute sera terminée : 

 private void StartListening()
{
    try
    {
        beepStart.Play();
        this.SearchTextBox.Text = "Ecoute...";

        // Start listening to the user and set up the completion handler for the result
        // this fires when you press the button to start listening 
        this.CurrentRecognizerOperation = this.Recognizer.RecognizeAsync();
        this.CurrentRecognizerOperation.Completed = recoCompletedAction;
    }
    catch (Exception)
    {
        beepStop.Play();
        recoCompletedAction.Invoke(null, AsyncStatus.Error);
    }
}

 

Voyons voir maintenant comment fonctionne l’application :

 

Capture d’écran

Description

#1

L’utilisateur arrive sur l’interface de l’application.

Il peut cliquer sur le micro pour démarrer l’écoute de la commande vocale.

#2

Le texte de la zone de texte en bas change avec le texte « Ecoute… ».

#3

Si la commande vocale a été comprise, nous allons avoir un message vocal de confirmation de la part de Cortana et la requête est affichée dans la zone de texte central.

#4

La requête de l’Office Graph retourne les résultats, et nous les affichons à l’utilisateur via l’interface réalisée dans le chapitre précédent.

 

Voilà, nous sommes maintenant capables de lancer des commandes vocales via Cortana, comprendre les commandes réalisées et lancer l’Office Graph selon les critères choisis par l’utilisateur.

Il ne nous reste plus qu’à ajouter la « cerise sur le gâteau », en permettant de démarrer des recherches sur l’Office Graph sans même démarrer manuellement l’application My Office Graph !

 

Comment utiliser Cortana pour démarrer directement nos commandes vocales ?

 

C’est une des fonctionnalités les plus impressionnantes de Cortana : sa capacité à apprendre de nouvelles commandes grâce aux applications installées sur le téléphone.

Lorsqu’une application utilise cette capacité, l’utilisateur a la possibilité d’envoyer des commandes vocales à une application directement depuis l’interface principale de Cortana. Cortana va ouvrir l’application en question et « envoyer » à l’application la commande vocale identifiée. Cortana va être capable de comprendre que telle ou telle commande concerne telle ou telle application, grâce à un système de préfixes.

Dans notre exemple, nous allons définir qu’en commençant sa phrase par « Office Graph », Cortana pourra savoir s’il s’agit d’une commande spécifique vers l’Office Graph et démarrer l’application My Office Graph. Elle va également analyser le texte après les mots « Office Graph » pour détecter une commande prédéfinie et lancer cette commande au sein de l’application.

Nous pourrions définir les commandes suivantes pour démarrer des requêtes : « Office Graph mes travaux », « Office Graph, recherche les éléments partagés », etc. etc.

Pour cela, il nous faut définir un fichier de commande vocale, qui est un fichier au format XML inclus dans l’application. Ce fichier va contenir le préfixe de l’application, ainsi que les différentes commandes. Les différentes commandes vont définir le texte d’exemple, les mots écoutés, qu’ils soient facultatifs ou obligatoires :

 <?xml version="1.0" encoding="utf-8"?>

<!-- Be sure to use the new v1.1 namespace to utilize the new PhraseTopic feature -->
<VoiceCommands xmlns="https://schemas.microsoft.com/voicecommands/1.1">
    
  <CommandSet xml:lang="fr-fr" Name="officeGraphCommandSet">
    <!-- The CommandPrefix provides an alternative to your full app name for invocation -->
    <CommandPrefix> Office Graph </CommandPrefix>
    <!-- The CommandSet Example appears in the global help alongside your app name -->
    <Example> affiche mes travaux </Example>

    <Command Name="popular">
      <Example> eléments populaires </Example>
      <ListenFor>[Affiche] [Trouve] [Recherche] [les] [éléments] populaire</ListenFor>
      <Feedback>Recherche des éléments populaires...</Feedback>
      <Navigate  />
    </Command>
...

 

Pour charger les commandes vocales dans Cortana, on peut exécuter la méthode ci-dessous lors de l’initialisation de l’application. Cette méthode va installer les commandes contenues dans le fichier VoiceCommandDefinition_8.1.xml contenu dans le package de l’App :

 /// <summary>
/// Install the voice commands
/// </summary>
private async void InstallVoiceCommands()
{
    const string wp81vcdPath = "ms-appx:///VoiceCommandDefinition_8.1.xml";

    Uri vcdUri = new Uri(wp81vcdPath);
    StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(vcdUri);
    await VoiceCommandManager.InstallCommandSetsFromStorageFileAsync(file);
}

 

Une fois les commandes installées, l’application est visible depuis l’interface d’exemple de Cortana. Pour le vérifier, il nous suffit d’ouvrir Cortana (en bouton sur le bouton Recherche du téléphone par exemple), descendre tout en bas pour voir les applications installées utilisant Cortana, cliquer sur notre app « My Office Graph » et la liste des exemples de commandes disponibles est affichée :

 

Maintenant que les commandes sont installées, Cortana va être capable de reconnaitre notre commande lors d’une saisie vocale, récapituler la commande comprise puis lancer l’application. Les captures d’écran suivantes montrent le processus pour l’utilisateur :

 

Lorsque Cortana va lancer notre application, nous allons être notifiés dans le code via l’évènement OnActivated de notre App. Cortana va nous envoyer un argument de type « VoiceCommand » pour lequel nous allons être capables de connaître le nom de la commande détectée et éventuellement la page qui doit être ouverte avec cette commande :

 protected override void OnActivated(IActivatedEventArgs args)
{
// When a Voice Command activates the app, this method is going to 
// be called and OnLaunched is not. Because of that we need similar
// code to the code we have in OnLaunched
// For VoiceCommand activations, the activation Kind is ActivationKind.VoiceCommand
if (args.Kind == ActivationKind.VoiceCommand)
{
  // since we know this is the kind, a cast will work fine
  VoiceCommandActivatedEventArgs vcArgs = (VoiceCommandActivatedEventArgs)args;

  // The NavigationTarget retrieved here is the value of the Target attribute in the
  // Voice Command Definition xml Navigate node
  string voiceCommandName = vcArgs.Result.RulePath.First();
  string target = vcArgs.Result.SemanticInterpretation.Properties["NavigationTarget"][0];
…
}
}

 

Et voilà, nous avons maintenant réussit à intégrer l’Office Graph avec Cortana au sein d’une application Windows Phone 8.1. Nous sommes capables maintenant de voir notre graphe social d’entreprise en quelques secondes grâce à la voix. Nous sommes maintenant en permanence capables de connaître l’actualité de notre réseau dans notre organisation, et  de ne manquer aucun document, présentation, matrice Excel ou encore vidéo qui seraient publiés autour de nous !

Dans cet exemple, nous avons vu qu’il est simple d’interroger son graphe d’entreprise et de l’intégrer dans une application tiers. L’Office Graph est puissant et nous offre un moyen robuste pour intégrer une dimension sociale à toute application d’entreprise.

Nous pourrions avec les mêmes principes que ceux détaillés dans cet article, afficher dans une App ou un site Intranet un grand nombre d’informations susceptibles d’aider l’utilisateur final à retrouver ou identifier en quelques secondes.

Merci pour votre attention et intérêt pour cet article, et amusez-vous bien avec l’Office Graph !

MyOfficeGraph-20150113.zip