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