Skip to content

Commit f575051

Browse files
tzolovilayaperumalg
authored andcommitted
fix(anthropic): Add streaming parameter-less tool support
- Remove partialJson text check from isEmpty() method in AnthropicApi - Add parameterized test for streaming parameter-less tools across Claude models - Addresses issue #1878 with parameter-less tool streaming functionality Auto-cherry-pick to 1.0.x Fixes #1878 Signed-off-by: Christian Tzolov <[email protected]>
1 parent a2a92bb commit f575051

File tree

2 files changed

+41
-2
lines changed

2 files changed

+41
-2
lines changed

models/spring-ai-anthropic/src/main/java/org/springframework/ai/anthropic/api/AnthropicApi.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1060,8 +1060,7 @@ public List<ContentBlockStartEvent.ContentBlockToolUse> getToolContentBlocks() {
10601060
* @return True if the event is empty, false otherwise.
10611061
*/
10621062
public boolean isEmpty() {
1063-
return (this.index == null || this.id == null || this.name == null
1064-
|| !StringUtils.hasText(this.partialJson));
1063+
return (this.index == null || this.id == null || this.name == null);
10651064
}
10661065

10671066
ToolUseAggregationEvent withIndex(Integer index) {

models/spring-ai-anthropic/src/test/java/org/springframework/ai/anthropic/client/AnthropicChatClientMethodInvokingFunctionCallbackIT.java

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,23 @@
1919
import java.util.List;
2020
import java.util.Map;
2121
import java.util.concurrent.ConcurrentHashMap;
22+
import java.util.stream.Collectors;
2223

2324
import org.junit.jupiter.api.BeforeEach;
2425
import org.junit.jupiter.api.Test;
2526
import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
27+
import org.junit.jupiter.params.ParameterizedTest;
28+
import org.junit.jupiter.params.provider.ValueSource;
2629
import org.slf4j.Logger;
2730
import org.slf4j.LoggerFactory;
2831

2932
import org.springframework.ai.anthropic.AnthropicTestConfiguration;
3033
import org.springframework.ai.chat.client.ChatClient;
3134
import org.springframework.ai.chat.messages.Message;
3235
import org.springframework.ai.chat.model.ChatModel;
36+
import org.springframework.ai.chat.model.ChatResponse;
3337
import org.springframework.ai.chat.model.ToolContext;
38+
import org.springframework.ai.model.tool.ToolCallingChatOptions;
3439
import org.springframework.ai.tool.annotation.Tool;
3540
import org.springframework.ai.tool.method.MethodToolCallback;
3641
import org.springframework.ai.tool.support.ToolDefinitions;
@@ -39,6 +44,8 @@
3944
import org.springframework.test.context.ActiveProfiles;
4045
import org.springframework.util.ReflectionUtils;
4146

47+
import reactor.core.publisher.Flux;
48+
4249
import static org.assertj.core.api.Assertions.assertThat;
4350
import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy;
4451

@@ -262,6 +269,39 @@ void toolAnnotation() {
262269
.containsEntry("color", TestFunctionClass.LightColor.RED);
263270
}
264271

272+
// https://github.com/spring-projects/spring-ai/issues/1878
273+
@ParameterizedTest
274+
@ValueSource(strings = { "claude-opus-4-20250514", "claude-sonnet-4-20250514", "claude-3-7-sonnet-latest" })
275+
void streamingParameterLessTool(String modelName) {
276+
277+
ChatClient chatClient = ChatClient.builder(this.chatModel).build();
278+
279+
Flux<ChatResponse> responses = chatClient.prompt()
280+
.options(ToolCallingChatOptions.builder().model(modelName).build())
281+
.tools(new ParameterLessTools())
282+
.user("Get current weather in Amsterdam")
283+
.stream()
284+
.chatResponse();
285+
286+
String content = responses.collectList()
287+
.block()
288+
.stream()
289+
.filter(cr -> cr.getResult() != null)
290+
.map(cr -> cr.getResult().getOutput().getText())
291+
.collect(Collectors.joining());
292+
293+
assertThat(content).contains("20 degrees");
294+
}
295+
296+
public static class ParameterLessTools {
297+
298+
@Tool(description = "Get the current weather forecast in Amsterdam")
299+
String getCurrentDateTime() {
300+
return "Weather is hot and sunny with a temperature of 20 degrees";
301+
}
302+
303+
}
304+
265305
@Autowired
266306
ChatModel chatModel;
267307

0 commit comments

Comments
 (0)