Files
discourse-ai/app/controllers/discourse_ai/sentiment/sentiment_controller.rb
T
Keegan George 9aafca03f5 UX: Improvements to sentiment analysis report (#1150)
This update improves some of the UI around sentiment analysis reports:

1. Improve titles so it is above and truncated when long
2. Change doughnut to only show total count
3. Ensures sentiment posts have dates
4. Ensure expand post doesn't appear on short posts
2025-02-25 07:47:30 -08:00

102 lines
3.3 KiB
Ruby

# frozen_string_literal: true
module DiscourseAi
module Sentiment
class SentimentController < ::Admin::StaffController
include Constants
requires_plugin ::DiscourseAi::PLUGIN_NAME
DEFAULT_POSTS_LIMIT = 50
MAX_POSTS_LIMIT = 100
def posts
group_by = params.required(:group_by)&.to_sym
group_value = params.required(:group_value).presence
start_date = params[:start_date].presence
end_date = params[:end_date]
threshold = SENTIMENT_THRESHOLD
raise Discourse::InvalidParameters if %i[category tag].exclude?(group_by)
limit = fetch_limit_from_params(default: DEFAULT_POSTS_LIMIT, max: MAX_POSTS_LIMIT)
offset = params[:offset].to_i || 0
case group_by
when :category
grouping_clause = "c.name"
grouping_join = "" # categories already joined
when :tag
grouping_clause = "tags.name"
grouping_join =
"INNER JOIN topic_tags tt ON tt.topic_id = p.topic_id INNER JOIN tags ON tags.id = tt.tag_id"
end
posts =
DB.query(
<<~SQL,
SELECT
p.id AS post_id,
p.topic_id,
t.title AS topic_title,
p.cooked as post_cooked,
p.user_id,
p.post_number,
p.created_at AS created_at,
u.username,
u.name,
u.uploaded_avatar_id,
c.id AS category_id,
c.name AS category_name,
c.color AS category_color,
c.slug AS category_slug,
c.description AS category_description,
(CASE
WHEN (cr.classification::jsonb->'positive')::float > :threshold THEN 'positive'
WHEN (cr.classification::jsonb->'negative')::float > :threshold THEN 'negative'
ELSE 'neutral'
END) AS sentiment
FROM posts p
INNER JOIN topics t ON t.id = p.topic_id
INNER JOIN classification_results cr ON cr.target_id = p.id AND cr.target_type = 'Post'
LEFT JOIN users u ON u.id = p.user_id
LEFT JOIN categories c ON c.id = t.category_id
#{grouping_join}
WHERE
#{grouping_clause} = :group_value AND
t.archetype = 'regular' AND
p.user_id > 0 AND
cr.model_used = 'cardiffnlp/twitter-roberta-base-sentiment-latest' AND
((:start_date IS NULL OR p.created_at > :start_date) AND (:end_date IS NULL OR p.created_at < :end_date))
AND p.deleted_at IS NULL
ORDER BY p.created_at DESC
LIMIT :limit OFFSET :offset
SQL
group_value: group_value,
start_date: start_date,
end_date: end_date,
threshold: threshold,
limit: limit + 1,
offset: offset,
)
has_more = posts.length > limit
posts.pop if has_more
render_json_dump(
posts:
serialize_data(
posts,
AiSentimentPostSerializer,
scope: guardian,
add_raw: true,
add_excerpt: true,
add_title: true,
),
has_more: has_more,
next_offset: has_more ? offset + limit : nil,
)
end
end
end
end