diff --git a/spring-ai-core/pom.xml b/spring-ai-core/pom.xml
index d0aa33b6c..e278f72cc 100644
--- a/spring-ai-core/pom.xml
+++ b/spring-ai-core/pom.xml
@@ -54,6 +54,18 @@
${jsonschema.version}
+
+ org.springframework.cloud
+ spring-cloud-function-context
+ ${spring-cloud-function-context.version}
+
+
+ org.springframework.boot
+ spring-boot-autoconfigure
+
+
+
+
org.antlr
@@ -126,13 +138,6 @@
${jackson.version}
-
- org.jetbrains.kotlin
- kotlin-stdlib
- ${kotlin.version}
- true
-
-
org.springframework.boot
@@ -141,16 +146,16 @@
- com.fasterxml.jackson.module
- jackson-module-kotlin
- ${jackson.version}
+ org.jetbrains.kotlin
+ kotlin-stdlib
+ ${kotlin.version}
test
- io.mockk
- mockk-jvm
- 1.13.13
+ com.fasterxml.jackson.module
+ jackson-module-kotlin
+ ${jackson.version}
test
diff --git a/spring-ai-core/src/main/java/org/springframework/ai/model/function/FunctionCallbackContext.java b/spring-ai-core/src/main/java/org/springframework/ai/model/function/FunctionCallbackContext.java
index 3e3b4ac43..ecbb9a4c1 100644
--- a/spring-ai-core/src/main/java/org/springframework/ai/model/function/FunctionCallbackContext.java
+++ b/spring-ai-core/src/main/java/org/springframework/ai/model/function/FunctionCallbackContext.java
@@ -16,22 +16,20 @@
package org.springframework.ai.model.function;
+import java.lang.reflect.Type;
import java.util.function.BiFunction;
import java.util.function.Function;
import com.fasterxml.jackson.annotation.JsonClassDescription;
-import kotlin.jvm.functions.Function1;
-import kotlin.jvm.functions.Function2;
import org.springframework.ai.chat.model.ToolContext;
import org.springframework.beans.BeansException;
-import org.springframework.beans.factory.NoSuchBeanDefinitionException;
-import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.cloud.function.context.catalog.FunctionTypeUtils;
+import org.springframework.cloud.function.context.config.FunctionContextUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Description;
import org.springframework.context.support.GenericApplicationContext;
-import org.springframework.core.ResolvableType;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.util.StringUtils;
@@ -51,7 +49,6 @@ import org.springframework.util.StringUtils;
*
* @author Christian Tzolov
* @author Christopher Smith
- * @author Sebastien Deleuze
*/
public class FunctionCallbackContext implements ApplicationContextAware {
@@ -71,19 +68,23 @@ public class FunctionCallbackContext implements ApplicationContextAware {
@SuppressWarnings({ "rawtypes", "unchecked" })
public FunctionCallback getFunctionCallback(@NonNull String beanName, @Nullable String defaultDescription) {
- BeanDefinition beanDefinition;
- try {
- beanDefinition = this.applicationContext.getBeanDefinition(beanName);
- }
- catch (NoSuchBeanDefinitionException ex) {
+ Type beanType = FunctionContextUtils.findType(this.applicationContext.getBeanFactory(), beanName);
+
+ if (beanType == null) {
throw new IllegalArgumentException(
- "Functional bean with name " + beanName + " does not exist in the context.");
+ "Functional bean with name: " + beanName + " does not exist in the context.");
}
- ResolvableType functionType = beanDefinition.getResolvableType();
- ResolvableType functionInputType = TypeResolverHelper.getFunctionArgumentType(functionType.getType(), 0);
+ if (!Function.class.isAssignableFrom(FunctionTypeUtils.getRawType(beanType))
+ && !BiFunction.class.isAssignableFrom(FunctionTypeUtils.getRawType(beanType))) {
+ throw new IllegalArgumentException(
+ "Function call Bean must be of type Function or BiFunction. Found: " + beanType.getTypeName());
+ }
- Class> functionInputClass = functionInputType.toClass();
+ Type functionInputType = TypeResolverHelper.getFunctionArgumentType(beanType, 0);
+
+ Class> functionInputClass = FunctionTypeUtils.getRawType(functionInputType);
+ String functionName = beanName;
String functionDescription = defaultDescription;
if (!StringUtils.hasText(functionDescription)) {
@@ -113,40 +114,24 @@ public class FunctionCallbackContext implements ApplicationContextAware {
Object bean = this.applicationContext.getBean(beanName);
- if (KotlinDelegate.isKotlinFunction(functionType.toClass())) {
- return FunctionCallbackWrapper.builder(KotlinDelegate.wrapKotlinFunction(bean))
- .withName(beanName)
- .withSchemaType(this.schemaType)
- .withDescription(functionDescription)
- .withInputType(functionInputClass)
- .build();
- }
- else if (KotlinDelegate.isKotlinBiFunction(functionType.toClass())) {
- return FunctionCallbackWrapper.builder(KotlinDelegate.wrapKotlinBiFunction(bean))
- .withName(beanName)
- .withSchemaType(this.schemaType)
- .withDescription(functionDescription)
- .withInputType(functionInputClass)
- .build();
- }
- else if (bean instanceof Function, ?> function) {
+ if (bean instanceof Function, ?> function) {
return FunctionCallbackWrapper.builder(function)
- .withName(beanName)
+ .withName(functionName)
.withSchemaType(this.schemaType)
.withDescription(functionDescription)
.withInputType(functionInputClass)
.build();
}
- else if (bean instanceof BiFunction, ?, ?>) {
- return FunctionCallbackWrapper.builder((BiFunction, ToolContext, ?>) bean)
- .withName(beanName)
+ else if (bean instanceof BiFunction, ?, ?> biFunction) {
+ return FunctionCallbackWrapper.builder((BiFunction, ToolContext, ?>) biFunction)
+ .withName(functionName)
.withSchemaType(this.schemaType)
.withDescription(functionDescription)
.withInputType(functionInputClass)
.build();
}
else {
- throw new IllegalStateException();
+ throw new IllegalArgumentException("Bean must be of type Function");
}
}
@@ -156,26 +141,4 @@ public class FunctionCallbackContext implements ApplicationContextAware {
}
- private static class KotlinDelegate {
-
- public static boolean isKotlinFunction(Class> clazz) {
- return Function1.class.isAssignableFrom(clazz);
- }
-
- @SuppressWarnings("unchecked")
- public static Function, ?> wrapKotlinFunction(Object function) {
- return t -> ((Function1