16
16
17
17
package org .springframework .ai .anthropic .api ;
18
18
19
+ import java .util .ArrayList ;
19
20
import java .util .List ;
20
21
21
22
import org .junit .jupiter .api .Test ;
22
23
import org .junit .jupiter .api .condition .EnabledIfEnvironmentVariable ;
24
+ import org .springframework .ai .model .ModelOptionsUtils ;
23
25
import reactor .core .publisher .Flux ;
24
26
25
27
import org .springframework .ai .anthropic .api .AnthropicApi .AnthropicMessage ;
@@ -41,6 +43,24 @@ public class AnthropicApiIT {
41
43
42
44
AnthropicApi anthropicApi = new AnthropicApi (System .getenv ("ANTHROPIC_API_KEY" ));
43
45
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
+
44
64
@ Test
45
65
void chatCompletionEntity () {
46
66
@@ -72,6 +92,47 @@ void chatCompletionStream() {
72
92
bla .stream ().forEach (r -> System .out .println (r ));
73
93
}
74
94
95
+ @ Test
96
+ void chatCompletionStreamWithToolCall () {
97
+ List <AnthropicMessage > messageConversation = new ArrayList <>();
98
+
99
+ AnthropicMessage chatCompletionMessage = new AnthropicMessage (
100
+ List .of (new ContentBlock ("What's the weather like in San Francisco? Show the temperature in Celsius." )),
101
+ Role .USER );
102
+
103
+ messageConversation .add (chatCompletionMessage );
104
+
105
+ ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest .builder ()
106
+ .withModel (AnthropicApi .ChatModel .CLAUDE_3_OPUS )
107
+ .withMessages (messageConversation )
108
+ .withMaxTokens (1500 )
109
+ .withStream (true )
110
+ .withTemperature (0.8 )
111
+ .withTools (tools )
112
+ .build ();
113
+
114
+ List <ChatCompletionResponse > responses = this .anthropicApi .chatCompletionStream (chatCompletionRequest )
115
+ .collectList ()
116
+ .block ();
117
+
118
+ // Check that tool uses response returned only once
119
+ List <ChatCompletionResponse > toolCompletionResponses = responses .stream ()
120
+ .filter (r -> r .stopReason () != null && r .stopReason ().equals (ContentBlock .Type .TOOL_USE .value ))
121
+ .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
+
75
136
@ Test
76
137
void chatCompletionStreamError () {
77
138
AnthropicMessage chatCompletionMessage = new AnthropicMessage (List .of (new ContentBlock ("Tell me a Joke?" )),
0 commit comments