-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Description
Description
When using the non-streaming API (internalCall), the reasoningContent field is not included in the AssistantMessage metadata, but the streaming API (internalStream) correctly includes it.
Affected Versions
- 1.1.2
- 1.1.4
- 2.0.0-SNAPSHOT (main branch)
Root Cause
In OpenAiChatModel.java, the internalCall method builds metadata without reasoningContent:
// internalCall (non-streaming) - missing reasoningContent
Map<String, Object> metadata = Map.of(
"id", chatCompletion.id() != null ? chatCompletion.id() : "",
"role", choice.message().role() != null ? choice.message().role().name() : "",
"index", choice.index() != null ? choice.index() : 0,
"finishReason", getFinishReasonJson(choice.finishReason()),
"refusal", StringUtils.hasText(choice.message().refusal()) ? choice.message().refusal() : "",
"annotations", choice.message().annotations() != null ? choice.message().annotations() : List.of(Map.of()));But internalStream (streaming) correctly includes it:
// internalStream (streaming) - has reasoningContent
Map<String, Object> metadata = Map.of(
"id", id,
"role", roleMap.getOrDefault(id, ""),
"index", choice.index() != null ? choice.index() : 0,
"finishReason", getFinishReasonJson(choice.finishReason()),
"refusal", StringUtils.hasText(choice.message().refusal()) ? choice.message().refusal() : "",
"annotations", choice.message().annotations() != null ? choice.message().annotations() : List.of(),
"reasoningContent", choice.message().reasoningContent() != null ? choice.message().reasoningContent() : "");Expected Behavior
The internalCall method should also include reasoningContent in the metadata, consistent with the streaming API.
Proposed Fix
Add reasoningContent to the metadata map in internalCall:
Map<String, Object> metadata = Map.of(
"id", chatCompletion.id() != null ? chatCompletion.id() : "",
"role", choice.message().role() != null ? choice.message().role().name() : "",
"index", choice.index() != null ? choice.index() : 0,
"finishReason", getFinishReasonJson(choice.finishReason()),
"refusal", StringUtils.hasText(choice.message().refusal()) ? choice.message().refusal() : "",
"annotations", choice.message().annotations() != null ? choice.message().annotations() : List.of(),
"reasoningContent", choice.message().reasoningContent() != null ? choice.message().reasoningContent() : "");Workaround
Currently, users can use the streaming API (stream()) with .last().block() to get the reasoningContent, but this is not ideal for non-streaming use cases.
Related
This affects models like Qwen3.5-plus and DeepSeek-R1 that return reasoning content in API responses.