Skip to content

feat: AI moderation feature - #288

Open
Alam-2U wants to merge 1 commit into
openedx:masterfrom
Alam-2U:feat/ai-moderation
Open

feat: AI moderation feature#288
Alam-2U wants to merge 1 commit into
openedx:masterfrom
Alam-2U:feat/ai-moderation

Conversation

@Alam-2U

@Alam-2U Alam-2U commented Aug 27, 2026

Copy link
Copy Markdown

Description

Adds provider-agnostic AI moderation to forum-v2.

New threads and comments are classified by a configured AI backend. Content classified as spam is flagged, optionally deleted, and recorded in an audit log.

Forum provides the moderation interface and workflow, but does not include a specific AI provider. AI_MODERATION_BACKEND has no default; deployments configure the backend they want to use, and each backend handles its own provider-specific credentials and model settings.

What's Included

Moderation Pipeline

Located under forum/ai_moderation/:

  • backends/base.py — Adds BaseModerationBackend as the backend interface and HTTPModerationBackend as a reusable base for JSON-over-HTTP providers. classify() returns {classification, reasoning, confidence_score, full_api_response} or None. Classification failures never raise exceptions, allowing posting to continue if moderation is unavailable.
  • service.py — Runs the moderation workflow: classify → flag → optionally delete → audit-log. Spam verdicts are cached using a content hash to avoid repeated API calls for identical content. Clean verdicts are not cached.
  • defaults.py — Provides provider-independent defaults, including a ready-to-use spam classification prompt.

Hook Points

The following operations trigger moderation after successful content creation: create_thread, create_parent_comment, create_child_comment.

Moderation runs inside a broad try/except. Any moderation failure is logged and does not cause the original post/comment creation to fail.

Data Model

Migration 0006 adds:

  • is_spam boolean field to CommentThread and Comment, with indexes on is_spam, (course_id, is_spam), and (author, course_id, is_spam).
  • ModerationAuditLog containing content body, full classifier response, reasoning, classification, actions taken, confidence score, original author, moderator_override, and override_reason.
  • flag_content_as_spam and unflag_content_as_spam backend methods.

Flagged content is attributed to the configured AI moderation user through abuse_flaggers, allowing it to surface through the existing report path.

Admin

Adds is_spam to thread and comment list displays and filters. Adds a read-only ModerationAuditLog admin with search across author, moderator, reasoning, and body.

Documentation

Adds docs/how-tos/configure_ai_moderation.rst, covering backend implementation, required and optional settings, and enabling the course-level waffle flags.

Configuration

Required

Setting Purpose
AI_MODERATION_BACKEND Dotted path to the backend class
AI_MODERATION_API_URL Provider endpoint
AI_MODERATION_USER_ID User ID used to attribute flagging/deletion; the user is not auto-created

Optional

AI_MODERATION_SYSTEM_MESSAGE, AI_MODERATION_CONNECTION_TIMEOUT (1.0s), AI_MODERATION_READ_TIMEOUT (30s), AI_MODERATION_FLAGGED_CACHE_TTL (24h), AI_MODERATION_FLAGGED_CACHE_PREFIX.

Course Waffle Flags

Both flags are off by default: discussions.enable_ai_moderation, discussions.enable_ai_auto_delete_spam.

Testing

Added and updated tests covering service behaviour, caching, flagging, deletion, audit logging, failure handling, backend interface, and HTTP backend.

  • tests/test_ai_moderation.py
  • tests/test_ai_moderation_backends.py
  • test_utils/moderation.py
  • Extended tests/test_backends/test_mysql/test_api.py and tests/test_backends/test_mysql/test_models.py

Rollout

The feature has zero impact when unconfigured. With no AI_MODERATION_BACKEND configured and both waffle flags disabled, no moderation calls are made and existing forum behaviour remains unchanged.

AI moderation can be enabled on a per-course basis.

Related PRs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant