Bug description
OpenAiChatOptions
does not have a topK
parameter, but the generic ChatOptions
rsp. ToolCallingChatOptions
builders do.
Specifying that parameter via one of these leads to a NotWritablePropertyException
upon executing a query, as ModelOptionsUtils.copyToTarget()
can't map the property and fails.
Environment
The problem occurs in the current Spring AI 1.0.0-SNAPSHOT using Spring Boot 3.4.5, but is reproducible in earlier releases too. We don't use the OpenAiChatOptions
directly, but the generic builders instead, talking to the together.ai OpenAI-compatible API (but the issue is not related to OpenAI itself, but the mapping before the actual call).
Steps to reproduce
Example:
var chatOptions = ToolCallingChatOptions.builder()
.temperature(settings.getTemperature())
.topK(settings.getTopK()) // does not work with OpenAI ChatOptions
.topP(settings.getTopP())
.frequencyPenalty(settings.getFrequencyPenalty())
.presencePenalty(settings.getPresencePenalty())
.build();
and then execute an arbitrary ChatClient
call with these options, using OpenAI.
Stack trace:
java.lang.RuntimeException: Failed to convert the org.springframework.ai.model.tool.ToolCallingChatOptions into org.springframework.ai.openai.OpenAiChatOptions
at org.springframework.ai.model.ModelOptionsUtils.copyToTarget(ModelOptionsUtils.java:296) ~[spring-ai-model-1.0.0-20250430.052125-121.jar:1.0.0-SNAPSHOT]
at org.springframework.ai.openai.OpenAiChatModel.buildRequestPrompt(OpenAiChatModel.java:490) ~[spring-ai-openai-1.0.0-20250430.052125-1423.jar:1.0.0-SNAPSHOT]
at org.springframework.ai.openai.OpenAiChatModel.call(OpenAiChatModel.java:178) ~[spring-ai-openai-1.0.0-20250430.052125-1423.jar:1.0.0-SNAPSHOT]
(...rest omitted for sake of brevity...)
Caused by: org.springframework.beans.NotWritablePropertyException: Invalid property 'topK' of bean class [org.springframework.ai.openai.OpenAiChatOptions]: Bean property 'topK' is not writable or has an invalid setter method. Did you mean 'stop', or 'topP'?
at org.springframework.beans.BeanWrapperImpl.createNotWritablePropertyException(BeanWrapperImpl.java:209) ~[spring-beans-6.2.6.jar:6.2.6]
at org.springframework.beans.AbstractNestablePropertyAccessor.processLocalProperty(AbstractNestablePropertyAccessor.java:429) ~[spring-beans-6.2.6.jar:6.2.6]
at org.springframework.beans.AbstractNestablePropertyAccessor.setPropertyValue(AbstractNestablePropertyAccessor.java:278) ~[spring-beans-6.2.6.jar:6.2.6]
at org.springframework.beans.AbstractNestablePropertyAccessor.setPropertyValue(AbstractNestablePropertyAccessor.java:246) ~[spring-beans-6.2.6.jar:6.2.6]
at org.springframework.ai.model.ModelOptionsUtils.mergeBeans(ModelOptionsUtils.java:338) ~[spring-ai-model-1.0.0-20250430.052125-121.jar:1.0.0-SNAPSHOT]
at org.springframework.ai.model.ModelOptionsUtils.copyToTarget(ModelOptionsUtils.java:290) ~[spring-ai-model-1.0.0-20250430.052125-121.jar:1.0.0-SNAPSHOT]
... 54 common frames omitted
Expected behavior I would suggest an unsupported property on the target options class should better be silently ignored in this case.
Comment From: jingbio
事实上这个问题在最新RC1上依然存在。
Comment From: cbollmeyer
The issue remains also in Spring AI 1.0.1, you cannot programmatically set topK in one of the high level Options builders unless you want to get an exception.