*/ private static array $option_key_map = array( 'system_instruction' => 'systemInstruction', 'candidate_count' => 'candidateCount', 'max_tokens' => 'maxTokens', 'temperature' => 'temperature', 'top_p' => 'topP', 'top_k' => 'topK', 'stop_sequences' => 'stopSequences', 'presence_penalty' => 'presencePenalty', 'frequency_penalty' => 'frequencyPenalty', 'logprobs' => 'logprobs', 'top_logprobs' => 'topLogprobs', ); /** * Gets the singleton instance. * * @since 0.2.1 * * @return \WordPress\AI\Services\AI_Service The singleton instance. */ public static function get_instance(): self { if ( null === self::$instance ) { self::$instance = new self(); } return self::$instance; } /** * Private constructor to enforce singleton pattern. * * The deprecation notice lives here rather than in `get_instance()` so that * it is emitted once per request instead of on every call. * * @since 0.2.1 */ private function __construct() { _deprecated_class( self::class, '1.3.0', 'wp_ai_client_prompt()' ); } /** * Creates a text generation prompt builder with default configuration applied. * * This is the primary method for text generation with AI providers. It returns * a configured prompt builder that consumers can use with the full SDK API. * * Example usage: * ```php * $service = AI_Service::get_instance(); * * // Simple usage * $text = $service->create_textgen_prompt( 'Summarize this text' )->generate_text(); * * // With options * $text = $service->create_textgen_prompt( 'Translate to French', array( * 'system_instruction' => 'You are a translator.', * 'temperature' => 0.3, * 'max_tokens' => 500, * ) )->generate_text(); * * // Generate multiple candidates * $titles = $service->create_textgen_prompt( 'Generate titles', array( * 'candidate_count' => 5, * 'temperature' => 0.8, * ) )->generate_texts(); * ``` * * @since 0.2.1 * * @param string|null $prompt Optional. Initial prompt content. * @param array $options Optional. Configuration options. { * @type string $system_instruction System instruction for the AI. * @type float $temperature Temperature for generation (0.0-2.0). * @type int $max_tokens Maximum tokens to generate. * @type float $top_p Top-p (nucleus) sampling value. * @type int $top_k Top-k sampling value. * @type int $candidate_count Number of candidates to generate. * @type float $presence_penalty Presence penalty for generation. * @type float $frequency_penalty Frequency penalty for generation. * @type list $stop_sequences Stop sequences for generation. * @type bool $logprobs Whether to return log probabilities. * @type int $top_logprobs Top log probabilities to return. * } * @return \WP_AI_Client_Prompt_Builder The prompt builder instance. */ public function create_textgen_prompt( ?string $prompt = null, array $options = array() ) { $builder = wp_ai_client_prompt( $prompt ); // Apply default model preferences. $models = get_preferred_models_for_text_generation(); if ( ! empty( $models ) ) { $builder = $builder->using_model_preference( ...$models ); } // Apply options via ModelConfig if any are provided. if ( ! empty( $options ) ) { $config_array = $this->map_options_to_config( $options ); if ( ! empty( $config_array ) ) { $config = ModelConfig::fromArray( $config_array ); $builder = $builder->using_model_config( $config ); } } return $builder; } /** * Maps WordPress snake_case options to SDK camelCase config array. * * @since 0.2.1 * * @param array $options The options array with snake_case keys. * @return array The mapped config array with camelCase keys. */ private function map_options_to_config( array $options ): array { $config = array(); foreach ( self::$option_key_map as $wp_key => $sdk_key ) { if ( ! array_key_exists( $wp_key, $options ) ) { continue; } $config[ $sdk_key ] = $options[ $wp_key ]; } return $config; } }