Rapporti sull'analisi del sentiment e delle emozioni dell'IA

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.

  1. 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
  2. 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:

  1. Plugin Discourse AI installato e abilitato: Il plugin Discourse AI deve essere installato sulla tua istanza
  2. Analisi del sentiment abilitata: Il modulo Sentiment Analysis deve essere configurato e attivo
  3. Plugin Data Explorer: Necessario per eseguire queste query SQL
  4. 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:

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

Risorse aggiuntive

1 Mi Piace