Le plugin Discourse AI inclut des capacités d’analyse des sentiments qui peuvent vous aider à mieux comprendre le ton émotionnel des discussions au sein de votre communauté. Ce sujet présente deux requêtes détaillées pour l’explorateur de données qui exploitent ces capacités d’IA pour fournir des insights sur les communautés Discourse.
- Sentiment IA par catégorie et niveau de confiance total : Une analyse de séries temporelles qui suit les tendances des sentiments par semaine au sein de catégories et de niveaux de confiance spécifiques.
- Sujets aberrants d’émotion IA : Identifie les sujets de discussion qui déclenchent des réponses émotionnelles significatives sur un site Discourse.
Prérequis
Pour utiliser ces rapports, vous avez besoin de :
- Plugin Discourse AI installé et activé : Le plugin Discourse AI doit être installé sur votre instance.
- Analyse des sentiments activée : Le module Analyse des sentiments doit être configuré et actif.
- Plugin Data Explorer : Requis pour exécuter ces requêtes SQL.
- Données historiques de sentiments : Suffisamment de posts analysés pour des résultats significatifs (une opération de remplissage rétrospectif peut être nécessaire).
Modèles de sentiment IA et leur fonctionnement
Avant de plonger dans les rapports, il est utile de comprendre ce que les modèles de sentiment analysent dans les posts de votre communauté :
- Sentiment global : Le modèle cardiffnlp/twitter-roberta-base-sentiment-latest classe les posts comme positifs, négatifs ou neutres.
- Détection des émotions : Le modèle SamLowe/roberta-base-go_emotions identifie des émotions spécifiques dans les posts, telles que la joie, la tristesse, la colère, etc.
Ces modèles analysent le texte de chaque post et stockent leurs classifications dans votre base de données, qui peuvent ensuite être interrogées par le plugin Data Explorer.
Rapport Sentiment IA par catégorie et niveau de confiance total
-- [params]
-- date :start_date = 2025-01-01
-- date :end_date = 2025-12-31
-- category_id :category_id = 6
-- int :min_trust_level = 0
-- boolean :exclude_staff = false
-- Créer un jeu de résultats temporaire qui agrège les métriques de sentiment par semaine pour la catégorie spécifiée
WITH sentiment_counts AS (
SELECT
c.id as category_id,
c.name as category_name,
-- Regrouper les posts par semaine pour l'analyse de séries temporelles
DATE_TRUNC('week', p.created_at) as week_starting,
EXTRACT(YEAR FROM p.created_at) as year,
EXTRACT(WEEK FROM p.created_at) as week_number,
-- Compter les posts avec un sentiment positif (seuil > 0.6)
COUNT(CASE WHEN (cr.classification::jsonb->'positive')::float > 0.6 THEN 1
ELSE NULL END) as positive_count,
-- Compter les posts avec un sentiment négatif (seuil > 0.6)
COUNT(CASE WHEN (cr.classification::jsonb->'negative')::float > 0.6 THEN 1
ELSE NULL END) as negative_count,
-- Compter les posts avec un sentiment neutre (positif et négatif <= 0.6)
COUNT(CASE WHEN (cr.classification::jsonb->'positive')::float <= 0.6
AND (cr.classification::jsonb->'negative')::float <= 0.6 THEN 1
ELSE NULL END) as neutral_count,
-- Nombre total de posts avec analyse de sentiment
COUNT(*) as total_classifications
FROM classification_results cr
-- Joindre les données des posts pour obtenir les dates de création et les métadonnées
JOIN posts p ON p.id = cr.target_id AND cr.target_type = 'Post'
-- Joindre les données des sujets pour filtrer par catégorie
JOIN topics t ON t.id = p.topic_id
-- Joindre les données des utilisateurs pour filtrer par niveau de confiance
JOIN users u ON u.id = p.user_id
-- Joindre les données des catégories pour obtenir le nom de la catégorie
JOIN categories c ON c.id = t.category_id
WHERE
-- Inclure uniquement les résultats de sentiment de ce modèle spécifique
cr.model_used = 'cardiffnlp/twitter-roberta-base-sentiment-latest'
-- Inclure uniquement les sujets réguliers (pas de MP, etc.)
AND t.archetype = 'regular'
-- Exclure les posts système
AND p.user_id > 0
-- Filtrer par la catégorie sélectionnée
AND c.id = :category_id
-- Filtrer par le niveau de confiance minimum
AND u.trust_level >= :min_trust_level
-- Exclure les utilisateurs du personnel si le paramètre est coché
AND (:exclude_staff = false OR (u.admin = false AND u.moderator = false))
-- Filtrer par plage de dates
AND p.created_at BETWEEN :start_date AND :end_date
-- Regrouper par semaine et catégorie
GROUP BY c.id, c.name, week_starting, year, week_number
)
-- Formater les résultats finaux pour l'affichage
SELECT
category_id,
category_name,
-- Convertir en Date pour un affichage plus propre
week_starting::Date,
-- Formater en notation de semaine ISO (AAAA-SXX)
year || '-W' || LPAD(week_number::text, 2, '0') as year_week,
-- Calculer le bilan des sentiments (positif moins négatif)
positive_count - negative_count as sentiment_balance,
positive_count,
negative_count,
neutral_count,
-- Calculer le pourcentage de posts positifs (arrondi à 2 décimales)
ROUND(
(positive_count::float / NULLIF(total_classifications, 0) * 100)::numeric,
2
) as positive_percentage
FROM sentiment_counts
-- Trier chronologiquement pour montrer les tendances des sentiments dans le temps
ORDER BY week_starting ASC
Ce rapport fournit une analyse hebdomadaire des tendances des sentiments au sein d’une catégorie spécifique, montrant :
- Le nombre de posts positifs, négatifs et neutres pour chaque semaine
- Un calcul de bilan des sentiments (posts positifs moins posts négatifs)
- Le pourcentage de posts positifs par rapport au total des posts analysés
- Un filtrage par niveau de confiance des utilisateurs et une option pour exclure les posts du personnel
Ce rapport est précieux pour :
- Suivre les tendances des sentiments de la communauté dans le temps au sein de catégories spécifiques
- Identifier les fluctuations de l’humeur de la communauté qui pourraient être corrélées à des événements ou des changements spécifiques
- Comparer les sentiments entre différents segments d’utilisateurs (par niveau de confiance)
- Mesurer l’impact des interventions de modération sur le sentiment global de la communauté
Paramètres
La requête accepte plusieurs paramètres pour personnaliser votre analyse :
- Plage de dates : Définir les dates de début et de fin pour votre période d’analyse
- Catégorie : Sélectionner la catégorie à analyser
- Niveau de confiance minimum : Filtrer pour n’inclure que les posts d’utilisateurs ayant un niveau de confiance égal ou supérieur à un niveau spécifique
- Exclure le personnel : Option pour supprimer les posts du personnel de l’analyse (pour se concentrer sur les membres réguliers de la communauté)
Résultats
Les résultats sont présentés dans un tableau où chaque ligne représente une semaine de données :
- Informations sur la catégorie : ID et nom de la catégorie analysée
- Périodes de temps : Date de début de semaine et notation de semaine ISO (AAAA-SXX)
- Métriques de sentiment :
- Bilan des sentiments : La différence entre les posts positifs et négatifs (une valeur positive indique un sentiment global positif)
- Comptages positifs/négatifs/neutres : Le nombre de posts dans chaque catégorie de sentiment
- Pourcentage positif : Le pourcentage de posts classés comme positifs
Exemple de résultats
| category_name | week_starting | year_week | sentiment_balance | positive_count | negative_count | neutral_count | positive_percentage |
|---|---|---|---|---|---|---|---|
| Product Discussion | 2025-01-06 | 2025-W01 | -8 | 24 | 32 | 145 | 11.94 |
| Product Discussion | 2025-01-13 | 2025-W02 | -11 | 30 | 41 | 210 | 10.68 |
| Product Discussion | 2025-01-20 | 2025-W03 | -9 | 28 | 37 | 220 | 9.82 |
| Product Discussion | 2025-01-27 | 2025-W04 | -13 | 33 | 46 | 260 | 9.74 |
| Product Discussion | 2025-02-03 | 2025-W05 | -15 | 22 | 37 | 180 | 9.21 |
| Product Discussion | 2025-02-10 | 2025-W06 | -6 | 37 | 43 | 195 | 13.45 |
Rapport Sujets aberrants d’émotion IA
-- [params]
-- date :start_date = 2025-01-01
-- date :end_date = 2025-12-31
-- category_id :category_id = 6
-- int :min_trust_level = 1
-- int :emotion_threshold = 10
-- D'abord, créer une Expression de Table Commune (CTE) qui agrège les réactions émotionnelles par sujet
WITH topic_emotions AS (
SELECT
topics.id AS topic_id, -- Stocker l'ID du sujet pour une jointure/filtrage ultérieur
topics.title, -- Inclure le titre du sujet pour des résultats lisibles
topics.created_at::date AS topic_date, -- Stocker la date de création du sujet
-- Pour chaque type d'émotion, compter les posts où cette émotion dépasse le seuil de confiance de 0.1
-- La table classification_results stocke les scores d'émotion sous forme de valeurs JSON
COUNT(*) FILTER (WHERE (classification_results.classification::jsonb->'admiration')::float > 0.1) AS admiration_count,
COUNT(*) FILTER (WHERE (classification_results.classification::jsonb->'amusement')::float > 0.1) AS amusement_count,
COUNT(*) FILTER (WHERE (classification_results.classification::jsonb->'anger')::float > 0.1) AS anger_count,
COUNT(*) FILTER (WHERE (classification_results.classification::jsonb->'annoyance')::float > 0.1) AS annoyance_count,
COUNT(*) FILTER (WHERE (classification_results.classification::jsonb->'approval')::float > 0.1) AS approval_count,
COUNT(*) FILTER (WHERE (classification_results.classification::jsonb->'caring')::float > 0.1) AS caring_count,
COUNT(*) FILTER (WHERE (classification_results.classification::jsonb->'confusion')::float > 0.1) AS confusion_count,
COUNT(*) FILTER (WHERE (classification_results.classification::jsonb->'curiosity')::float > 0.1) AS curiosity_count,
COUNT(*) FILTER (WHERE (classification_results.classification::jsonb->'desire')::float > 0.1) AS desire_count,
COUNT(*) FILTER (WHERE (classification_results.classification::jsonb->'disappointment')::float > 0.1) AS disappointment_count,
COUNT(*) FILTER (WHERE (classification_results.classification::jsonb->'disapproval')::float > 0.1) AS disapproval_count,
COUNT(*) FILTER (WHERE (classification_results.classification::jsonb->'disgust')::float > 0.1) AS disgust_count,
COUNT(*) FILTER (WHERE (classification_results.classification::jsonb->'embarrassment')::float > 0.1) AS embarrassment_count,
COUNT(*) FILTER (WHERE (classification_results.classification::jsonb->'excitement')::float > 0.1) AS excitement_count,
COUNT(*) FILTER (WHERE (classification_results.classification::jsonb->'fear')::float > 0.1) AS fear_count,
COUNT(*) FILTER (WHERE (classification_results.classification::jsonb->'gratitude')::float > 0.1) AS gratitude_count,
COUNT(*) FILTER (WHERE (classification_results.classification::jsonb->'grief')::float > 0.1) AS grief_count,
COUNT(*) FILTER (WHERE (classification_results.classification::jsonb->'joy')::float > 0.1) AS joy_count,
COUNT(*) FILTER (WHERE (classification_results.classification::jsonb->'love')::float > 0.1) AS love_count,
COUNT(*) FILTER (WHERE (classification_results.classification::jsonb->'nervousness')::float > 0.1) AS nervousness_count,
COUNT(*) FILTER (WHERE (classification_results.classification::jsonb->'neutral')::float > 0.1) AS neutral_count,
COUNT(*) FILTER (WHERE (classification_results.classification::jsonb->'optimism')::float > 0.1) AS optimism_count,
COUNT(*) FILTER (WHERE (classification_results.classification::jsonb->'pride')::float > 0.1) AS pride_count,
COUNT(*) FILTER (WHERE (classification_results.classification::jsonb->'realization')::float > 0.1) AS realization_count,
COUNT(*) FILTER (WHERE (classification_results.classification::jsonb->'relief')::float > 0.1) AS relief_count,
COUNT(*) FILTER (WHERE (classification_results.classification::jsonb->'remorse')::float > 0.1) AS remorse_count,
COUNT(*) FILTER (WHERE (classification_results.classification::jsonb->'sadness')::float > 0.1) AS sadness_count,
COUNT(*) FILTER (WHERE (classification_results.classification::jsonb->'surprise')::float > 0.1) AS surprise_count,
-- Calculer le total des réactions émotionnelles pour le classement
COUNT(*) AS total_emotional_reactions
FROM
classification_results
-- Joindre la table posts pour obtenir les métadonnées des posts et filtrer les posts supprimés
INNER JOIN
posts ON posts.id = classification_results.target_id AND
posts.deleted_at IS NULL -- Exclure les posts supprimés
-- Joindre la table topics pour obtenir les métadonnées des sujets et filtrer par type/statut du sujet
INNER JOIN
topics ON topics.id = posts.topic_id AND
topics.archetype = 'regular' AND -- Inclure uniquement les sujets standards (pas de MP ni de messages système)
topics.deleted_at IS NULL -- Exclure les sujets supprimés
-- Joindre la table users pour obtenir le niveau de confiance des utilisateurs pour le filtrage
INNER JOIN
users ON users.id = posts.user_id
WHERE
-- Inclure uniquement les classifications d'émotion pour les posts (pas d'autres types de contenu)
classification_results.target_type = 'Post' AND
-- Utiliser uniquement les résultats de ce modèle spécifique de détection d'émotion
classification_results.model_used = 'SamLowe/roberta-base-go_emotions' AND
-- Filtrer par plage de dates en utilisant des valeurs paramétrées
posts.created_at BETWEEN :start_date AND :end_date AND
-- Filtrer par la catégorie spécifiée
(topics.category_id = :category_id) AND
-- Inclure uniquement les posts d'utilisateurs ayant un niveau de confiance suffisant
(users.trust_level >= :min_trust_level)
-- Regrouper tous les comptages par sujet
GROUP BY
topics.id, topics.title, topics.created_at::date
)
-- Requête principale qui formate et filtre les données agrégées de la CTE
SELECT
topic_id, -- Afficher l'ID du sujet (sera rendu comme un lien dans Discourse)
--title, -- Afficher le titre du sujet
topic_date, -- Afficher la date de création du sujet
total_emotional_reactions, -- Afficher le nombre total d'émotions détectées
-- Convertir le tableau d'émotions significatives en une chaîne formatée
-- Seules les émotions dépassant le seuil sont incluses, les autres deviennent NULL et sont omises
-- Chaque émotion est formatée comme "NomEmotion(compte)"
ARRAY_TO_STRING(ARRAY[
CASE WHEN admiration_count >= :emotion_threshold THEN 'Admiration(' || admiration_count || ')' ELSE NULL END,
CASE WHEN amusement_count >= :emotion_threshold THEN 'Amusement(' || amusement_count || ')' ELSE NULL END,
CASE WHEN anger_count >= :emotion_threshold THEN 'Colère(' || anger_count || ')' ELSE NULL END,
CASE WHEN annoyance_count >= :emotion_threshold THEN 'Agacement(' || annoyance_count || ')' ELSE NULL END,
CASE WHEN approval_count >= :emotion_threshold THEN 'Approbation(' || approval_count || ')' ELSE NULL END,
CASE WHEN caring_count >= :emotion_threshold THEN 'Bienveillance(' || caring_count || ')' ELSE NULL END,
CASE WHEN confusion_count >= :emotion_threshold THEN 'Confusion(' || confusion_count || ')' ELSE NULL END,
CASE WHEN curiosity_count >= :emotion_threshold THEN 'Curiosité(' || curiosity_count || ')' ELSE NULL END,
CASE WHEN desire_count >= :emotion_threshold THEN 'Désir(' || desire_count || ')' ELSE NULL END,
CASE WHEN disappointment_count >= :emotion_threshold THEN 'Déception(' || disappointment_count || ')' ELSE NULL END,
CASE WHEN disapproval_count >= :emotion_threshold THEN 'Désapprobation(' || disapproval_count || ')' ELSE NULL END,
CASE WHEN disgust_count >= :emotion_threshold THEN 'Dégoût(' || disgust_count || ')' ELSE NULL END,
CASE WHEN embarrassment_count >= :emotion_threshold THEN 'Embarras(' || embarrassment_count || ')' ELSE NULL END,
CASE WHEN excitement_count >= :emotion_threshold THEN 'Excitation(' || excitement_count || ')' ELSE NULL END,
CASE WHEN fear_count >= :emotion_threshold THEN 'Peur(' || fear_count || ')' ELSE NULL END,
CASE WHEN gratitude_count >= :emotion_threshold THEN 'Gratitude(' || gratitude_count || ')' ELSE NULL END,
CASE WHEN grief_count >= :emotion_threshold THEN 'Chagrin(' || grief_count || ')' ELSE NULL END,
CASE WHEN joy_count >= :emotion_threshold THEN 'Joie(' || joy_count || ')' ELSE NULL END,
CASE WHEN love_count >= :emotion_threshold THEN 'Amour(' || love_count || ')' ELSE NULL END,
CASE WHEN nervousness_count >= :emotion_threshold THEN 'Nervosité(' || nervousness_count || ')' ELSE NULL END,
CASE WHEN optimism_count >= :emotion_threshold THEN 'Optimisme(' || optimism_count || ')' ELSE NULL END,
CASE WHEN pride_count >= :emotion_threshold THEN 'Fierté(' || pride_count || ')' ELSE NULL END,
CASE WHEN realization_count >= :emotion_threshold THEN 'Réalisation(' || realization_count || ')' ELSE NULL END,
CASE WHEN relief_count >= :emotion_threshold THEN 'Soulagement(' || relief_count || ')' ELSE NULL END,
CASE WHEN remorse_count >= :emotion_threshold THEN 'Remords(' || remorse_count || ')' ELSE NULL END,
CASE WHEN sadness_count >= :emotion_threshold THEN 'Tristesse(' || sadness_count || ')' ELSE NULL END,
CASE WHEN surprise_count >= :emotion_threshold THEN 'Surprise(' || surprise_count || ')' ELSE NULL END
], ', ', '') AS significant_emotions -- Joindre avec des délimiteurs virgule, chaîne vide si aucun délimiteur n'est nécessaire
FROM
topic_emotions
WHERE
-- Inclure uniquement les sujets ayant au moins une émotion dépassant le seuil
-- Cela identifie les sujets ayant un impact émotionnel significatif
(
admiration_count >= :emotion_threshold OR
amusement_count >= :emotion_threshold OR
anger_count >= :emotion_threshold OR
annoyance_count >= :emotion_threshold OR
approval_count >= :emotion_threshold OR
caring_count >= :emotion_threshold OR
confusion_count >= :emotion_threshold OR
curiosity_count >= :emotion_threshold OR
desire_count >= :emotion_threshold OR
disappointment_count >= :emotion_threshold OR
disapproval_count >= :emotion_threshold OR
disgust_count >= :emotion_threshold OR
embarrassment_count >= :emotion_threshold OR
excitement_count >= :emotion_threshold OR
fear_count >= :emotion_threshold OR
gratitude_count >= :emotion_threshold OR
grief_count >= :emotion_threshold OR
joy_count >= :emotion_threshold OR
love_count >= :emotion_threshold OR
nervousness_count >= :emotion_threshold OR
optimism_count >= :emotion_threshold OR
pride_count >= :emotion_threshold OR
realization_count >= :emotion_threshold OR
relief_count >= :emotion_threshold OR
remorse_count >= :emotion_threshold OR
sadness_count >= :emotion_threshold OR
surprise_count >= :emotion_threshold
)
-- Trier les résultats par le plus grand nombre de réactions émotionnelles en premier
ORDER BY
total_emotional_reactions DESC
Ce rapport identifie les sujets qui ont déclenché des réponses émotionnelles significatives dans votre communauté, basé sur :
- Un comptage de chaque type d’émotion détecté dans les posts au sein du sujet
- Un seuil configurable pour déterminer ce qui constitue une réponse émotionnelle “significative”
- Un filtrage par catégorie, plage de dates et niveau de confiance des utilisateurs
Ce rapport vous aide à :
- Identifier les discussions potentiellement problématiques générant de fortes émotions négatives
- Trouver du contenu très engageant qui résonne émotionnellement avec votre communauté
- Détecter les sujets qui pourraient nécessiter une attention de modération avant qu’ils ne s’aggravent
- Découvrir des thèmes de contenu qui déclenchent des réponses émotionnelles spécifiques
- Mieux comprendre ce qui motive l’engagement émotionnel dans votre communauté
Paramètres
La requête accepte plusieurs paramètres :
- Plage de dates : Définir les dates de début et de fin pour votre période d’analyse
- Catégorie : Sélectionner la catégorie à analyser
- Niveau de confiance minimum : Filtrer pour n’inclure que les posts d’utilisateurs ayant un niveau de confiance égal ou supérieur à un niveau spécifique
- Seuil d’émotion : Définir le nombre d’occurrences d’une émotion requis pour la considérer comme significative
Résultats
Les résultats montrent :
- ID du sujet : Lien direct vers le sujet (cliquable dans Data Explorer)
- Date du sujet : Date de création du sujet
- Total des réactions émotionnelles : Le nombre total de réactions émotionnelles détectées
- Émotions significatives : Une liste formatée des émotions ayant dépassé votre seuil, avec leurs comptes indiqués entre parenthèses
Les émotions détectées incluent un large éventail : admiration, amusement, colère, agacement, approbation, bienveillance, confusion, curiosité, désir, déception, désapprobation, dégoût, embarras, excitation, peur, gratitude, chagrin, joie, amour, nervosité, neutre, optimisme, fierté, réalisation, soulagement, remords, tristesse et surprise.
Exemple de résultats
| topic | topic_date | total_emotional_reactions | significant_emotions |
|---|---|---|---|
| Feature Request: Increased API Rate Limits | 2025-03-06 | 42 | Approbation(15), Confusion(9), Curiosité(7), Gratitude(8) |
| Authentication Error with Third-Party Integration | 2025-01-07 | 33 | Curiosité(6), Gratitude(5), Désapprobation(8), Frustration(9) |
| Best Practices for Configuration Settings | 2025-02-16 | 31 | Curiosité(9), Excitation(6), Gratitude(5), Optimisme(5) |
| Troubleshooting Database Connection Issues | 2025-01-15 | 29 | Curiosité(7), Confusion(8), Déception(6), Frustration(5) |
| Critical Bug in Latest Beta Release | 2025-02-02 | 26 | Confusion(7), Préoccupation(6), Désapprobation(5), Urgence(6) |
Applications pratiques dans la gestion de communauté
Ces rapports peuvent améliorer votre flux de travail de gestion de communauté de plusieurs façons :
- Intervention précoce : Identifier les sujets chargés émotionnellement qui pourraient nécessiter une modération avant de devenir problématiques
- Planification du contenu : Utiliser les insights sur ce qui déclenche des émotions positives pour informer votre stratégie de contenu
- Mesure de l’impact : Évaluer comment les changements de politique, les nouvelles fonctionnalités ou les événements affectent le sentiment de la communauté
- Engagement ciblé : Concentrer l’attention du personnel sur les sujets avec de fortes réactions émotionnelles qui pourraient bénéficier de réponses officielles