Voir le flux RSS

Blog de Hinault Romaric (.NET Core, ASP.NET Core, Azure, DevOps)

Analyse sentimentale des tweets avec Text Analyctics API, partie II : utilisation de l'API Text Analyctics

Noter ce billet
par , 28/02/2020 à 11h00 (226 Affichages)
Dans la première partie de ce billet de blog, nous avons créer l'application d'exemple et apporter les modifications nécessaires à cette dernière pour rechercher des tweets sur Twitter en utilisant l'API TwwtinviAPI.

Dans ce second billet, nous allons mettre à jour notre application afin qu'elle puisse utiliser Azure Text Analytics API pour analyser les tweets et détecter les sentiments exprimés par ces derniers.

C’est quoi Azure Text Analytics ?

Text Analytics est un service cognitif de traitement en langage naturel de texte brut. Ce service inclut la détection de la langue de l’utilisateur, la détection des mots clés, la détection d’entités et l’analyse des sentiments.

  • Détection du langage


Après analyse d’un texte, Text Analytics détermine la langue dans laquelle le texte est écrit et attribut un score à ce dernier, compris entre 0 et 1. Plus le score est proche de 1, plus la réponse retournée par le service est précise. Text Analytics supporte près de 120 langues.

  • Détection des sentiments


Text Analytics est capable d’analyser le texte et ressortir le sentiment exprimé par l’auteur du texte. La valeur est comprise entre 0 et 1. Un score proche de 1 est un sentiment position, tandis qu’un score proche de 0 est un sentiment négatif. Cette fonctionnalité est pratique pour analyser les retours des utilisateurs sur un produit donné.

Pour utiliser Text Analytics, vous devez disposer d’un compte Microsoft Azure. Vous pouvez en créer un gratuitement si vous n’en disposez pas d’un.

Création du service Azure Text Analytics

La première chose à faire sera de créer le service Azure Text Analytics en utilisant le portail Azure (https://portal.azure.com/).

Cliquez sur “Créer une ressource”, dans la zone de saisie de la fenêtre qui va s’afficher, saisissez “Text Analytics”, puis sélectionnez ce qui sera affiché dans la liste déroulante :


Cliquez sur Créer.

Dans la fenêtre qui va s’afficher, renseigner les informations sur votre service (nom, emplacement, groupe de ressources et pricing). Prenez F0 pour le pricing. Ce dernier est gratuit. La tarification est fonction de l’utilisation. La tarification gratuite permet un maximum de 5 000 appels au service sur 30 jours.


Une fois les informations renseignées, cliquez sur Créer.

Le service sera créé et déployé dans le groupe de ressources correspondant. Un message de confirmation sera affiché dans le portail.

Dans la vue d’ensemble du service, veuillez noter le endpoint et les clés d’utilisation mis à votre disposition.



Ajout du package Text Analytics API

Revenez à votre application dans Visual Studio. Vous allez utiliser le gestionnaire Nuget pour installer le package Microsoft.Azure.CognitiveServices.Language.Text :

Nom : img7.png
Affichages : 28
Taille : 38,3 Ko

Ensuite, vous devez modifier le fichier de configuration appsettings.json, pour y ajouter les informations de connexion à votre service TextAnalytics :

Code json : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
"Textanalytics": {
 
    "SubscriptionKey": "f158c05875xxxxxxxxxxxxx",
    "EndPoint": "https://canadacentral.api.cognitive.microsoft.com"
  }

Subscriptionkey doit contenir la clé de souscription au service obtenu depuis le portail Azure.

Endpoint doit contenir l’adresse du service, sans le numéro de version : https://[region].api.cognitive.microsoft.com.

Le fichier AppSettings au complet devrait ressembler à ce qui suit :

Code json : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{
  "Logging": {
    "LogLevel": {
      "Default": "Warning"
    }
  },
  "Twitter": {
    "ConsumerKey": "6vm8vRNxxxxxxxxx",
    "ConsumerSecret": "PgXYSeJAL4xOgxxxxxxxxxxxxxxxxxxx",
    "AccesToken": "143790187-cEFwappMEH3fJ4Hxxxxxxxxxxxxxxxxxxx",
    "AccesTokenSecret": "RIwUSDOqq7U1IkONVNFCSBxxxxxxxxxxxxxxxxxxxx"
 
  },
  "Textanalytics": {
 
    "SubscriptionKey": "f158c058756e4xxxxxxxxxxxxxxx",
    "EndPoint": "https://canadacentral.api.cognitive.microsoft.com"
  },
  "AllowedHosts": "*"
}

Accès au service

Dans le dossier Services, vous allez ajouter l’interface ITextAnalyticsService avec le code suivant :

Code csharp : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
public interface ITextAnalyticsService
    {
        Task<IList<ResultModel>> Sentiment(IList<ResultModel> result);
 
        Task<IList<ResultModel>> Language(IList<string> tweett);
    }

En effet, nous allons implémenter deux méthodes. La première pour la détection de la langue de l’utilisateur et la seconde pour détecter les sentiments. À ce stade, vous devez créer une classe TextAnalycticsService qui implémente l’interface ItextAnalyticsService :

Code csharp : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/// <summary>
    /// Service pour l'analyse sentimentale
    /// </summary>
    public class TextAnalyticsService : ITextAnalyticsService
    {
        /// <summary>
        /// Journalisation
        /// </summary>
        private readonly ILogger<TextAnalyticsService> _logger;
 
        /// <summary>
        /// Client pour l'accès à l'API TextAnalytics
        /// </summary>
        private readonly ITextAnalyticsClient _client;
 
        /// <summary>
        /// 
        /// </summary>
        /// <param name="logger">Requis pour la journalisation</param>
        /// <param name="client">Requis pour le client TexteAnalytics</param>
        public TextAnalyticsService(ILogger<TextAnalyticsService> logger,  ITextAnalyticsClient client)
        {
            _logger = logger;
            _client = client;
        }
 
        public Task<IList<ResultModel>> Language(IList<string> tweett)
        {
            throw new NotImplementedException();
        }
 
        public Task<IList<ResultModel>> Sentiment(IList<ResultModel> result)
        {
            throw new NotImplementedException();
        }
    }

Le constructeur de cette classe doit prendre en paramètre les objets de type ILogger, ITextAnalyticsClient. Les instances correspondantes seront fournies par le conteneur d’injection de dépendance de ASP.NET Core.

Passons à l’implémentation des méthodes pour la détection de la langue et l’analyse sentimentale.

Détection de la langue :

La méthode DetectLanguageAsync du Client TextAnalytics API est utilisée pour effectuer la détection de la langue. Elle prend en paramètre un objet de type LanguageBatchInput. Cet objet est initialisé en passant en paramètre une liste de LanguageInput.

Le LanguageInput est une entité ayant une propriété Text, qui est le texte à analyser et une propriété Id qui est l’identifiant attribué au texte.
Nous devons mettre en place le code permettant d’initialiser le LanguageBatchInput en utilisant la liste des tweets :

Code csharp : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public async Task<IList<ResultModel>> Language(IList<string> tweets)
        {
            //Journalisation
            _logger.LogInformation("TextAnalyticsService.Language called");
 
            //Initialisation d'une liste de LanguageInput pour la requête 
            var languagesInput = new List<LanguageInput>();
 
            //Création du document qui sera analysé. Ajout des tweets au document en attribuant à chacun des identifiant. 
            int i = 1;
            foreach (string tweet in tweets)
            {
                languagesInput.Add(new LanguageInput(id:i.ToString(), text:tweet));
                i++;
            }
 
            //..
        }

Ensuite, vous devez appeler _client.DetectLanguageAsync pour exécuter votre requête. Cette fonction va retourner un objet de type LanguageBatchResult contenant une propriété Documents représentant les résultats pour chaque texte de la requête. Vous devez itérer sur cette liste. Chaque document est une entité de type DetectedLanguage qui dispose des propriétés Name pour la langue détectée, Iso6391Name pour le format Iso de la langue détectée et le Score qui représente le dégrée de confiance que le service attribut au résultat qu’il retourne. Plus ce score est proche de 0, plus le risque d’erreur dans l’information retournée est considérable.
Le code pour cette partie est le suivant :


Code csharp : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//Passage du document à l'API pour la détection de la langue
            var langResults = await _client.DetectLanguageAsync(false, new LanguageBatchInput(languagesInput));
 
            //Initialisation de l'objet de retour
            var resultsModel = new List<ResultModel>();
 
            //AJout des résultats de la détection de la langue au resulatModels
            foreach(var document in langResults.Documents)
            {
                resultsModel.Add(new ResultModel { Language = document.DetectedLanguages[0].Name,
                    LanguageIso = document.DetectedLanguages[0].Iso6391Name, Id = document.Id,
                    Text = tweets.ElementAt(int.Parse(document.Id) - 1) });
 
                _logger.LogInformation($"Document ID: {document.Id} , Language: {document.DetectedLanguages[0].Name}");
            }
 
            return resultsModel;

Analyse sentimentale

La méthode SentimentAsync du Client TextAnalytics API est utilisée pour effectuer l’analyse sentimentale. Elle prend en paramètre un objet de type MultiLanguageBatchInput. Cet objet est initialisé en passant en paramètre une liste de MultiLanguageInput.

Le MultiLanguageInput est une entité ayant une propriété Text, qui est le texte à analyser, une propriété Language qui est la langue du texte au format ISO et une propriété Id qui est l’identifiant attribué au texte.
Nous devons mettre en place le code permettant d’initialiser le MultiLanguageBatchInput :

Code csharp : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public async Task<IList<ResultModel>> Sentiment(IList<ResultModel> result)
        {
            //Journalisation
            _logger.LogInformation("TextAnalyticsService.Sentiment called");
 
            //Initialisation d'une liste de MultiLanguageInput pour la requete 
            var multilanguagesInput = new List<MultiLanguageInput>();
 
            //Création du document qui sera analysé. Ajout du texte, de la langue du texte et l'ID. 
            foreach (var item in result)
            {
                multilanguagesInput.Add(new MultiLanguageInput(item.LanguageIso, item.Id, item.Text));
            }
 
            //…
        }

Vous devez appeler _client.SentimentAsync pour exécuter votre requête. Cette fonction va retourner un objet de type SentimentBatchResult contenant une propriété Documents représentant les résultats pour chaque élément de la requête. Vous devez itérer sur cette liste. Chaque document est une entité de type SentimentBatchResultItem qui dispose une propriété Score qui représente le score attribué suite à l’analyse sentimentale du texte. Une valeur proche de 0 signifie un sentiment négatif, tandis qu’un score proche de 1 signifie un sentiment positif.

Le code pour cette partie est le suivant :

Code csharp : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//Passage du document à l'API pour la detectiion des sentiments
            var sentimentResults = await _client.SentimentAsync(
                false,
                new MultiLanguageBatchInput(multilanguagesInput));
 
            //Lecture des reponses et ajout du score aux resultats 
            foreach (var document in sentimentResults.Documents)
            {
                result.Single(x => x.Id == document.Id).Score = document.Score.Value.ToString();
 
                _logger.LogInformation($"Document ID: {document.Id} , Sentiment Score: {document.Score:0.00}");
            }
 
            return result;

Le code au complet de la classe TextAnalyticsService est le suivant :


Code csharp : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
  /// <summary>
    /// Service pour l'analyse sentimentale
    /// </summary>
    public class TextAnalyticsService : ITextAnalyticsService
    {
        /// <summary>
        /// Journalisation
        /// </summary>
        private readonly ILogger<TextAnalyticsService> _logger;
 
        /// <summary>
        /// Client pour l'accès à l'API TextAnalytics
        /// </summary>
        private readonly ITextAnalyticsClient _client;
 
        /// <summary>
        /// 
        /// </summary>
        /// <param name="logger">Requis pour la journalisation</param>
        /// <param name="client">Requis pour le client TexteAnalytics</param>
        public TextAnalyticsService(ILogger<TextAnalyticsService> logger,  ITextAnalyticsClient client)
        {
            _logger = logger;
            _client = client;
        }
        /// <summary>
        /// Detection de la langue
        /// </summary>
        /// <param name="tweets">Liste des tweets à utiliser</param>
        /// <returns>Liste de type ResultModel</returns>
        public async Task<IList<ResultModel>> Language(IList<string> tweets)
        {
            //Journalisation
            _logger.LogInformation("TextAnalyticsService.Language called");
 
            //Initialisation d'une liste de LanguageInput pour la requête 
            var languagesInput = new List<LanguageInput>();
 
            //Création du document qui sera analysé. Ajout des tweets au document en attribuant à chacun des identifiant. 
            int i = 1;
            foreach (string tweet in tweets)
            {
                languagesInput.Add(new LanguageInput(id:i.ToString(), text:tweet));
                i++;
            }
 
            //Passage du document à l'API pour la détection de la langue
            var langResults = await _client.DetectLanguageAsync(false, new LanguageBatchInput(languagesInput));
 
            //Initialisation de l'objet de retour
            var resultsModel = new List<ResultModel>();
 
            //AJout des résultats de la détection de la langue au resulatModels
            foreach(var document in langResults.Documents)
            {
                resultsModel.Add(new ResultModel { Language = document.DetectedLanguages[0].Name,
                    LanguageIso = document.DetectedLanguages[0].Iso6391Name, Id = document.Id,
                    Text = tweets.ElementAt(int.Parse(document.Id) - 1) });
 
                _logger.LogInformation($"Document ID: {document.Id} , Language: {document.DetectedLanguages[0].Name}");
            }
 
            return resultsModel;
        }
 
 
        /// <summary>
        /// Detection des sentiments
        /// </summary>
        /// <param name="result"></param>
        /// <returns>Liste de type ResultModel</returns>
        public async Task<IList<ResultModel>> Sentiment(IList<ResultModel> result)
        {
            //Journalisation
            _logger.LogInformation("TextAnalyticsService.Sentiment called");
 
            //Initialisation d'une liste de MultiLanguageInput pour la requete 
            var multilanguagesInput = new List<MultiLanguageInput>();
 
            //Création du document qui sera analysé. Ajout du texte, de la langue du texte et l'ID. 
            foreach (var item in result)
            {
                multilanguagesInput.Add(new MultiLanguageInput(item.LanguageIso, item.Id, item.Text));
            }
 
            //Passage du document à l'API pour la detectiion des sentiments
            var sentimentResults = await _client.SentimentAsync(
                false,
                new MultiLanguageBatchInput(multilanguagesInput));
 
            //Lecture des reponses et ajout du score aux resultats 
            foreach (var document in sentimentResults.Documents)
            {
                result.Single(x => x.Id == document.Id).Score = document.Score.Value.ToString();
 
                _logger.LogInformation($"Document ID: {document.Id} , Sentiment Score: {document.Score:0.00}");
            }
 
            return result;
        }
 
    }

Création du ServiceClientCredentials

Le client TextAnalytics prend en paramètre un objet de type ServiceClientCredentials. Nous devons implémenter une classe qui hérite de ce type.
Cette classe permettra d’ajouter à l’entête de la requête HTTP la clé d’accès au service TexteAnalytics sur le portail Azure. Vous devez donc créer une nouvelle classe ApiKeyServiceClientCredentials, avec le code suivant :

Code csharp : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class ApiKeyServiceClientCredentials : ServiceClientCredentials
    {
        private string _apiKey;
 
        public ApiKeyServiceClientCredentials(string apikey)
        {
 
            this._apiKey = apikey;
        }
 
 
        public override Task ProcessHttpRequestAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            request.Headers.Add("Ocp-Apim-Subscription-Key", _apiKey);
            return base.ProcessHttpRequestAsync(request, cancellationToken);
        }
    }

Edition du Startup.cs

Maintenant nous allons modifier la méthode ConfigureServices de la classe et ajouter nos deux services et le client TextAnalytics au conteneur d’IoC :


Code csharp : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<CookiePolicyOptions>(options =>
            {
                // This lambda determines whether user consent for non-essential cookies is needed for a given request.
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });
 
 
            //Ajout du client TextAnalytics au conteneur d'IoC
            services.AddSingleton<ITextAnalyticsClient>(s=> new TextAnalyticsClient(new ApiKeyServiceClientCredentials(Configuration.GetValue<string>("Textanalytics:SubscriptionKey")))
            {
                Endpoint = Configuration.GetValue<string>("Textanalytics:EndPoint")
            });
 
            //Ajout du service TweetsSearch au conteneur d'IoC
            services.AddTransient<ITweetsSearch, TweetsSearch>();
            //Ajout du service TextAnalyticsService au conteneur d'IoC
            services.AddTransient<ITextAnalyticsService, TextAnalyticsService>();
 
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
        }


Mise à jour de la vue

Nous allons commencer par modifier le fichier Index.cshtml.cs. Nous devons injecter notre service ITextAnalyticsService via le constructeur de classe IndexModel et modifier le code appeler la fonction de détection de la langue, ensuite la fonction d’analyse sentimentale.

Ci-dessous le nouveau code de cette classe :

Code csharp : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
public class IndexModel : PageModel
    {
 
        /// <summary>
        /// Liste des Tweets
        /// </summary>
        public IList<string> Tweets { get; set; }
        public IList<ResultModel> Results { get; set; }
        /// <summary>
        /// Paramètre de recherche
        /// </summary>
        [Required]
        [StringLength(50)]
        [BindProperty]
        public string Tag { get; set; }
 
        /// <summary>
        /// Recherche avec Twitter
        /// </summary>
        private readonly ITweetsSearch _tweetsSearch;
 
 
        private readonly ITextAnalyticsService _textAnalyticsService;
 
        /// <summary>
        ///  Initialisation d’une nouvelle instance de la classe PageModel
        /// </summary>
        /// <param name="tweetsSearch">Requis pour injecter le service ITweetsSearch </param>
        public IndexModel(ITweetsSearch tweetsSearch, ITextAnalyticsService textAnalyticsService)
        {
 
            _tweetsSearch = tweetsSearch;
            _textAnalyticsService = textAnalyticsService;
        }
 
        /// <summary>
        /// Méthode appelée lors d'une requête Get
        /// </summary>
        public void OnGet()
        {
            Results = new List<ResultModel>();
        }
 
 
        /// <summary>
        /// Méthode appelée lors d'une requête Post
        /// </summary>
 
        public void OnPost()
        {
            Results = new List<ResultModel>();
 
            Tweets = _tweetsSearch.GetTweets(Tag);
 
            if(Tweets.Any())
            { 
            Results = _textAnalyticsService.Language(Tweets).Result;
 
            Results = _textAnalyticsService.Sentiment(Results).Result;
            }
        }
    }

Pour finir, nous devons modifier notre vue (Index.cshtml) pour afficher la langue et le score de l’analyse sentimentale :


À l’exécution, vous devez obtenir ce qui suit :

Nom : img6.PNG
Affichages : 30
Taille : 77,7 Ko

Le code complet de cet exemple est disponible sur mon GitHub à l’adresse suivante :

https://github.com/hinault/tweets-sentiment-analysis

Envoyer le billet « Analyse sentimentale des tweets avec Text Analyctics API, partie II : utilisation de l'API Text Analyctics » dans le blog Viadeo Envoyer le billet « Analyse sentimentale des tweets avec Text Analyctics API, partie II : utilisation de l'API Text Analyctics » dans le blog Twitter Envoyer le billet « Analyse sentimentale des tweets avec Text Analyctics API, partie II : utilisation de l'API Text Analyctics » dans le blog Google Envoyer le billet « Analyse sentimentale des tweets avec Text Analyctics API, partie II : utilisation de l'API Text Analyctics » dans le blog Facebook Envoyer le billet « Analyse sentimentale des tweets avec Text Analyctics API, partie II : utilisation de l'API Text Analyctics » dans le blog Digg Envoyer le billet « Analyse sentimentale des tweets avec Text Analyctics API, partie II : utilisation de l'API Text Analyctics » dans le blog Delicious Envoyer le billet « Analyse sentimentale des tweets avec Text Analyctics API, partie II : utilisation de l'API Text Analyctics » dans le blog MySpace Envoyer le billet « Analyse sentimentale des tweets avec Text Analyctics API, partie II : utilisation de l'API Text Analyctics » dans le blog Yahoo

Commentaires