From db7ec7404f4df5886d62d41908f94744fcf53146 Mon Sep 17 00:00:00 2001 From: shen <> Date: Tue, 15 Sep 2026 22:06:52 +0800 Subject: [PATCH] feat: set default reasoning effort to low for all AI requests --- kouyu_english/assets/config/ai_config.json | 1 + kouyu_english/lib/core/ai_config.dart | 10 +++ kouyu_english/lib/core/ai_service.dart | 96 ++++++++++++++-------- 3 files changed, 72 insertions(+), 35 deletions(-) diff --git a/kouyu_english/assets/config/ai_config.json b/kouyu_english/assets/config/ai_config.json index 6dbbfb4..201e8f3 100644 --- a/kouyu_english/assets/config/ai_config.json +++ b/kouyu_english/assets/config/ai_config.json @@ -2,6 +2,7 @@ "provider": "compatible", "endpoint": "https://codex.slcydia.fun/v1/responses", "model": "gemini-3.7-flash-high", + "reasoningEffort": "low", "apiKey": "***REMOVED***", "description": "默认 AI 对话服务配置。provider 可选: compatible (OpenAI 兼容/CLIProxyAPI/OneAPI), openAi, gemini, mock" } diff --git a/kouyu_english/lib/core/ai_config.dart b/kouyu_english/lib/core/ai_config.dart index 2789b2f..a9c1897 100644 --- a/kouyu_english/lib/core/ai_config.dart +++ b/kouyu_english/lib/core/ai_config.dart @@ -7,6 +7,7 @@ class AiConfigFile { required this.provider, required this.endpoint, required this.model, + this.reasoningEffort = 'low', this.apiKey, this.description, }); @@ -14,6 +15,7 @@ class AiConfigFile { final AiProviderType provider; final String endpoint; final String model; + final String reasoningEffort; final String? apiKey; final String? description; @@ -25,10 +27,15 @@ class AiConfigFile { (p) => p.name.toLowerCase() == providerStr.toLowerCase(), orElse: () => AiProviderType.compatible, ); + final effort = (json['reasoningEffort'] as String? ?? + json['reasoning_effort'] as String? ?? + 'low') + .trim(); return AiConfigFile( provider: provider, endpoint: (json['endpoint'] as String? ?? '').trim(), model: (json['model'] as String? ?? '').trim(), + reasoningEffort: effort.isEmpty ? 'low' : effort, apiKey: json['apiKey'] as String?, description: json['description'] as String?, ); @@ -43,6 +50,7 @@ class AiConfigFile { 'provider': provider.name, 'endpoint': endpoint, 'model': model, + 'reasoningEffort': reasoningEffort, if (apiKey != null) 'apiKey': apiKey, if (description != null) 'description': description, }; @@ -62,12 +70,14 @@ class AiConfigFile { AiProviderType? provider, String? endpoint, String? model, + String? reasoningEffort, String? apiKey, String? description, }) => AiConfigFile( provider: provider ?? this.provider, endpoint: endpoint ?? this.endpoint, model: model ?? this.model, + reasoningEffort: reasoningEffort ?? this.reasoningEffort, apiKey: apiKey ?? this.apiKey, description: description ?? this.description, ); diff --git a/kouyu_english/lib/core/ai_service.dart b/kouyu_english/lib/core/ai_service.dart index b59452e..5c6e2a2 100644 --- a/kouyu_english/lib/core/ai_service.dart +++ b/kouyu_english/lib/core/ai_service.dart @@ -157,7 +157,12 @@ class AiService { } ] } - ] + ], + 'generationConfig': { + 'thinkingConfig': { + 'thinkingBudget': 1024, + }, + }, }), ).timeout(const Duration(seconds: 25)); if (response.statusCode < 200 || response.statusCode >= 300) return null; @@ -189,6 +194,7 @@ class AiService { ], } ], + 'reasoning_effort': 'low', 'temperature': 0.1, }), ).timeout(const Duration(seconds: 25)); @@ -212,12 +218,15 @@ class AiService { required List> messages, double? temperature, int? maxTokens, + String reasoningEffort = 'low', }) { final isResponses = uri.path.endsWith('/responses'); if (isResponses) { return { 'model': model, 'input': messages, + 'reasoning': {'effort': reasoningEffort}, + 'reasoning_effort': reasoningEffort, if (temperature != null) 'temperature': temperature, if (maxTokens != null) 'max_output_tokens': maxTokens, }; @@ -225,11 +234,28 @@ class AiService { return { 'model': model, 'messages': messages, + 'reasoning_effort': reasoningEffort, if (temperature != null) 'temperature': temperature, if (maxTokens != null) 'max_tokens': maxTokens, }; } + static Map _buildGeminiGenerationConfig({ + double? temperature, + int? maxOutputTokens, + String? responseMimeType, + int thinkingBudget = 1024, + }) { + return { + if (temperature != null) 'temperature': temperature, + if (maxOutputTokens != null) 'maxOutputTokens': maxOutputTokens, + if (responseMimeType != null) 'responseMimeType': responseMimeType, + 'thinkingConfig': { + 'thinkingBudget': thinkingBudget, + }, + }; + } + /// Returns a display-only Chinese gloss for an unknown word or phrase. /// This is deliberately not a LexiconEntry and cannot affect review/mastery. Future temporaryDefinition({ @@ -278,10 +304,10 @@ class AiService { ], }, ], - 'generationConfig': { - 'maxOutputTokens': 200, - 'responseMimeType': 'application/json', - }, + 'generationConfig': _buildGeminiGenerationConfig( + maxOutputTokens: 200, + responseMimeType: 'application/json', + ), } : _buildOpenAiPayload( uri: uri, @@ -365,11 +391,11 @@ class AiService { ], }, ], - 'generationConfig': { - 'temperature': 0, - 'maxOutputTokens': 200, - 'responseMimeType': 'application/json', - }, + 'generationConfig': _buildGeminiGenerationConfig( + temperature: 0, + maxOutputTokens: 200, + responseMimeType: 'application/json', + ), } : _buildOpenAiPayload( uri: uri, @@ -483,11 +509,11 @@ class AiService { }, ) .toList(), - 'generationConfig': { - 'temperature': 0.3, - 'maxOutputTokens': 300, - 'responseMimeType': 'application/json', - }, + 'generationConfig': _buildGeminiGenerationConfig( + temperature: 0.3, + maxOutputTokens: 300, + responseMimeType: 'application/json', + ), } : _buildOpenAiPayload( uri: uri, @@ -559,11 +585,11 @@ class AiService { ], }, ], - 'generationConfig': { - 'temperature': 0.2, - 'maxOutputTokens': 300, - 'responseMimeType': 'application/json', - }, + 'generationConfig': _buildGeminiGenerationConfig( + temperature: 0.2, + maxOutputTokens: 300, + responseMimeType: 'application/json', + ), } : _buildOpenAiPayload( uri: uri, @@ -652,11 +678,11 @@ Learner wrote: $answer'''; ], }, ], - 'generationConfig': { - 'temperature': 0, - 'maxOutputTokens': 300, - 'responseMimeType': 'application/json', - }, + 'generationConfig': _buildGeminiGenerationConfig( + temperature: 0, + maxOutputTokens: 300, + responseMimeType: 'application/json', + ), } : _buildOpenAiPayload( uri: uri, @@ -730,11 +756,11 @@ Learner wrote: $answer'''; ], }, ], - 'generationConfig': { - 'temperature': 0.1, - 'maxOutputTokens': 850, - 'responseMimeType': 'application/json', - }, + 'generationConfig': _buildGeminiGenerationConfig( + temperature: 0.1, + maxOutputTokens: 850, + responseMimeType: 'application/json', + ), } : _buildOpenAiPayload( uri: uri, @@ -838,11 +864,11 @@ Learner wrote: $answer'''; ], }, ], - 'generationConfig': { - 'temperature': 0, - 'maxOutputTokens': 200, - 'responseMimeType': 'application/json', - }, + 'generationConfig': _buildGeminiGenerationConfig( + temperature: 0, + maxOutputTokens: 200, + responseMimeType: 'application/json', + ), } : _buildOpenAiPayload( uri: uri,