1616
1717package org .springframework .ai .anthropic .api ;
1818
19+ import java .util .ArrayList ;
1920import java .util .List ;
2021
2122import org .junit .jupiter .api .Test ;
2223import org .junit .jupiter .api .condition .EnabledIfEnvironmentVariable ;
24+ import org .springframework .ai .model .ModelOptionsUtils ;
2325import reactor .core .publisher .Flux ;
2426
2527import org .springframework .ai .anthropic .api .AnthropicApi .AnthropicMessage ;
@@ -41,6 +43,25 @@ public class AnthropicApiIT {
4143
4244 AnthropicApi anthropicApi = new AnthropicApi (System .getenv ("ANTHROPIC_API_KEY" ));
4345
46+ List <AnthropicApi .Tool > tools = List .of (new AnthropicApi .Tool ("getCurrentWeather" ,
47+ "Get the weather in location. Return temperature in 30°F or 30°C format." , ModelOptionsUtils .jsonToMap ("""
48+ {
49+ "type": "object",
50+ "properties": {
51+ "location": {
52+ "type": "string",
53+ "description": "The city and state e.g. San Francisco, CA"
54+ },
55+ "unit": {
56+ "type": "string",
57+ "enum": ["C", "F"]
58+ }
59+ },
60+ "required": ["location", "unit"]
61+ }
62+ """ )));
63+
64+
4465 @ Test
4566 void chatCompletionEntity () {
4667
@@ -72,6 +93,46 @@ void chatCompletionStream() {
7293 bla .stream ().forEach (r -> System .out .println (r ));
7394 }
7495
96+ @ Test
97+ void chatCompletionStreamWithToolCall () {
98+ List <AnthropicMessage > messageConversation = new ArrayList <>();
99+
100+ AnthropicMessage chatCompletionMessage = new AnthropicMessage (List .of (new ContentBlock (
101+ "What's the weather like in San Francisco? Show the temperature in Celsius." )),
102+ Role .USER );
103+
104+ messageConversation .add (chatCompletionMessage );
105+
106+ ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest .builder ()
107+ .withModel (AnthropicApi .ChatModel .CLAUDE_3_OPUS )
108+ .withMessages (messageConversation )
109+ .withMaxTokens (1500 )
110+ .withStream (true )
111+ .withTemperature (0.8 )
112+ .withTools (tools )
113+ .build ();
114+
115+ List <ChatCompletionResponse > responses = this .anthropicApi .chatCompletionStream (chatCompletionRequest )
116+ .collectList ()
117+ .block ();
118+
119+ // Check that tool uses response returned only once
120+ List <ChatCompletionResponse > toolCompletionResponses = responses .stream ().filter (r ->
121+ r .stopReason () != null && r .stopReason ().equals (ContentBlock .Type .TOOL_USE .value )).toList ();
122+ assertThat (toolCompletionResponses ).size ().isEqualTo (1 );
123+ List <ContentBlock > toolContentBlocks = toolCompletionResponses .get (0 ).content ();
124+ assertThat (toolContentBlocks ).size ().isEqualTo (1 );
125+ ContentBlock toolContentBlock = toolContentBlocks .get (0 );
126+ assertThat (toolContentBlock .type ()).isEqualTo (ContentBlock .Type .TOOL_USE );
127+ assertThat (toolContentBlock .name ()).isEqualTo ("getCurrentWeather" );
128+
129+ // Check that message stop response also returned
130+ List <ChatCompletionResponse > messageStopEvents = responses .stream ()
131+ .filter (r -> r .type ().equals (AnthropicApi .EventType .MESSAGE_STOP .name ()))
132+ .toList ();
133+ assertThat (messageStopEvents ).size ().isEqualTo (1 );
134+ }
135+
75136 @ Test
76137 void chatCompletionStreamError () {
77138 AnthropicMessage chatCompletionMessage = new AnthropicMessage (List .of (new ContentBlock ("Tell me a Joke?" )),
0 commit comments