Skip to content

Commit 8f0655e

Browse files
committed
Merge branch 'develop' of github.com:10up/classifai into develop
2 parents 36aac2d + 34b65a3 commit 8f0655e

18 files changed

+954
-11
lines changed

README.md

+23-3
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
* [Set Up Azure AI Language Processing](#set-up-language-processing-via-microsoft-azure)
2323
* [Set Up Azure AI Vision Image Processing](#set-up-image-processing-via-microsoft-azure)
2424
* [Set Up OpenAI DALL·E Image Processing](#set-up-image-processing-via-openai)
25+
* [Set Up OpenAI Moderation Language Processing](#set-up-comment-moderation-via-openai-moderation)
2526
* [Set Up Azure AI Personalizer Recommended Content](#set-up-recommended-content-via-microsoft-azure-ai-personalizer)
2627
* [WP CLI Commands](#wp-cli-commands)
2728
* [FAQs](#frequently-asked-questions)
@@ -40,6 +41,7 @@ Tap into leading cloud-based services like [OpenAI](https://openai.com/), [Micro
4041
* Expand or condense text content using [OpenAI's ChatGPT API](https://platform.openai.com/docs/guides/chat)
4142
* 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)
4243
* Generate transcripts of audio files using [OpenAI's Whisper API](https://platform.openai.com/docs/guides/speech-to-text)
44+
* Moderate incoming comments for sensitive content using [OpenAI's Moderation API](https://platform.openai.com/docs/guides/moderation)
4345
* 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)
4446
* 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)
4547
* 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)_
@@ -49,9 +51,9 @@ Tap into leading cloud-based services like [OpenAI](https://openai.com/), [Micro
4951

5052
### Language Processing
5153

52-
| Tagging | Recommended Content | Excerpt Generation |
53-
| :-: | :-: | :-: |
54-
| ![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.") |
54+
| Tagging | Recommended Content | Excerpt Generation | Comment Moderation |
55+
| :-: | :-: | :-: | :-: |
56+
| ![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.") |
5557

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

376+
## Set Up Comment Moderation (via OpenAI Moderation)
377+
378+
### 1. Sign up for OpenAI
379+
380+
* [Sign up for an OpenAI account](https://platform.openai.com/signup) or sign into your existing one.
381+
* If creating a new account, complete the verification process (requires confirming your email and phone number).
382+
* Log into your account and go to the [API key page](https://platform.openai.com/account/api-keys).
383+
* Click `Create new secret key` and copy the key that is shown.
384+
385+
### 2. Configure OpenAI API Keys under Tools > ClassifAI > Language Processing > Moderation
386+
387+
* Enter your API Key copied from the above step into the `API Key` field.
388+
389+
### 3. Enable Comment Moderation
390+
391+
* Select the "Enable" checkbox in above screen.
392+
* Select "Comments" in the "Content to moderate" section.
393+
374394
## Set Up Recommended Content (via Microsoft Azure AI Personalizer)
375395

376396
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.

assets/img/screenshot-13.png

45.8 KB
Loading

includes/Classifai/Admin/BulkActions.php

+89
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
use Classifai\Features\ImageTextExtraction;
1111
use Classifai\Features\PDFTextExtraction;
1212
use Classifai\Features\TextToSpeech;
13+
use Classifai\Features\Moderation;
14+
1315
use function Classifai\attachment_is_pdf;
1416

1517
/**
@@ -58,6 +60,7 @@ public function register_language_processing_hooks() {
5860
new Classification(),
5961
new ExcerptGeneration(),
6062
new TextToSpeech(),
63+
new Moderation(),
6164
];
6265

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

6871
$settings = $feature->get_settings();
6972

73+
if (
74+
Moderation::ID === $feature::ID &&
75+
in_array( 'comments', $feature->get_moderation_content_settings(), true )
76+
) {
77+
add_filter( 'bulk_actions-edit-comments', [ $this, 'register_bulk_actions_comments' ] );
78+
add_filter( 'handle_bulk_actions-edit-comments', [ $this, 'bulk_action_handler_comments' ], 10, 3 );
79+
}
80+
7081
if ( ! isset( $settings['post_types'] ) ) {
7182
continue;
7283
}
@@ -185,6 +196,80 @@ function ( $feature ) {
185196
return esc_url_raw( $redirect_to );
186197
}
187198

199+
/**
200+
* Register comment bulk actions.
201+
*
202+
* @param array $bulk_actions Current bulk actions.
203+
* @return array
204+
*/
205+
public function register_bulk_actions_comments( array $bulk_actions ): array {
206+
foreach ( $this->language_processing_features as $feature ) {
207+
if ( ! $feature->is_feature_enabled() ) {
208+
continue;
209+
}
210+
211+
switch ( $feature::ID ) {
212+
case Moderation::ID:
213+
$bulk_actions[ $feature::ID ] = esc_html__( 'Moderate', 'classifai' );
214+
break;
215+
}
216+
}
217+
218+
return $bulk_actions;
219+
}
220+
221+
/**
222+
* Handle comment bulk actions.
223+
*
224+
* @param string $redirect_to Redirect URL after bulk actions.
225+
* @param string $doaction Action ID.
226+
* @param array $comment_ids Comment ids to apply bulk actions to.
227+
* @return string
228+
*/
229+
public function bulk_action_handler_comments( string $redirect_to, string $doaction, array $comment_ids ): string {
230+
$feature_ids = array_map(
231+
function ( $feature ) {
232+
return $feature::ID;
233+
},
234+
$this->language_processing_features
235+
);
236+
237+
if (
238+
empty( $comment_ids ) ||
239+
! in_array( $doaction, $feature_ids, true )
240+
) {
241+
return $redirect_to;
242+
}
243+
244+
foreach ( $comment_ids as $comment_id ) {
245+
switch ( $doaction ) {
246+
case Moderation::ID:
247+
$moderation_feature = new Moderation();
248+
249+
$result = $moderation_feature->run( $comment_id, 'comment' );
250+
if ( ! empty( $result ) && ! is_wp_error( $result ) ) {
251+
$moderation_feature->save_comment( $result, $comment_id );
252+
}
253+
254+
$action = $doaction;
255+
256+
break;
257+
}
258+
}
259+
260+
$args_to_remove = array_map(
261+
function ( $feature ) {
262+
return "bulk_{$feature}";
263+
},
264+
$feature_ids
265+
);
266+
267+
$redirect_to = remove_query_arg( $args_to_remove, $redirect_to );
268+
$redirect_to = add_query_arg( rawurlencode( "bulk_{$action}" ), count( $comment_ids ), $redirect_to );
269+
270+
return esc_url_raw( $redirect_to );
271+
}
272+
188273
/**
189274
* Register Language Processing row actions.
190275
*
@@ -517,6 +602,10 @@ function ( $feature ) {
517602
case Classification::ID:
518603
$action_text = __( 'Classification done for', 'classifai' );
519604
break;
605+
606+
case Moderation::ID:
607+
$action_text = __( 'Moderation done for', 'classifai' );
608+
break;
520609
}
521610

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

includes/Classifai/Features/DescriptiveTextGenerator.php

+2
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,8 @@ public function maybe_rescan_image( int $attachment_id ) {
263263
$result = $this->run( $attachment_id, 'descriptive_text' );
264264

265265
if ( $result && ! is_wp_error( $result ) ) {
266+
// Ensure we don't re-run this when the attachment is updated.
267+
remove_action( 'edit_attachment', [ $this, 'maybe_rescan_image' ] );
266268
$this->save( $result, $attachment_id );
267269
}
268270
}

includes/Classifai/Features/ImageCropping.php

+1-3
Original file line numberDiff line numberDiff line change
@@ -295,10 +295,8 @@ public function attachment_data_meta_box_content() {
295295
* @param int $attachment_id Attachment ID.
296296
*/
297297
public function maybe_crop_image( int $attachment_id ) {
298-
$metadata = wp_get_attachment_metadata( $attachment_id );
299-
300298
if ( clean_input( 'rescan-smart-crop' ) ) {
301-
$result = $this->run( $attachment_id, 'crop', $metadata );
299+
$result = $this->run( $attachment_id, 'crop' );
302300

303301
if ( ! empty( $result ) && ! is_wp_error( $result ) ) {
304302
$meta = $this->save( $result, $attachment_id );

includes/Classifai/Features/ImageTextExtraction.php

+2
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,8 @@ public function maybe_rescan_image( int $attachment_id ) {
301301
$result = $this->run( $attachment_id, 'ocr' );
302302

303303
if ( $result && ! is_wp_error( $result ) ) {
304+
// Ensure we don't re-run this when the attachment is updated.
305+
remove_action( 'edit_attachment', [ $this, 'maybe_rescan_image' ] );
304306
$this->save( $result, $attachment_id );
305307
}
306308
}

0 commit comments

Comments
 (0)