Il plugin Discourse AI include funzionalità di analisi del sentiment che possono aiutarti a comprendere più a fondo il tono emotivo delle discussioni nella tua community. Questo argomento presenta due query dettagliate per l’Esploratore di dati che sfruttano queste capacità AI per fornire approfondimenti sulle community di Discourse.
- Sentiment AI per Categoria e Totale Livello di Fiducia: Un’analisi delle serie temporali che traccia le tendenze del sentiment settimanalmente all’interno di categorie e livelli di fiducia specifici
- Argomenti Anomali di Emozione AI: Identifica gli argomenti di discussione che generano risposte emotive significative su un sito Discourse.
Prerequisiti
Per utilizzare questi report, è necessario:
- Plugin Discourse AI installato e abilitato: Il plugin Discourse AI deve essere installato sulla tua istanza
- Analisi del sentiment abilitata: Il modulo Sentiment Analysis deve essere configurato e attivo
- Plugin Data Explorer: Necessario per eseguire queste query SQL
- Dati storici del sentiment: Post sufficienti analizzati per il sentiment per ottenere risultati significativi (potrebbe essere necessaria un’operazione di backfill)
Modelli di sentiment AI e come funzionano
Prima di approfondire i report, è utile comprendere cosa analizzano i modelli di sentiment nei post della tua community:
- Sentiment complessivo: Il modello cardiffnlp/twitter-roberta-base-sentiment-latest classifica i post come positivi, negativi o neutri
- Rilevamento delle emozioni: Il modello SamLowe/roberta-base-go_emotions identifica emozioni specifiche nei post, come gioia, tristezza, rabbia, ecc.
Questi modelli analizzano il testo di ogni post e memorizzano le loro classificazioni nel tuo database, che possono poi essere interrogate dal plugin Data Explorer.
Report Sentiment AI per Categoria e Totale Livello di Fiducia
-- [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
-- Crea un set di risultati temporaneo che aggrega le metriche del sentiment per settimana per la categoria specificata
WITH sentiment_counts AS (
SELECT
c.id as category_id,
c.name as category_name,
-- Raggruppa i post per settimana per l'analisi delle serie temporali
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,
-- Conta i post con sentiment positivo (soglia > 0.6)
COUNT(CASE WHEN (cr.classification::jsonb->'positive')::float > 0.6 THEN 1
ELSE NULL END) as positive_count,
-- Conta i post con sentiment negativo (soglia > 0.6)
COUNT(CASE WHEN (cr.classification::jsonb->'negative')::float > 0.6 THEN 1
ELSE NULL END) as negative_count,
-- Conta i post con sentiment neutro (sia positivo che negativo <= 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,
-- Numero totale di post con analisi del sentiment
COUNT(*) as total_classifications
FROM classification_results cr
-- Unisci i dati dei post per ottenere le date di creazione e i metadati
JOIN posts p ON p.id = cr.target_id AND cr.target_type = 'Post'
-- Unisci i dati degli argomenti per filtrare per categoria
JOIN topics t ON t.id = p.topic_id
-- Unisci i dati degli utenti per filtrare per livello di fiducia
JOIN users u ON u.id = p.user_id
-- Unisci i dati delle categorie per ottenere il nome della categoria
JOIN categories c ON c.id = t.category_id
WHERE
-- Includi solo i risultati del sentiment da questo modello specifico
cr.model_used = 'cardiffnlp/twitter-roberta-base-sentiment-latest'
-- Includi solo argomenti regolari (nessun MP, ecc.)
AND t.archetype = 'regular'
-- Escludi i post di sistema
AND p.user_id > 0
-- Filtra per la categoria selezionata
AND c.id = :category_id
-- Filtra per il livello di fiducia minimo
AND u.trust_level >= :min_trust_level
-- Escludi gli utenti staff se il parametro è selezionato
AND (:exclude_staff = false OR (u.admin = false AND u.moderator = false))
-- Filtra per intervallo di date
AND p.created_at BETWEEN :start_date AND :end_date
-- Raggruppa per settimana e categoria
GROUP BY c.id, c.name, week_starting, year, week_number
)
-- Formatta i risultati finali per la visualizzazione
SELECT
category_id,
category_name,
-- Converti in Data per una visualizzazione più pulita
week_starting::Date,
-- Formatta come notazione ISO della settimana (YYYY-WXX)
year || '-W' || LPAD(week_number::text, 2, '0') as year_week,
-- Calcola il saldo del sentiment (positivo meno negativo)
positive_count - negative_count as sentiment_balance,
positive_count,
negative_count,
neutral_count,
-- Calcola la percentuale di post positivi (arrotondata a 2 decimali)
ROUND(
(positive_count::float / NULLIF(total_classifications, 0) * 100)::numeric,
2
) as positive_percentage
FROM sentiment_counts
-- Ordina cronologicamente per mostrare le tendenze del sentiment nel tempo
ORDER BY week_starting ASC
Questo report fornisce un’analisi settimanale delle tendenze del sentiment all’interno di una categoria specifica, mostrando:
- Conteggi di post positivi, negativi e neutri per ogni settimana
- Un calcolo del saldo del sentiment (post positivi meno post negativi)
- La percentuale di post positivi rispetto al totale dei post analizzati
- Filtri per livello di fiducia dell’utente e opzione per escludere i post dello staff
Questo report è utile per:
- Tracciare le tendenze del sentiment della community nel tempo in categorie specifiche
- Identificare fluttuazioni nell’umore della community che potrebbero correlarsi con eventi o cambiamenti specifici
- Confrontare il sentiment tra diversi segmenti di utenti (per livello di fiducia)
- Misurare l’impatto degli interventi di moderazione sul sentiment complessivo della community
Parametri
La query accetta diversi parametri per personalizzare la tua analisi:
- Intervallo di date: Imposta le date di inizio e fine per il tuo periodo di analisi
- Categoria: Seleziona quale categoria analizzare
- Livello di fiducia minimo: Filtra per includere solo i post di utenti a un livello di fiducia specifico o superiore
- Escludi staff: Opzione per rimuovere i post dello staff dall’analisi (per concentrarsi sui membri regolari della community)
Risultati
I risultati sono presentati in una tabella con ogni riga che rappresenta una settimana di dati:
- Informazioni sulla categoria: ID e nome della categoria analizzata
- Periodi temporali: Data di inizio della settimana e notazione ISO della settimana (YYYY-WXX)
- Metriche del sentiment:
- Saldo del sentiment: La differenza tra post positivi e negativi (un valore positivo indica un sentiment complessivo positivo)
- Conteggi positivi/negativi/neutri: Il numero di post in ciascuna categoria di sentiment
- Percentuale positiva: La percentuale di post classificati come positivi
Esempio di Risultati
| 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 |
Report Argomenti Anomali di Emozione AI
-- [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
-- Prima, crea una Common Table Expression (CTE) che aggrega le reazioni emotive per argomento
WITH topic_emotions AS (
SELECT
topics.id AS topic_id, -- Memorizza l'ID dell'argomento per successive unione/filtro
topics.title, -- Includi il titolo dell'argomento per risultati leggibili
topics.created_at::date AS topic_date, -- Memorizza la data di creazione dell'argomento
-- Per ogni tipo di emozione, conta i post in cui quell'emozione supera la soglia di confidenza di 0.1
-- La tabella classification_results memorizza i punteggi delle emozioni come valori 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,
-- Calcola il totale delle reazioni emotive per scopi di classificazione
COUNT(*) AS total_emotional_reactions
FROM
classification_results
-- Unisci alla tabella posts per ottenere i metadati del post e filtrare i post eliminati
INNER JOIN
posts ON posts.id = classification_results.target_id AND
posts.deleted_at IS NULL -- Escludi i post eliminati
-- Unisci alla tabella topics per ottenere i metadati dell'argomento e filtrare per tipo/stato dell'argomento
INNER JOIN
topics ON topics.id = posts.topic_id AND
topics.archetype = 'regular' AND -- Includi solo argomenti standard (nessun MP o messaggio di sistema)
topics.deleted_at IS NULL -- Escludi gli argomenti eliminati
-- Unisci alla tabella users per ottenere il livello di fiducia dell'utente per il filtro
INNER JOIN
users ON users.id = posts.user_id
WHERE
-- Includi solo le classificazioni delle emozioni per i post (non altri tipi di contenuto)
classification_results.target_type = 'Post' AND
-- Utilizza solo i risultati da questo modello specifico di rilevamento delle emozioni
classification_results.model_used = 'SamLowe/roberta-base-go_emotions' AND
-- Filtra per intervallo di date utilizzando valori parametrizzati
posts.created_at BETWEEN :start_date AND :end_date AND
-- Filtra per la categoria specificata
(topics.category_id = :category_id) AND
-- Includi solo i post di utenti con un livello di fiducia sufficiente
(users.trust_level >= :min_trust_level)
-- Raggruppa tutti i conteggi per argomento
GROUP BY
topics.id, topics.title, topics.created_at::date
)
-- Query principale che formatta e filtra i dati aggregati dalla CTE
SELECT
topic_id, -- Visualizza l'ID dell'argomento (verrà renderizzato come link in Discourse)
--title, -- Visualizza il titolo dell'argomento
topic_date, -- Visualizza la data di creazione dell'argomento
total_emotional_reactions, -- Mostra il conteggio totale delle emozioni rilevate
-- Converti l'array di emozioni significative in una stringa formattata
-- Sono incluse solo le emozioni che superano la soglia, le altre diventano NULL e vengono omesse
-- Ogni emozione è formattata come "NomeEmozione(conto)"
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 'Anger(' || anger_count || ')' ELSE NULL END,
CASE WHEN annoyance_count >= :emotion_threshold THEN 'Annoyance(' || annoyance_count || ')' ELSE NULL END,
CASE WHEN approval_count >= :emotion_threshold THEN 'Approval(' || approval_count || ')' ELSE NULL END,
CASE WHEN caring_count >= :emotion_threshold THEN 'Caring(' || 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 'Curiosity(' || curiosity_count || ')' ELSE NULL END,
CASE WHEN desire_count >= :emotion_threshold THEN 'Desire(' || desire_count || ')' ELSE NULL END,
CASE WHEN disappointment_count >= :emotion_threshold THEN 'Disappointment(' || disappointment_count || ')' ELSE NULL END,
CASE WHEN disapproval_count >= :emotion_threshold THEN 'Disapproval(' || disapproval_count || ')' ELSE NULL END,
CASE WHEN disgust_count >= :emotion_threshold THEN 'Disgust(' || disgust_count || ')' ELSE NULL END,
CASE WHEN embarrassment_count >= :emotion_threshold THEN 'Embarrassment(' || embarrassment_count || ')' ELSE NULL END,
CASE WHEN excitement_count >= :emotion_threshold THEN 'Excitement(' || excitement_count || ')' ELSE NULL END,
CASE WHEN fear_count >= :emotion_threshold THEN 'Fear(' || 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 'Grief(' || grief_count || ')' ELSE NULL END,
CASE WHEN joy_count >= :emotion_threshold THEN 'Joy(' || joy_count || ')' ELSE NULL END,
CASE WHEN love_count >= :emotion_threshold THEN 'Love(' || love_count || ')' ELSE NULL END,
CASE WHEN nervousness_count >= :emotion_threshold THEN 'Nervousness(' || nervousness_count || ')' ELSE NULL END,
CASE WHEN optimism_count >= :emotion_threshold THEN 'Optimism(' || optimism_count || ')' ELSE NULL END,
CASE WHEN pride_count >= :emotion_threshold THEN 'Pride(' || pride_count || ')' ELSE NULL END,
CASE WHEN realization_count >= :emotion_threshold THEN 'Realization(' || realization_count || ')' ELSE NULL END,
CASE WHEN relief_count >= :emotion_threshold THEN 'Relief(' || relief_count || ')' ELSE NULL END,
CASE WHEN remorse_count >= :emotion_threshold THEN 'Remorse(' || remorse_count || ')' ELSE NULL END,
CASE WHEN sadness_count >= :emotion_threshold THEN 'Sadness(' || sadness_count || ')' ELSE NULL END,
CASE WHEN surprise_count >= :emotion_threshold THEN 'Surprise(' || surprise_count || ')' ELSE NULL END
], ', ', '') AS significant_emotions -- Unisci con delimitatori a virgola, stringa vuota se non necessario delimitatore
FROM
topic_emotions
WHERE
-- Includi solo gli argomenti che hanno almeno un'emozione che supera la soglia
-- Questo identifica gli argomenti con un impatto emotivo significativo
(
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
)
-- Ordina i risultati per le reazioni emotive più elevate per prime
ORDER BY
total_emotional_reactions DESC
Questo report identifica gli argomenti che hanno generato risposte emotive significative nella tua community, basandosi su:
- Un conteggio di ogni tipo di emozione rilevata nei post all’interno dell’argomento
- Una soglia configurabile per determinare cosa costituisce una risposta emotiva “significativa”
- Filtri per categoria, intervallo di date e livello di fiducia dell’utente
Questo report ti aiuta a:
- Identificare discussioni potenzialmente problematiche che generano forti emozioni negative
- Trovare contenuti altamente coinvolgenti che risuonano emotivamente con la tua community
- Rilevare argomenti che potrebbero richiedere attenzione da parte della moderazione prima che si aggravino
- Scoprire temi di contenuto che innescano risposte emotive specifiche
- Comprendere meglio cosa guida l’impegno emotivo nella tua community
Parametri
La query accetta diversi parametri:
- Intervallo di date: Imposta le date di inizio e fine per il tuo periodo di analisi
- Categoria: Seleziona quale categoria analizzare
- Livello di fiducia minimo: Filtra per includere solo i post di utenti a un livello di fiducia specifico o superiore
- Soglia delle emozioni: Imposta quante istanze di un’emozione sono necessarie per considerarla significativa
Risultati
I risultati mostrano:
- ID argomento: Collega direttamente all’argomento (cliccabile in Data Explorer)
- Data dell’argomento: Quando è stato creato l’argomento
- Totale reazioni emotive: Il conteggio complessivo delle reazioni emotive rilevate
- Emozioni significative: Un elenco formattato delle emozioni che hanno superato la tua soglia, con i loro conteggi mostrati tra parentesi
Le emozioni rilevate includono una vasta gamma: ammirazione, divertimento, rabbia, fastidio, approvazione, cura, confusione, curiosità, desiderio, delusione, disapprovazione, disgusto, imbarazzo, eccitazione, paura, gratitudine, dolore, gioia, amore, nervosismo, neutralità, ottimismo, orgoglio, realizzazione, sollievo, rimorso, tristezza e sorpresa.
Esempio di Risultati
| topic | topic_date | total_emotional_reactions | significant_emotions |
|---|---|---|---|
| Feature Request: Increased API Rate Limits | 2025-03-06 | 42 | Approval(15), Confusion(9), Curiosity(7), Gratitude(8) |
| Authentication Error with Third-Party Integration | 2025-01-07 | 33 | Curiosity(6), Gratitude(5), Disapproval(8), Frustration(9) |
| Best Practices for Configuration Settings | 2025-02-16 | 31 | Curiosity(9), Excitement(6), Gratitude(5), Optimism(5) |
| Troubleshooting Database Connection Issues | 2025-01-15 | 29 | Curiosity(7), Confusion(8), Disappointment(6), Frustration(5) |
| Critical Bug in Latest Beta Release | 2025-02-02 | 26 | Confusion(7), Concern(6), Disapproval(5), Urgency(6) |
Applicazioni pratiche nella gestione della community
Questi report possono migliorare il tuo flusso di lavoro di gestione della community in diversi modi:
- Intervento precoce: Identifica argomenti carichi di emozioni che potrebbero richiedere moderazione prima di diventare problematici
- Pianificazione dei contenuti: Utilizza gli approfondimenti su ciò che innesca emozioni positive per informare la tua strategia di contenuti
- Misurazione dell’impatto: Valuta come i cambiamenti delle politiche, le nuove funzionalità o gli eventi influenzano il sentiment della community
- Coinvolgimento mirato: Concentra l’attenzione dello staff sugli argomenti con forti reazioni emotive che potrebbero beneficiare di risposte ufficiali