diff --git a/assets/javascripts/discourse/templates/admin-dashboard-sentiment.hbs b/assets/javascripts/discourse/templates/admin-dashboard-sentiment.hbs index 90850b92..5d20c19f 100644 --- a/assets/javascripts/discourse/templates/admin-dashboard-sentiment.hbs +++ b/assets/javascripts/discourse/templates/admin-dashboard-sentiment.hbs @@ -27,8 +27,16 @@ diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 3cc17f86..82cde4fd 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -12,7 +12,9 @@ en: categories: discourse_ai: "Discourse AI" dashboard: - emotion: "Emotion" + emotion: + title: "Emotion" + description: "The table lists a count of posts classified with a determined emotion. Classified with the model 'SamLowe/roberta-base-go_emotions'." js: discourse_automation: scriptables: diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml index fdbd16c5..ef99602a 100644 --- a/config/locales/server.en.yml +++ b/config/locales/server.en.yml @@ -112,7 +112,7 @@ en: reports: overall_sentiment: title: "Overall sentiment" - description: 'The chart compares the number of posts classified as either positive or negative. These are calculated when positive or negative scores > the set threshold score. This means neutral posts are not shown. Private messages (PMs) are also excluded. Classified with "cardiffnlp/twitter-roberta-base-sentiment-latest"' + description: 'The chart compares the number of posts classified as either positive or negative. These are calculated when positive or negative scores > the set threshold score. This means neutral posts are not shown. Personal messages (PMs) are also excluded. Classified with "cardiffnlp/twitter-roberta-base-sentiment-latest"' xaxis: "Positive(%)" yaxis: "Date" emotion_admiration: diff --git a/lib/sentiment/emotion_filter_order.rb b/lib/sentiment/emotion_filter_order.rb index 56285608..34cad293 100644 --- a/lib/sentiment/emotion_filter_order.rb +++ b/lib/sentiment/emotion_filter_order.rb @@ -6,14 +6,25 @@ module DiscourseAi def self.register!(plugin) Emotions::LIST.each do |emotion| filter_order_emotion = ->(scope, order_direction) do + scope_period = + scope + .arel + &.constraints + &.flat_map(&:children) + &.find do |node| + node.is_a?(Arel::Nodes::Grouping) && + node.expr.to_s.match?(/topics\.bumped_at\s*>=/) + end + &.expr + &.split(">=") + &.last if scope.arel.constraints.present? && + scope.arel.constraints.any? { |c| c.is_a?(Arel::Nodes::Grouping) } + + # Fallback in case we can't find the scope period + scope_period ||= "CURRENT_DATE - INTERVAL '1 year'" + emotion_clause = <<~SQL - SUM( - CASE - WHEN (classification_results.classification::jsonb->'#{emotion}')::float > 0.1 - THEN 1 - ELSE 0 - END - )::float / COUNT(posts.id) + COUNT(*) FILTER (WHERE (classification_results.classification::jsonb->'#{emotion}')::float > 0.1) SQL # TODO: This is slow, we will need to materialize this in the future @@ -35,10 +46,11 @@ module DiscourseAi AND topics.deleted_at IS NULL AND posts.deleted_at IS NULL AND posts.post_type = 1 + AND posts.created_at >= #{scope_period} GROUP BY 1 HAVING - #{emotion_clause} > 0.05 + #{emotion_clause} > 0 SQL scope