From 6393ae66fb2face5faec8ffcaf3b76bb12c07c14 Mon Sep 17 00:00:00 2001 From: Thomas Vitale Date: Tue, 7 Jan 2025 23:00:35 +0100 Subject: [PATCH] refactor(ai): Improve modularization of AI logic --- arconia-ai/arconia-ai-client/build.gradle | 33 +++++++++++ .../arconia/ai}/client/ArconiaChatClient.java | 4 +- .../ai}/client/DefaultArconiaChatClient.java | 10 ++-- .../DefaultArconiaChatClientBuilder.java | 8 +-- .../ai}/client/advisor/CallAdvisor.java | 2 +- .../ai}/client/advisor/StreamAdvisor.java | 2 +- .../ai/client/advisor}/package-info.java | 2 +- .../io/arconia/ai}/client/package-info.java | 2 +- .../ai/core/client/advisor/package-info.java | 6 -- .../arconia/ai/core/tools/ToolCallback.java | 32 ---------- .../core/tools/annotation/package-info.java | 6 -- .../aot/JacksonJsonSchemaRuntimeHints.java | 21 ------- .../ai/core/tools/metadata/package-info.java | 6 -- .../ai/core/tools/method/package-info.java | 6 -- .../ai/core/tools/util/package-info.java | 6 -- .../resources/META-INF/spring/aot.factories | 2 - .../JacksonJsonSchemaRuntimeHintsTests.java | 25 -------- arconia-ai/arconia-ai-mcp/build.gradle | 2 +- .../arconia/ai/mcp/tools/McpToolCallback.java | 59 +++++++++++++++---- .../ai/mcp/tools/McpToolCallbackProvider.java | 11 ++-- .../ai/mcp/tools/McpToolCallbacks.java | 3 +- .../build.gradle | 3 +- .../ArconiaChatClientAutoConfiguration.java | 2 +- .../autoconfigure/core/tools/TestTools.java | 2 +- .../build.gradle | 4 +- .../io/arconia/ai/tools/ToolCallback.java | 40 +++++++++++++ .../ai}/tools/ToolCallbackProvider.java | 2 +- .../io/arconia/ai}/tools/ToolCallbacks.java | 4 +- .../io/arconia/ai}/tools/annotation/Tool.java | 14 +++-- .../ai/tools/annotation/package-info.java | 6 ++ .../definition/DefaultToolDefinition.java} | 32 ++++------ .../ai/tools/definition/ToolDefinition.java | 39 ++++++++++++ .../ai/tools/definition/package-info.java | 6 ++ .../ai/tools/execution/ToolExecutionMode.java | 8 +++ .../io/arconia/ai}/tools/json/JsonParser.java | 12 +++- .../ai}/tools/json/JsonSchemaGenerator.java | 18 +----- .../arconia/ai}/tools/json/package-info.java | 2 +- .../tools/metadata/DefaultToolMetadata.java | 48 +++++++++++++++ .../ai}/tools/metadata/ToolMetadata.java | 29 ++++----- .../ai/tools/metadata/package-info.java | 6 ++ .../ai}/tools/method/MethodToolCallback.java | 29 +++++++-- .../method/MethodToolCallbackProvider.java | 30 +++++----- .../arconia/ai/tools/method/package-info.java | 6 ++ .../io/arconia/ai/tools}/package-info.java | 2 +- .../io/arconia/ai}/tools/util/ToolUtils.java | 34 ++++++----- .../arconia/ai/tools/util/package-info.java | 6 ++ .../arconia/ai/core/tools/ToolUtilsTests.java | 14 ++--- .../tools/json/JsonSchemaGeneratorTests.java | 2 +- .../MethodToolCallbackProviderTests.java | 6 +- .../tools/method/MethodToolCallbackTests.java | 10 ++-- settings.gradle | 3 +- 51 files changed, 408 insertions(+), 259 deletions(-) create mode 100644 arconia-ai/arconia-ai-client/build.gradle rename arconia-ai/{arconia-ai-core/src/main/java/io/arconia/ai/core => arconia-ai-client/src/main/java/io/arconia/ai}/client/ArconiaChatClient.java (98%) rename arconia-ai/{arconia-ai-core/src/main/java/io/arconia/ai/core => arconia-ai-client/src/main/java/io/arconia/ai}/client/DefaultArconiaChatClient.java (99%) rename arconia-ai/{arconia-ai-core/src/main/java/io/arconia/ai/core => arconia-ai-client/src/main/java/io/arconia/ai}/client/DefaultArconiaChatClientBuilder.java (96%) rename arconia-ai/{arconia-ai-core/src/main/java/io/arconia/ai/core => arconia-ai-client/src/main/java/io/arconia/ai}/client/advisor/CallAdvisor.java (96%) rename arconia-ai/{arconia-ai-core/src/main/java/io/arconia/ai/core => arconia-ai-client/src/main/java/io/arconia/ai}/client/advisor/StreamAdvisor.java (96%) rename arconia-ai/{arconia-ai-core/src/main/java/io/arconia/ai/core/tools/aot => arconia-ai-client/src/main/java/io/arconia/ai/client/advisor}/package-info.java (75%) rename arconia-ai/{arconia-ai-core/src/main/java/io/arconia/ai/core => arconia-ai-client/src/main/java/io/arconia/ai}/client/package-info.java (77%) delete mode 100644 arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/client/advisor/package-info.java delete mode 100644 arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/ToolCallback.java delete mode 100644 arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/annotation/package-info.java delete mode 100644 arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/aot/JacksonJsonSchemaRuntimeHints.java delete mode 100644 arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/metadata/package-info.java delete mode 100644 arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/method/package-info.java delete mode 100644 arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/util/package-info.java delete mode 100644 arconia-ai/arconia-ai-core/src/main/resources/META-INF/spring/aot.factories delete mode 100644 arconia-ai/arconia-ai-core/src/test/java/io/arconia/ai/core/tools/aot/JacksonJsonSchemaRuntimeHintsTests.java rename arconia-ai/{arconia-ai-core => arconia-ai-tools}/build.gradle (87%) create mode 100644 arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/ToolCallback.java rename arconia-ai/{arconia-ai-core/src/main/java/io/arconia/ai/core => arconia-ai-tools/src/main/java/io/arconia/ai}/tools/ToolCallbackProvider.java (83%) rename arconia-ai/{arconia-ai-core/src/main/java/io/arconia/ai/core => arconia-ai-tools/src/main/java/io/arconia/ai}/tools/ToolCallbacks.java (76%) rename arconia-ai/{arconia-ai-core/src/main/java/io/arconia/ai/core => arconia-ai-tools/src/main/java/io/arconia/ai}/tools/annotation/Tool.java (64%) create mode 100644 arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/annotation/package-info.java rename arconia-ai/{arconia-ai-core/src/main/java/io/arconia/ai/core/tools/metadata/DefaultToolMetadata.java => arconia-ai-tools/src/main/java/io/arconia/ai/tools/definition/DefaultToolDefinition.java} (50%) create mode 100644 arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/definition/ToolDefinition.java create mode 100644 arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/definition/package-info.java create mode 100644 arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/execution/ToolExecutionMode.java rename arconia-ai/{arconia-ai-core/src/main/java/io/arconia/ai/core => arconia-ai-tools/src/main/java/io/arconia/ai}/tools/json/JsonParser.java (91%) rename arconia-ai/{arconia-ai-core/src/main/java/io/arconia/ai/core => arconia-ai-tools/src/main/java/io/arconia/ai}/tools/json/JsonSchemaGenerator.java (80%) rename arconia-ai/{arconia-ai-core/src/main/java/io/arconia/ai/core => arconia-ai-tools/src/main/java/io/arconia/ai}/tools/json/package-info.java (75%) create mode 100644 arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/metadata/DefaultToolMetadata.java rename arconia-ai/{arconia-ai-core/src/main/java/io/arconia/ai/core => arconia-ai-tools/src/main/java/io/arconia/ai}/tools/metadata/ToolMetadata.java (50%) create mode 100644 arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/metadata/package-info.java rename arconia-ai/{arconia-ai-core/src/main/java/io/arconia/ai/core => arconia-ai-tools/src/main/java/io/arconia/ai}/tools/method/MethodToolCallback.java (84%) rename arconia-ai/{arconia-ai-core/src/main/java/io/arconia/ai/core => arconia-ai-tools/src/main/java/io/arconia/ai}/tools/method/MethodToolCallbackProvider.java (79%) create mode 100644 arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/method/package-info.java rename arconia-ai/{arconia-ai-core/src/main/java/io/arconia/ai/core => arconia-ai-tools/src/main/java/io/arconia/ai/tools}/package-info.java (80%) rename arconia-ai/{arconia-ai-core/src/main/java/io/arconia/ai/core => arconia-ai-tools/src/main/java/io/arconia/ai}/tools/util/ToolUtils.java (52%) create mode 100644 arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/util/package-info.java rename arconia-ai/{arconia-ai-core => arconia-ai-tools}/src/test/java/io/arconia/ai/core/tools/ToolUtilsTests.java (80%) rename arconia-ai/{arconia-ai-core => arconia-ai-tools}/src/test/java/io/arconia/ai/core/tools/json/JsonSchemaGeneratorTests.java (96%) rename arconia-ai/{arconia-ai-core => arconia-ai-tools}/src/test/java/io/arconia/ai/core/tools/method/MethodToolCallbackProviderTests.java (95%) rename arconia-ai/{arconia-ai-core => arconia-ai-tools}/src/test/java/io/arconia/ai/core/tools/method/MethodToolCallbackTests.java (94%) diff --git a/arconia-ai/arconia-ai-client/build.gradle b/arconia-ai/arconia-ai-client/build.gradle new file mode 100644 index 0000000..aca3a43 --- /dev/null +++ b/arconia-ai/arconia-ai-client/build.gradle @@ -0,0 +1,33 @@ +plugins { + id 'code-quality-conventions' + id 'java-conventions' + id 'sbom-conventions' + id 'release-conventions' +} + +repositories { + maven { url 'https://repo.spring.io/milestone' } +} + +dependencies { + implementation project(":arconia-ai:arconia-ai-tools") + + implementation "org.slf4j:slf4j-api" + implementation "org.springframework:spring-context" + + compileOnly "org.springframework.ai:spring-ai-core:${springAiVersion}" + + testImplementation "org.springframework.boot:spring-boot-starter-test" + testImplementation "org.springframework.ai:spring-ai-core:${springAiVersion}" +} + +publishing { + publications { + mavenJava(MavenPublication) { + pom { + name = "Arconia AI Client" + description = "Arconia AI Client." + } + } + } +} diff --git a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/client/ArconiaChatClient.java b/arconia-ai/arconia-ai-client/src/main/java/io/arconia/ai/client/ArconiaChatClient.java similarity index 98% rename from arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/client/ArconiaChatClient.java rename to arconia-ai/arconia-ai-client/src/main/java/io/arconia/ai/client/ArconiaChatClient.java index b92ecb0..2f6fba9 100644 --- a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/client/ArconiaChatClient.java +++ b/arconia-ai/arconia-ai-client/src/main/java/io/arconia/ai/client/ArconiaChatClient.java @@ -1,4 +1,4 @@ -package io.arconia.ai.core.client; +package io.arconia.ai.client; import java.nio.charset.Charset; import java.util.List; @@ -22,7 +22,7 @@ import org.springframework.lang.Nullable; import org.springframework.util.Assert; -import io.arconia.ai.core.tools.ToolCallback; +import io.arconia.ai.tools.ToolCallback; /** * A {@link ChatClient} enhanced for more advanced features. diff --git a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/client/DefaultArconiaChatClient.java b/arconia-ai/arconia-ai-client/src/main/java/io/arconia/ai/client/DefaultArconiaChatClient.java similarity index 99% rename from arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/client/DefaultArconiaChatClient.java rename to arconia-ai/arconia-ai-client/src/main/java/io/arconia/ai/client/DefaultArconiaChatClient.java index d8c7044..952eea4 100644 --- a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/client/DefaultArconiaChatClient.java +++ b/arconia-ai/arconia-ai-client/src/main/java/io/arconia/ai/client/DefaultArconiaChatClient.java @@ -1,4 +1,4 @@ -package io.arconia.ai.core.client; +package io.arconia.ai.client; import java.io.IOException; import java.net.URL; @@ -33,10 +33,10 @@ import org.springframework.util.MimeType; import org.springframework.util.StringUtils; -import io.arconia.ai.core.client.advisor.CallAdvisor; -import io.arconia.ai.core.client.advisor.StreamAdvisor; -import io.arconia.ai.core.tools.ToolCallback; -import io.arconia.ai.core.tools.ToolCallbacks; +import io.arconia.ai.client.advisor.CallAdvisor; +import io.arconia.ai.client.advisor.StreamAdvisor; +import io.arconia.ai.tools.ToolCallback; +import io.arconia.ai.tools.ToolCallbacks; /** * Default implementation of {@link ArconiaChatClient} based on {@link DefaultChatClient}. diff --git a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/client/DefaultArconiaChatClientBuilder.java b/arconia-ai/arconia-ai-client/src/main/java/io/arconia/ai/client/DefaultArconiaChatClientBuilder.java similarity index 96% rename from arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/client/DefaultArconiaChatClientBuilder.java rename to arconia-ai/arconia-ai-client/src/main/java/io/arconia/ai/client/DefaultArconiaChatClientBuilder.java index e326f07..c305617 100644 --- a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/client/DefaultArconiaChatClientBuilder.java +++ b/arconia-ai/arconia-ai-client/src/main/java/io/arconia/ai/client/DefaultArconiaChatClientBuilder.java @@ -1,4 +1,4 @@ -package io.arconia.ai.core.client; +package io.arconia.ai.client; import java.io.IOException; import java.nio.charset.Charset; @@ -21,9 +21,9 @@ import org.springframework.lang.Nullable; import org.springframework.util.Assert; -import io.arconia.ai.core.client.DefaultArconiaChatClient.DefaultArconiaChatClientRequestSpec; -import io.arconia.ai.core.tools.ToolCallback; -import io.arconia.ai.core.tools.ToolCallbacks; +import io.arconia.ai.client.DefaultArconiaChatClient.DefaultArconiaChatClientRequestSpec; +import io.arconia.ai.tools.ToolCallback; +import io.arconia.ai.tools.ToolCallbacks; /** * Default implementation of {@link ArconiaChatClient.ArconiaBuilder} diff --git a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/client/advisor/CallAdvisor.java b/arconia-ai/arconia-ai-client/src/main/java/io/arconia/ai/client/advisor/CallAdvisor.java similarity index 96% rename from arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/client/advisor/CallAdvisor.java rename to arconia-ai/arconia-ai-client/src/main/java/io/arconia/ai/client/advisor/CallAdvisor.java index 3e2fdb2..122b7a4 100644 --- a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/client/advisor/CallAdvisor.java +++ b/arconia-ai/arconia-ai-client/src/main/java/io/arconia/ai/client/advisor/CallAdvisor.java @@ -1,4 +1,4 @@ -package io.arconia.ai.core.client.advisor; +package io.arconia.ai.client.advisor; import java.util.Map; diff --git a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/client/advisor/StreamAdvisor.java b/arconia-ai/arconia-ai-client/src/main/java/io/arconia/ai/client/advisor/StreamAdvisor.java similarity index 96% rename from arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/client/advisor/StreamAdvisor.java rename to arconia-ai/arconia-ai-client/src/main/java/io/arconia/ai/client/advisor/StreamAdvisor.java index 5d2c2b3..5eaad0e 100644 --- a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/client/advisor/StreamAdvisor.java +++ b/arconia-ai/arconia-ai-client/src/main/java/io/arconia/ai/client/advisor/StreamAdvisor.java @@ -1,4 +1,4 @@ -package io.arconia.ai.core.client.advisor; +package io.arconia.ai.client.advisor; import java.util.Map; diff --git a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/aot/package-info.java b/arconia-ai/arconia-ai-client/src/main/java/io/arconia/ai/client/advisor/package-info.java similarity index 75% rename from arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/aot/package-info.java rename to arconia-ai/arconia-ai-client/src/main/java/io/arconia/ai/client/advisor/package-info.java index 1b9d9ad..6f575fb 100644 --- a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/aot/package-info.java +++ b/arconia-ai/arconia-ai-client/src/main/java/io/arconia/ai/client/advisor/package-info.java @@ -1,6 +1,6 @@ @NonNullApi @NonNullFields -package io.arconia.ai.core.tools.aot; +package io.arconia.ai.client.advisor; import org.springframework.lang.NonNullApi; import org.springframework.lang.NonNullFields; diff --git a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/client/package-info.java b/arconia-ai/arconia-ai-client/src/main/java/io/arconia/ai/client/package-info.java similarity index 77% rename from arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/client/package-info.java rename to arconia-ai/arconia-ai-client/src/main/java/io/arconia/ai/client/package-info.java index b378504..92397c4 100644 --- a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/client/package-info.java +++ b/arconia-ai/arconia-ai-client/src/main/java/io/arconia/ai/client/package-info.java @@ -1,6 +1,6 @@ @NonNullApi @NonNullFields -package io.arconia.ai.core.client; +package io.arconia.ai.client; import org.springframework.lang.NonNullApi; import org.springframework.lang.NonNullFields; diff --git a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/client/advisor/package-info.java b/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/client/advisor/package-info.java deleted file mode 100644 index 9e9034c..0000000 --- a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/client/advisor/package-info.java +++ /dev/null @@ -1,6 +0,0 @@ -@NonNullApi -@NonNullFields -package io.arconia.ai.core.client.advisor; - -import org.springframework.lang.NonNullApi; -import org.springframework.lang.NonNullFields; diff --git a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/ToolCallback.java b/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/ToolCallback.java deleted file mode 100644 index 704f6e0..0000000 --- a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/ToolCallback.java +++ /dev/null @@ -1,32 +0,0 @@ -package io.arconia.ai.core.tools; - -import org.springframework.ai.model.function.FunctionCallback; - -import io.arconia.ai.core.tools.metadata.ToolMetadata; - -/** - * Specialization of {@link FunctionCallback} to identify tools in Spring AI. - */ -public interface ToolCallback extends FunctionCallback { - - /** - * Metadata for the tool. - */ - ToolMetadata getToolMetadata(); - - @Override - default String getName() { - return getToolMetadata().name(); - } - - @Override - default String getDescription() { - return getToolMetadata().description(); - } - - @Override - default String getInputTypeSchema() { - return getToolMetadata().inputTypeSchema(); - } - -} diff --git a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/annotation/package-info.java b/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/annotation/package-info.java deleted file mode 100644 index 0809d85..0000000 --- a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/annotation/package-info.java +++ /dev/null @@ -1,6 +0,0 @@ -@NonNullApi -@NonNullFields -package io.arconia.ai.core.tools.annotation; - -import org.springframework.lang.NonNullApi; -import org.springframework.lang.NonNullFields; diff --git a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/aot/JacksonJsonSchemaRuntimeHints.java b/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/aot/JacksonJsonSchemaRuntimeHints.java deleted file mode 100644 index fc4ded5..0000000 --- a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/aot/JacksonJsonSchemaRuntimeHints.java +++ /dev/null @@ -1,21 +0,0 @@ -package io.arconia.ai.core.tools.aot; - -import com.fasterxml.jackson.module.jsonSchema.JsonSchemaIdResolver; -import org.springframework.aot.hint.MemberCategory; -import org.springframework.aot.hint.RuntimeHints; -import org.springframework.aot.hint.RuntimeHintsRegistrar; -import org.springframework.lang.NonNull; -import org.springframework.lang.Nullable; - -/** - * Registers runtime hints for Jackson JSON Schema classes. - */ -public class JacksonJsonSchemaRuntimeHints implements RuntimeHintsRegistrar { - - @Override - public void registerHints(@NonNull RuntimeHints hints, @Nullable ClassLoader classLoader) { - var mcs = MemberCategory.values(); - hints.reflection().registerType(JsonSchemaIdResolver.class, mcs); - } - -} diff --git a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/metadata/package-info.java b/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/metadata/package-info.java deleted file mode 100644 index 5ee210b..0000000 --- a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/metadata/package-info.java +++ /dev/null @@ -1,6 +0,0 @@ -@NonNullApi -@NonNullFields -package io.arconia.ai.core.tools.metadata; - -import org.springframework.lang.NonNullApi; -import org.springframework.lang.NonNullFields; diff --git a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/method/package-info.java b/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/method/package-info.java deleted file mode 100644 index ceaa72c..0000000 --- a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/method/package-info.java +++ /dev/null @@ -1,6 +0,0 @@ -@NonNullApi -@NonNullFields -package io.arconia.ai.core.tools.method; - -import org.springframework.lang.NonNullApi; -import org.springframework.lang.NonNullFields; diff --git a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/util/package-info.java b/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/util/package-info.java deleted file mode 100644 index bf41e91..0000000 --- a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/util/package-info.java +++ /dev/null @@ -1,6 +0,0 @@ -@NonNullApi -@NonNullFields -package io.arconia.ai.core.tools.util; - -import org.springframework.lang.NonNullApi; -import org.springframework.lang.NonNullFields; diff --git a/arconia-ai/arconia-ai-core/src/main/resources/META-INF/spring/aot.factories b/arconia-ai/arconia-ai-core/src/main/resources/META-INF/spring/aot.factories deleted file mode 100644 index ff7ecd9..0000000 --- a/arconia-ai/arconia-ai-core/src/main/resources/META-INF/spring/aot.factories +++ /dev/null @@ -1,2 +0,0 @@ -org.springframework.aot.hint.RuntimeHintsRegistrar=\ - io.arconia.ai.core.tools.aot.JacksonJsonSchemaRuntimeHints diff --git a/arconia-ai/arconia-ai-core/src/test/java/io/arconia/ai/core/tools/aot/JacksonJsonSchemaRuntimeHintsTests.java b/arconia-ai/arconia-ai-core/src/test/java/io/arconia/ai/core/tools/aot/JacksonJsonSchemaRuntimeHintsTests.java deleted file mode 100644 index 7e5fed3..0000000 --- a/arconia-ai/arconia-ai-core/src/test/java/io/arconia/ai/core/tools/aot/JacksonJsonSchemaRuntimeHintsTests.java +++ /dev/null @@ -1,25 +0,0 @@ -package io.arconia.ai.core.tools.aot; - -import com.fasterxml.jackson.module.jsonSchema.JsonSchemaIdResolver; - -import org.junit.jupiter.api.Test; -import org.springframework.aot.hint.RuntimeHints; - -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; -import static org.springframework.aot.hint.predicate.RuntimeHintsPredicates.reflection; - -/** - * Unit tests for {@link JacksonJsonSchemaRuntimeHints}. - */ -class JacksonJsonSchemaRuntimeHintsTests { - - @Test - void registerHints() { - RuntimeHints runtimeHints = new RuntimeHints(); - JacksonJsonSchemaRuntimeHints jacksonJsonSchemaRuntimeHints = new JacksonJsonSchemaRuntimeHints(); - jacksonJsonSchemaRuntimeHints.registerHints(runtimeHints, null); - - assertThat(runtimeHints).matches(reflection().onType(JsonSchemaIdResolver.class)); - } - -} diff --git a/arconia-ai/arconia-ai-mcp/build.gradle b/arconia-ai/arconia-ai-mcp/build.gradle index dfb3c02..a709b25 100644 --- a/arconia-ai/arconia-ai-mcp/build.gradle +++ b/arconia-ai/arconia-ai-mcp/build.gradle @@ -10,7 +10,7 @@ repositories { } dependencies { - implementation project(":arconia-ai:arconia-ai-core") + implementation project(":arconia-ai:arconia-ai-tools") implementation "org.slf4j:slf4j-api" implementation "org.springframework:spring-context" diff --git a/arconia-ai/arconia-ai-mcp/src/main/java/io/arconia/ai/mcp/tools/McpToolCallback.java b/arconia-ai/arconia-ai-mcp/src/main/java/io/arconia/ai/mcp/tools/McpToolCallback.java index b8753f3..2f177f1 100644 --- a/arconia-ai/arconia-ai-mcp/src/main/java/io/arconia/ai/mcp/tools/McpToolCallback.java +++ b/arconia-ai/arconia-ai-mcp/src/main/java/io/arconia/ai/mcp/tools/McpToolCallback.java @@ -1,45 +1,84 @@ package io.arconia.ai.mcp.tools; import java.util.Map; +import java.util.function.Function; import com.fasterxml.jackson.core.type.TypeReference; import org.springframework.ai.mcp.client.McpSyncClient; import org.springframework.ai.mcp.spec.McpSchema; import org.springframework.ai.model.ModelOptionsUtils; +import org.springframework.lang.Nullable; -import io.arconia.ai.core.tools.ToolCallback; -import io.arconia.ai.core.tools.json.JsonParser; -import io.arconia.ai.core.tools.metadata.DefaultToolMetadata; -import io.arconia.ai.core.tools.metadata.ToolMetadata; +import io.arconia.ai.tools.ToolCallback; +import io.arconia.ai.tools.definition.ToolDefinition; +import io.arconia.ai.tools.json.JsonParser; /** * A {@link ToolCallback} for handling calls to MCP tools. */ public class McpToolCallback implements ToolCallback { - private final ToolMetadata toolMetadata; + private static final Function> DEFAULT_TOOL_INPUT_PARSER = + toolInput -> JsonParser.fromJson(toolInput, new TypeReference<>() {}); + + private final ToolDefinition toolDefinition; private final McpSyncClient mcpClient; + private final Function> toolInputParser; - public McpToolCallback(McpSchema.Tool tool, McpSyncClient mcpClient) { - this.toolMetadata = DefaultToolMetadata.builder() + public McpToolCallback(McpSchema.Tool tool, McpSyncClient mcpClient, @Nullable Function> toolInputParser) { + this.toolDefinition = ToolDefinition.builder() .name(tool.name()) .description(tool.description()) .inputTypeSchema(JsonParser.toJson(tool.inputSchema())) .build(); this.mcpClient = mcpClient; + this.toolInputParser = toolInputParser != null ? toolInputParser : DEFAULT_TOOL_INPUT_PARSER; } @Override - public ToolMetadata getToolMetadata() { - return this.toolMetadata; + public ToolDefinition getToolDefinition() { + return toolDefinition; } @Override public String call(String toolInput) { - Map arguments = JsonParser.fromJson(toolInput, new TypeReference<>() {}); + Map arguments = toolInputParser.apply(toolInput); McpSchema.CallToolResult response = this.mcpClient.callTool(new McpSchema.CallToolRequest(this.getName(), arguments)); return ModelOptionsUtils.toJsonString(response.content()); } + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + + private McpSchema.Tool tool; + private McpSyncClient mcpClient; + private Function> toolInputParser; + + private Builder() {} + + public Builder tool(McpSchema.Tool tool) { + this.tool = tool; + return this; + } + + public Builder mcpClient(McpSyncClient mcpClient) { + this.mcpClient = mcpClient; + return this; + } + + public Builder toolInputParser(Function> toolInputParser) { + this.toolInputParser = toolInputParser; + return this; + } + + public McpToolCallback build() { + return new McpToolCallback(tool, mcpClient, toolInputParser); + } + + } + } diff --git a/arconia-ai/arconia-ai-mcp/src/main/java/io/arconia/ai/mcp/tools/McpToolCallbackProvider.java b/arconia-ai/arconia-ai-mcp/src/main/java/io/arconia/ai/mcp/tools/McpToolCallbackProvider.java index 870abcb..87f8c9f 100644 --- a/arconia-ai/arconia-ai-mcp/src/main/java/io/arconia/ai/mcp/tools/McpToolCallbackProvider.java +++ b/arconia-ai/arconia-ai-mcp/src/main/java/io/arconia/ai/mcp/tools/McpToolCallbackProvider.java @@ -8,9 +8,9 @@ import org.springframework.ai.mcp.client.McpSyncClient; import org.springframework.util.Assert; -import io.arconia.ai.core.tools.ToolCallback; -import io.arconia.ai.core.tools.ToolCallbackProvider; -import io.arconia.ai.core.tools.util.ToolUtils; +import io.arconia.ai.tools.ToolCallback; +import io.arconia.ai.tools.ToolCallbackProvider; +import io.arconia.ai.tools.util.ToolUtils; /** * A {@link ToolCallbackProvider} that builds {@link ToolCallback} instances from MCP @@ -32,7 +32,10 @@ public ToolCallback[] getToolCallbacks() { .flatMap(mcpClient -> mcpClient.listTools() .tools() .stream() - .map(tool -> new McpToolCallback(tool, mcpClient))) + .map(tool -> McpToolCallback.builder() + .tool(tool) + .mcpClient(mcpClient) + .build())) .toArray(ToolCallback[]::new); validateToolCallbacks(toolCallbacks); diff --git a/arconia-ai/arconia-ai-mcp/src/main/java/io/arconia/ai/mcp/tools/McpToolCallbacks.java b/arconia-ai/arconia-ai-mcp/src/main/java/io/arconia/ai/mcp/tools/McpToolCallbacks.java index e0e2bfd..74ae8ca 100644 --- a/arconia-ai/arconia-ai-mcp/src/main/java/io/arconia/ai/mcp/tools/McpToolCallbacks.java +++ b/arconia-ai/arconia-ai-mcp/src/main/java/io/arconia/ai/mcp/tools/McpToolCallbacks.java @@ -2,9 +2,8 @@ import org.springframework.ai.mcp.client.McpAsyncClient; import org.springframework.ai.mcp.client.McpSyncClient; -import org.springframework.ai.model.function.FunctionCallback; -import io.arconia.ai.core.tools.ToolCallback; +import io.arconia.ai.tools.ToolCallback; /** * Provides {@link ToolCallback} instances for tools defined in different sources. diff --git a/arconia-ai/arconia-ai-spring-boot-starters/arconia-ai-spring-boot-starter/build.gradle b/arconia-ai/arconia-ai-spring-boot-starters/arconia-ai-spring-boot-starter/build.gradle index c5d0811..e9c9efd 100644 --- a/arconia-ai/arconia-ai-spring-boot-starters/arconia-ai-spring-boot-starter/build.gradle +++ b/arconia-ai/arconia-ai-spring-boot-starters/arconia-ai-spring-boot-starter/build.gradle @@ -13,7 +13,8 @@ dependencies { annotationProcessor 'org.springframework.boot:spring-boot-autoconfigure-processor' annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor' - api project(":arconia-ai:arconia-ai-core") + api project(":arconia-ai:arconia-ai-client") + api project(":arconia-ai:arconia-ai-tools") implementation "org.slf4j:slf4j-api" implementation "org.springframework.boot:spring-boot-starter" diff --git a/arconia-ai/arconia-ai-spring-boot-starters/arconia-ai-spring-boot-starter/src/main/java/io/arconia/ai/autoconfigure/core/client/ArconiaChatClientAutoConfiguration.java b/arconia-ai/arconia-ai-spring-boot-starters/arconia-ai-spring-boot-starter/src/main/java/io/arconia/ai/autoconfigure/core/client/ArconiaChatClientAutoConfiguration.java index 9eafb73..a8e4caf 100644 --- a/arconia-ai/arconia-ai-spring-boot-starters/arconia-ai-spring-boot-starter/src/main/java/io/arconia/ai/autoconfigure/core/client/ArconiaChatClientAutoConfiguration.java +++ b/arconia-ai/arconia-ai-spring-boot-starters/arconia-ai-spring-boot-starter/src/main/java/io/arconia/ai/autoconfigure/core/client/ArconiaChatClientAutoConfiguration.java @@ -12,7 +12,7 @@ import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Scope; -import io.arconia.ai.core.client.ArconiaChatClient; +import io.arconia.ai.client.ArconiaChatClient; @AutoConfiguration public class ArconiaChatClientAutoConfiguration { diff --git a/arconia-ai/arconia-ai-spring-boot-starters/arconia-ai-spring-boot-starter/src/test/java/io/arconia/ai/autoconfigure/core/tools/TestTools.java b/arconia-ai/arconia-ai-spring-boot-starters/arconia-ai-spring-boot-starter/src/test/java/io/arconia/ai/autoconfigure/core/tools/TestTools.java index 26b194d..4599bf5 100644 --- a/arconia-ai/arconia-ai-spring-boot-starters/arconia-ai-spring-boot-starter/src/test/java/io/arconia/ai/autoconfigure/core/tools/TestTools.java +++ b/arconia-ai/arconia-ai-spring-boot-starters/arconia-ai-spring-boot-starter/src/test/java/io/arconia/ai/autoconfigure/core/tools/TestTools.java @@ -4,7 +4,7 @@ import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; -import io.arconia.ai.core.tools.annotation.Tool; +import io.arconia.ai.tools.annotation.Tool; @Component public class TestTools { diff --git a/arconia-ai/arconia-ai-core/build.gradle b/arconia-ai/arconia-ai-tools/build.gradle similarity index 87% rename from arconia-ai/arconia-ai-core/build.gradle rename to arconia-ai/arconia-ai-tools/build.gradle index f4e12e3..70145c7 100644 --- a/arconia-ai/arconia-ai-core/build.gradle +++ b/arconia-ai/arconia-ai-tools/build.gradle @@ -23,8 +23,8 @@ publishing { publications { mavenJava(MavenPublication) { pom { - name = "Arconia AI Core" - description = "Arconia AI Core." + name = "Arconia AI Tools" + description = "Arconia AI Tools." } } } diff --git a/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/ToolCallback.java b/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/ToolCallback.java new file mode 100644 index 0000000..e50479a --- /dev/null +++ b/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/ToolCallback.java @@ -0,0 +1,40 @@ +package io.arconia.ai.tools; + +import org.springframework.ai.model.function.FunctionCallback; + +import io.arconia.ai.tools.definition.ToolDefinition; +import io.arconia.ai.tools.metadata.ToolMetadata; + +/** + * Specialization of {@link FunctionCallback} to identify tools in Spring AI. + */ +public interface ToolCallback extends FunctionCallback { + + /** + * Definition of the tool. + */ + ToolDefinition getToolDefinition(); + + /** + * Metadata for the tool. + */ + default ToolMetadata getToolMetadata() { + return ToolMetadata.builder().build(); + } + + @Override + default String getName() { + return getToolDefinition().name(); + } + + @Override + default String getDescription() { + return getToolDefinition().description(); + } + + @Override + default String getInputTypeSchema() { + return getToolDefinition().inputTypeSchema(); + } + +} diff --git a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/ToolCallbackProvider.java b/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/ToolCallbackProvider.java similarity index 83% rename from arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/ToolCallbackProvider.java rename to arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/ToolCallbackProvider.java index a4af604..99d4db7 100644 --- a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/ToolCallbackProvider.java +++ b/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/ToolCallbackProvider.java @@ -1,4 +1,4 @@ -package io.arconia.ai.core.tools; +package io.arconia.ai.tools; /** * Provides {@link ToolCallback} instances for tools defined in different sources. diff --git a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/ToolCallbacks.java b/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/ToolCallbacks.java similarity index 76% rename from arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/ToolCallbacks.java rename to arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/ToolCallbacks.java index 41142ca..361ab85 100644 --- a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/ToolCallbacks.java +++ b/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/ToolCallbacks.java @@ -1,6 +1,6 @@ -package io.arconia.ai.core.tools; +package io.arconia.ai.tools; -import io.arconia.ai.core.tools.method.MethodToolCallbackProvider; +import io.arconia.ai.tools.method.MethodToolCallbackProvider; /** * Provides {@link ToolCallback} instances for tools defined in different sources. diff --git a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/annotation/Tool.java b/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/annotation/Tool.java similarity index 64% rename from arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/annotation/Tool.java rename to arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/annotation/Tool.java index 579c4a9..1cc726e 100644 --- a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/annotation/Tool.java +++ b/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/annotation/Tool.java @@ -1,4 +1,4 @@ -package io.arconia.ai.core.tools.annotation; +package io.arconia.ai.tools.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; @@ -6,7 +6,7 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.springframework.ai.model.function.FunctionCallback; +import io.arconia.ai.tools.execution.ToolExecutionMode; /** * Marks a method as a tool in Spring AI. @@ -27,9 +27,13 @@ String value() default ""; /** - * The schema type of the tool. JSON Schema will work for most cases. - * Vertex AI requires OpenAPI Schema. + * How the tool should be executed. */ - FunctionCallback.SchemaType schemaType() default FunctionCallback.SchemaType.JSON_SCHEMA; + ToolExecutionMode executionMode() default ToolExecutionMode.BLOCKING; + + /** + * Whether the tool result should be returned directly or passed back to the model. + */ + boolean returnDirect() default false; } diff --git a/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/annotation/package-info.java b/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/annotation/package-info.java new file mode 100644 index 0000000..8cc66d2 --- /dev/null +++ b/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/annotation/package-info.java @@ -0,0 +1,6 @@ +@NonNullApi +@NonNullFields +package io.arconia.ai.tools.annotation; + +import org.springframework.lang.NonNullApi; +import org.springframework.lang.NonNullFields; diff --git a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/metadata/DefaultToolMetadata.java b/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/definition/DefaultToolDefinition.java similarity index 50% rename from arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/metadata/DefaultToolMetadata.java rename to arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/definition/DefaultToolDefinition.java index 5acf873..416fa7e 100644 --- a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/metadata/DefaultToolMetadata.java +++ b/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/definition/DefaultToolDefinition.java @@ -1,28 +1,27 @@ -package io.arconia.ai.core.tools.metadata; +package io.arconia.ai.tools.definition; import java.lang.reflect.Method; import org.springframework.util.Assert; -import io.arconia.ai.core.tools.annotation.Tool; -import io.arconia.ai.core.tools.json.JsonSchemaGenerator; -import io.arconia.ai.core.tools.util.ToolUtils; +import io.arconia.ai.tools.json.JsonSchemaGenerator; +import io.arconia.ai.tools.util.ToolUtils; /** - * Default implementation of {@link ToolMetadata}. + * Default implementation of {@link ToolDefinition}. */ -public record DefaultToolMetadata(String name, String description, String inputTypeSchema, boolean returnDirect) implements ToolMetadata { +public record DefaultToolDefinition(String name, String description, String inputTypeSchema) implements ToolDefinition { - public DefaultToolMetadata { + public DefaultToolDefinition { Assert.hasText(name, "name cannot be null"); Assert.hasText(description, "description cannot be null"); Assert.hasText(inputTypeSchema, "inputTypeSchema cannot be null"); } - static DefaultToolMetadata from(Method method) { - return DefaultToolMetadata.builder() - .name(ToolUtils.getToolName(method.getAnnotation(Tool.class), method.getName())) - .description(ToolUtils.getToolDescription(method.getAnnotation(Tool.class), method.getName())) + static DefaultToolDefinition from(Method method) { + return DefaultToolDefinition.builder() + .name(ToolUtils.getToolName(method)) + .description(ToolUtils.getToolDescription(method)) .inputTypeSchema(JsonSchemaGenerator.generate(method)) .build(); } @@ -39,8 +38,6 @@ public static class Builder { private String inputTypeSchema; - private boolean returnDirect; - private Builder() {} public Builder name(String name) { @@ -58,13 +55,8 @@ public Builder inputTypeSchema(String inputTypeSchema) { return this; } - public Builder returnDirect(boolean returnDirect) { - this.returnDirect = returnDirect; - return this; - } - - public DefaultToolMetadata build() { - return new DefaultToolMetadata(name, description, inputTypeSchema, returnDirect); + public DefaultToolDefinition build() { + return new DefaultToolDefinition(name, description, inputTypeSchema); } } diff --git a/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/definition/ToolDefinition.java b/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/definition/ToolDefinition.java new file mode 100644 index 0000000..8faf302 --- /dev/null +++ b/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/definition/ToolDefinition.java @@ -0,0 +1,39 @@ +package io.arconia.ai.tools.definition; + +import java.lang.reflect.Method; + +/** + * Definition of a tool that can be used by a model. + */ +public interface ToolDefinition { + + /** + * The tool name. Unique within the tool set provided to a model. + */ + String name(); + + /** + * The tool description, used by the model to decide if and when to use the tool. + */ + String description(); + + /** + * The JSON Schema of the parameters used to call the tool. + */ + String inputTypeSchema(); + + /** + * Create a default {@link ToolDefinition} builder. + */ + static DefaultToolDefinition.Builder builder() { + return DefaultToolDefinition.builder(); + } + + /** + * Create {@link ToolDefinition} from a {@link Method}. + */ + static ToolDefinition from(Method method) { + return DefaultToolDefinition.from(method); + } + +} diff --git a/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/definition/package-info.java b/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/definition/package-info.java new file mode 100644 index 0000000..0b663f9 --- /dev/null +++ b/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/definition/package-info.java @@ -0,0 +1,6 @@ +@NonNullApi +@NonNullFields +package io.arconia.ai.tools.definition; + +import org.springframework.lang.NonNullApi; +import org.springframework.lang.NonNullFields; diff --git a/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/execution/ToolExecutionMode.java b/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/execution/ToolExecutionMode.java new file mode 100644 index 0000000..5e50fc6 --- /dev/null +++ b/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/execution/ToolExecutionMode.java @@ -0,0 +1,8 @@ +package io.arconia.ai.tools.execution; + +/** + * How the tool should be executed. + */ +public enum ToolExecutionMode { + BLOCKING +} diff --git a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/json/JsonParser.java b/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/json/JsonParser.java similarity index 91% rename from arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/json/JsonParser.java rename to arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/json/JsonParser.java index 0a6faca..8e7d793 100644 --- a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/json/JsonParser.java +++ b/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/json/JsonParser.java @@ -1,4 +1,4 @@ -package io.arconia.ai.core.tools.json; +package io.arconia.ai.tools.json; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; @@ -23,12 +23,18 @@ public class JsonParser { .addModules(JacksonUtils.instantiateAvailableModules()) .build(); + public static ObjectMapper getObjectMapper() { + return OBJECT_MAPPER; + } + public static T fromJson(String json, TypeReference type) { + Assert.notNull(json, "json cannot be null"); + Assert.notNull(type, "type cannot be null"); + try { return OBJECT_MAPPER.readValue(json, type); } catch (JsonProcessingException ex) { - throw new IllegalStateException("Conversion from JSON to %s failed".formatted(type.getType().getTypeName()), - ex); + throw new IllegalStateException("Conversion from JSON to %s failed".formatted(type.getType().getTypeName()), ex); } } diff --git a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/json/JsonSchemaGenerator.java b/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/json/JsonSchemaGenerator.java similarity index 80% rename from arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/json/JsonSchemaGenerator.java rename to arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/json/JsonSchemaGenerator.java index ad71d33..20ec6fb 100644 --- a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/json/JsonSchemaGenerator.java +++ b/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/json/JsonSchemaGenerator.java @@ -1,14 +1,10 @@ -package io.arconia.ai.core.tools.json; +package io.arconia.ai.tools.json; import java.lang.reflect.Method; import java.lang.reflect.Parameter; import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Stream; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature; -import com.fasterxml.jackson.databind.json.JsonMapper; import com.fasterxml.jackson.databind.node.ObjectNode; import com.github.victools.jsonschema.generator.Option; import com.github.victools.jsonschema.generator.OptionPreset; @@ -20,25 +16,17 @@ import com.github.victools.jsonschema.module.jackson.JacksonOption; import com.github.victools.jsonschema.module.swagger2.Swagger2Module; -import org.springframework.ai.util.JacksonUtils; - /** * Utilities to generate JSON Schemas from Java entities. */ public class JsonSchemaGenerator { - private static final ObjectMapper OBJECT_MAPPER = JsonMapper.builder() - .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) - .disable(SerializationFeature.FAIL_ON_EMPTY_BEANS) - .addModules(JacksonUtils.instantiateAvailableModules()) - .build(); - private static final AtomicReference SCHEMA_GENERATOR = new AtomicReference<>(); public static String generate(Method method) { var generator = buildSchemaGenerator(); - ObjectNode schema = OBJECT_MAPPER.createObjectNode(); + ObjectNode schema = JsonParser.getObjectMapper().createObjectNode(); schema.put("$schema", SchemaVersion.DRAFT_2020_12.getIdentifier()); // Option.SCHEMA_VERSION_INDICATOR schema.put("type", "object"); @@ -67,7 +55,7 @@ private static SchemaGenerator buildSchemaGenerator() { JacksonModule jacksonModule = new JacksonModule(JacksonOption.RESPECT_JSONPROPERTY_REQUIRED); Swagger2Module swaggerModule = new Swagger2Module(); - SchemaGeneratorConfig schemaGeneratorConfig = new SchemaGeneratorConfigBuilder(OBJECT_MAPPER, + SchemaGeneratorConfig schemaGeneratorConfig = new SchemaGeneratorConfigBuilder(JsonParser.getObjectMapper(), SchemaVersion.DRAFT_2020_12, OptionPreset.PLAIN_JSON) .with(jacksonModule) .with(swaggerModule) diff --git a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/json/package-info.java b/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/json/package-info.java similarity index 75% rename from arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/json/package-info.java rename to arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/json/package-info.java index cbed002..f3246cc 100644 --- a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/json/package-info.java +++ b/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/json/package-info.java @@ -1,6 +1,6 @@ @NonNullApi @NonNullFields -package io.arconia.ai.core.tools.json; +package io.arconia.ai.tools.json; import org.springframework.lang.NonNullApi; import org.springframework.lang.NonNullFields; diff --git a/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/metadata/DefaultToolMetadata.java b/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/metadata/DefaultToolMetadata.java new file mode 100644 index 0000000..e8a8357 --- /dev/null +++ b/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/metadata/DefaultToolMetadata.java @@ -0,0 +1,48 @@ +package io.arconia.ai.tools.metadata; + +import java.lang.reflect.Method; + +import io.arconia.ai.tools.execution.ToolExecutionMode; +import io.arconia.ai.tools.util.ToolUtils; + +/** + * Default implementation of {@link ToolMetadata}. + */ +public record DefaultToolMetadata(ToolExecutionMode executionMode, boolean returnDirect) implements ToolMetadata { + + static DefaultToolMetadata from(Method method) { + return DefaultToolMetadata.builder() + .executionMode(ToolUtils.getToolExecutionMode(method)) + .returnDirect(ToolUtils.getToolReturnDirect(method)) + .build(); + } + + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + + private ToolExecutionMode executionMode = ToolExecutionMode.BLOCKING; + + private boolean returnDirect = false; + + private Builder() {} + + public Builder executionMode(ToolExecutionMode executionMode) { + this.executionMode = executionMode; + return this; + } + + public Builder returnDirect(boolean returnDirect) { + this.returnDirect = returnDirect; + return this; + } + + public DefaultToolMetadata build() { + return new DefaultToolMetadata(executionMode, returnDirect); + } + + } + +} diff --git a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/metadata/ToolMetadata.java b/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/metadata/ToolMetadata.java similarity index 50% rename from arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/metadata/ToolMetadata.java rename to arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/metadata/ToolMetadata.java index 6f07913..9fea0fd 100644 --- a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/metadata/ToolMetadata.java +++ b/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/metadata/ToolMetadata.java @@ -1,26 +1,20 @@ -package io.arconia.ai.core.tools.metadata; +package io.arconia.ai.tools.metadata; import java.lang.reflect.Method; +import io.arconia.ai.tools.execution.ToolExecutionMode; + /** - * Metadata for a tool. + * Metadata about a tool specification and execution. */ public interface ToolMetadata { /** - * The tool name. Unique within the tool set provided to a model. - */ - String name(); - - /** - * The tool description, used by the model to decide if and when to use the tool. - */ - String description(); - - /** - * The JSON Schema of the parameters used to call the tool. + * How the tool should be executed. */ - String inputTypeSchema(); + default ToolExecutionMode executionMode() { + return ToolExecutionMode.BLOCKING; + } /** * Whether the tool result should be returned directly or passed back to the model. @@ -29,6 +23,13 @@ default boolean returnDirect() { return false; } + /** + * Create a default {@link ToolMetadata} builder. + */ + static DefaultToolMetadata.Builder builder() { + return DefaultToolMetadata.builder(); + } + /** * Create {@link ToolMetadata} from a {@link Method}. */ diff --git a/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/metadata/package-info.java b/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/metadata/package-info.java new file mode 100644 index 0000000..b38c5b1 --- /dev/null +++ b/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/metadata/package-info.java @@ -0,0 +1,6 @@ +@NonNullApi +@NonNullFields +package io.arconia.ai.tools.metadata; + +import org.springframework.lang.NonNullApi; +import org.springframework.lang.NonNullFields; diff --git a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/method/MethodToolCallback.java b/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/method/MethodToolCallback.java similarity index 84% rename from arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/method/MethodToolCallback.java rename to arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/method/MethodToolCallback.java index 5acee9a..ce0b8bc 100644 --- a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/method/MethodToolCallback.java +++ b/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/method/MethodToolCallback.java @@ -1,4 +1,4 @@ -package io.arconia.ai.core.tools.method; +package io.arconia.ai.tools.method; import java.lang.reflect.Method; import java.lang.reflect.Modifier; @@ -14,15 +14,18 @@ import org.springframework.util.CollectionUtils; import org.springframework.util.ReflectionUtils; -import io.arconia.ai.core.tools.ToolCallback; -import io.arconia.ai.core.tools.json.JsonParser; -import io.arconia.ai.core.tools.metadata.ToolMetadata; +import io.arconia.ai.tools.ToolCallback; +import io.arconia.ai.tools.definition.ToolDefinition; +import io.arconia.ai.tools.json.JsonParser; +import io.arconia.ai.tools.metadata.ToolMetadata; /** * A {@link ToolCallback} implementation to invoke methods as tools. */ public class MethodToolCallback implements ToolCallback { + private final ToolDefinition toolDefinition; + private final ToolMetadata toolMetadata; private final Method toolMethod; @@ -30,17 +33,24 @@ public class MethodToolCallback implements ToolCallback { @Nullable private final Object toolObject; - public MethodToolCallback(ToolMetadata toolMetadata, Method toolMethod, @Nullable Object toolObject) { + public MethodToolCallback(ToolDefinition toolDefinition, ToolMetadata toolMetadata, Method toolMethod, @Nullable Object toolObject) { + Assert.notNull(toolDefinition, "toolDefinition cannot be null"); Assert.notNull(toolMetadata, "toolMetadata cannot be null"); Assert.notNull(toolMethod, "toolMethod cannot be null"); if (!Modifier.isStatic(toolMethod.getModifiers())) { Assert.notNull(toolObject, "toolObject cannot be null for non-static method"); } + this.toolDefinition = toolDefinition; this.toolMetadata = toolMetadata; this.toolMethod = toolMethod; this.toolObject = toolObject; } + @Override + public ToolDefinition getToolDefinition() { + return toolDefinition; + } + @Override public ToolMetadata getToolMetadata() { return toolMetadata; @@ -133,6 +143,8 @@ public static Builder builder() { public static class Builder { + private ToolDefinition toolDefinition; + private ToolMetadata toolMetadata; private Method toolMethod; @@ -141,6 +153,11 @@ public static class Builder { private Builder() {} + public Builder toolDefinition(ToolDefinition toolDefinition) { + this.toolDefinition = toolDefinition; + return this; + } + public Builder toolMetadata(ToolMetadata toolMetadata) { this.toolMetadata = toolMetadata; return this; @@ -157,7 +174,7 @@ public Builder toolObject(Object toolObject) { } public MethodToolCallback build() { - return new MethodToolCallback(toolMetadata, toolMethod, toolObject); + return new MethodToolCallback(toolDefinition, toolMetadata, toolMethod, toolObject); } } diff --git a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/method/MethodToolCallbackProvider.java b/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/method/MethodToolCallbackProvider.java similarity index 79% rename from arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/method/MethodToolCallbackProvider.java rename to arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/method/MethodToolCallbackProvider.java index d07bf1a..d50544f 100644 --- a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/method/MethodToolCallbackProvider.java +++ b/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/method/MethodToolCallbackProvider.java @@ -1,4 +1,4 @@ -package io.arconia.ai.core.tools.method; +package io.arconia.ai.tools.method; import java.lang.reflect.Method; import java.util.Arrays; @@ -15,11 +15,12 @@ import org.springframework.util.ClassUtils; import org.springframework.util.ReflectionUtils; -import io.arconia.ai.core.tools.ToolCallback; -import io.arconia.ai.core.tools.ToolCallbackProvider; -import io.arconia.ai.core.tools.annotation.Tool; -import io.arconia.ai.core.tools.metadata.ToolMetadata; -import io.arconia.ai.core.tools.util.ToolUtils; +import io.arconia.ai.tools.ToolCallback; +import io.arconia.ai.tools.ToolCallbackProvider; +import io.arconia.ai.tools.annotation.Tool; +import io.arconia.ai.tools.definition.ToolDefinition; +import io.arconia.ai.tools.metadata.ToolMetadata; +import io.arconia.ai.tools.util.ToolUtils; /** * A {@link ToolCallbackProvider} that builds {@link ToolCallback} instances @@ -40,17 +41,18 @@ private MethodToolCallbackProvider(List toolObjects) { @Override public ToolCallback[] getToolCallbacks() { var toolCallbacks = toolObjects.stream() - .map(toolObject -> Stream.of(ReflectionUtils.getDeclaredMethods(toolObject.getClass())) + .map(toolObject -> Stream.of(ReflectionUtils.getDeclaredMethods(toolObject.getClass())) .filter(toolMethod -> toolMethod.isAnnotationPresent(Tool.class)) .filter(toolMethod -> !isFunctionalType(toolMethod)) .map(toolMethod -> MethodToolCallback.builder() - .toolMetadata(ToolMetadata.from(toolMethod)) - .toolMethod(toolMethod) - .toolObject(toolObject) - .build()) - .toArray(ToolCallback[]::new)) - .flatMap(Stream::of) - .toArray(ToolCallback[]::new); + .toolDefinition(ToolDefinition.from(toolMethod)) + .toolMetadata(ToolMetadata.from(toolMethod)) + .toolMethod(toolMethod) + .toolObject(toolObject) + .build()) + .toArray(ToolCallback[]::new)) + .flatMap(Stream::of) + .toArray(ToolCallback[]::new); validateToolCallbacks(toolCallbacks); diff --git a/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/method/package-info.java b/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/method/package-info.java new file mode 100644 index 0000000..365ab25 --- /dev/null +++ b/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/method/package-info.java @@ -0,0 +1,6 @@ +@NonNullApi +@NonNullFields +package io.arconia.ai.tools.method; + +import org.springframework.lang.NonNullApi; +import org.springframework.lang.NonNullFields; diff --git a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/package-info.java b/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/package-info.java similarity index 80% rename from arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/package-info.java rename to arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/package-info.java index 46ec2c4..0334330 100644 --- a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/package-info.java +++ b/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/package-info.java @@ -1,6 +1,6 @@ @NonNullApi @NonNullFields -package io.arconia.ai.core; +package io.arconia.ai.tools; import org.springframework.lang.NonNullApi; import org.springframework.lang.NonNullFields; diff --git a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/util/ToolUtils.java b/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/util/ToolUtils.java similarity index 52% rename from arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/util/ToolUtils.java rename to arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/util/ToolUtils.java index 1c39d03..9d36114 100644 --- a/arconia-ai/arconia-ai-core/src/main/java/io/arconia/ai/core/tools/util/ToolUtils.java +++ b/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/util/ToolUtils.java @@ -1,5 +1,6 @@ -package io.arconia.ai.core.tools.util; +package io.arconia.ai.tools.util; +import java.lang.reflect.Method; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -7,35 +8,40 @@ import org.springframework.ai.model.function.FunctionCallback; import org.springframework.ai.util.ParsingUtils; -import org.springframework.lang.Nullable; import org.springframework.util.StringUtils; -import io.arconia.ai.core.tools.annotation.Tool; +import io.arconia.ai.tools.annotation.Tool; +import io.arconia.ai.tools.execution.ToolExecutionMode; /** * Miscellaneous tool utility methods. Mainly for internal use within the framework. */ public final class ToolUtils { - public static String getToolName(@Nullable Tool tool, String methodName) { + public static String getToolName(Method method) { + var tool = method.getAnnotation(Tool.class); if (tool == null) { - return methodName; + return method.getName(); } - return StringUtils.hasText(tool.name()) ? tool.name() : methodName; + return StringUtils.hasText(tool.name()) ? tool.name() : method.getName(); } - public static String getToolDescription(@Nullable Tool tool, String methodName) { + public static String getToolDescription(Method method) { + var tool = method.getAnnotation(Tool.class); if (tool == null) { - return ParsingUtils.reConcatenateCamelCase(methodName, " "); + return ParsingUtils.reConcatenateCamelCase(method.getName(), " "); } - return StringUtils.hasText(tool.value()) ? tool.value() : methodName; + return StringUtils.hasText(tool.value()) ? tool.value() : method.getName(); } - public static FunctionCallback.SchemaType getToolSchemaType(@Nullable Tool tool) { - if (tool == null) { - return FunctionCallback.SchemaType.JSON_SCHEMA; - } - return tool.schemaType(); + public static ToolExecutionMode getToolExecutionMode(Method method) { + var tool = method.getAnnotation(Tool.class); + return tool != null ? tool.executionMode() : ToolExecutionMode.BLOCKING; + } + + public static boolean getToolReturnDirect(Method method) { + var tool = method.getAnnotation(Tool.class); + return tool != null && tool.returnDirect(); } public static List getDuplicateToolNames(FunctionCallback... functionCallbacks) { diff --git a/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/util/package-info.java b/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/util/package-info.java new file mode 100644 index 0000000..b82d507 --- /dev/null +++ b/arconia-ai/arconia-ai-tools/src/main/java/io/arconia/ai/tools/util/package-info.java @@ -0,0 +1,6 @@ +@NonNullApi +@NonNullFields +package io.arconia.ai.tools.util; + +import org.springframework.lang.NonNullApi; +import org.springframework.lang.NonNullFields; diff --git a/arconia-ai/arconia-ai-core/src/test/java/io/arconia/ai/core/tools/ToolUtilsTests.java b/arconia-ai/arconia-ai-tools/src/test/java/io/arconia/ai/core/tools/ToolUtilsTests.java similarity index 80% rename from arconia-ai/arconia-ai-core/src/test/java/io/arconia/ai/core/tools/ToolUtilsTests.java rename to arconia-ai/arconia-ai-tools/src/test/java/io/arconia/ai/core/tools/ToolUtilsTests.java index 32006dc..95da5e6 100644 --- a/arconia-ai/arconia-ai-core/src/test/java/io/arconia/ai/core/tools/ToolUtilsTests.java +++ b/arconia-ai/arconia-ai-tools/src/test/java/io/arconia/ai/core/tools/ToolUtilsTests.java @@ -2,11 +2,11 @@ import java.util.List; +import io.arconia.ai.tools.ToolCallback; import org.junit.jupiter.api.Test; -import io.arconia.ai.core.tools.metadata.DefaultToolMetadata; -import io.arconia.ai.core.tools.metadata.ToolMetadata; -import io.arconia.ai.core.tools.util.ToolUtils; +import io.arconia.ai.tools.definition.ToolDefinition; +import io.arconia.ai.tools.util.ToolUtils; import static org.assertj.core.api.Assertions.assertThat; @@ -40,10 +40,10 @@ void shouldNotDetectDuplicateToolNames() { static class TestToolCallback implements ToolCallback { - private final ToolMetadata toolMetadata; + private final ToolDefinition toolDefinition; public TestToolCallback(String name) { - this.toolMetadata = DefaultToolMetadata.builder() + this.toolDefinition = ToolDefinition.builder() .name(name) .description(name) .inputTypeSchema("{}") @@ -51,8 +51,8 @@ public TestToolCallback(String name) { } @Override - public ToolMetadata getToolMetadata() { - return toolMetadata; + public ToolDefinition getToolDefinition() { + return toolDefinition; } @Override diff --git a/arconia-ai/arconia-ai-core/src/test/java/io/arconia/ai/core/tools/json/JsonSchemaGeneratorTests.java b/arconia-ai/arconia-ai-tools/src/test/java/io/arconia/ai/core/tools/json/JsonSchemaGeneratorTests.java similarity index 96% rename from arconia-ai/arconia-ai-core/src/test/java/io/arconia/ai/core/tools/json/JsonSchemaGeneratorTests.java rename to arconia-ai/arconia-ai-tools/src/test/java/io/arconia/ai/core/tools/json/JsonSchemaGeneratorTests.java index d6edea4..556a746 100644 --- a/arconia-ai/arconia-ai-core/src/test/java/io/arconia/ai/core/tools/json/JsonSchemaGeneratorTests.java +++ b/arconia-ai/arconia-ai-tools/src/test/java/io/arconia/ai/core/tools/json/JsonSchemaGeneratorTests.java @@ -1,4 +1,4 @@ -package io.arconia.ai.core.tools.json; +package io.arconia.ai.tools.json; import java.lang.reflect.Method; import java.util.Arrays; diff --git a/arconia-ai/arconia-ai-core/src/test/java/io/arconia/ai/core/tools/method/MethodToolCallbackProviderTests.java b/arconia-ai/arconia-ai-tools/src/test/java/io/arconia/ai/core/tools/method/MethodToolCallbackProviderTests.java similarity index 95% rename from arconia-ai/arconia-ai-core/src/test/java/io/arconia/ai/core/tools/method/MethodToolCallbackProviderTests.java rename to arconia-ai/arconia-ai-tools/src/test/java/io/arconia/ai/core/tools/method/MethodToolCallbackProviderTests.java index cc4665e..dd58523 100644 --- a/arconia-ai/arconia-ai-core/src/test/java/io/arconia/ai/core/tools/method/MethodToolCallbackProviderTests.java +++ b/arconia-ai/arconia-ai-tools/src/test/java/io/arconia/ai/core/tools/method/MethodToolCallbackProviderTests.java @@ -1,4 +1,4 @@ -package io.arconia.ai.core.tools.method; +package io.arconia.ai.tools.method; import java.util.List; import java.util.function.Function; @@ -6,8 +6,8 @@ import org.junit.jupiter.api.Test; -import io.arconia.ai.core.tools.ToolCallback; -import io.arconia.ai.core.tools.annotation.Tool; +import io.arconia.ai.tools.ToolCallback; +import io.arconia.ai.tools.annotation.Tool; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; diff --git a/arconia-ai/arconia-ai-core/src/test/java/io/arconia/ai/core/tools/method/MethodToolCallbackTests.java b/arconia-ai/arconia-ai-tools/src/test/java/io/arconia/ai/core/tools/method/MethodToolCallbackTests.java similarity index 94% rename from arconia-ai/arconia-ai-core/src/test/java/io/arconia/ai/core/tools/method/MethodToolCallbackTests.java rename to arconia-ai/arconia-ai-tools/src/test/java/io/arconia/ai/core/tools/method/MethodToolCallbackTests.java index 309d992..463fdfa 100644 --- a/arconia-ai/arconia-ai-core/src/test/java/io/arconia/ai/core/tools/method/MethodToolCallbackTests.java +++ b/arconia-ai/arconia-ai-tools/src/test/java/io/arconia/ai/core/tools/method/MethodToolCallbackTests.java @@ -1,4 +1,4 @@ -package io.arconia.ai.core.tools.method; +package io.arconia.ai.tools.method; import java.lang.reflect.Method; import java.util.Arrays; @@ -10,9 +10,10 @@ import org.junit.jupiter.params.provider.ValueSource; import org.springframework.util.ReflectionUtils; -import io.arconia.ai.core.tools.annotation.Tool; -import io.arconia.ai.core.tools.json.JsonParser; -import io.arconia.ai.core.tools.metadata.ToolMetadata; +import io.arconia.ai.tools.annotation.Tool; +import io.arconia.ai.tools.definition.ToolDefinition; +import io.arconia.ai.tools.json.JsonParser; +import io.arconia.ai.tools.metadata.ToolMetadata; import static org.assertj.core.api.Assertions.assertThat; @@ -64,6 +65,7 @@ private static void validateAssertions(String methodName, Object toolObject) { Method toolMethod = getMethod(methodName, toolObject.getClass()); assertThat(toolMethod).isNotNull(); MethodToolCallback callback = MethodToolCallback.builder() + .toolDefinition(ToolDefinition.from(toolMethod)) .toolMetadata(ToolMetadata.from(toolMethod)) .toolMethod(toolMethod) .toolObject(toolObject) diff --git a/settings.gradle b/settings.gradle index c096739..0001fef 100644 --- a/settings.gradle +++ b/settings.gradle @@ -5,8 +5,9 @@ plugins { rootProject.name = 'arconia' // AI -include 'arconia-ai:arconia-ai-core' +include 'arconia-ai:arconia-ai-client' include 'arconia-ai:arconia-ai-mcp' +include 'arconia-ai:arconia-ai-tools' include 'arconia-ai:arconia-ai-spring-boot-starters:arconia-ai-spring-boot-starter'