|
19 | 19 | import java.util.List;
|
20 | 20 | import java.util.Map;
|
21 | 21 | import java.util.concurrent.ConcurrentHashMap;
|
| 22 | +import java.util.stream.Collectors; |
22 | 23 |
|
23 | 24 | import org.junit.jupiter.api.BeforeEach;
|
24 | 25 | import org.junit.jupiter.api.Test;
|
25 | 26 | import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
|
| 27 | +import org.junit.jupiter.params.ParameterizedTest; |
| 28 | +import org.junit.jupiter.params.provider.ValueSource; |
26 | 29 | import org.slf4j.Logger;
|
27 | 30 | import org.slf4j.LoggerFactory;
|
28 | 31 |
|
29 | 32 | import org.springframework.ai.anthropic.AnthropicTestConfiguration;
|
30 | 33 | import org.springframework.ai.chat.client.ChatClient;
|
31 | 34 | import org.springframework.ai.chat.messages.Message;
|
32 | 35 | import org.springframework.ai.chat.model.ChatModel;
|
| 36 | +import org.springframework.ai.chat.model.ChatResponse; |
33 | 37 | import org.springframework.ai.chat.model.ToolContext;
|
| 38 | +import org.springframework.ai.model.tool.ToolCallingChatOptions; |
34 | 39 | import org.springframework.ai.tool.annotation.Tool;
|
35 | 40 | import org.springframework.ai.tool.method.MethodToolCallback;
|
36 | 41 | import org.springframework.ai.tool.support.ToolDefinitions;
|
|
39 | 44 | import org.springframework.test.context.ActiveProfiles;
|
40 | 45 | import org.springframework.util.ReflectionUtils;
|
41 | 46 |
|
| 47 | +import reactor.core.publisher.Flux; |
| 48 | + |
42 | 49 | import static org.assertj.core.api.Assertions.assertThat;
|
43 | 50 | import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy;
|
44 | 51 |
|
@@ -262,6 +269,39 @@ void toolAnnotation() {
|
262 | 269 | .containsEntry("color", TestFunctionClass.LightColor.RED);
|
263 | 270 | }
|
264 | 271 |
|
| 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 | + |
265 | 305 | @Autowired
|
266 | 306 | ChatModel chatModel;
|
267 | 307 |
|
|
0 commit comments