Skip to content

Commit d184938

Browse files
committed
Fix missing "thinking" key in Ollama message metadata when streaming.
Signed-off-by: Chris Salch <[email protected]>
1 parent 89a3b32 commit d184938

File tree

2 files changed

+64
-3
lines changed

2 files changed

+64
-3
lines changed

models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/OllamaChatModel.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -345,12 +345,16 @@ private Flux<ChatResponse> internalStream(Prompt prompt, ChatResponse previousCh
345345
.toolCalls(toolCalls)
346346
.build();
347347

348-
ChatGenerationMetadata generationMetadata = ChatGenerationMetadata.NULL;
348+
ChatGenerationMetadata.Builder generationMetadataBuilder = ChatGenerationMetadata.builder();
349349
if (chunk.promptEvalCount() != null && chunk.evalCount() != null) {
350-
generationMetadata = ChatGenerationMetadata.builder().finishReason(chunk.doneReason()).build();
350+
generationMetadataBuilder.finishReason(chunk.doneReason());
351351
}
352352

353-
var generator = new Generation(assistantMessage, generationMetadata);
353+
if (chunk.message() != null && chunk.message().thinking() != null) {
354+
generationMetadataBuilder.metadata("thinking", chunk.message().thinking());
355+
}
356+
357+
var generator = new Generation(assistantMessage, generationMetadataBuilder.build());
354358
return new ChatResponse(List.of(generator), from(chunk, previousChatResponse));
355359
});
356360

models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/OllamaChatModelMetadataTests.java

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,12 @@
1616

1717
package org.springframework.ai.ollama;
1818

19+
import java.util.concurrent.atomic.AtomicBoolean;
20+
1921
import io.micrometer.observation.tck.TestObservationRegistry;
2022
import org.junit.jupiter.api.BeforeEach;
2123
import org.junit.jupiter.api.Test;
24+
import reactor.core.publisher.Flux;
2225

2326
import org.springframework.ai.chat.metadata.ChatGenerationMetadata;
2427
import org.springframework.ai.chat.model.ChatResponse;
@@ -70,6 +73,60 @@ void ollamaThinkingMetadataCaptured() {
7073
});
7174
}
7275

76+
@Test
77+
void ollamaThinkingMedataCapturedWhenStreaming() {
78+
var options = OllamaChatOptions.builder().model(MODEL).enableThinking().build();
79+
var response = new StringBuilder();
80+
var thinking = new StringBuilder();
81+
var foundThinking = new AtomicBoolean(false);
82+
83+
Prompt prompt = new Prompt("Why is the sky blue?", options);
84+
85+
Flux<ChatResponse> chatResponse = this.chatModel.stream(prompt);
86+
var captured = chatResponse.collectList().block();
87+
88+
assertThat(captured).isNotEmpty();
89+
90+
captured.forEach(chunk -> {
91+
ChatGenerationMetadata chatGenerationMetadata = chunk.getResult().getMetadata();
92+
assertThat(chatGenerationMetadata).isNotNull();
93+
94+
if (chatGenerationMetadata.containsKey("thinking") && chatGenerationMetadata.get("thinking") != null) {
95+
foundThinking.set(true);
96+
thinking.append(chatGenerationMetadata.get("thinking").toString());
97+
}
98+
99+
response.append(chunk.getResult().getOutput().getText());
100+
});
101+
102+
assertThat(response.toString()).isNotEmpty();
103+
assertThat(thinking.toString()).isNotEmpty();
104+
}
105+
106+
@Test
107+
void ollamaThinkingMedataNotCapturedWhenStreamingWhenSetThinkingToFalse() {
108+
var options = OllamaChatOptions.builder().model(MODEL).disableThinking().build();
109+
var response = new StringBuilder();
110+
111+
Prompt prompt = new Prompt("Why is the sky blue?", options);
112+
113+
Flux<ChatResponse> chatResponse = this.chatModel.stream(prompt);
114+
var captured = chatResponse.collectList().block();
115+
116+
assertThat(captured).isNotEmpty();
117+
118+
captured.forEach(chunk -> {
119+
ChatGenerationMetadata chatGenerationMetadata = chunk.getResult().getMetadata();
120+
assertThat(chatGenerationMetadata).isNotNull();
121+
var thinking = chatGenerationMetadata.get("thinking");
122+
assertThat(thinking).isNull();
123+
124+
response.append(chunk.getResult().getOutput().getText());
125+
});
126+
127+
assertThat(response.toString()).isNotEmpty();
128+
}
129+
73130
@Test
74131
void ollamaThinkingMetadataNotCapturedWhenSetThinkFlagToFalse() {
75132
// Note: Thinking-capable models (e.g., qwen3:*) auto-enable thinking by default

0 commit comments

Comments
 (0)