diff --git a/core/deployment/src/main/java/io/quarkiverse/langchain4j/deployment/ToolProcessor.java b/core/deployment/src/main/java/io/quarkiverse/langchain4j/deployment/ToolProcessor.java index eb67c7dd1..8ce9e95aa 100644 --- a/core/deployment/src/main/java/io/quarkiverse/langchain4j/deployment/ToolProcessor.java +++ b/core/deployment/src/main/java/io/quarkiverse/langchain4j/deployment/ToolProcessor.java @@ -89,20 +89,13 @@ public void telemetry(Capabilities capabilities, BuildProducer additionalBeanProducer, - RecorderContext recorderContext, BuildProducer transformerProducer, BuildProducer generatedClassProducer, BuildProducer reflectiveClassProducer, BuildProducer validation, - BuildProducer toolsMetadataProducer) { - recorderContext.registerSubstitution(ToolSpecification.class, ToolSpecificationObjectSubstitution.Serialized.class, - ToolSpecificationObjectSubstitution.class); - recorderContext.registerSubstitution(ToolParameters.class, ToolParametersObjectSubstitution.Serialized.class, - ToolParametersObjectSubstitution.class); + BuildProducer toolsMetadataProducer) { IndexView index = indexBuildItem.getIndex(); @@ -250,8 +243,38 @@ public void handleTools(CombinedIndexBuildItem indexBuildItem, .build()); } - toolsMetadataProducer.produce(new ToolsMetadataBuildItem(metadata)); - recorder.setMetadata(metadata); + toolsMetadataProducer.produce(new ToolsMetadataBeforeRemovalBuildItem(metadata)); + } + + /** + * Transforms ToolsMetadataBeforeRemovalBuildItem into ToolsMetadataBuildItem by filtering + * out tools belonging to beans that have been removed by ArC. + */ + @BuildStep + @Record(ExecutionTime.STATIC_INIT) + public ToolsMetadataBuildItem filterOutRemovedTools(ToolsMetadataBeforeRemovalBuildItem beforeRemoval, + ValidationPhaseBuildItem validationPhase, + RecorderContext recorderContext, + ToolsRecorder recorder) { + if (beforeRemoval != null) { + recorderContext.registerSubstitution(ToolSpecification.class, ToolSpecificationObjectSubstitution.Serialized.class, + ToolSpecificationObjectSubstitution.class); + recorderContext.registerSubstitution(ToolParameters.class, ToolParametersObjectSubstitution.Serialized.class, + ToolParametersObjectSubstitution.class); + Map> metadataWithoutRemovedBeans = beforeRemoval.getMetadata().entrySet() + .stream() + .filter(entry -> validationPhase.getContext().removedBeans().stream() + .noneMatch( + retainedBean -> DotName.createSimple(entry.getKey()).equals(retainedBean.getBeanClass()))) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + ToolsMetadataBuildItem toolsMetadata = new ToolsMetadataBuildItem(metadataWithoutRemovedBeans); + recorder.setMetadata(toolsMetadata.getMetadata()); + log.debug("Tool classes before filtering out removed beans: " + beforeRemoval.getMetadata().keySet()); + log.debug("Tool classes after filtering out removed beans: " + toolsMetadata.getMetadata().keySet()); + return toolsMetadata; + } else { + return null; + } } private boolean ignoreToolMethod(MethodInfo toolMethod, IndexView indexView) { diff --git a/core/deployment/src/main/java/io/quarkiverse/langchain4j/deployment/ToolsMetadataBeforeRemovalBuildItem.java b/core/deployment/src/main/java/io/quarkiverse/langchain4j/deployment/ToolsMetadataBeforeRemovalBuildItem.java new file mode 100644 index 000000000..622f98334 --- /dev/null +++ b/core/deployment/src/main/java/io/quarkiverse/langchain4j/deployment/ToolsMetadataBeforeRemovalBuildItem.java @@ -0,0 +1,27 @@ +package io.quarkiverse.langchain4j.deployment; + +import java.util.List; +import java.util.Map; + +import io.quarkiverse.langchain4j.runtime.tool.ToolMethodCreateInfo; +import io.quarkus.builder.item.SimpleBuildItem; + +/** + * Holds metadata about tools discovered at build time, but tools belonging + * to beans removed by ArC have not been filtered out yet + * (ToolsMetadataBuildItem is the build item that already has them filtered + * out). + */ +public final class ToolsMetadataBeforeRemovalBuildItem extends SimpleBuildItem { + + Map> metadata; + + public ToolsMetadataBeforeRemovalBuildItem(Map> metadata) { + this.metadata = metadata; + } + + public Map> getMetadata() { + return metadata; + } + +}