diff --git a/includes/Classifai/Providers/Azure/Read.php b/includes/Classifai/Providers/Azure/Read.php index 57562eabe..c1a5abb62 100644 --- a/includes/Classifai/Providers/Azure/Read.php +++ b/includes/Classifai/Providers/Azure/Read.php @@ -147,7 +147,7 @@ public function read_document() { * Filters the request arguments sent to Read endpoint. * * @since 1.7.0 - * @hook classifai_azure_read_should_process + * @hook classifai_azure_read_request_args * * @param {array} $args Whether to run OCR processing or not. * @param {int} $attachment_id The attachment ID. diff --git a/includes/Classifai/Providers/OpenAI/APIRequest.php b/includes/Classifai/Providers/OpenAI/APIRequest.php index 333954e2c..5ffb23728 100644 --- a/includes/Classifai/Providers/OpenAI/APIRequest.php +++ b/includes/Classifai/Providers/OpenAI/APIRequest.php @@ -25,13 +25,22 @@ class APIRequest { */ public $api_key; + /** + * The feature name. + * + * @var string + */ + public $feature; + /** * OpenAI APIRequest constructor. * * @param string $api_key OpenAI API key. + * @param string $feature Feature name. */ - public function __construct( string $api_key = '' ) { + public function __construct( string $api_key = '', string $feature = '' ) { $this->api_key = $api_key; + $this->feature = $feature; } /** @@ -42,8 +51,55 @@ public function __construct( string $api_key = '' ) { * @return array|WP_Error */ public function get( string $url, array $options = [] ) { + /** + * Filter the URL for the get request. + * + * @since 2.4.0 + * @hook classifai_openai_api_request_get_url + * + * @param {string} $url The URL for the request. + * @param {array} $options The options for the request. + * @param {string} $this->feature The feature name. + * + * @return {string} The URL for the request. + */ + $url = apply_filters( 'classifai_openai_api_request_get_url', $url, $options, $this->feature ); + + /** + * Filter the options for the get request. + * + * @since 2.4.0 + * @hook classifai_openai_api_request_get_options + * + * @param {array} $options The options for the request. + * @param {string} $url The URL for the request. + * @param {string} $this->feature The feature name. + * + * @return {array} The options for the request. + */ + $options = apply_filters( 'classifai_openai_api_request_get_options', $options, $url, $this->feature ); + $this->add_headers( $options ); - return $this->get_result( wp_remote_get( $url, $options ) ); // phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.wp_remote_get_wp_remote_get + + /** + * Filter the response from OpenAI for a get request. + * + * @since 2.4.0 + * @hook classifai_openai_api_response_get + * + * @param {string} $url Request URL. + * @param {array} $options Request body options. + * @param {string} $this->feature Feature name. + * + * @return {array} API response. + */ + return apply_filters( + 'classifai_openai_api_response_get', + $this->get_result( wp_remote_get( $url, $options ) ), // phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.wp_remote_get_wp_remote_get + $url, + $options, + $this->feature + ); } /** @@ -60,8 +116,56 @@ public function post( string $url = '', array $options = [] ) { 'timeout' => 60, // phpcs:ignore WordPressVIPMinimum.Performance.RemoteRequestTimeout.timeout_timeout ] ); + + /** + * Filter the URL for the post request. + * + * @since 2.4.0 + * @hook classifai_openai_api_request_post_url + * + * @param {string} $url The URL for the request. + * @param {array} $options The options for the request. + * @param {string} $this->feature The feature name. + * + * @return {string} The URL for the request. + */ + $url = apply_filters( 'classifai_openai_api_request_post_url', $url, $options, $this->feature ); + + /** + * Filter the options for the post request. + * + * @since 2.4.0 + * @hook classifai_openai_api_request_post_options + * + * @param {array} $options The options for the request. + * @param {string} $url The URL for the request. + * @param {string} $this->feature The feature name. + * + * @return {array} The options for the request. + */ + $options = apply_filters( 'classifai_openai_api_request_post_options', $options, $url, $this->feature ); + $this->add_headers( $options ); - return $this->get_result( wp_remote_post( $url, $options ) ); // phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.wp_remote_get_wp_remote_get + + /** + * Filter the response from OpenAI for a post request. + * + * @since 2.4.0 + * @hook classifai_openai_api_response_post + * + * @param {string} $url Request URL. + * @param {array} $options Request body options. + * @param {string} $this->feature Feature name. + * + * @return {array} API response. + */ + return apply_filters( + 'classifai_openai_api_response_post', + $this->get_result( wp_remote_post( $url, $options ) ), // phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.wp_remote_get_wp_remote_get + $url, + $options, + $this->feature + ); } /** @@ -72,6 +176,19 @@ public function post( string $url = '', array $options = [] ) { * @return array|WP_Error */ public function post_form( string $url = '', array $body = [] ) { + /** + * Filter the URL for the post form request. + * + * @since 2.4.0 + * @hook classifai_openai_api_request_post_form_url + * + * @param {string} $url The URL for the request. + * @param {string} $this->feature The feature name. + * + * @return {string} The URL for the request. + */ + $url = apply_filters( 'classifai_openai_api_request_post_form_url', $url, $this->feature ); + $boundary = wp_generate_password( 24, false ); $payload = ''; @@ -95,17 +212,54 @@ public function post_form( string $url = '', array $body = [] ) { $payload .= '--' . $boundary . '--'; - $options = [ - 'body' => $payload, - 'headers' => [ - 'Content-Type' => 'multipart/form-data; boundary=' . $boundary, + /** + * Filter the options for the post form request. + * + * @since 2.4.0 + * @hook classifai_openai_api_request_post_form_options + * + * @param {array} $options The options for the request. + * @param {string} $url The URL for the request. + * @param {array} $body The body of the request. + * @param {string} $this->feature The feature name. + * + * @return {array} The options for the request. + */ + $options = apply_filters( + 'classifai_openai_api_request_post_form_options', + [ + 'body' => $payload, + 'headers' => [ + 'Content-Type' => 'multipart/form-data; boundary=' . $boundary, + ], + 'timeout' => 60, // phpcs:ignore WordPressVIPMinimum.Performance.RemoteRequestTimeout.timeout_timeout ], - 'timeout' => 60, // phpcs:ignore WordPressVIPMinimum.Performance.RemoteRequestTimeout.timeout_timeout - ]; + $url, + $body, + $this->feature + ); $this->add_headers( $options ); - return $this->get_result( wp_remote_post( $url, $options ) ); + /** + * Filter the response from OpenAI for a post form request. + * + * @since 2.4.0 + * @hook classifai_openai_api_response_post_form + * + * @param {string} $url Request URL. + * @param {array} $options Request body options. + * @param {string} $this->feature Feature name. + * + * @return {array} API response. + */ + return apply_filters( + 'classifai_openai_api_response_post_form', + $this->get_result( wp_remote_post( $url, $options ) ), // phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.wp_remote_get_wp_remote_get + $url, + $options, + $this->feature + ); } /** diff --git a/includes/Classifai/Providers/OpenAI/ChatGPT.php b/includes/Classifai/Providers/OpenAI/ChatGPT.php index b307dfc3b..7110d5bd6 100644 --- a/includes/Classifai/Providers/OpenAI/ChatGPT.php +++ b/includes/Classifai/Providers/OpenAI/ChatGPT.php @@ -796,7 +796,7 @@ public function generate_excerpt( int $post_id = 0, array $args = [] ) { $excerpt_length = absint( $settings['length'] ?? 55 ); - $request = new APIRequest( $settings['api_key'] ?? '' ); + $request = new APIRequest( $settings['api_key'] ?? '', $this->get_option_name() ); $excerpt_prompt = ! empty( $settings['generate_excerpt_prompt'] ) ? esc_textarea( $settings['generate_excerpt_prompt'] ) : $this->generate_excerpt_prompt; @@ -899,7 +899,7 @@ public function generate_titles( int $post_id = 0, array $args = [] ) { return new WP_Error( 'not_enabled', esc_html__( 'Title generation is disabled or OpenAI authentication failed. Please check your settings.', 'classifai' ) ); } - $request = new APIRequest( $settings['api_key'] ?? '' ); + $request = new APIRequest( $settings['api_key'] ?? '', $this->get_option_name() ); $prompt = ! empty( $settings['generate_title_prompt'] ) ? esc_textarea( $settings['generate_title_prompt'] ) : $this->generate_title_prompt; @@ -998,7 +998,7 @@ public function resize_content( int $post_id, array $args = array() ) { ] ); - $request = new APIRequest( $settings['api_key'] ?? '' ); + $request = new APIRequest( $settings['api_key'] ?? '', $this->get_option_name() ); if ( 'shrink' === $args['resize_type'] ) { $prompt = ! empty( $settings['shrink_content_prompt'] ) ? esc_textarea( $settings['shrink_content_prompt'] ) : $this->shrink_content_prompt; @@ -1010,6 +1010,7 @@ public function resize_content( int $post_id, array $args = array() ) { * Filter the resize prompt we will send to ChatGPT. * * @since 2.3.0 + * @hook classifai_chatgpt_' . $args['resize_type'] . '_content_prompt * * @param {string} $prompt Resize prompt we are sending to ChatGPT. Gets added as a system prompt. * @param {int} $post_id ID of post. diff --git a/includes/Classifai/Providers/OpenAI/DallE.php b/includes/Classifai/Providers/OpenAI/DallE.php index 7a3b4a070..ab3732e11 100644 --- a/includes/Classifai/Providers/OpenAI/DallE.php +++ b/includes/Classifai/Providers/OpenAI/DallE.php @@ -482,7 +482,7 @@ public function generate_image_callback( string $prompt = '', array $args = [] ) return new WP_Error( 'invalid_param', esc_html__( 'Your image prompt is too long. Please ensure it doesn\'t exceed 1000 characters.', 'classifai' ) ); } - $request = new APIRequest( $settings['api_key'] ?? '' ); + $request = new APIRequest( $settings['api_key'] ?? '', 'generate-image' ); /** * Filter the request body before sending to DALLĀ·E. diff --git a/includes/Classifai/Providers/OpenAI/Embeddings.php b/includes/Classifai/Providers/OpenAI/Embeddings.php index 9b4ae9556..103c1edc3 100644 --- a/includes/Classifai/Providers/OpenAI/Embeddings.php +++ b/includes/Classifai/Providers/OpenAI/Embeddings.php @@ -580,7 +580,7 @@ public function generate_embeddings( int $id = 0, $type = 'post' ) { return false; } - $request = new APIRequest( $settings['api_key'] ?? '' ); + $request = new APIRequest( $settings['api_key'] ?? '', $this->get_option_name() ); /** * Filter the request body before sending to OpenAI. diff --git a/includes/Classifai/Providers/OpenAI/Tokenizer.php b/includes/Classifai/Providers/OpenAI/Tokenizer.php index 70663a570..6785fe446 100644 --- a/includes/Classifai/Providers/OpenAI/Tokenizer.php +++ b/includes/Classifai/Providers/OpenAI/Tokenizer.php @@ -35,6 +35,32 @@ class Tokenizer { */ public function __construct( $max_tokens ) { $this->max_tokens = $max_tokens; + + /** + * How many characters in one token (roughly) + * + * @since 2.4..0 + * @hook classifai_openai_characters_in_token + * + * @param {int} $characters_in_token How many characters in one token (roughly) + * @param {int} $max_tokens Maximum tokens the model supports. + * + * @return {int} + */ + $this->characters_in_token = apply_filters( 'classifai_openai_characters_in_token', $this->characters_in_token, $max_tokens ); + + /** + * How many tokens a word will take (roughly) + * + * @since 2.4.0 + * @hook classifai_openai_tokens_per_word + * + * @param {int} $tokens_per_word How many tokens a word will take (roughly) + * @param {int} $max_tokens Maximum tokens the model supports. + * + * @return {int} + */ + $this->tokens_per_word = apply_filters( 'classifai_openai_tokens_per_word', $this->tokens_per_word, $max_tokens ); } /** diff --git a/includes/Classifai/Providers/OpenAI/Whisper/Transcribe.php b/includes/Classifai/Providers/OpenAI/Whisper/Transcribe.php index 9faebb731..449585826 100644 --- a/includes/Classifai/Providers/OpenAI/Whisper/Transcribe.php +++ b/includes/Classifai/Providers/OpenAI/Whisper/Transcribe.php @@ -63,7 +63,7 @@ public function process() { return new WP_Error( 'process_error', esc_html__( 'Attachment does not meet processing requirements. Ensure the file type and size meet requirements.', 'classifai' ) ); } - $request = new APIRequest( $this->settings['api_key'] ?? '' ); + $request = new APIRequest( $this->settings['api_key'] ?? '', 'whisper' ); /** * Filter the request body before sending to Whisper.