fix: reverse ToolContext validation logic in MethodToolCallback
Changes the validation logic in MethodToolCallback to check if a ToolContext is required by the method but not provided, rather than checking if a ToolContext is provided but not supported by the method. This ensures methods that expect a ToolContext parameter receive one. Updates tests cases to reflect the new validation logic Resolves #2337 Signed-off-by: Christian Tzolov <christian.tzolov@broadcom.com>
This commit is contained in:
@@ -192,13 +192,13 @@ class AnthropicChatClientMethodInvokingFunctionCallbackIT {
|
||||
}
|
||||
|
||||
@Test
|
||||
void methodGetWeatherToolContextButNonContextMethod() {
|
||||
void methodGetWeatherWithContextMethodButMissingContext() {
|
||||
|
||||
TestFunctionClass targetObject = new TestFunctionClass();
|
||||
|
||||
// @formatter:off
|
||||
var toolMethod = ReflectionUtils.findMethod(
|
||||
TestFunctionClass.class, "getWeatherNonStatic", String.class, Unit.class);
|
||||
TestFunctionClass.class, "getWeatherWithContext", String.class, Unit.class, ToolContext.class);
|
||||
|
||||
assertThatThrownBy(() -> ChatClient.create(this.chatModel).prompt()
|
||||
.user("What's the weather like in San Francisco, Tokyo, and Paris? Use Celsius.")
|
||||
@@ -209,11 +209,10 @@ class AnthropicChatClientMethodInvokingFunctionCallbackIT {
|
||||
.toolMethod(toolMethod)
|
||||
.toolObject(targetObject)
|
||||
.build())
|
||||
.toolContext(Map.of("tool", "value"))
|
||||
.call()
|
||||
.content())
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("ToolContext is not supported by the method as an argument");
|
||||
.hasMessage("ToolContext is required by the method as an argument");
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
|
||||
@@ -165,12 +165,12 @@ class OpenAiChatClientMethodInvokingFunctionCallbackIT {
|
||||
}
|
||||
|
||||
@Test
|
||||
void methodGetWeatherToolContextButNonContextMethod() {
|
||||
void methodGetWeatherToolContextButMissingContextArgument() {
|
||||
|
||||
TestFunctionClass targetObject = new TestFunctionClass();
|
||||
|
||||
var toolMethod = ReflectionUtils.findMethod(TestFunctionClass.class, "getWeatherNonStatic", String.class,
|
||||
Unit.class);
|
||||
var toolMethod = ReflectionUtils.findMethod(TestFunctionClass.class, "getWeatherWithContext", String.class,
|
||||
Unit.class, ToolContext.class);
|
||||
|
||||
// @formatter:off
|
||||
assertThatThrownBy(() -> ChatClient.create(this.chatModel).prompt()
|
||||
@@ -181,12 +181,11 @@ class OpenAiChatClientMethodInvokingFunctionCallbackIT {
|
||||
.build())
|
||||
.toolMethod(toolMethod)
|
||||
.toolObject(targetObject)
|
||||
.build())
|
||||
.toolContext(Map.of("tool", "value"))
|
||||
.build())
|
||||
.call()
|
||||
.content())
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("ToolContext is not supported by the method as an argument");
|
||||
.hasMessage("ToolContext is required by the method as an argument");
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
|
||||
@@ -115,11 +115,11 @@ public class MethodToolCallback implements ToolCallback {
|
||||
}
|
||||
|
||||
private void validateToolContextSupport(@Nullable ToolContext toolContext) {
|
||||
var isToolContextRequired = toolContext != null && !CollectionUtils.isEmpty(toolContext.getContext());
|
||||
var isNonEmptyToolContextProvided = toolContext != null && !CollectionUtils.isEmpty(toolContext.getContext());
|
||||
var isToolContextAcceptedByMethod = Stream.of(toolMethod.getParameterTypes())
|
||||
.anyMatch(type -> ClassUtils.isAssignable(type, ToolContext.class));
|
||||
if (isToolContextRequired && !isToolContextAcceptedByMethod) {
|
||||
throw new IllegalArgumentException("ToolContext is not supported by the method as an argument");
|
||||
if (isToolContextAcceptedByMethod && !isNonEmptyToolContextProvided) {
|
||||
throw new IllegalArgumentException("ToolContext is required by the method as an argument");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -69,8 +69,8 @@ class MethodToolCallbackTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldThrowExceptionWhenToolContextNotSupported() {
|
||||
Method toolMethod = getMethod("publicMethod", PublicTools.class);
|
||||
void shouldThrowExceptionWhenToolContextArgumentIsMissing() {
|
||||
Method toolMethod = getMethod("methodWithToolContext", ToolContextTools.class);
|
||||
MethodToolCallback callback = MethodToolCallback.builder()
|
||||
.toolDefinition(ToolDefinition.from(toolMethod))
|
||||
.toolMetadata(ToolMetadata.from(toolMethod))
|
||||
@@ -78,14 +78,12 @@ class MethodToolCallbackTests {
|
||||
.toolObject(new PublicTools())
|
||||
.build();
|
||||
|
||||
ToolContext toolContext = new ToolContext(Map.of("key", "value"));
|
||||
|
||||
assertThatThrownBy(() -> callback.call("""
|
||||
{
|
||||
"input": "test"
|
||||
}
|
||||
""", toolContext)).isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessageContaining("ToolContext is not supported");
|
||||
""")).isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessageContaining("ToolContext is required by the method as an argument");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user