Skip to content

Fix DeepSeekChatModel rejecting assistant messages without content - #6775

Open
subhashpolisetti wants to merge 1 commit into
spring-projects:mainfrom
subhashpolisetti:fix-deepseek-null-assistant-content
Open

Fix DeepSeekChatModel rejecting assistant messages without content#6775
subhashpolisetti wants to merge 1 commit into
spring-projects:mainfrom
subhashpolisetti:fix-deepseek-null-assistant-content

Conversation

@subhashpolisetti

Copy link
Copy Markdown
Contributor

createRequest rejects an assistant message with a null text, but that is the normal
shape of a tool call turn: DeepSeek sends no content alongside tool_calls, and
ChatCompletionMessage#content is documented as null in that case. Replaying such a
message after tool execution, as ToolCallingManager does, fails with
IllegalStateException: text must not be null, so a blocking tool calling conversation
cannot complete. Streaming is unaffected because MessageAggregator rebuilds the
content from a StringBuilder.

Dropping the assertion forwards the null unchanged. ChatCompletionMessage is
@JsonInclude(NON_NULL), so content is omitted from the request rather than sent as
null, which is what MistralAiChatModel and OllamaChatModel already do. #5568 fixed
the same regression on the response side.

Both tests are offline: one builds the request directly, the other drives a tool call
round trip against a mocked DeepSeekApi.

See #5568

`createRequest` asserted that the assistant message text is non-null,
but a null text is the normal shape of a tool call turn: DeepSeek
returns no content alongside `tool_calls`, and
`DeepSeekApi.ChatCompletionMessage#content` is documented as null in
that case. `AbstractMessage` requires content only for system and user
messages, and `buildGeneration` forwards the API value unchanged, so
the assistant message built for a tool call carries a null text.

Replaying that message in the next round, as `ToolCallingManager` does
once the tool calls have been executed, therefore failed with
`IllegalStateException: text must not be null`, so a blocking tool
calling conversation could not complete. The streaming path escaped it
because `MessageAggregator` rebuilds the content from a
`StringBuilder`.

Remove the assertion so the null text is forwarded as is. The wire
representation does not change: `ChatCompletionMessage` is annotated
with `@JsonInclude(NON_NULL)`, so an absent content is left out of the
request, and `MistralAiChatModel` and `OllamaChatModel` already pass
the assistant content through unchecked.

See spring-projects#5568

Signed-off-by: subhash polisetti <subhashr161347@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants