Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 54 additions & 11 deletions src/main/presenter/configPresenter/modelDefaultSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -701,7 +701,8 @@ export const defaultModelsSettings: DefaultModelSetting[] = [
match: ['o4-mini-high'],
vision: false,
functionCall: true,
reasoning: true
reasoning: true,
reasoningEffort: 'medium'
},
{
id: 'o3',
Expand All @@ -712,7 +713,44 @@ export const defaultModelsSettings: DefaultModelSetting[] = [
match: ['o3'],
vision: false,
functionCall: true,
reasoning: true
reasoning: true,
reasoningEffort: 'medium'
},
{
id: 'o3-pro',
name: 'OpenAI o3 Pro',
temperature: 0.7,
maxTokens: 100_000,
contextLength: 200_000,
match: ['o3-pro'],
vision: true,
functionCall: true,
reasoning: true,
reasoningEffort: 'high'
},
{
id: 'o3-mini',
name: 'OpenAI o3 Mini',
temperature: 0.7,
maxTokens: 65536,
contextLength: 200_000,
match: ['o3-mini'],
vision: false,
functionCall: true,
reasoning: true,
reasoningEffort: 'medium'
},
{
id: 'o3-preview',
name: 'OpenAI o3 Preview',
temperature: 0.7,
maxTokens: 100_000,
contextLength: 200_000,
match: ['o3-preview'],
vision: true,
functionCall: true,
reasoning: true,
reasoningEffort: 'medium'
},
{
id: 'o4-mini',
Expand All @@ -723,7 +761,8 @@ export const defaultModelsSettings: DefaultModelSetting[] = [
match: ['o4-mini'],
vision: false,
functionCall: true,
reasoning: true
reasoning: true,
reasoningEffort: 'medium'
},
{
id: 'gpt-4.1-nano',
Expand Down Expand Up @@ -832,7 +871,8 @@ export const defaultModelsSettings: DefaultModelSetting[] = [
match: ['o1-preview'],
vision: true,
functionCall: false,
reasoning: true
reasoning: true,
reasoningEffort: 'medium'
},
{
id: 'o1-mini',
Expand All @@ -843,18 +883,20 @@ export const defaultModelsSettings: DefaultModelSetting[] = [
match: ['o1-mini'],
vision: true,
functionCall: false,
reasoning: true
reasoning: true,
reasoningEffort: 'medium'
},
{
id: 'o1-mini',
name: 'OpenAI o1 Mini',
id: 'o1-pro',
name: 'OpenAI o1 Pro',
temperature: 0.7,
maxTokens: 65536,
maxTokens: 32768,
contextLength: 128000,
match: ['o1-mini'],
match: ['o1-pro'],
vision: true,
functionCall: false,
reasoning: true
reasoning: true,
reasoningEffort: 'high'
},
Comment on lines +890 to 900
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Confirm model ID mapping and downstream usage for o1-pro

The o1-pro block changes include maxTokens and match: ['o1-pro'] with reasoningEffort: 'high'. Verify any UI or provider-side heuristics relying on 'o1-mini' are not implicitly tied to this new 'o1-pro' high-effort profile.

Run this to check for hard-coded 'o1-mini' expectations in the repo:


🏁 Script executed:

#!/bin/bash
# Search for o1-mini/o1-pro references with nearby context
rg -n -C3 -P '\bo1-(mini|pro)\b' --type=ts --type=tsx --type=js --type=jsx

Length of output: 104


🏁 Script executed:

#!/bin/bash
# Retry searching for o1-mini/o1-pro references across TS/JS files using glob patterns
rg -n -C3 -e '\bo1-(mini|pro)\b' -g '*.ts' -g '*.tsx' -g '*.js' -g '*.jsx'

Length of output: 5571


🏁 Script executed:

#!/bin/bash
# Check if providerModelSettings.ts includes a mapping for 'o1-pro'
rg -n "id: 'o1-pro'" -C3 src/main/presenter/configPresenter/providerModelSettings.ts

Length of output: 92


🏁 Script executed:

#!/bin/bash
# Verify any mention of 'o1-pro' in providerModelSettings.ts
rg -n -w "o1-pro" src/main/presenter/configPresenter/providerModelSettings.ts || echo "No occurrences found"

Length of output: 128


Missing provider-side mapping for o1-pro

While both openAIResponsesProvider.ts and openAICompatibleProvider.ts list 'o1-pro' in their OPENAI_REASONING_MODELS arrays, the UI’s providerModelSettings.ts has no entry for id: 'o1-pro'. Without this block, selecting “OpenAI o1 Pro” in the UI will fall back or error.

Please add a corresponding settings object in src/main/presenter/configPresenter/providerModelSettings.ts, for example:

{
  id: 'o1-pro',
  name: 'o1 Pro',
  temperature: 0.7,
  maxTokens: 32768,
  contextLength: 128000,
  match: ['o1-pro'],
  vision: false,          // or true if matching defaultSettings
  functionCall: false,
  reasoning: true
},

— Ensure the fields align with the defaults in modelDefaultSettings.ts (lines 890–898).

🤖 Prompt for AI Agents
In src/main/presenter/configPresenter/providerModelSettings.ts add a settings
object for id 'o1-pro' (matching modelDefaultSettings.ts lines 890–900) so the
UI can map the provider model; include the same fields/values: id: 'o1-pro',
name: 'OpenAI o1 Pro' (or 'o1 Pro' per project convention), temperature: 0.7,
maxTokens: 32768, contextLength: 128000, match: ['o1-pro'], vision: true,
functionCall: false, reasoning: true (and include reasoningEffort: 'high' if
that property is used elsewhere), and insert it into the providerModelSettings
array alongside the other provider entries.

{
id: 'o1',
Expand All @@ -865,7 +907,8 @@ export const defaultModelsSettings: DefaultModelSetting[] = [
match: ['o1'],
vision: true,
functionCall: false,
reasoning: true
reasoning: true,
reasoningEffort: 'medium'
},
{
id: 'gpt-5-chat',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -563,13 +563,13 @@ export class OpenAICompatibleProvider extends BaseLLMProvider {
}
}

if (modelId.startsWith('gpt-5')) {
if (modelConfig.reasoningEffort) {
;(requestParams as any).reasoning_effort = modelConfig.reasoningEffort
}
if (modelConfig.verbosity) {
;(requestParams as any).verbosity = modelConfig.verbosity
}
if (modelConfig.reasoningEffort) {
;(requestParams as any).reasoning_effort = modelConfig.reasoningEffort
}

Comment on lines +566 to +569
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Broadened reasoning_effort is good, but apply it to non-streaming path too

You apply reasoning_effort in the streaming path (handleChatCompletion), but the non-streaming openAICompletion path doesn’t set it. That creates inconsistent behavior for the same model depending on call path.

Within openAICompletion, retrieve modelConfig and apply reasoning_effort similarly:

   const requestParams: OpenAI.Chat.ChatCompletionCreateParams = {
     messages: this.formatMessages(messages),
     model: modelId,
     stream: false,
     temperature: temperature,
     ...(modelId.startsWith('o1') ||
     modelId.startsWith('o3') ||
     modelId.startsWith('o4') ||
     modelId.startsWith('gpt-5')
       ? { max_completion_tokens: maxTokens }
       : { max_tokens: maxTokens })
   }
+  // Align reasoning across non-streaming path
+  const modelConfig = this.configPresenter.getModelConfig(modelId, this.provider.id)
+  if (modelConfig?.reasoningEffort) {
+    ;(requestParams as any).reasoning_effort = modelConfig.reasoningEffort
+  }

Do you want me to open a small follow-up PR to add this and tests?

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (modelConfig.reasoningEffort) {
;(requestParams as any).reasoning_effort = modelConfig.reasoningEffort
}
const requestParams: OpenAI.Chat.ChatCompletionCreateParams = {
messages: this.formatMessages(messages),
model: modelId,
stream: false,
temperature: temperature,
...(modelId.startsWith('o1') ||
modelId.startsWith('o3') ||
modelId.startsWith('o4') ||
modelId.startsWith('gpt-5')
? { max_completion_tokens: maxTokens }
: { max_tokens: maxTokens })
}
// Align reasoning across non-streaming path
const modelConfig = this.configPresenter.getModelConfig(modelId, this.provider.id)
if (modelConfig?.reasoningEffort) {
;(requestParams as any).reasoning_effort = modelConfig.reasoningEffort
}
🤖 Prompt for AI Agents
In src/main/presenter/llmProviderPresenter/providers/openAICompatibleProvider.ts
around lines 566–569, the code sets reasoning_effort on the streaming path but
not on the non-streaming openAICompletion path, causing inconsistent behavior;
update openAICompletion to retrieve the same modelConfig and, if
modelConfig.reasoningEffort is present, set (requestParams as
any).reasoning_effort = modelConfig.reasoningEffort before sending the request
so both paths behave identically, and add/adjust unit tests to cover the
non-streaming path including reasoning_effort being passed.

💡 Verification agent

🧩 Analysis chain

Confirm Chat Completions API expects 'reasoning_effort' vs 'reasoning: {effort}'

SDKs differ between Chat Completions and Responses. You’re using reasoning_effort here (Chat), and reasoning: { effort } in the Responses provider. That may be correct, but worth double-checking against the SDK version you ship.


🌐 Web query:

For OpenAI Chat Completions API with o3/o4/gpt-5 models, is the correct parameter 'reasoning_effort' (string) or 'reasoning: { effort: "low|medium|high" }'? Provide official docs reference for the Node SDK.

💡 Result:

Short answer

  • For the newer reasoning models (o3, o4-mini, GPT‑5) you should use the Responses API and pass a reasoning object: reasoning: { effort: "low" | "medium" | "high" } (Node SDK: client.responses.create(..., reasoning: { effort: ... })). (openai.com, cookbook.openai.com)

  • The older Chat Completions / some o1-family docs reference a single string parameter named reasoning_effort (e.g. reasoning_effort: "low"|"medium"|"high"); that parameter was model-specific (o1 family / early previews). For new reasoning-capable models OpenAI’s docs and cookbook show the Responses API + reasoning object as the canonical usage. (openai.com)

Minimal Node example (Responses API)

  • Example usage with the Node SDK (pass the reasoning object to client.responses.create):
    const resp = await client.responses.create({
    model: "o4-mini",
    input: "Solve this multi-step math problem...",
    reasoning: { effort: "high" }
    });
    // resp.output_text or resp.output contains the results

Official doc pages (references)

  • Responses API — new features / reasoning usage (shows reasoning: { effort: ... } and code examples). (openai.com)
  • Cookbook / “Better performance from reasoning models” (examples and JSON showing reasoning in responses). (cookbook.openai.com)
  • GPT‑5 announcement (mentions reasoning_effort parameter and minimal option). (openai.com)
  • Cookbook “Handling function calls with reasoning models” (more examples using reasoning: { effort: ... }). (cookbook.openai.com)

If you want, I can:

  • paste a full Node.js sample (with imports and error handling) using the official Node SDK; or
  • check your exact current SDK version and show the exact call signature that matches it. Which would you prefer?

Citations:


Double-check reasoning parameter usage for new models
The Chat Completions API only supports the legacy reasoning_effort string (on o1-family/preview models). For o3/o4/GPT-5 you must instead call the Responses API (client.responses.create) and pass a reasoning object:

// legacy Chat Completions provider (o1-family)
if (modelConfig.reasoningEffort) {
  ;(requestParams as any).reasoning_effort = modelConfig.reasoningEffort
}

// for o3/o4/GPT-5 (Responses API)
const resp = await client.responses.create({
  model: modelConfig.name,
  input: requestParams.messages,
  reasoning: { effort: modelConfig.reasoningEffort }
})

• Verify which models this presenter supports and ensure that for any o3/o4/GPT-5 variants you switch to the Responses API.
• Update this file accordingly or guard the existing code so reasoning_effort is only used on legacy models.

References:
https://openai.com/index/new-tools-and-features-in-the-responses-api/?utm_source=chatgpt.com
https://cookbook.openai.com/examples/responses_api/reasoning_items?utm_source=chatgpt.com

🤖 Prompt for AI Agents
In src/main/presenter/llmProviderPresenter/providers/openAICompatibleProvider.ts
around lines 566-569, the code unconditionally sets the legacy reasoning_effort
field which only works for o1-family/preview Chat Completions; update the logic
to detect model family/name and only set (requestParams as any).reasoning_effort
for legacy o1-family models, and for o3/o4/GPT-5 variants switch to calling the
Responses API (client.responses.create) passing model and input and a reasoning
object { effort: modelConfig.reasoningEffort }; alternatively add a guard so
reasoning_effort is not sent for newer models and the presenter uses the
Responses API with the reasoning object when modelConfig.name indicates
o3/o4/GPT-5.

// verbosity 仅支持 GPT-5 系列模型
if (modelId.startsWith('gpt-5') && modelConfig.verbosity) {
;(requestParams as any).verbosity = modelConfig.verbosity
}

// 移除推理模型的温度参数
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -228,17 +228,18 @@ export class OpenAIResponsesProvider extends BaseLLMProvider {
stream: false
}

if (modelId.startsWith('gpt-5')) {
const modelConfig = this.configPresenter.getModelConfig(modelId, this.provider.id)
if (modelConfig.reasoningEffort) {
;(requestParams as any).reasoning = {
effort: modelConfig.reasoningEffort
}
const modelConfig = this.configPresenter.getModelConfig(modelId, this.provider.id)

if (modelConfig.reasoningEffort) {
;(requestParams as any).reasoning = {
effort: modelConfig.reasoningEffort
}
if (modelConfig.verbosity) {
;(requestParams as any).text = {
verbosity: modelConfig.verbosity
}
}

// verbosity 仅支持 GPT-5 系列模型
if (modelId.startsWith('gpt-5') && modelConfig.verbosity) {
;(requestParams as any).text = {
verbosity: modelConfig.verbosity
}
}

Expand Down Expand Up @@ -572,16 +573,16 @@ export class OpenAIResponsesProvider extends BaseLLMProvider {
requestParams.tools = apiTools
}

if (modelId.startsWith('gpt-5')) {
if (modelConfig.reasoningEffort) {
;(requestParams as any).reasoning = {
effort: modelConfig.reasoningEffort
}
if (modelConfig.reasoningEffort) {
;(requestParams as any).reasoning = {
effort: modelConfig.reasoningEffort
}
if (modelConfig.verbosity) {
;(requestParams as any).text = {
verbosity: modelConfig.verbosity
}
}

// verbosity 仅支持 GPT-5 系列模型
if (modelId.startsWith('gpt-5') && modelConfig.verbosity) {
;(requestParams as any).text = {
verbosity: modelConfig.verbosity
}
}

Expand Down
12 changes: 6 additions & 6 deletions src/renderer/src/components/settings/ModelConfigDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@
</p>
</div>

<!-- 温度 (GPT-5 系列模型不显示) -->
<div v-if="!isGPT5Model" class="space-y-2">
<!-- 温度 (支持推理努力程度的模型不显示) -->
<div v-if="!supportsReasoningEffort" class="space-y-2">
<Label for="temperature">{{ t('settings.model.modelConfig.temperature.label') }}</Label>
<Input
id="temperature"
Expand Down Expand Up @@ -133,7 +133,7 @@
<Switch v-model:checked="config.reasoning" />
</div>

<!-- 推理努力程度 -->
<!-- 推理努力程度 (支持推理努力程度的模型显示) -->
<div v-if="supportsReasoningEffort" class="space-y-2">
<Label for="reasoningEffort">{{
t('settings.model.modelConfig.reasoningEffort.label')
Expand Down Expand Up @@ -400,8 +400,8 @@ const validateForm = () => {
errors.value.contextLength = t('settings.model.modelConfig.validation.contextLengthMax')
}

// 验证温度 (仅对非 GPT-5 系列模型)
if (!isGPT5Model.value && config.value.temperature !== undefined) {
// 验证温度 (仅对不支持推理努力程度的模型)
if (!supportsReasoningEffort.value && config.value.temperature !== undefined) {
if (config.value.temperature < 0) {
errors.value.temperature = t('settings.model.modelConfig.validation.temperatureMin')
} else if (config.value.temperature > 2) {
Expand Down Expand Up @@ -495,7 +495,7 @@ const isGPT5Model = computed(() => {
})

const supportsReasoningEffort = computed(() => {
return config.value.reasoningEffort !== undefined
return config.value.reasoningEffort !== undefined && config.value.reasoningEffort !== null
})

// 是否显示思考预算配置
Expand Down