Skip to content

Commit 024e02e

Browse files
authored
Merge pull request #117 from IBM/add-enabled-field-to-thinking
Add explicit `enabled` flag to Thinking configuration
2 parents 606a405 + 2d3d73c commit 024e02e

File tree

5 files changed

+77
-12
lines changed

5 files changed

+77
-12
lines changed

modules/watsonx-ai/src/main/java/com/ibm/watsonx/ai/chat/ChatRequest.java

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*/
55
package com.ibm.watsonx.ai.chat;
66

7+
import static java.util.Objects.isNull;
78
import static java.util.Objects.requireNonNull;
89
import java.util.List;
910
import com.ibm.watsonx.ai.chat.model.ChatMessage;
@@ -198,12 +199,7 @@ public Builder parameters(ChatParameters parameters) {
198199
* @param enabled {@code true} to enable reasoning with default settings, {@code false} to disable reasoning
199200
*/
200201
public Builder thinking(boolean enabled) {
201-
if (enabled) {
202-
return thinking(Thinking.builder().build());
203-
} else {
204-
thinking = null;
205-
return this;
206-
}
202+
return thinking(Thinking.builder().enabled(enabled).build());
207203
}
208204

209205
/**
@@ -223,6 +219,11 @@ public Builder thinking(boolean enabled) {
223219
* @param tags an {@link ExtractionTags} instance defining the reasoning and response tags
224220
*/
225221
public Builder thinking(ExtractionTags tags) {
222+
if (isNull(tags)) {
223+
thinking = null;
224+
return this;
225+
}
226+
226227
return thinking(Thinking.of(tags));
227228
}
228229

@@ -242,6 +243,11 @@ public Builder thinking(ExtractionTags tags) {
242243
* @param thinkingEffort the desired {@link ThinkingEffort} level
243244
*/
244245
public Builder thinking(ThinkingEffort thinkingEffort) {
246+
if (isNull(thinkingEffort)) {
247+
thinking = null;
248+
return this;
249+
}
250+
245251
return thinking(Thinking.of(thinkingEffort));
246252
}
247253

modules/watsonx-ai/src/main/java/com/ibm/watsonx/ai/chat/ChatService.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,10 +93,11 @@ public ChatResponse chat(ChatRequest chatRequest) {
9393
Map<String, Object> chatTemplateKwargs = null;
9494
if (nonNull(chatRequest.getThinking())) {
9595
var thinking = chatRequest.getThinking();
96-
chatTemplateKwargs = Map.of("thinking", true);
9796
extractionTags = thinking.getExtractionTags();
9897
includeReasoning = thinking.getIncludeReasoning();
9998
thinkingEffort = nonNull(thinking.getThinkingEffort()) ? thinking.getThinkingEffort().getValue() : null;
99+
if (nonNull(thinking.getEnabled()))
100+
chatTemplateKwargs = Map.of("thinking", thinking.getEnabled());
100101
}
101102

102103
var textChatRequest = TextChatRequest.builder()
@@ -153,10 +154,11 @@ public CompletableFuture<Void> chatStreaming(ChatRequest chatRequest, ChatHandle
153154
Map<String, Object> chatTemplateKwargs = null;
154155
if (nonNull(chatRequest.getThinking())) {
155156
var thinking = chatRequest.getThinking();
156-
chatTemplateKwargs = Map.of("thinking", true);
157157
extractionTags = thinking.getExtractionTags();
158158
includeReasoning = thinking.getIncludeReasoning();
159159
thinkingEffort = nonNull(thinking.getThinkingEffort()) ? thinking.getThinkingEffort().getValue() : null;
160+
if (nonNull(thinking.getEnabled()))
161+
chatTemplateKwargs = Map.of("thinking", thinking.getEnabled());
160162
}
161163

162164
var textChatRequest = TextChatRequest.builder()

modules/watsonx-ai/src/main/java/com/ibm/watsonx/ai/chat/model/Thinking.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
*/
55
package com.ibm.watsonx.ai.chat.model;
66

7+
import static java.util.Objects.isNull;
8+
import static java.util.Objects.nonNull;
9+
710
/**
811
* Represents the reasoning configuration used by the LLM.
912
* <p>
@@ -35,16 +38,25 @@
3538
*/
3639
public final class Thinking {
3740

41+
private final Boolean enabled;
3842
private final Boolean includeReasoning;
3943
private final ExtractionTags extractionTags;
4044
private final ThinkingEffort thinkingEffort;
4145

4246
private Thinking(Builder builder) {
47+
enabled = builder.enabled;
4348
includeReasoning = builder.includeReasoning;
4449
extractionTags = builder.extractionTags;
4550
thinkingEffort = builder.thinkingEffort;
4651
}
4752

53+
public Boolean getEnabled() {
54+
if (isNull(enabled) && (nonNull(includeReasoning) || nonNull(extractionTags) || nonNull(thinkingEffort)))
55+
return true;
56+
57+
return enabled;
58+
}
59+
4860
public Boolean getIncludeReasoning() {
4961
return includeReasoning;
5062
}
@@ -75,12 +87,19 @@ public static Builder builder() {
7587
}
7688

7789
public final static class Builder {
90+
private Boolean enabled;
7891
private Boolean includeReasoning;
7992
private ExtractionTags extractionTags;
8093
private ThinkingEffort thinkingEffort;
8194

8295
private Builder() {}
8396

97+
98+
public Builder enabled(Boolean enabled) {
99+
this.enabled = enabled;
100+
return this;
101+
}
102+
84103
/**
85104
* Sets whether reasoning should be included in the LLM response.
86105
* <p>
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Copyright IBM Corp. 2025 - 2025
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
package com.ibm.watsonx.ai.chat;
6+
7+
import static org.junit.jupiter.api.Assertions.assertNull;
8+
import org.junit.jupiter.api.Test;
9+
import com.ibm.watsonx.ai.chat.model.ExtractionTags;
10+
import com.ibm.watsonx.ai.chat.model.ThinkingEffort;
11+
import com.ibm.watsonx.ai.chat.model.UserMessage;
12+
13+
public class ChatRequestTest {
14+
15+
@Test
16+
void should_not_set_thinking_when_null_is_passed() {
17+
18+
ExtractionTags tags = null;
19+
20+
var chatRequest = ChatRequest.builder()
21+
.messages(UserMessage.text("Hello"))
22+
.thinking(tags)
23+
.build();
24+
25+
assertNull(chatRequest.getThinking());
26+
27+
ThinkingEffort thinkingEffort = null;
28+
29+
chatRequest = ChatRequest.builder()
30+
.messages(UserMessage.text("Hello"))
31+
.thinking(thinkingEffort)
32+
.build();
33+
34+
assertNull(chatRequest.getThinking());
35+
}
36+
}

modules/watsonx-ai/src/test/java/com/ibm/watsonx/ai/chat/ChatServiceThinkingTest.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ void test_thinking_with_efforts() throws Exception {
249249
}
250250

251251
@Test
252-
void test_thinking_without_thinking() throws Exception {
252+
void test_thinking_with_enabled_false() throws Exception {
253253

254254
wireMock.stubFor(post("/ml/v1/text/chat?version=%s".formatted(API_VERSION))
255255
.withHeader("Authorization", equalTo("Bearer my-token"))
@@ -268,7 +268,10 @@ void test_thinking_without_thinking() throws Exception {
268268
]
269269
}
270270
],
271-
"time_limit": 60000
271+
"time_limit": 60000,
272+
"chat_template_kwargs" : {
273+
"thinking": false
274+
}
272275
}"""))
273276
.willReturn(aResponse()
274277
.withStatus(200)
@@ -798,7 +801,7 @@ public void onPartialThinking(String partialThinking, PartialChatResponse partia
798801
}
799802

800803
@Test
801-
void test_thinking_without_thinking() throws Exception {
804+
void test_thinking_with_enabled_false() throws Exception {
802805

803806
wireMock.stubFor(post("/ml/v1/text/chat_stream?version=%s".formatted(API_VERSION))
804807
.withHeader("Authorization", equalTo("Bearer my-token"))
@@ -898,7 +901,6 @@ void test_thinking_without_thinking() throws Exception {
898901
.build();
899902

900903
var chatRequest = ChatRequest.builder()
901-
.thinking(false)
902904
.messages(UserMessage.text("Translate 'Hello' to Italian"))
903905
.build();
904906

0 commit comments

Comments
 (0)