From 8532d7bf7d993de59b5314dd6c27497422ebfb56 Mon Sep 17 00:00:00 2001 From: Siddharth Thevaril Date: Wed, 8 Nov 2023 18:27:58 +0530 Subject: [PATCH] migrate text to speech under language processing --- includes/Classifai/Admin/BulkActions.php | 10 +- includes/Classifai/Admin/SavePostHandler.php | 26 +- .../Classifai/Command/ClassifaiCommand.php | 4 +- .../Classifai/Features/ContentResizing.php | 22 +- .../Classifai/Features/ExcerptGeneration.php | 16 +- includes/Classifai/Features/Feature.php | 34 +- includes/Classifai/Features/TextToSpeech.php | 257 +++++++++++++++ .../Classifai/Features/TitleGeneration.php | 18 +- includes/Classifai/Helpers.php | 16 +- .../Azure/{TextToSpeech.php => Speech.php} | 310 +++++++++++++----- .../Classifai/Providers/OpenAI/ChatGPT.php | 96 +----- includes/Classifai/Providers/Provider.php | 40 ++- .../Classifai/Services/LanguageProcessing.php | 2 +- .../Classifai/Services/ServicesManager.php | 1 + 14 files changed, 606 insertions(+), 246 deletions(-) create mode 100644 includes/Classifai/Features/TextToSpeech.php rename includes/Classifai/Providers/Azure/{TextToSpeech.php => Speech.php} (73%) diff --git a/includes/Classifai/Admin/BulkActions.php b/includes/Classifai/Admin/BulkActions.php index e01e75f9d..efae92ebb 100644 --- a/includes/Classifai/Admin/BulkActions.php +++ b/includes/Classifai/Admin/BulkActions.php @@ -2,7 +2,7 @@ namespace Classifai\Admin; use Classifai\Providers\Azure\ComputerVision; -use Classifai\Providers\Azure\TextToSpeech; +use Classifai\Providers\Azure\Speech; use Classifai\Providers\OpenAI\ChatGPT; use Classifai\Providers\OpenAI\Embeddings; use Classifai\Providers\OpenAI\Whisper; @@ -51,7 +51,7 @@ public function can_register() { private $whisper; /** - * @var \Classifai\Providers\Azure\TextToSpeech + * @var \Classifai\Providers\Azure\Speech */ private $text_to_speech; @@ -160,7 +160,7 @@ public function register_bulk_actions( $bulk_actions ) { } if ( - is_a( $this->text_to_speech, '\Classifai\Providers\Azure\TextToSpeech' ) && + is_a( $this->text_to_speech, '\Classifai\Providers\Azure\Speech' ) && in_array( get_current_screen()->post_type, $this->text_to_speech->get_supported_post_types(), true ) ) { $bulk_actions['text_to_speech'] = __( 'Text to speech', 'classifai' ); @@ -250,7 +250,7 @@ public function bulk_action_handler( $redirect_to, $doaction, $post_ids ) { if ( 'text_to_speech' === $doaction ) { // Handle Azure Text to Speech generation. if ( - is_a( $this->text_to_speech, '\Classifai\Providers\Azure\TextToSpeech' ) && + is_a( $this->text_to_speech, '\Classifai\Providers\Azure\Speech' ) && is_a( $this->save_post_handler, '\Classifai\Admin\SavePostHandler' ) ) { $action = 'text_to_speech'; @@ -415,7 +415,7 @@ public function register_row_action( $actions, $post ) { } } - if ( is_a( $this->text_to_speech, '\Classifai\Providers\Azure\TextToSpeech' ) ) { + if ( is_a( $this->text_to_speech, '\Classifai\Providers\Azure\Speech' ) ) { if ( in_array( $post->post_type, $this->text_to_speech->get_supported_post_types(), true ) ) { $actions['text_to_speech'] = sprintf( '%s', diff --git a/includes/Classifai/Admin/SavePostHandler.php b/includes/Classifai/Admin/SavePostHandler.php index 0b8ba9f03..304708a8c 100644 --- a/includes/Classifai/Admin/SavePostHandler.php +++ b/includes/Classifai/Admin/SavePostHandler.php @@ -2,7 +2,8 @@ namespace Classifai\Admin; -use \Classifai\Providers\Azure\TextToSpeech; +use Classifai\Features\TextToSpeech; +use \Classifai\Providers\Azure\Speech; use \Classifai\Watson\Normalizer; /** @@ -173,6 +174,10 @@ public function classify( $post_id ) { /** * Synthesizes speech from the post title and content. * + * @todo: This method is copied to the Azure\Speech provider. + * Once all the speech-synthesize changed are migrated, we should + * remove this method. + * * @param int $post_id Post ID. * @return bool|int|WP_Error */ @@ -193,11 +198,12 @@ public function synthesize_speech( $post_id ) { } $normalizer = new Normalizer(); - $settings = \Classifai\get_plugin_settings( 'language_processing', TextToSpeech::FEATURE_NAME ); + $feature = new TextToSpeech(); + $settings = $feature->get_settings(); $post = get_post( $post_id ); $post_content = $normalizer->normalize_content( $post->post_content, $post->post_title, $post_id ); - $content_hash = get_post_meta( $post_id, TextToSpeech::AUDIO_HASH_KEY, true ); - $saved_attachment_id = (int) get_post_meta( $post_id, TextToSpeech::AUDIO_ID_KEY, true ); + $content_hash = get_post_meta( $post_id, Speech::AUDIO_HASH_KEY, true ); + $saved_attachment_id = (int) get_post_meta( $post_id, Speech::AUDIO_ID_KEY, true ); // Don't regenerate the audio file it it already exists and the content hasn't changed. if ( $saved_attachment_id ) { @@ -248,7 +254,7 @@ public function synthesize_speech( $post_id ) { ), ); - $remote_url = sprintf( '%s%s', $settings['credentials']['url'], TextToSpeech::API_PATH ); + $remote_url = sprintf( '%s%s', $settings['credentials']['url'], Speech::API_PATH ); $response = wp_remote_post( $remote_url, $request_params ); if ( is_wp_error( $response ) ) { @@ -272,8 +278,8 @@ public function synthesize_speech( $post_id ) { // If audio already exists for this post, delete it. if ( $saved_attachment_id ) { wp_delete_attachment( $saved_attachment_id, true ); - delete_post_meta( $post_id, TextToSpeech::AUDIO_ID_KEY ); - delete_post_meta( $post_id, TextToSpeech::AUDIO_TIMESTAMP_KEY ); + delete_post_meta( $post_id, Speech::AUDIO_ID_KEY ); + delete_post_meta( $post_id, Speech::AUDIO_TIMESTAMP_KEY ); } // The audio file name. @@ -315,9 +321,9 @@ public function synthesize_speech( $post_id ) { ); } - update_post_meta( $post_id, TextToSpeech::AUDIO_ID_KEY, absint( $attachment_id ) ); - update_post_meta( $post_id, TextToSpeech::AUDIO_TIMESTAMP_KEY, time() ); - update_post_meta( $post_id, TextToSpeech::AUDIO_HASH_KEY, md5( $post_content ) ); + update_post_meta( $post_id, Speech::AUDIO_ID_KEY, absint( $attachment_id ) ); + update_post_meta( $post_id, Speech::AUDIO_TIMESTAMP_KEY, time() ); + update_post_meta( $post_id, Speech::AUDIO_HASH_KEY, md5( $post_content ) ); return $attachment_id; } diff --git a/includes/Classifai/Command/ClassifaiCommand.php b/includes/Classifai/Command/ClassifaiCommand.php index bc677063c..38f48e2a7 100644 --- a/includes/Classifai/Command/ClassifaiCommand.php +++ b/includes/Classifai/Command/ClassifaiCommand.php @@ -9,7 +9,7 @@ use Classifai\PostClassifier; use Classifai\Providers\Azure\ComputerVision; use Classifai\Providers\Azure\SmartCropping; -use Classifai\Providers\Azure\TextToSpeech; +use Classifai\Providers\Azure\Speech; use Classifai\Providers\OpenAI\Whisper; use Classifai\Providers\OpenAI\Whisper\Transcribe; use Classifai\Providers\OpenAI\ChatGPT; @@ -244,7 +244,7 @@ public function text_to_speech( $args = [], $opts = [] ) { $opts = wp_parse_args( $opts, $defaults ); $opts['per_page'] = (int) $opts['per_page'] > 0 ? $opts['per_page'] : 100; - $allowed_post_types = TextToSpeech::get_supported_post_types(); + $allowed_post_types = Speech::get_supported_post_types(); $count = 0; $errors = 0; diff --git a/includes/Classifai/Features/ContentResizing.php b/includes/Classifai/Features/ContentResizing.php index 579aeed39..28cdc4007 100644 --- a/includes/Classifai/Features/ContentResizing.php +++ b/includes/Classifai/Features/ContentResizing.php @@ -50,7 +50,7 @@ public function get_providers() { * Sets up the fields and sections for the feature. */ public function setup_fields_sections() { - $default_settings = $this->get_default_settings(); + $settings = $this->get_settings(); add_settings_section( $this->get_option_name() . '_section', @@ -68,8 +68,8 @@ public function setup_fields_sections() { [ 'label_for' => 'status', 'input_type' => 'checkbox', - 'default_value' => $default_settings['status'], - 'description' => __( 'A button will be added to the status panel that can be used to generate titles.', 'classifai' ), + 'default_value' => $settings['status'], + 'description' => __( '"Condense this text" and "Expand this text" menu items will be added to the paragraph block\'s toolbar menu.', 'classifai' ), ] ); @@ -82,8 +82,8 @@ public function setup_fields_sections() { [ 'label_for' => 'roles', 'options' => $this->roles, - 'default_values' => $default_settings['roles'], - 'description' => __( 'Choose which roles are allowed to generate excerpts.', 'classifai' ), + 'default_values' => $settings['roles'], + 'description' => __( 'Choose which roles are allowed to use this feature.', 'classifai' ), ] ); @@ -96,7 +96,7 @@ public function setup_fields_sections() { [ 'label_for' => 'provider', 'options' => $this->get_providers(), - 'default_value' => $default_settings['provider'], + 'default_value' => $settings['provider'], ] ); @@ -209,7 +209,6 @@ public function get_default_settings() { */ public function sanitize_settings( $settings ) { $new_settings = $this->get_settings(); - $chat_gpt = new ChatGPT( $this ); if ( empty( $settings['status'] ) || 1 !== (int) $settings['status'] ) { $new_settings['status'] = 'no'; @@ -236,12 +235,13 @@ public function sanitize_settings( $settings ) { * When multiple providers are supported, the sanitization methods for each provider should be called here. */ if ( isset( $settings[ ChatGPT::ID ] ) ) { - $api_key_settings = $chat_gpt->sanitize_api_key_settings( $settings ); + $provider_instance = new ChatGPT( $this ); + $api_key_settings = $provider_instance->sanitize_api_key_settings( $settings ); $new_settings[ ChatGPT::ID ]['api_key'] = $api_key_settings[ ChatGPT::ID ]['api_key']; $new_settings[ ChatGPT::ID ]['authenticated'] = $api_key_settings[ ChatGPT::ID ]['authenticated']; - $new_settings[ ChatGPT::ID ]['number_of_suggestions'] = $chat_gpt->sanitize_number_of_responses_field( 'number_of_suggestions', $settings ); - $new_settings[ ChatGPT::ID ]['condense_text_prompt'] = $chat_gpt->sanitize_prompts( 'condense_text_prompt', $settings ); - $new_settings[ ChatGPT::ID ]['expand_text_prompt'] = $chat_gpt->sanitize_prompts( 'expand_text_prompt', $settings ); + $new_settings[ ChatGPT::ID ]['number_of_suggestions'] = $provider_instance->sanitize_number_of_responses_field( 'number_of_suggestions', $settings ); + $new_settings[ ChatGPT::ID ]['condense_text_prompt'] = $provider_instance->sanitize_prompts( 'condense_text_prompt', $settings ); + $new_settings[ ChatGPT::ID ]['expand_text_prompt'] = $provider_instance->sanitize_prompts( 'expand_text_prompt', $settings ); } return $new_settings; diff --git a/includes/Classifai/Features/ExcerptGeneration.php b/includes/Classifai/Features/ExcerptGeneration.php index 113895992..1349d8911 100644 --- a/includes/Classifai/Features/ExcerptGeneration.php +++ b/includes/Classifai/Features/ExcerptGeneration.php @@ -45,7 +45,7 @@ public function get_providers() { * Sets up the fields and sections for the feature. */ public function setup_fields_sections() { - $default_settings = $this->get_default_settings(); + $settings = $this->get_settings(); add_settings_section( $this->get_option_name() . '_section', @@ -63,7 +63,7 @@ public function setup_fields_sections() { [ 'label_for' => 'status', 'input_type' => 'checkbox', - 'default_value' => $default_settings['status'], + 'default_value' => $settings['status'], 'description' => __( 'A button will be added to the status panel that can be used to generate titles.', 'classifai' ), ] ); @@ -77,7 +77,7 @@ public function setup_fields_sections() { [ 'label_for' => 'roles', 'options' => $this->roles, - 'default_values' => $default_settings['roles'], + 'default_values' => $settings['roles'], 'description' => __( 'Choose which roles are allowed to generate excerpts.', 'classifai' ), ] ); @@ -93,7 +93,7 @@ public function setup_fields_sections() { 'input_type' => 'number', 'min' => 1, 'step' => 1, - 'default_value' => $default_settings['length'], + 'default_value' => $settings['length'], 'description' => __( 'How many words should the excerpt be? Note that the final result may not exactly match this. In testing, ChatGPT tended to exceed this number by 10-15 words.', 'classifai' ), ] ); @@ -107,7 +107,7 @@ public function setup_fields_sections() { [ 'label_for' => 'provider', 'options' => $this->get_providers(), - 'default_value' => $default_settings['provider'], + 'default_value' => $settings['provider'], ] ); @@ -197,7 +197,6 @@ public function get_default_settings() { */ public function sanitize_settings( $settings ) { $new_settings = $this->get_settings(); - $chat_gpt = new ChatGPT( $this ); if ( empty( $settings['status'] ) || 1 !== (int) $settings['status'] ) { $new_settings['status'] = 'no'; @@ -230,10 +229,11 @@ public function sanitize_settings( $settings ) { * When multiple providers are supported, the sanitization methods for each provider should be called here. */ if ( isset( $settings[ ChatGPT::ID ] ) ) { - $api_key_settings = $chat_gpt->sanitize_api_key_settings( $settings ); + $provider_instance = new ChatGPT( $this ); + $api_key_settings = $provider_instance->sanitize_api_key_settings( $settings ); $new_settings[ ChatGPT::ID ]['api_key'] = $api_key_settings[ ChatGPT::ID ]['api_key']; $new_settings[ ChatGPT::ID ]['authenticated'] = $api_key_settings[ ChatGPT::ID ]['authenticated']; - $new_settings[ ChatGPT::ID ]['generate_excerpt_prompt'] = $chat_gpt->sanitize_prompts( 'generate_excerpt_prompt', $settings ); + $new_settings[ ChatGPT::ID ]['generate_excerpt_prompt'] = $provider_instance->sanitize_prompts( 'generate_excerpt_prompt', $settings ); } return $new_settings; diff --git a/includes/Classifai/Features/Feature.php b/includes/Classifai/Features/Feature.php index 2051ddcb3..758092720 100644 --- a/includes/Classifai/Features/Feature.php +++ b/includes/Classifai/Features/Feature.php @@ -106,12 +106,7 @@ public function register() { return; } - $feature_settings = $this->get_settings(); - $provider_id = $feature_settings['provider']; - $provider_instance = find_provider_class( $this->provider_instances, $provider_id ); - $provider_class = get_class( $provider_instance ); - $provider_instance = new $provider_class( $this ); - + $provider_instance = $this->get_feature_provider_instance(); $provider_instance->register(); } @@ -156,6 +151,28 @@ public function get_settings( $index = false ) { return $settings; } + /** + * Returns the instance of the provider set for the feature. + * + * @param string $provider_id The ID of the provider. + * + * @return \Classifai\Providers + */ + public function get_feature_provider_instance( $provider_id = '' ) { + $new_settings = $this->get_settings(); + $provider_id = $provider_id ? $provider_id : $new_settings['provider']; + $provider_instance = find_provider_class( $this->provider_instances ?? [], $provider_id ); + + if ( is_wp_error( $provider_instance ) ) { + return null; + } + + $provider_class = get_class( $provider_instance ); + $provider_instance = new $provider_class( $this ); + + return $provider_instance; + } + /** * Returns whether the provider is configured or not. * @@ -376,7 +393,8 @@ class="button-secondary js-classifai-add-prompt-fieldset"> * @param array $args The args passed to add_settings_field. */ public function render_select( $args ) { - $setting_index = $this->get_settings(); + $option_index = isset( $args['option_index'] ) ? $args['option_index'] : false; + $setting_index = $this->get_settings( $option_index ); $saved = ( isset( $setting_index[ $args['label_for'] ] ) ) ? $setting_index[ $args['label_for'] ] : ''; $data_attr = isset( $args['data_attr'] ) ?: []; @@ -387,7 +405,7 @@ public function render_select( $args ) {