Discourse AI - סנטימנט

:bookmark: This guide explains how to configure sentiment and emotion classification in Discourse AI and use the reports to explore your community’s posts.

:person_raising_hand: Required user level: Administrator to configure; administrator or moderator to view reports.

Sentiment and emotion classification help you explore patterns in your community’s discussions:

  • Sentiment classifies posts as positive, neutral or negative.
  • Emotion assigns scores across 28 labels, including gratitude, curiosity, anger and sadness.

These are separate capabilities. You can enable either one or both, and choose a different classification backend for each. Reports count classified posts, not unique people or personality types. Use them to find discussions worth reading, not as a substitute for understanding their context.

Before you start

You need Discourse AI enabled through discourse_ai_enabled and a configured classification backend.

Hosted by Discourse? Your site may already have dedicated classification endpoints provisioned. Check its existing configuration before changing it. Contact team@discourse.org if you need help with availability, endpoint configuration or backfill limits.

Self-hosted? Configure a compatible dedicated endpoint, an AI agent with a language model, or a decision model. Enabling the feature alone does not provide an inference service.

Review your provider’s privacy policy, retention rules and costs before enabling automatic processing. Classification sends post text to the selected backend. The screenshots below use invented posts on a test site and a decision model; they do not recommend that provider for private community content.

Configure sentiment and emotion

  1. Open Admin → Plugins → AI → Features.
  2. Open “Sentiment and emotion”.
  3. Under “Sentiment”, select “Enabled” if you want positive, neutral and negative classification. This controls ai_sentiment_enabled.
  4. Choose its “Backend” and configure the corresponding endpoint, agent or model as described below.
  5. Under “Emotion”, select “Enabled” if you want emotion classification. This controls ai_sentiment_emotion_enabled.
  6. Choose its backend and configure it independently.
  7. Set the background-processing limits described in the next section.
  8. Click “Submit” and check that your selections were saved.

This example uses a decision model for both capabilities. “Posts per hour” is deliberately set to 0 to pause automatic scanning while testing. Use a positive value to process new and historical posts automatically.

Use dedicated classification endpoints

Choose “Dedicated classification endpoint” for each capability you want to run with a dedicated model. Follow “Configure dedicated classification endpoints” to the ai_sentiment_model_configs setting.

The reference dedicated models are:

Capability Model
Sentiment cardiffnlp/twitter-roberta-base-sentiment-latest
Emotion SamLowe/roberta-base-go_emotions

Each configuration entry identifies its classification_type (sentiment or emotion), model_name, endpoint and api_key. Supply a separate entry for each dedicated classifier you use. Keep credentials private; do not include them in support posts or screenshots.

See Self-hosting sentiment and emotion for Discourse AI for inference-server deployment. Enable and select each capability separately using the controls above.

The dedicated backend expects a compatible classification API. Copying an Anthropic, OpenAI chat or Azure Language endpoint into this setting does not make it compatible. A successful connection test for a language model elsewhere in Discourse does not test a dedicated sentiment endpoint.

Use an AI agent or decision model

For “LLM agent”, select an appropriate classifier agent with a configured language model. Discourse includes sentiment and emotion classifier agents. A general conversational agent is not a substitute for an agent configured to return the expected label scores.

For “Decision model”, first configure and test a compatible decision model, then select it for each enabled capability. A decision model does not require a separate conversational language model for this classification.

Agent and decision-model requests can incur provider charges or consume credits. Review the selected model’s data-handling rules before assigning it to an automatically processed feature.

Control processing and historical coverage

A scheduled job checks for posts with missing classifications every five minutes. New and historical posts share this scan; results are not necessarily available immediately after posting. There is no minimum number of posts or days before data can appear: one successfully classified post can contribute.

Control Site setting Default Effect
Posts per hour ai_sentiment_backfill_maximum_posts_per_hour 240 Approximate number of posts processed per hour. 0 stops the scheduled scan, including new posts.
Post age limit, in days ai_sentiment_backfill_post_max_age_days 60 Scan posts created within this age window. 0 means today, not unlimited history.

Increase the age limit to include older posts. The scheduled job processes missing results over time; selecting an older report date range does not itself classify that history.

The rate is approximate, not an exact request or spending cap. Enabling both classifiers can make two requests per post. Failed requests or refusals can be retried. Edited posts are checked separately and are not controlled by the scheduled scan’s rate or age limits.

Private messages, deleted posts, deleted topics and non-regular post types are excluded from the scheduled backfill scan. The PM exclusion in the scanner and reports is not a guarantee about all classification paths: the edited-post job does not apply the same PM filter. Take this into account before configuring an external provider.

Explore sentiment by category or tag

  1. Open Admin → Reports → Sentiment analysis, or visit /admin/reports/sentiment_analysis on your site.
  2. Select the start and end dates.
  3. Choose “Category” or “Tag” to group the results.
  4. Use the corresponding category or tag filter to narrow the results. Category filtering also provides an option to include subcategories.
  5. Read each group’s total and its positive, negative and neutral breakdown.
  6. Click a group’s row to inspect its chart and underlying posts.

The example contains nine classified posts: three positive, three negative and three neutral. Neutral posts are included in this report.

In the detail view:

  • Select “All”, “Positive”, “Neutral” or “Negative” to filter the loaded posts.
  • Open a post’s topic to read the surrounding discussion.
  • Use the link icon beside the chart to copy the URL for that report view. Recipients still need staff access.
  • Click “Back” to return to the grouped results.

Report dates refer to when posts were created, not when classification ran. A post can contribute to multiple tag groups if its topic has multiple tags, so adding tag totals can count the same post more than once.

Read the overall sentiment trend

Open the “Overall sentiment” report from Admin → Reports, or visit /admin/reports/overall_sentiment.

The score is:

Number of positive posts − number of negative posts

A positive or negative score must be greater than 0.6 for the post to count in that group. If neither exceeds the threshold, the grouped report treats the post as neutral. The threshold is fixed; there is no site setting to change it.

Overall sentiment is a net post count, not an average probability or happiness percentage. Three positive posts and three negative posts produce an overall score of 0, regardless of how many neutral posts there are. Inspect the grouped breakdown and underlying discussions before interpreting a flat trend as an absence of strong opinions.

Explore emotions

Each emotion has a report under Admin → Reports. For example, visit /admin/reports/emotion_anger for “Anger” or /admin/reports/emotion_curiosity for “Curiosity”. Choose a date range and daily, weekly or monthly grouping to explore the trend.

An emotion report counts posts whose score for that label is greater than 0.1. This threshold is also fixed. More than one emotion can qualify for the same post, so emotion totals are not mutually exclusive.

You can also filter topics by an emotion. Visit /filter?q=order:emotion_anger to find matching topics, ranked by their number of qualifying anger-classified posts rather than by an average emotion score. Use order:emotion_anger-asc to reverse the order. Without an activity-after: filter, this ordering counts qualifying posts from the past year. Normal topic-list access permissions still apply.

Available emotion labels

Admiration, amusement, anger, annoyance, approval, caring, confusion, curiosity, desire, disappointment, disapproval, disgust, embarrassment, excitement, fear, gratitude, grief, joy, love, nervousness, neutral, optimism, pride, realization, relief, remorse, sadness and surprise.

Understand the limitations

  • Classification is model-dependent. Sarcasm, quoted material, specialist language and multilingual discussions can be misinterpreted. Language coverage and accuracy depend on your chosen model. Scores from different backends are not necessarily calibrated alike.
  • Reports only cover stored results. An enabled feature with no working backend, paused processing or insufficient historical coverage can produce empty or incomplete reports.
  • Existing classifications are reused. Editing a classified post does not automatically replace its results. Changing the selected agent or decision model within the same backend does not reclassify existing results either.
  • Changing backend changes the report’s result source. Old results are not converted to the selected backend. Reports can appear empty while missing classifications are processed.
  • Reports exclude private messages. This reporting exclusion is separate from the data-processing limitation described above.

Troubleshoot missing or unexpected results

Problem What to check
No results after enabling Confirm the relevant capability is enabled, its backend is configured, “Posts per hour” is positive, and background jobs are running. Allow time for the five-minute scan and processing queue.
Sentiment works but emotion is empty Enable and configure “Emotion” separately. A sentiment-only dedicated endpoint does not provide emotion classifications.
Older dates have no results Increase the post age limit, allow processing time, and check that the report range includes the posts’ creation dates.
Dedicated endpoint returns an error Check its URL, credentials, model and response format. The adapter expects a flat array of labels and scores, with sentiment labels such as positive, neutral and negative, not arbitrary chat responses or LABEL_0-style labels.
Private-network endpoint cannot be reached Check connectivity and, where required, add only the trusted inference endpoint hostname or IP to allowed_internal_hosts. Do not broadly disable server-side request forgery protections.
Results do not change after an edit or model selection Existing results are reused. Do not assume that editing content or saving another model schedules a full reclassification.
A filter shows fewer posts than its count The count describes the whole group, while sentiment tabs filter loaded posts. Check for more results to load and open the original topics when investigating discrepancies.

Administrators can review agent and decision-model request records in Admin → Plugins → AI → Logs. Check /logs for background classification errors, including dedicated endpoint failures. Treat log contents as sensitive: they can contain post text and model responses. Remove credentials and private content before sharing diagnostics.

Additional resources

Last edited by @keegan 2025-10-23T22:28:36Z

Last checked by @hugh 2024-08-06T05:27:46Z

Check documentPerform check on document:
10 לייקים

A post was merged into an existing topic: Problems with Sentiment Backfill

A post was merged into an existing topic: Problems with Sentiment Backfill

The OP has been updated with a new video showcasing the updated features of Sentiment including a ton more emotions and understanding which topics/posts are associated with each emotion

I configured the sentiment model config with a model_name, endpoint, and api_key copied from the LLM settings, where it passes the test, but I get the error below in /logs.

(But maybe I don’t understand correctly, because why doesn’t sentiment use one of the configured LLMs?)

Using claude-3-5-sonnet.


{"type":"error","error":{"type":"invalid_request_error","message":"anthropic-version: header is required"}} (Net::HTTPBadResponse)
/var/www/discourse/plugins/discourse-ai/lib/inference/hugging_face_text_embeddings.rb:71:in `classify'
/var/www/discourse/plugins/discourse-ai/lib/sentiment/post_classification.rb:142:in `request_with'
/var/www/discourse/plugins/discourse-ai/lib/sentiment/post_classification.rb:78:in `block (4 levels) in bulk_classify!'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.5/lib/concurrent-ruby/concurrent/promises.rb:1593:in `evaluate_to'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.5/lib/concurrent-ruby/concurrent/promises.rb:1776:in `block in on_resolvable'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.5/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb:359:in `run_task'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.5/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb:350:in `block (3 levels) in create_worker'
<internal:kernel>:187:in `loop'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.5/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb:341:in `block (2 levels) in create_worker'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.5/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb:340:in `catch'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.5/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb:340:in `block in create_worker'
Status: 400

{"type":"error","error":{"type":"invalid_request_error","message":"anthropic-version: header is required"}} (Net::HTTPBadResponse)
/var/www/discourse/plugins/discourse-ai/lib/inference/hugging_face_text_embeddings.rb:71:in `classify'
/var/www/discourse/plugins/discourse-ai/lib/sentiment/post_classification.rb:142:in `request_wit...

The sentiment module doesn’t use general LLMs, but models specifically fine tuned to sentiment classification. If you want to run those models on your own that is documented at Self-Hosting Sentiment and Emotion for DiscourseAI

3 לייקים

@Falco שמתי לב שרגש הפסיק לפעול מאז ינואר 2025. ההערכה שלי היא שיש הגדרה חדשה ai_sentiment_model, כפי שמוסבר בקישור למעלה, שמיועדת להרצת מודל רגש ייעודי משלך/תמונה. שמתי לב שבעדכון התוכנה ה-Discourse עכשיו ai_sentiment_model_configs ריק (האם זה צריך להיות ריק?).

כאשר אני מנסה להריץ את הפקודה rake ai:sentiment:backfill, זה מחזיר לי שגיאה:

rake aborted!
ActiveRecord::StatementInvalid: PG::SyntaxError: שגיאת סינטקס ב- or ליד ")" (ActiveRecord::StatementInvalid)
LINE 1: ...e_upload_id", "posts"."outbound_message_id" מ- () כ- posts..

The plugin defaulted to a server located in DigitalOcean which I put together to make testing easier.

I have since changed the plugin defaults to a clean slate and people who want AI classified need to run servers following the documentation here on Meta.

Indeed, but we were paying that cost for testing purposes. It’s not sustainable to offer that for every self hoster.

Worth mentioning, that we do offer this classification service on GPU accelerated servers as part of our hosting service.

2 לייקים

ternal:kernel">:187:in loop' /var/www/discourse/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.5/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb:341:in block (2 levels) in create_worker’
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.5/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb:340:in catch' /var/www/discourse/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.5/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb:340:in block in create_worker’
no implicit conversion of Symbol into Integer (TypeError)
/var/www/discourse/plugins/discourse-ai/lib/sentiment/post_classification.rb:163:in block in transform_result' /var/www/discourse/plugins/discourse-ai/lib/sentiment/post_classification.rb:163:in each’
/var/www/discourse/plugin…

---

### **בעיה 2: תצורת מודל Microsoft Azure מובילה לשגיאת Hugging Face**

כשניסיתי לעבור למודל Microsoft Text Analytics בהגדרות Discourse AI, נתקלתי בשגיאת `404 Resource not found`, ומפתיע שהמעקב אחר העקבות עדיין מצביע על `hugging_face_text_embeddings.rb`.

**הודעת שגיאה (מתוך חריגת משימה):**


Job exception: 416 errors
{“error”:{“code”:“404”,“message”: “Resource not found”}} (Net::HTTPBadResponse)


**קטע רלוונטי של מעקב אחר העקבות (מצביע על Hugging Face למרות שנבחר מודל Microsoft):**


/var/www/discourse/plugins/discourse-ai/lib/inference/hugging_face_text_embeddings.rb:76:in do_request!' /var/www/discourse/plugins/discourse-ai/lib/inference/hugging_face_text_embeddings.rb:51:in classify_by_sentiment!’
/var/www/discourse/plugins/discourse-ai/lib/sentiment/post_classification.rb:156:in `request_with’


**תצפית:** זה מצביע על כך שגם כאשר אני בוחר ומגדיר את נקודת הקצה ואת מפתח ה-API של מודל Microsoft, נראה שהתוסף Discourse AI מקודד בצורה קשיחה או שמנתב באופן שגוי את בקשות ניתוח הסנטימנט דרך לוגיקה או נקודות קצה ספציפיות ל-Hugging Face. זה מונע את השימוש במודל Microsoft בכלל.

---

### **צילומי מסך של תצורה:**

צירפתי צילום מסך של הגדרות Discourse AI שלי כדי להציג את התצורה:

* תצורה מפורטת עבור מודלי סנטימנט AI (המציגה גם את מודלי Hugging Face וגם את מודלי Microsoft) - בדקתי עם תצורות מודל Hugging Face בלבד או Microsoft בלבד עם אותה תוצאה
![AI Sentiment Model Config|258x500](upload://76UboIJyIF77Lzpp0G65vcw5U3y.png)

בעיות אלה הופכות את תכונת ניתוח הסנטימנט לבלתי שמישה למעשה. נראה שהתוסף דורש עדכון כדי לטפל בפורמט התגובה החדש של Hugging Face וכדי לנתב נכון בקשות כאשר ספקי סנטימנט שונים מוגדרים.

כל סיוע או הדרכה בנושאים אלה יתקבלו בברכה רבה.

תודה!
2 לייקים

מעניין אותי אם דיווח סנטימנט פועל אצל אחרים, או אם הגדרתי משהו בצורה שגויה. ארצה לדעת מה עוד עלי לבדוק או להגדיר כדי לאפשר דיווח סנטימנט, מכיוון שאני עדיין חווה את אותה הבעיה.

לייק 1

We are trying to use this feature with Azure AI Language (from our self-hosted Discourse instance) - as we are already using our Azure subscription to integrate GPT-4.5 with Discourse (for summarization and chat-bot functionality):

…but we are getting no data in the the sentiment dashboard, and can see these errors in the logs:

Discourse AI: Errors during bulk classification: Failed to classify 208 posts (example ids: 2256, 909, 2270, 2260, 2797) : JSON::ParserError : An empty string is not a valid JSON string.

The backtrace shows that Discourse might be trying to use HuggingFace - are these the only models supported at the moment?

Thanks,

N

לייק 1

אז, האם הדרך היחידה להשתמש בתכונה זו היא להגדיר מופעים משלך של המודלים (שדורשים מופעי GPU כבדים שיהיו יקרים)? תכונה זו נראית שימושית מאוד, אבל נראה שהיא תעלה לי יותר להגדרה מאשר האירוח הנוכחי שלי ב-Discourse.

Yes, the supported models are the ones listed in the OP.

We will eventually add support for classifying using LLMs for people whose cost isn’t an issue.

Well, the whole feature is build around classifying posts using ML models, so yes, you need somewhere to run those.

And since Discourse can run in the very cheapest VPS out there, running ML models is indeed more expensive. If you wanna have the feature on the cheapest way possible, it is doable to run it on a server with just a handful of CPU cores, as long as you have enough RAM to load the models.

לייק 1

Sorry if this question has already been asked before, but I was unable to find a reference to where exactly the threshold score can be configured :sweat_smile:

לייק 1

Unfortunately, the threshold score is not something that is configurable by users or admins. It’s a specific value set in the code base.

לייק 1