feat: add OpenRouter reasoning mode support (v0.4.9)
Enables reasoning-capable models (Grok 4.1 Fast, DeepSeek-R1, etc.) via new admin settings: Enable Reasoning toggle and Reasoning Effort selector. Provider auto-injects reasoning params when enabled; callers can override per-call via options array. Response parser captures reasoning_tokens and reasoning_content for visibility. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -80,6 +80,31 @@ class PRAutoBlogger_Settings_Fields_Extended {
|
||||
*/
|
||||
public static function get_fields(): array {
|
||||
return [
|
||||
// ── AI Models (extended) ────────────────────────────────────
|
||||
[
|
||||
'id' => 'prautoblogger_reasoning_enabled',
|
||||
'label' => __( 'Enable Reasoning', 'prautoblogger' ),
|
||||
'type' => 'toggle',
|
||||
'section' => 'prautoblogger_models',
|
||||
'default' => '0',
|
||||
'description' => __( 'Send reasoning instructions to models that support it (e.g. Grok, DeepSeek-R1). Reasoning tokens are billed as output tokens — expect higher costs per call. Models that don\'t support reasoning will ignore this.', 'prautoblogger' ),
|
||||
],
|
||||
[
|
||||
'id' => 'prautoblogger_reasoning_effort',
|
||||
'label' => __( 'Reasoning Effort', 'prautoblogger' ),
|
||||
'type' => 'select',
|
||||
'section' => 'prautoblogger_models',
|
||||
'default' => 'medium',
|
||||
'options' => [
|
||||
'xhigh' => __( 'Extra High — maximum depth, highest cost', 'prautoblogger' ),
|
||||
'high' => __( 'High — thorough reasoning', 'prautoblogger' ),
|
||||
'medium' => __( 'Medium — balanced (recommended)', 'prautoblogger' ),
|
||||
'low' => __( 'Low — light reasoning, lower cost', 'prautoblogger' ),
|
||||
'minimal' => __( 'Minimal — barely any reasoning', 'prautoblogger' ),
|
||||
],
|
||||
'description' => __( 'How much effort the model spends reasoning before answering. Higher effort = more reasoning tokens = higher cost. Only applies when reasoning is enabled above.', 'prautoblogger' ),
|
||||
],
|
||||
|
||||
// ── Schedule & Budget ───────────────────────────────────────
|
||||
[
|
||||
'id' => 'prautoblogger_daily_article_target',
|
||||
|
||||
@@ -36,7 +36,8 @@ class PRAutoBlogger_OpenRouter_Provider implements PRAutoBlogger_LLM_Provider_In
|
||||
* temperature?: float,
|
||||
* max_tokens?: int,
|
||||
* response_format?: array{type: string},
|
||||
* } $options Optional parameters.
|
||||
* reasoning?: array{enabled: bool, effort?: string},
|
||||
* } $options Optional parameters. Pass 'reasoning' to override the global setting.
|
||||
*
|
||||
* @return array{
|
||||
* content: string,
|
||||
@@ -88,6 +89,16 @@ class PRAutoBlogger_OpenRouter_Provider implements PRAutoBlogger_LLM_Provider_In
|
||||
$body['response_format'] = $options['response_format'];
|
||||
}
|
||||
|
||||
// Reasoning mode: explicit caller override takes priority, then global setting.
|
||||
if ( isset( $options['reasoning'] ) ) {
|
||||
$body['reasoning'] = $options['reasoning'];
|
||||
} elseif ( '1' === get_option( 'prautoblogger_reasoning_enabled', '0' ) ) {
|
||||
$body['reasoning'] = [
|
||||
'enabled' => true,
|
||||
'effort' => get_option( 'prautoblogger_reasoning_effort', 'medium' ),
|
||||
];
|
||||
}
|
||||
|
||||
$last_error = '';
|
||||
|
||||
$config = new PRAutoBlogger_OpenRouter_Config();
|
||||
|
||||
@@ -43,8 +43,10 @@ class PRAutoBlogger_OpenRouter_Response_Parser {
|
||||
* model: string,
|
||||
* prompt_tokens: int,
|
||||
* completion_tokens: int,
|
||||
* reasoning_tokens: int,
|
||||
* total_tokens: int,
|
||||
* finish_reason: string,
|
||||
* reasoning_content: string,
|
||||
* }
|
||||
*
|
||||
* @throws \RuntimeException If response structure is invalid.
|
||||
@@ -94,13 +96,18 @@ class PRAutoBlogger_OpenRouter_Response_Parser {
|
||||
|
||||
$usage = $data['usage'] ?? [];
|
||||
|
||||
// Reasoning content lives alongside 'content' in the message object.
|
||||
$reasoning_content = $data['choices'][0]['message']['reasoning'] ?? '';
|
||||
|
||||
return [
|
||||
'content' => (string) $content,
|
||||
'model' => $data['model'] ?? $model,
|
||||
'prompt_tokens' => (int) ( $usage['prompt_tokens'] ?? 0 ),
|
||||
'completion_tokens' => (int) ( $usage['completion_tokens'] ?? 0 ),
|
||||
'reasoning_tokens' => (int) ( $usage['reasoning_tokens'] ?? 0 ),
|
||||
'total_tokens' => (int) ( $usage['total_tokens'] ?? 0 ),
|
||||
'finish_reason' => $data['choices'][0]['finish_reason'] ?? 'unknown',
|
||||
'reasoning_content' => (string) $reasoning_content,
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user