Skip to content

Commit

Permalink
Merge pull request #531 from 10up/feature/moderation
Browse files Browse the repository at this point in the history
Add comment moderation feature
  • Loading branch information
dkotter authored Feb 1, 2024
2 parents 517af08 + c4400cc commit 34b65a3
Show file tree
Hide file tree
Showing 13 changed files with 945 additions and 7 deletions.
26 changes: 23 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
* [Set Up Azure AI Language Processing](#set-up-language-processing-via-microsoft-azure)
* [Set Up Azure AI Vision Image Processing](#set-up-image-processing-via-microsoft-azure)
* [Set Up OpenAI DALL·E Image Processing](#set-up-image-processing-via-openai)
* [Set Up OpenAI Moderation Language Processing](#set-up-comment-moderation-via-openai-moderation)
* [Set Up Azure AI Personalizer Recommended Content](#set-up-recommended-content-via-microsoft-azure-ai-personalizer)
* [WP CLI Commands](#wp-cli-commands)
* [FAQs](#frequently-asked-questions)
Expand All @@ -40,6 +41,7 @@ Tap into leading cloud-based services like [OpenAI](https://openai.com/), [Micro
* Expand or condense text content using [OpenAI's ChatGPT API](https://platform.openai.com/docs/guides/chat)
* Generate new images on demand to use in-content or as a featured image using [OpenAI's DALL·E API](https://platform.openai.com/docs/guides/images)
* Generate transcripts of audio files using [OpenAI's Whisper API](https://platform.openai.com/docs/guides/speech-to-text)
* Moderate incoming comments for sensitive content using [OpenAI's Moderation API](https://platform.openai.com/docs/guides/moderation)
* Convert text content into audio and output a "read-to-me" feature on the front-end to play this audio using [Microsoft Azure's Text to Speech API](https://learn.microsoft.com/en-us/azure/cognitive-services/speech-service/text-to-speech)
* Classify post content using [IBM Watson's Natural Language Understanding API](https://www.ibm.com/watson/services/natural-language-understanding/) and [OpenAI's Embedding API](https://platform.openai.com/docs/guides/embeddings)
* BETA: Recommend content based on overall site traffic via [Microsoft Azure's AI Personalizer API](https://azure.microsoft.com/en-us/services/cognitive-services/personalizer/) _(note that we're gathering feedback on this feature and may significantly iterate depending on community input)_
Expand All @@ -49,9 +51,9 @@ Tap into leading cloud-based services like [OpenAI](https://openai.com/), [Micro

### Language Processing

| Tagging | Recommended Content | Excerpt Generation |
| :-: | :-: | :-: |
| ![Screenshot of ClassifAI post tagging](assets/img/screenshot-1.png "Example of a Block Editor post with Watson Categories, Keywords, Concepts, and Entities.") | ![Screenshot of ClassifAI recommended content](assets/img/screenshot-2.png "Example of a Recommended Content Block with Azure AI Personalizer.") | ![Screenshot of ClassifAI excerpt generation](assets/img/screenshot-7.png "Example of automatic excerpt generation with OpenAI.") |
| Tagging | Recommended Content | Excerpt Generation | Comment Moderation |
| :-: | :-: | :-: | :-: |
| ![Screenshot of ClassifAI post tagging](assets/img/screenshot-1.png "Example of a Block Editor post with Watson Categories, Keywords, Concepts, and Entities.") | ![Screenshot of ClassifAI recommended content](assets/img/screenshot-2.png "Example of a Recommended Content Block with Azure AI Personalizer.") | ![Screenshot of ClassifAI excerpt generation](assets/img/screenshot-7.png "Example of automatic excerpt generation with OpenAI.") | ![Screenshot of ClassifAI comment moderation](assets/img/screenshot-13.png "Example of automatic comment moderation with OpenAI.") |

| Audio Transcripts | Title Generation | Expand or Condense Text | Text to Speech |
| :-: | :-: | :-: | :-: |
Expand Down Expand Up @@ -371,6 +373,24 @@ Note that [Azure AI Vision](https://docs.microsoft.com/en-us/azure/cognitive-ser
* Once images are generated, choose one or more images to import into your media library
* Choose one image to insert into the content

## Set Up Comment Moderation (via OpenAI Moderation)

### 1. Sign up for OpenAI

* [Sign up for an OpenAI account](https://platform.openai.com/signup) or sign into your existing one.
* If creating a new account, complete the verification process (requires confirming your email and phone number).
* Log into your account and go to the [API key page](https://platform.openai.com/account/api-keys).
* Click `Create new secret key` and copy the key that is shown.

### 2. Configure OpenAI API Keys under Tools > ClassifAI > Language Processing > Moderation

* Enter your API Key copied from the above step into the `API Key` field.

### 3. Enable Comment Moderation

* Select the "Enable" checkbox in above screen.
* Select "Comments" in the "Content to moderate" section.

## Set Up Recommended Content (via Microsoft Azure AI Personalizer)

Note that [Personalizer](https://azure.microsoft.com/en-us/services/cognitive-services/personalizer/) requires sufficient data volume to enable Personalizer to learn. In general, we recommend a minimum of ~1,000 events per day to ensure Personalizer learns effectively. If Personalizer doesn't receive sufficient data, the service takes longer to determine the best actions.
Expand Down
Binary file added assets/img/screenshot-13.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
89 changes: 89 additions & 0 deletions includes/Classifai/Admin/BulkActions.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
use Classifai\Features\ImageTextExtraction;
use Classifai\Features\PDFTextExtraction;
use Classifai\Features\TextToSpeech;
use Classifai\Features\Moderation;

use function Classifai\attachment_is_pdf;

/**
Expand Down Expand Up @@ -58,6 +60,7 @@ public function register_language_processing_hooks() {
new Classification(),
new ExcerptGeneration(),
new TextToSpeech(),
new Moderation(),
];

foreach ( $this->language_processing_features as $feature ) {
Expand All @@ -67,6 +70,14 @@ public function register_language_processing_hooks() {

$settings = $feature->get_settings();

if (
Moderation::ID === $feature::ID &&
in_array( 'comments', $feature->get_moderation_content_settings(), true )
) {
add_filter( 'bulk_actions-edit-comments', [ $this, 'register_bulk_actions_comments' ] );
add_filter( 'handle_bulk_actions-edit-comments', [ $this, 'bulk_action_handler_comments' ], 10, 3 );
}

if ( ! isset( $settings['post_types'] ) ) {
continue;
}
Expand Down Expand Up @@ -185,6 +196,80 @@ function ( $feature ) {
return esc_url_raw( $redirect_to );
}

/**
* Register comment bulk actions.
*
* @param array $bulk_actions Current bulk actions.
* @return array
*/
public function register_bulk_actions_comments( array $bulk_actions ): array {
foreach ( $this->language_processing_features as $feature ) {
if ( ! $feature->is_feature_enabled() ) {
continue;
}

switch ( $feature::ID ) {
case Moderation::ID:
$bulk_actions[ $feature::ID ] = esc_html__( 'Moderate', 'classifai' );
break;
}
}

return $bulk_actions;
}

/**
* Handle comment bulk actions.
*
* @param string $redirect_to Redirect URL after bulk actions.
* @param string $doaction Action ID.
* @param array $comment_ids Comment ids to apply bulk actions to.
* @return string
*/
public function bulk_action_handler_comments( string $redirect_to, string $doaction, array $comment_ids ): string {
$feature_ids = array_map(
function ( $feature ) {
return $feature::ID;
},
$this->language_processing_features
);

if (
empty( $comment_ids ) ||
! in_array( $doaction, $feature_ids, true )
) {
return $redirect_to;
}

foreach ( $comment_ids as $comment_id ) {
switch ( $doaction ) {
case Moderation::ID:
$moderation_feature = new Moderation();

$result = $moderation_feature->run( $comment_id, 'comment' );
if ( ! empty( $result ) && ! is_wp_error( $result ) ) {
$moderation_feature->save_comment( $result, $comment_id );
}

$action = $doaction;

break;
}
}

$args_to_remove = array_map(
function ( $feature ) {
return "bulk_{$feature}";
},
$feature_ids
);

$redirect_to = remove_query_arg( $args_to_remove, $redirect_to );
$redirect_to = add_query_arg( rawurlencode( "bulk_{$action}" ), count( $comment_ids ), $redirect_to );

return esc_url_raw( $redirect_to );
}

/**
* Register Language Processing row actions.
*
Expand Down Expand Up @@ -517,6 +602,10 @@ function ( $feature ) {
case Classification::ID:
$action_text = __( 'Classification done for', 'classifai' );
break;

case Moderation::ID:
$action_text = __( 'Moderation done for', 'classifai' );
break;
}

$output = '<div id="message" class="notice notice-success is-dismissible fade"><p>';
Expand Down
Loading

0 comments on commit 34b65a3

Please sign in to comment.