This guide explains how to configure sentiment and emotion classification in Discourse AI and use the reports to explore your community’s posts.
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
- Open Admin → Plugins → AI → Features.
- Open “Sentiment and emotion”.
- Under “Sentiment”, select “Enabled” if you want positive, neutral and negative classification. This controls
ai_sentiment_enabled. - Choose its “Backend” and configure the corresponding endpoint, agent or model as described below.
- Under “Emotion”, select “Enabled” if you want emotion classification. This controls
ai_sentiment_emotion_enabled. - Choose its backend and configure it independently.
- Set the background-processing limits described in the next section.
- 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
- Open Admin → Reports → Sentiment analysis, or visit
/admin/reports/sentiment_analysison your site. - Select the start and end dates.
- Choose “Category” or “Tag” to group the results.
- Use the corresponding category or tag filter to narrow the results. Category filtering also provides an option to include subcategories.
- Read each group’s total and its positive, negative and neutral breakdown.
- 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
- Discourse AI
- Self-Hosting Sentiment and Emotion for DiscourseAI
- Configure a decision model in Discourse AI
- Managing AI credentials
Last edited by @keegan 2025-10-23T22:28:36Z
Last checked by @hugh 2024-08-06T05:27:46Z
Check document
Perform check on document:



