3131import org .springframework .ai .chat .messages .Message ;
3232import org .springframework .ai .chat .model .ChatModel ;
3333import org .springframework .ai .chat .model .ToolContext ;
34- import org .springframework .ai .model .function .FunctionCallback ;
34+ import org .springframework .ai .tool .definition .ToolDefinition ;
35+ import org .springframework .ai .tool .method .MethodToolCallback ;
3536import org .springframework .beans .factory .annotation .Autowired ;
3637import org .springframework .boot .test .context .SpringBootTest ;
3738import org .springframework .test .context .ActiveProfiles ;
39+ import org .springframework .util .ReflectionUtils ;
3840
3941import static org .assertj .core .api .Assertions .assertThat ;
4042import static org .assertj .core .api .AssertionsForClassTypes .assertThatThrownBy ;
4143
4244@ SpringBootTest (classes = AnthropicTestConfiguration .class , properties = "spring.ai.retry.on-http-codes=429" )
4345@ EnabledIfEnvironmentVariable (named = "ANTHROPIC_API_KEY" , matches = ".+" )
4446@ ActiveProfiles ("logging-test" )
47+ @ SuppressWarnings ("null" )
4548class AnthropicChatClientMethodInvokingFunctionCallbackIT {
4649
4750 private static final Logger logger = LoggerFactory
@@ -58,11 +61,14 @@ void beforeEach() {
5861 void methodGetWeatherGeneratedDescription () {
5962
6063 // @formatter:off
64+ var toolMethod = ReflectionUtils .findMethod (
65+ TestFunctionClass .class , "getWeatherInLocation" , String .class , Unit .class );
66+
6167 String response = ChatClient .create (this .chatModel ).prompt ()
6268 .user ("What's the weather like in San Francisco, Tokyo, and Paris? Use Celsius." )
63- .functions ( FunctionCallback .builder ()
64- .method ( "getWeatherInLocation" , String . class , Unit . class )
65- .targetClass ( TestFunctionClass . class )
69+ .tools ( MethodToolCallback .builder ()
70+ .toolDefinition ( ToolDefinition . builder ( toolMethod ). build () )
71+ .toolMethod ( toolMethod )
6672 .build ())
6773 .call ()
6874 .content ();
@@ -77,12 +83,16 @@ void methodGetWeatherGeneratedDescription() {
7783 void methodGetWeatherStatic () {
7884
7985 // @formatter:off
86+ var toolMethod = ReflectionUtils .findMethod (
87+ TestFunctionClass .class , "getWeatherStatic" , String .class , Unit .class );
88+
8089 String response = ChatClient .create (this .chatModel ).prompt ()
8190 .user ("What's the weather like in San Francisco, Tokyo, and Paris? Use Celsius." )
82- .functions (FunctionCallback .builder ()
83- .method ("getWeatherStatic" , String .class , Unit .class )
84- .description ("Get the weather in location" )
85- .targetClass (TestFunctionClass .class )
91+ .tools (MethodToolCallback .builder ()
92+ .toolDefinition (ToolDefinition .builder (toolMethod )
93+ .description ("Get the weather in location" )
94+ .build ())
95+ .toolMethod (toolMethod )
8696 .build ())
8797 .call ()
8898 .content ();
@@ -99,12 +109,18 @@ void methodTurnLightNoResponse() {
99109 TestFunctionClass targetObject = new TestFunctionClass ();
100110
101111 // @formatter:off
112+
113+ var turnLightMethod = ReflectionUtils .findMethod (
114+ TestFunctionClass .class , "turnLight" , String .class , boolean .class );
115+
102116 String response = ChatClient .create (this .chatModel ).prompt ()
103117 .user ("Turn light on in the living room." )
104- .functions (FunctionCallback .builder ()
105- .method ("turnLight" , String .class , boolean .class )
106- .description ("Turn light on in the living room." )
107- .targetObject (targetObject )
118+ .tools (MethodToolCallback .builder ()
119+ .toolDefinition (ToolDefinition .builder (turnLightMethod )
120+ .description ("Turn light on in the living room." )
121+ .build ())
122+ .toolMethod (turnLightMethod )
123+ .toolObject (targetObject )
108124 .build ())
109125 .call ()
110126 .content ();
@@ -122,12 +138,17 @@ void methodGetWeatherNonStatic() {
122138 TestFunctionClass targetObject = new TestFunctionClass ();
123139
124140 // @formatter:off
141+ var toolMethod = ReflectionUtils .findMethod (
142+ TestFunctionClass .class , "getWeatherNonStatic" , String .class , Unit .class );
143+
125144 String response = ChatClient .create (this .chatModel ).prompt ()
126145 .user ("What's the weather like in San Francisco, Tokyo, and Paris? Use Celsius." )
127- .functions (FunctionCallback .builder ()
128- .method ("getWeatherNonStatic" , String .class , Unit .class )
129- .description ("Get the weather in location" )
130- .targetObject (targetObject )
146+ .tools (MethodToolCallback .builder ()
147+ .toolDefinition (ToolDefinition .builder (toolMethod )
148+ .description ("Get the weather in location" )
149+ .build ())
150+ .toolMethod (toolMethod )
151+ .toolObject (targetObject )
131152 .build ())
132153 .call ()
133154 .content ();
@@ -144,17 +165,21 @@ void methodGetWeatherToolContext() {
144165 TestFunctionClass targetObject = new TestFunctionClass ();
145166
146167 // @formatter:off
168+ var toolMethod = ReflectionUtils .findMethod (
169+ TestFunctionClass .class , "getWeatherWithContext" , String .class , Unit .class , ToolContext .class );
170+
147171 String response = ChatClient .create (this .chatModel ).prompt ()
148172 .user ("What's the weather like in San Francisco, Tokyo, and Paris? Use Celsius." )
149- .functions (FunctionCallback .builder ()
150- .method ("getWeatherWithContext" , String .class , Unit .class , ToolContext .class )
151- .description ("Get the weather in location" )
152- .targetObject (targetObject )
173+ .tools (MethodToolCallback .builder ()
174+ .toolDefinition (ToolDefinition .builder (toolMethod )
175+ .description ("Get the weather in location" )
176+ .build ())
177+ .toolMethod (toolMethod )
178+ .toolObject (targetObject )
153179 .build ())
154180 .toolContext (Map .of ("tool" , "value" ))
155181 .call ()
156182 .content ();
157- // @formatter:on
158183
159184 logger .info ("Response: {}" , response );
160185
@@ -171,18 +196,23 @@ void methodGetWeatherToolContextButNonContextMethod() {
171196 TestFunctionClass targetObject = new TestFunctionClass ();
172197
173198 // @formatter:off
199+ var toolMethod = ReflectionUtils .findMethod (
200+ TestFunctionClass .class , "getWeatherNonStatic" , String .class , Unit .class );
201+
174202 assertThatThrownBy (() -> ChatClient .create (this .chatModel ).prompt ()
175203 .user ("What's the weather like in San Francisco, Tokyo, and Paris? Use Celsius." )
176- .functions (FunctionCallback .builder ()
177- .method ("getWeatherNonStatic" , String .class , Unit .class )
178- .description ("Get the weather in location" )
179- .targetObject (targetObject )
204+ .tools (MethodToolCallback .builder ()
205+ .toolDefinition (ToolDefinition .builder (toolMethod )
206+ .description ("Get the weather in location" )
207+ .build ())
208+ .toolMethod (toolMethod )
209+ .toolObject (targetObject )
180210 .build ())
181211 .toolContext (Map .of ("tool" , "value" ))
182212 .call ()
183213 .content ())
184214 .isInstanceOf (IllegalArgumentException .class )
185- .hasMessage ("Configured method does not accept ToolContext as input parameter! " );
215+ .hasMessage ("ToolContext is not supported by the method as an argument " );
186216 // @formatter:on
187217 }
188218
@@ -191,13 +221,18 @@ void methodNoParameters() {
191221
192222 TestFunctionClass targetObject = new TestFunctionClass ();
193223
194- // @formatter:off
224+ // @formatter:off
225+ var toolMethod = ReflectionUtils .findMethod (
226+ TestFunctionClass .class , "turnLivingRoomLightOn" );
227+
195228 String response = ChatClient .create (this .chatModel ).prompt ()
196229 .user ("Turn light on in the living room." )
197- .functions (FunctionCallback .builder ()
198- .method ("turnLivingRoomLightOn" )
199- .description ("Can turn lights on in the Living Room" )
200- .targetObject (targetObject )
230+ .functions (MethodToolCallback .builder ()
231+ .toolMethod (toolMethod )
232+ .toolDefinition (ToolDefinition .builder (toolMethod )
233+ .description ("Can turn lights on in the Living Room" )
234+ .build ())
235+ .toolObject (targetObject )
201236 .build ())
202237 .call ()
203238 .content ();
0 commit comments