Skip to content

Commit f0a7f9d

Browse files
fix(openai): omit temperature when no custom value is set (Zoo-Code-Org#242)
When "use custom temperature" is off, the OpenAI-Compatible provider still sent temperature: 0 (the fallback), so the model's server-side default never applied. Per the discussion on Zoo-Code-Org#242 (option A), omit the temperature field in that case. Preserves the supportsTemperature gate (Zoo-Code-Org#233), model-required defaults (deepseek-reasoner), and a deliberately-set 0.
1 parent 71db2e6 commit f0a7f9d

2 files changed

Lines changed: 24 additions & 10 deletions

File tree

src/api/providers/__tests__/openai.spec.ts

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -409,13 +409,15 @@ describe("OpenAiHandler", () => {
409409
expect(callArgs).not.toHaveProperty("temperature")
410410
})
411411

412-
it("should include temperature by default when supportsTemperature is not set", async () => {
412+
it("should omit temperature by default when no custom temperature is set", async () => {
413+
// Option A: when "use custom temperature" is off (modelTemperature unset) and the model has no
414+
// required default, omit `temperature` so the server's own default applies instead of forcing 0.
413415
const stream = handler.createMessage(systemPrompt, messages)
414416
for await (const _chunk of stream) {
415417
}
416418
expect(mockCreate).toHaveBeenCalled()
417419
const callArgs = mockCreate.mock.calls[0][0]
418-
expect(callArgs).toHaveProperty("temperature")
420+
expect(callArgs).not.toHaveProperty("temperature")
419421
})
420422

421423
it("should use the configured modelTemperature when supportsTemperature is not false", async () => {
@@ -438,6 +440,17 @@ describe("OpenAiHandler", () => {
438440
expect(callArgs.temperature).toBe(DEEP_SEEK_DEFAULT_TEMPERATURE)
439441
})
440442

443+
it("should still send temperature when the user sets a custom value of 0", async () => {
444+
// A deliberate 0 must be distinguished from "unset" — it is sent, not omitted.
445+
const zeroTempHandler = new OpenAiHandler({ ...mockOptions, modelTemperature: 0 })
446+
const stream = zeroTempHandler.createMessage(systemPrompt, messages)
447+
for await (const _chunk of stream) {
448+
}
449+
expect(mockCreate).toHaveBeenCalled()
450+
const callArgs = mockCreate.mock.calls[0][0]
451+
expect(callArgs.temperature).toBe(0)
452+
})
453+
441454
it("should include max_tokens when includeMaxTokens is true", async () => {
442455
const optionsWithMaxTokens: ApiHandlerOptions = {
443456
...mockOptions,
@@ -679,7 +692,7 @@ describe("OpenAiHandler", () => {
679692
],
680693
stream: true,
681694
stream_options: { include_usage: true },
682-
temperature: 0,
695+
// No custom temperature set → `temperature` is omitted.
683696
tools: undefined,
684697
tool_choice: undefined,
685698
parallel_tool_calls: true,

src/api/providers/openai.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -155,13 +155,14 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl
155155
const requestOptions: OpenAI.Chat.Completions.ChatCompletionCreateParamsStreaming = {
156156
model: modelId,
157157
// Some OpenAI-Compatible models (e.g. claude-opus-4-7, claude-opus-4-8) reject
158-
// `temperature` as deprecated/unsupported. Honor the model's `supportsTemperature`
159-
// flag and omit it when explicitly set to false (undefined still sends temperature,
160-
// preserving behavior).
161-
...(modelInfo.supportsTemperature !== false && {
162-
temperature:
163-
this.options.modelTemperature ?? (deepseekReasoner ? DEEP_SEEK_DEFAULT_TEMPERATURE : 0),
164-
}),
158+
// `temperature` as deprecated/unsupported, so honor the model's `supportsTemperature`
159+
// flag and omit it when that flag is false. Beyond that, only send `temperature` when
160+
// the user set a custom value or the model needs a specific default (deepseek-reasoner);
161+
// otherwise omit it so the server's own default applies instead of forcing 0.
162+
...(modelInfo.supportsTemperature !== false &&
163+
(this.options.modelTemperature != null || deepseekReasoner) && {
164+
temperature: this.options.modelTemperature ?? DEEP_SEEK_DEFAULT_TEMPERATURE,
165+
}),
165166
messages: convertedMessages,
166167
stream: true as const,
167168
...(isGrokXAI ? {} : { stream_options: { include_usage: true } }),

0 commit comments

Comments
 (0)