-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Description
Environment
Spring AI 1.1.1+ produces this issue, no issues in prior versions
Steps to reproduce
Attempt to create and use Chat Client based on how the OpenAI chat model is initialized here:
public OpenAiChatModel getOpenAiCompatibleChatModel(final ChatSettings settings) throws IllegalArgumentException {
final String providerBaseUrl;
final String providerApiKey;
final String providerCompletionsPath;
switch (settings.getModel().getProvider()) {
case OPENAI:
providerBaseUrl = providerConfig.getOpenAiBaseUrl();
providerApiKey = providerConfig.getOpenAiApiKey();
providerCompletionsPath = providerConfig.getOpenAiCompletionsPath();
break;
case PERPLEXITY:
providerBaseUrl = providerConfig.getPerplexityBaseUrl();
providerApiKey = providerConfig.getPerplexityApiKey();
providerCompletionsPath = providerConfig.getPerplexityCompletionsPath();
break;
default:
throw new IllegalArgumentException(
"Unknown OpenAI-compatible provider: " + settings.getModel().getProvider().name());
}
final OpenAiApi api = new OpenAiApi.Builder()
.baseUrl(providerBaseUrl)
.apiKey(providerApiKey)
.completionsPath(providerCompletionsPath)
.build();
final Builder optsBuilder = OpenAiChatOptions
.builder()
.model(settings.getModel().getName())
.temperature(settings.getTemperature().getValue());
if (settings.getReasoningEffort() != null) {
optsBuilder.reasoningEffort(settings.getReasoningEffort().getValue());
}
if (settings.getVerbosity() != null) {
optsBuilder.verbosity(settings.getVerbosity().getValue());
}
final OpenAiChatOptions opts = optsBuilder.build();
return OpenAiChatModel.builder().openAiApi(api).defaultOptions(opts).build();
}
Expected behavior
The request should fail, returning this error:
17:58:10,218 WARN [org.springframework.ai.retry.RetryUtils] 9759c677-2b01-452b-a3bd-4111c396b7ca#633601 - Retry error. Retry count:1 org.springframework.ai.retry.NonTransientAiException: 400 - { "error": { "message": "Unknown parameter: 'extra_body'.", "type": "invalid_request_error", "param": "extra_body", "code": "unknown_parameter" } }
Did something change that would break this? I've changed nothing other than upgrade my Spring AI version, so I wonder if some parameter that is being set is no longer supported/recognized, and being converted into an extra_body parameter or something.
Investigation
See this commit for v1.1.0: 3fc939a
If extra_body is null, it is set to create a mutable, empty map for the purposes of deserialization using JsonAnySetter. However, I doubt that this was tested thoroughly because the JsonProperty annotation wasn't even present on ChatCompletionRequest until v1.1.1. I believe this to be an issue because OpenAI will throw an error to any unrecognized parameter, whether it is null or empty. The tests, while logically sound, do not account for the real-world usage of making the request to OpenAI API while passing an empty extra_body object, which produce errors.
See this commit for v1.1.1: 0646d1e
It seems most likely that the changes made in v1.1.0 were not tested properly because extra_body wasn't being included properly in a ChatCompletionRequest anyway, and since the v1.1.1 change that adds the annotation necessary, the mandatory inclusion of an empty extra_body object that is NOT being excluded in the request body is causing issues when making requests to OpenAI.
Contrary to what the documentation states, the official OpenAI API does not ignore unrecognized parameters... it fully rejects them and results in an error.
However, when logging the toString() output of OpenAiChatOptions right before using the OpenAiChatModel builder, the output does not show any signs of extra_body:
OpenAiChatOptions: {"streamUsage":false,"model":"gpt-5-mini","temperature":1.0}