100 lines
3.9 KiB
TypeScript
100 lines
3.9 KiB
TypeScript
/**
|
|
* GPT-5 sampling guard — `stripGpt5SamplingWhenReasoning`.
|
|
*
|
|
* GPT-5 reasoning models reject non-default `temperature`/`top_p` with HTTP 400 when a
|
|
* reasoning effort is active, but GPT-5.1+ accept them again under `reasoning_effort:"none"`
|
|
* (the default). These tests pin the conditional strip on the `openai` Chat Completions
|
|
* surface: drop sampling only when reasoning is active, never for `none` / non-gpt-5 / other
|
|
* providers. Refs: litellm#27351, Azure Foundry reasoning matrix, openai-python#2072.
|
|
*/
|
|
import test from "node:test";
|
|
import assert from "node:assert/strict";
|
|
import { stripGpt5SamplingWhenReasoning } from "../../open-sse/services/gpt5SamplingGuard.ts";
|
|
|
|
test("strips temperature+top_p for openai gpt-5.x when reasoning_effort is active", () => {
|
|
const body = {
|
|
model: "gpt-5.4",
|
|
temperature: 0.7,
|
|
top_p: 0.9,
|
|
reasoning_effort: "high",
|
|
messages: [],
|
|
};
|
|
const result = stripGpt5SamplingWhenReasoning(body, "openai", "gpt-5.4");
|
|
assert.equal(result.temperature, undefined);
|
|
assert.equal(result.top_p, undefined);
|
|
assert.equal(result.reasoning_effort, "high"); // effort itself is untouched
|
|
});
|
|
|
|
test("keeps temperature when reasoning_effort=none (gpt-5.1+ non-reasoning mode)", () => {
|
|
const body = { model: "gpt-5.4", temperature: 0.7, reasoning_effort: "none", messages: [] };
|
|
const result = stripGpt5SamplingWhenReasoning(body, "openai", "gpt-5.4");
|
|
assert.equal(result.temperature, 0.7);
|
|
});
|
|
|
|
test("keeps sampling when there is no reasoning signal (default none for gpt-5.1+)", () => {
|
|
const body = { model: "gpt-5.5", temperature: 0.5, top_p: 0.8, messages: [] };
|
|
const result = stripGpt5SamplingWhenReasoning(body, "openai", "gpt-5.5");
|
|
assert.equal(result.temperature, 0.5);
|
|
assert.equal(result.top_p, 0.8);
|
|
});
|
|
|
|
test("nested reasoning.effort active also triggers the strip", () => {
|
|
const body = { model: "gpt-5.4", top_p: 0.8, reasoning: { effort: "medium" }, messages: [] };
|
|
const result = stripGpt5SamplingWhenReasoning(body, "openai", "gpt-5.4");
|
|
assert.equal(result.top_p, undefined);
|
|
});
|
|
|
|
test("model suffix -high triggers strip; -none keeps sampling", () => {
|
|
const high = stripGpt5SamplingWhenReasoning(
|
|
{ model: "gpt-5.4-high", temperature: 0.3 },
|
|
"openai",
|
|
"gpt-5.4-high"
|
|
);
|
|
assert.equal(high.temperature, undefined);
|
|
|
|
const none = stripGpt5SamplingWhenReasoning(
|
|
{ model: "gpt-5.4-none", temperature: 0.3 },
|
|
"openai",
|
|
"gpt-5.4-none"
|
|
);
|
|
assert.equal(none.temperature, 0.3);
|
|
});
|
|
|
|
test("non-openai provider is untouched (codex is guarded by the executor allowlist)", () => {
|
|
const body = { model: "gpt-5.4", temperature: 0.7, reasoning_effort: "high" };
|
|
const result = stripGpt5SamplingWhenReasoning(body, "codex", "gpt-5.4");
|
|
assert.equal(result.temperature, 0.7);
|
|
});
|
|
|
|
test("non-gpt-5 openai model is untouched (e.g. gpt-4o)", () => {
|
|
const body = { model: "gpt-4o", temperature: 0.7, reasoning_effort: "high" };
|
|
const result = stripGpt5SamplingWhenReasoning(body, "openai", "gpt-4o");
|
|
assert.equal(result.temperature, 0.7);
|
|
});
|
|
|
|
test("returns the same reference when no sampling params are present", () => {
|
|
const body = { model: "gpt-5.4", reasoning_effort: "high", messages: [] };
|
|
const result = stripGpt5SamplingWhenReasoning(body, "openai", "gpt-5.4");
|
|
assert.equal(result, body);
|
|
});
|
|
|
|
test("non-string model is a no-op", () => {
|
|
const body = { temperature: 0.7, reasoning_effort: "high" };
|
|
const result = stripGpt5SamplingWhenReasoning(body, "openai", null);
|
|
assert.equal(result.temperature, 0.7);
|
|
});
|
|
|
|
test("logs the stripped params when a logger is provided", () => {
|
|
const calls: Array<[string, string]> = [];
|
|
const log = { warn: (tag: string, message: string) => calls.push([tag, message]) };
|
|
stripGpt5SamplingWhenReasoning(
|
|
{ model: "gpt-5.4", temperature: 0.7, reasoning_effort: "high" },
|
|
"openai",
|
|
"gpt-5.4",
|
|
log
|
|
);
|
|
assert.equal(calls.length, 1);
|
|
assert.equal(calls[0][0], "PARAMS");
|
|
assert.match(calls[0][1], /temperature/);
|
|
});
|