Bug Description
When using the Spring AI library and directly registering an ObjectMapper as bean, RestClientException and UnrecognizedPropertyException occur. This error does not happen when using the ObjectMapper bean provided by Spring internally.
The error message is as follows:
org.springframework.web.client.RestClientException: Error while extracting response for type [org.springframework.ai.openai.api.OpenAiApi$ChatCompletion] and content type [application/json]] with root cause
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "prompt_tokens_details" (class org.springframework.ai.openai.api.OpenAiApi$Usage), not marked as ignorable (4 known properties: "completion_tokens_details", "completion_tokens", "prompt_tokens", "total_tokens"])
at [Source: (org.springframework.util.StreamUtils$NonClosingInputStream); line: 28, column: 4] (through reference chain: org.springframework.ai.openai.api.OpenAiApi$ChatCompletion["usage"]->org.springframework.ai.openai.api.OpenAiApi$Usage["prompt_tokens_details"])
Environment
- Spring AI library version:
1.0.0-M3 - Java version:
17 - ObjectMapper:
ObjectMapperregistered directly via@Bean
Steps to Reproduce
- Register the
ObjectMapperbean directly as follows:
@Configuration
public class SpringConfig {
@Bean
public ObjectMapper objectMapper() {
return new ObjectMapper();
}
}
- A
RestClientExceptionoccurs when calling the OpenAI API using the Spring AI library. - The error does not occur when using the default
ObjectMapperbean provided by Spring.
Expected Behavior
The API call should work without any errors, even when using custom ObjectMapper bean.
Or maybe you need to fill in some related information.
Minimal Complete Reproducible Example
AiController
@RestController
public class ChatController {
private final OpenAiChatModel chatModel;
@Autowired
public ChatController(OpenAiChatModel chatModel) {
this.chatModel = chatModel;
}
@GetMapping("/ai/generate")
public Map<String,String> generate(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
return Map.of("generation", chatModel.call(message));
}
}
SpringConfig
@Configuration
public class SpringConfig {
@Bean
public ObjectMapper objectMapper() {
return new ObjectMapper();
}
}
Comment From: dafriz
The Jackson library class ObjectMapper is configured to fail on unknown properties by default.
If you want to customise an ObjectMapper but still get the config that Spring web configures ( such as disabling this flag ) you can use:
@Bean
public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder objectMapperBuilder) {
// customise here
return objectMapperBuilder.build();
}
If you are using Spring Boot and want to disable failing on unknown properties for all ObjectMappers created this way you can use a Customizer
@Bean
public Jackson2ObjectMapperBuilderCustomizer jsonCustomizer() {
return builder -> builder.failOnUnknownProperties(false);
}
It has been suggested ( https://github.com/spring-projects/spring-ai/issues/1369 ) Spring AI should add a @JsonIgnoreProperties(ignoreUnknown = true) to the incoming JSON DTO classes so these errors don't occur as new fields are added by OpenAI and others.
Perhaps sometimes we want to fail on unknown properties - for example to identify any unmapped / new fields, which would be difficult if disabled in each class.
Comment From: yeseong0412
@dafriz thx for reply
In the project, we decided to use the default ObjectMapper, but we encountered an original problem.
Instead of using @JsonIgnoreProperties(ignoreUnknown = true), I believe it would be more appropriate to add the missing field prompt_tokens_details to the relevant class.
(I think ignoring unknown properties can sometimes obscure important changes in the API)
However, I couldn't find any reference to prompt_tokens_details in the OpenAI API documentation, making it unclear whether this is a newly added field or specific to certain requests.
What can we do in this situation?
Comment From: dafriz
np,
I raised a PR the other day to add the prompt_tokens_details - https://github.com/spring-projects/spring-ai/pull/1516 it contains a nested cached_tokens usage metric.
OpenAI API docs are here - https://platform.openai.com/docs/api-reference/chat/object - expand the usage object to see the new nested fields.
Comment From: yeseong0412
I couldn't check it because it was hidden in the usage.
Good luck!
Comment From: tzolov
@yeseong0412 thank you for raising this issue and @dafriz thanks for jumping in and helping resolving it.
Now that the #1516 is merged, @yeseong0412 does this addresses your ObjectMapper issue as well?
I will bring the #1369 (e.g. @JsonIgnoreProperties(ignoreUnknown = true) to the team discussion again. I more inclined with @yeseong0412 opinion that "ignoring unknown properties can sometimes obscure important changes in the API".
On the other hand I understand how easy this could be to break the API with a single change.
I guess we need something in between
Comment From: yeseong0412
The issue has been resolved. Thank you so much for your interest in this issue! If any additional solutions come up, I’ll share them with you again.
Good luck!