diff --git a/README.md b/README.md index 46228b0ca..b70d46c1b 100644 --- a/README.md +++ b/README.md @@ -94,6 +94,12 @@ To check javadocs using the [javadoc:javadoc](https://maven.apache.org/plugins/m ./mvnw javadoc:javadoc -Pjavadoc ``` +To build with checkstyles enabled. +Checkstyles are currently disabled, but you can enable them by doing the following: +```shell +./mvnw clean package -DskipTests -Ddisable.checks=false +``` + ## Project Links * [Documentation](https://docs.spring.io/spring-ai/reference/) diff --git a/document-readers/markdown-reader/src/main/java/org/springframework/ai/reader/markdown/MarkdownDocumentReader.java b/document-readers/markdown-reader/src/main/java/org/springframework/ai/reader/markdown/MarkdownDocumentReader.java index 19ebed9ca..33c3709eb 100644 --- a/document-readers/markdown-reader/src/main/java/org/springframework/ai/reader/markdown/MarkdownDocumentReader.java +++ b/document-readers/markdown-reader/src/main/java/org/springframework/ai/reader/markdown/MarkdownDocumentReader.java @@ -111,7 +111,7 @@ public class MarkdownDocumentReader implements DocumentReader { private Document.Builder currentDocumentBuilder; - public DocumentVisitor(MarkdownDocumentReaderConfig config) { + DocumentVisitor(MarkdownDocumentReaderConfig config) { this.config = config; } diff --git a/document-readers/markdown-reader/src/main/java/org/springframework/ai/reader/markdown/config/MarkdownDocumentReaderConfig.java b/document-readers/markdown-reader/src/main/java/org/springframework/ai/reader/markdown/config/MarkdownDocumentReaderConfig.java index c22c573f0..a622f2531 100644 --- a/document-readers/markdown-reader/src/main/java/org/springframework/ai/reader/markdown/config/MarkdownDocumentReaderConfig.java +++ b/document-readers/markdown-reader/src/main/java/org/springframework/ai/reader/markdown/config/MarkdownDocumentReaderConfig.java @@ -56,7 +56,7 @@ public class MarkdownDocumentReaderConfig { return new Builder(); } - public static class Builder { + public static final class Builder { private boolean horizontalRuleCreateDocument = false; diff --git a/document-readers/pdf-reader/pom.xml b/document-readers/pdf-reader/pom.xml index 1a44d4ef3..94d106a75 100644 --- a/document-readers/pdf-reader/pom.xml +++ b/document-readers/pdf-reader/pom.xml @@ -37,7 +37,6 @@ - false diff --git a/models/spring-ai-anthropic/pom.xml b/models/spring-ai-anthropic/pom.xml index 74663049a..7cb9a41d8 100644 --- a/models/spring-ai-anthropic/pom.xml +++ b/models/spring-ai-anthropic/pom.xml @@ -38,7 +38,6 @@ - false diff --git a/models/spring-ai-azure-openai/pom.xml b/models/spring-ai-azure-openai/pom.xml index 35f8511d2..6e312cfca 100644 --- a/models/spring-ai-azure-openai/pom.xml +++ b/models/spring-ai-azure-openai/pom.xml @@ -36,7 +36,6 @@ - false diff --git a/models/spring-ai-bedrock-converse/pom.xml b/models/spring-ai-bedrock-converse/pom.xml index e684d6bf1..79c9364b2 100644 --- a/models/spring-ai-bedrock-converse/pom.xml +++ b/models/spring-ai-bedrock-converse/pom.xml @@ -1,4 +1,20 @@ + + @@ -81,4 +97,4 @@ - \ No newline at end of file + diff --git a/models/spring-ai-bedrock-converse/src/main/java/org/springframework/ai/bedrock/converse/BedrockProxyChatModel.java b/models/spring-ai-bedrock-converse/src/main/java/org/springframework/ai/bedrock/converse/BedrockProxyChatModel.java index 013cba9be..4687504e0 100644 --- a/models/spring-ai-bedrock-converse/src/main/java/org/springframework/ai/bedrock/converse/BedrockProxyChatModel.java +++ b/models/spring-ai-bedrock-converse/src/main/java/org/springframework/ai/bedrock/converse/BedrockProxyChatModel.java @@ -1,11 +1,11 @@ /* - * Copyright 2024 - 2024 the original author or authors. + * Copyright 2023-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.ai.bedrock.converse; import java.io.IOException; @@ -26,44 +27,11 @@ import java.util.List; import java.util.Map; import java.util.Set; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.ai.bedrock.converse.api.ConverseApiUtils; -import org.springframework.ai.bedrock.converse.api.URLValidator; -import org.springframework.ai.chat.messages.AssistantMessage; -import org.springframework.ai.chat.messages.MessageType; -import org.springframework.ai.chat.messages.ToolResponseMessage; -import org.springframework.ai.chat.messages.UserMessage; -import org.springframework.ai.chat.metadata.ChatGenerationMetadata; -import org.springframework.ai.chat.metadata.ChatResponseMetadata; -import org.springframework.ai.chat.metadata.DefaultUsage; -import org.springframework.ai.chat.model.AbstractToolCallSupport; -import org.springframework.ai.chat.model.ChatModel; -import org.springframework.ai.chat.model.ChatResponse; -import org.springframework.ai.chat.model.Generation; -import org.springframework.ai.chat.model.MessageAggregator; -import org.springframework.ai.chat.observation.ChatModelObservationContext; -import org.springframework.ai.chat.observation.ChatModelObservationConvention; -import org.springframework.ai.chat.observation.ChatModelObservationDocumentation; -import org.springframework.ai.chat.observation.DefaultChatModelObservationConvention; -import org.springframework.ai.chat.prompt.ChatOptions; -import org.springframework.ai.chat.prompt.ChatOptionsBuilder; -import org.springframework.ai.chat.prompt.Prompt; -import org.springframework.ai.model.ModelOptionsUtils; -import org.springframework.ai.model.function.FunctionCallback; -import org.springframework.ai.model.function.FunctionCallbackContext; -import org.springframework.ai.model.function.FunctionCallingOptions; -import org.springframework.ai.model.function.FunctionCallingOptionsBuilder; -import org.springframework.ai.model.function.FunctionCallingOptionsBuilder.PortableFunctionCallingOptions; -import org.springframework.ai.observation.conventions.AiProvider; -import org.springframework.util.Assert; -import org.springframework.util.CollectionUtils; -import org.springframework.util.StreamUtils; -import org.springframework.util.StringUtils; - import io.micrometer.observation.Observation; import io.micrometer.observation.ObservationRegistry; import io.micrometer.observation.contextpropagation.ObservationThreadLocalAccessor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.core.publisher.Sinks; @@ -97,6 +65,39 @@ import software.amazon.awssdk.services.bedrockruntime.model.ToolResultContentBlo import software.amazon.awssdk.services.bedrockruntime.model.ToolSpecification; import software.amazon.awssdk.services.bedrockruntime.model.ToolUseBlock; +import org.springframework.ai.bedrock.converse.api.ConverseApiUtils; +import org.springframework.ai.bedrock.converse.api.URLValidator; +import org.springframework.ai.chat.messages.AssistantMessage; +import org.springframework.ai.chat.messages.MessageType; +import org.springframework.ai.chat.messages.ToolResponseMessage; +import org.springframework.ai.chat.messages.UserMessage; +import org.springframework.ai.chat.metadata.ChatGenerationMetadata; +import org.springframework.ai.chat.metadata.ChatResponseMetadata; +import org.springframework.ai.chat.metadata.DefaultUsage; +import org.springframework.ai.chat.model.AbstractToolCallSupport; +import org.springframework.ai.chat.model.ChatModel; +import org.springframework.ai.chat.model.ChatResponse; +import org.springframework.ai.chat.model.Generation; +import org.springframework.ai.chat.model.MessageAggregator; +import org.springframework.ai.chat.observation.ChatModelObservationContext; +import org.springframework.ai.chat.observation.ChatModelObservationConvention; +import org.springframework.ai.chat.observation.ChatModelObservationDocumentation; +import org.springframework.ai.chat.observation.DefaultChatModelObservationConvention; +import org.springframework.ai.chat.prompt.ChatOptions; +import org.springframework.ai.chat.prompt.ChatOptionsBuilder; +import org.springframework.ai.chat.prompt.Prompt; +import org.springframework.ai.model.ModelOptionsUtils; +import org.springframework.ai.model.function.FunctionCallback; +import org.springframework.ai.model.function.FunctionCallbackContext; +import org.springframework.ai.model.function.FunctionCallingOptions; +import org.springframework.ai.model.function.FunctionCallingOptionsBuilder; +import org.springframework.ai.model.function.FunctionCallingOptionsBuilder.PortableFunctionCallingOptions; +import org.springframework.ai.observation.conventions.AiProvider; +import org.springframework.util.Assert; +import org.springframework.util.CollectionUtils; +import org.springframework.util.StreamUtils; +import org.springframework.util.StringUtils; + /** * A {@link ChatModel} implementation that uses the Amazon Bedrock Converse API to * interact with the generations = message.content() .stream() .filter(content -> content.type() != ContentBlock.Type.TOOL_USE) - .map(content -> { - return new Generation(new AssistantMessage(content.text(), Map.of()), - ChatGenerationMetadata.from(response.stopReasonAsString(), null)); - }) + .map(content -> new Generation(new AssistantMessage(content.text(), Map.of()), + ChatGenerationMetadata.from(response.stopReasonAsString(), null))) .toList(); List allGenerations = new ArrayList<>(generations); @@ -508,7 +507,7 @@ public class BedrockProxyChatModel extends AbstractToolCallSupport implements Ch // @formatter:off Flux chatResponses = ConverseApiUtils.toChatResponse(response); - Flux chatResponseFlux = chatResponses.switchMap(chatResponse -> { + Flux chatResponseFlux = chatResponses.switchMap(chatResponse -> { if (!this.isProxyToolCalls(prompt, this.defaultOptions) && chatResponse != null && this.isToolCall(chatResponse, Set.of("tool_use"))) { var toolCallConversation = this.handleToolCalls(prompt, chatResponse); @@ -540,14 +539,14 @@ public class BedrockProxyChatModel extends AbstractToolCallSupport implements Ch Sinks.Many eventSink = Sinks.many().multicast().onBackpressureBuffer(); ConverseStreamResponseHandler.Visitor visitor = ConverseStreamResponseHandler.Visitor.builder() - .onDefault((output) -> { + .onDefault(output -> { logger.debug("Received converse stream output:{}", output); eventSink.tryEmitNext(output); }) .build(); ConverseStreamResponseHandler responseHandler = ConverseStreamResponseHandler.builder() - .onEventStream(stream -> stream.subscribe((e) -> e.accept(visitor))) + .onEventStream(stream -> stream.subscribe(e -> e.accept(visitor))) .onComplete(() -> { EmitResult emitResult = eventSink.tryEmitComplete(); @@ -559,7 +558,7 @@ public class BedrockProxyChatModel extends AbstractToolCallSupport implements Ch eventSink.emitComplete(EmitFailureHandler.busyLooping(Duration.ofSeconds(3))); logger.info("Completed streaming response."); }) - .onError((error) -> { + .onError(error -> { logger.error("Error handling Bedrock converse stream response", error); eventSink.tryEmitError(error); }) @@ -571,11 +570,20 @@ public class BedrockProxyChatModel extends AbstractToolCallSupport implements Ch } + /** + * Use the provided convention for reporting observation data + * @param observationConvention The provided convention + */ + public void setObservationConvention(ChatModelObservationConvention observationConvention) { + Assert.notNull(observationConvention, "observationConvention cannot be null"); + this.observationConvention = observationConvention; + } + public static Builder builder() { return new Builder(); } - public static class Builder { + public static final class Builder { private AwsCredentialsProvider credentialsProvider; @@ -696,13 +704,4 @@ public class BedrockProxyChatModel extends AbstractToolCallSupport implements Ch } - /** - * Use the provided convention for reporting observation data - * @param observationConvention The provided convention - */ - public void setObservationConvention(ChatModelObservationConvention observationConvention) { - Assert.notNull(observationConvention, "observationConvention cannot be null"); - this.observationConvention = observationConvention; - } - } diff --git a/models/spring-ai-bedrock-converse/src/main/java/org/springframework/ai/bedrock/converse/api/BedrockUsage.java b/models/spring-ai-bedrock-converse/src/main/java/org/springframework/ai/bedrock/converse/api/BedrockUsage.java index 96186b9b7..ac58a7ca5 100644 --- a/models/spring-ai-bedrock-converse/src/main/java/org/springframework/ai/bedrock/converse/api/BedrockUsage.java +++ b/models/spring-ai-bedrock-converse/src/main/java/org/springframework/ai/bedrock/converse/api/BedrockUsage.java @@ -1,11 +1,11 @@ /* - * Copyright 2024 - 2024 the original author or authors. + * Copyright 2023-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,13 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.ai.bedrock.converse.api; +import software.amazon.awssdk.services.bedrockruntime.model.TokenUsage; + import org.springframework.ai.chat.metadata.Usage; import org.springframework.util.Assert; -import software.amazon.awssdk.services.bedrockruntime.model.TokenUsage; - /** * {@link Usage} implementation for Bedrock Converse API. * @@ -46,17 +47,17 @@ public class BedrockUsage implements Usage { @Override public Long getPromptTokens() { - return inputTokens; + return this.inputTokens; } @Override public Long getGenerationTokens() { - return outputTokens; + return this.outputTokens; } @Override public String toString() { - return "BedrockUsage [inputTokens=" + inputTokens + ", outputTokens=" + outputTokens + "]"; + return "BedrockUsage [inputTokens=" + this.inputTokens + ", outputTokens=" + this.outputTokens + "]"; } -} \ No newline at end of file +} diff --git a/models/spring-ai-bedrock-converse/src/main/java/org/springframework/ai/bedrock/converse/api/ConverseApiUtils.java b/models/spring-ai-bedrock-converse/src/main/java/org/springframework/ai/bedrock/converse/api/ConverseApiUtils.java index a5203c39d..29038d972 100644 --- a/models/spring-ai-bedrock-converse/src/main/java/org/springframework/ai/bedrock/converse/api/ConverseApiUtils.java +++ b/models/spring-ai-bedrock-converse/src/main/java/org/springframework/ai/bedrock/converse/api/ConverseApiUtils.java @@ -1,11 +1,11 @@ /* - * Copyright 2024 - 2024 the original author or authors. + * Copyright 2023-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.ai.bedrock.converse.api; import java.math.BigDecimal; @@ -24,18 +25,6 @@ import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Collectors; -import org.springframework.ai.chat.messages.AssistantMessage; -import org.springframework.ai.chat.metadata.ChatGenerationMetadata; -import org.springframework.ai.chat.metadata.ChatResponseMetadata; -import org.springframework.ai.chat.metadata.DefaultUsage; -import org.springframework.ai.chat.model.ChatResponse; -import org.springframework.ai.chat.model.Generation; -import org.springframework.ai.chat.prompt.ChatOptions; -import org.springframework.ai.model.ModelOptions; -import org.springframework.ai.model.ModelOptionsUtils; -import org.springframework.util.CollectionUtils; -import org.springframework.util.StringUtils; - import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import software.amazon.awssdk.core.SdkField; @@ -56,6 +45,18 @@ import software.amazon.awssdk.services.bedrockruntime.model.MessageStopEvent; import software.amazon.awssdk.services.bedrockruntime.model.TokenUsage; import software.amazon.awssdk.services.bedrockruntime.model.ToolUseBlockStart; +import org.springframework.ai.chat.messages.AssistantMessage; +import org.springframework.ai.chat.metadata.ChatGenerationMetadata; +import org.springframework.ai.chat.metadata.ChatResponseMetadata; +import org.springframework.ai.chat.metadata.DefaultUsage; +import org.springframework.ai.chat.model.ChatResponse; +import org.springframework.ai.chat.model.Generation; +import org.springframework.ai.chat.prompt.ChatOptions; +import org.springframework.ai.model.ModelOptions; +import org.springframework.ai.model.ModelOptionsUtils; +import org.springframework.util.CollectionUtils; +import org.springframework.util.StringUtils; + /** * Amazon Bedrock Converse API utils. * @@ -63,7 +64,16 @@ import software.amazon.awssdk.services.bedrockruntime.model.ToolUseBlockStart; * @author Christian Tzolov * @since 1.0.0 */ -public class ConverseApiUtils { +public final class ConverseApiUtils { + + public static final ChatResponse EMPTY_CHAT_RESPONSE = ChatResponse.builder() + .withGenerations(List.of()) + .withMetadata("empty", true) + .build(); + + private ConverseApiUtils() { + + } public static boolean isToolUseStart(ConverseStreamOutput event) { if (event == null || event.sdkEventType() == null || event.sdkEventType() != EventType.CONTENT_BLOCK_START) { @@ -80,139 +90,6 @@ public class ConverseApiUtils { return true; } - public record Aggregation(MetadataAggregation metadataAggregation, ChatResponse chatResponse) { - public Aggregation() { - this(MetadataAggregation.builder().build(), EMPTY_CHAT_RESPONSE); - } - } - - /** - * Special event used to aggregate multiple tool use events into a single event with - * list of aggregated ContentBlockToolUse. - */ - public static class ToolUseAggregationEvent implements ConverseStreamOutput { - - public record ToolUseEntry(Integer index, String id, String name, String input) { - } - - private Integer index; - - private String id; - - private String name; - - private String partialJson = ""; - - private List toolUseEntries = new ArrayList<>(); - - private DefaultUsage usage; - - public List toolUseEntries() { - return this.toolUseEntries; - } - - public boolean isEmpty() { - return (this.index == null || this.id == null || this.name == null - || !StringUtils.hasText(this.partialJson)); - } - - ToolUseAggregationEvent withIndex(Integer index) { - this.index = index; - return this; - } - - ToolUseAggregationEvent withId(String id) { - this.id = id; - return this; - } - - ToolUseAggregationEvent withName(String name) { - this.name = name; - return this; - } - - ToolUseAggregationEvent withUsage(DefaultUsage usage) { - this.usage = usage; - return this; - } - - ToolUseAggregationEvent appendPartialJson(String partialJson) { - this.partialJson = this.partialJson + partialJson; - return this; - } - - void squashIntoContentBlock() { - this.toolUseEntries.add(new ToolUseEntry(this.index, this.id, this.name, this.partialJson)); - this.index = null; - this.id = null; - this.name = null; - this.partialJson = ""; - this.usage = null; - } - - @Override - public String toString() { - return "EventToolUseBuilder [index=" + this.index + ", id=" + this.id + ", name=" + this.name - + ", partialJson=" + this.partialJson + ", toolUseMap=" + "]"; - } - - @Override - public List> sdkFields() { - return List.of(); - } - - @Override - public void accept(Visitor visitor) { - throw new UnsupportedOperationException(); - } - - } - - public static ConverseStreamOutput mergeToolUseEvents(ConverseStreamOutput previousEvent, - ConverseStreamOutput event) { - - ToolUseAggregationEvent toolUseEventAggregator = (ToolUseAggregationEvent) previousEvent; - - if (event.sdkEventType() == EventType.CONTENT_BLOCK_START) { - - ContentBlockStartEvent contentBlockStart = (ContentBlockStartEvent) event; - - if (ContentBlockStart.Type.TOOL_USE.equals(contentBlockStart.start().type())) { - ToolUseBlockStart cbToolUse = contentBlockStart.start().toolUse(); - - return toolUseEventAggregator.withIndex(contentBlockStart.contentBlockIndex()) - .withId(cbToolUse.toolUseId()) - .withName(cbToolUse.name()) - .appendPartialJson(""); // CB START always has empty JSON. - } - } - else if (event.sdkEventType() == EventType.CONTENT_BLOCK_DELTA) { - ContentBlockDeltaEvent contentBlockDelta = (ContentBlockDeltaEvent) event; - if (ContentBlockDelta.Type.TOOL_USE == contentBlockDelta.delta().type()) { - return toolUseEventAggregator.appendPartialJson(contentBlockDelta.delta().toolUse().input()); - } - } - else if (event.sdkEventType() == EventType.CONTENT_BLOCK_STOP) { - return toolUseEventAggregator; - } - else if (event.sdkEventType() == EventType.MESSAGE_STOP) { - return toolUseEventAggregator; - } - else if (event.sdkEventType() == EventType.METADATA) { - ConverseStreamMetadataEvent metadataEvent = (ConverseStreamMetadataEvent) event; - DefaultUsage usage = new DefaultUsage(metadataEvent.usage().inputTokens().longValue(), - metadataEvent.usage().outputTokens().longValue(), metadataEvent.usage().totalTokens().longValue()); - toolUseEventAggregator.withUsage(usage); - // TODO - if (!toolUseEventAggregator.isEmpty()) { - toolUseEventAggregator.squashIntoContentBlock(); - return toolUseEventAggregator; - } - } - - return event; - } - public static Flux toChatResponse(Flux responses) { AtomicBoolean isInsideTool = new AtomicBoolean(false); @@ -228,7 +105,7 @@ public class ConverseApiUtils { return true; } return !isInsideTool.get(); - }).concatMapIterable(window -> {// Merging the window chunks into a single chunk. + }).concatMapIterable(window -> { // Merging the window chunks into a single chunk. Mono monoChunk = window.reduce(new ToolUseAggregationEvent(), ConverseApiUtils::mergeToolUseEvents); return List.of(monoChunk); @@ -333,81 +210,49 @@ public class ConverseApiUtils { .filter(chatResponse -> chatResponse != ConverseApiUtils.EMPTY_CHAT_RESPONSE); } - public static final ChatResponse EMPTY_CHAT_RESPONSE = ChatResponse.builder() - .withGenerations(List.of()) - .withMetadata("empty", true) - .build(); + public static ConverseStreamOutput mergeToolUseEvents(ConverseStreamOutput previousEvent, + ConverseStreamOutput event) { - public record MetadataAggregation(String role, String stopReason, Document additionalModelResponseFields, - TokenUsage tokenUsage, ConverseStreamMetrics metrics, ConverseStreamTrace trace) { + ToolUseAggregationEvent toolUseEventAggregator = (ToolUseAggregationEvent) previousEvent; - public static Builder builder() { - return new Builder(); + if (event.sdkEventType() == EventType.CONTENT_BLOCK_START) { + + ContentBlockStartEvent contentBlockStart = (ContentBlockStartEvent) event; + + if (ContentBlockStart.Type.TOOL_USE.equals(contentBlockStart.start().type())) { + ToolUseBlockStart cbToolUse = contentBlockStart.start().toolUse(); + + return toolUseEventAggregator.withIndex(contentBlockStart.contentBlockIndex()) + .withId(cbToolUse.toolUseId()) + .withName(cbToolUse.name()) + .appendPartialJson(""); // CB START always has empty JSON. + } + } + else if (event.sdkEventType() == EventType.CONTENT_BLOCK_DELTA) { + ContentBlockDeltaEvent contentBlockDelta = (ContentBlockDeltaEvent) event; + if (ContentBlockDelta.Type.TOOL_USE == contentBlockDelta.delta().type()) { + return toolUseEventAggregator.appendPartialJson(contentBlockDelta.delta().toolUse().input()); + } + } + else if (event.sdkEventType() == EventType.CONTENT_BLOCK_STOP) { + return toolUseEventAggregator; + } + else if (event.sdkEventType() == EventType.MESSAGE_STOP) { + return toolUseEventAggregator; + } + else if (event.sdkEventType() == EventType.METADATA) { + ConverseStreamMetadataEvent metadataEvent = (ConverseStreamMetadataEvent) event; + DefaultUsage usage = new DefaultUsage(metadataEvent.usage().inputTokens().longValue(), + metadataEvent.usage().outputTokens().longValue(), metadataEvent.usage().totalTokens().longValue()); + toolUseEventAggregator.withUsage(usage); + // TODO + if (!toolUseEventAggregator.isEmpty()) { + toolUseEventAggregator.squashIntoContentBlock(); + return toolUseEventAggregator; + } } - public final static class Builder { - - private String role; - - private String stopReason; - - private Document additionalModelResponseFields; - - private TokenUsage tokenUsage; - - private ConverseStreamMetrics metrics; - - private ConverseStreamTrace trace; - - private Builder() { - } - - public Builder copy(MetadataAggregation metadataAggregation) { - this.role = metadataAggregation.role; - this.stopReason = metadataAggregation.stopReason; - this.additionalModelResponseFields = metadataAggregation.additionalModelResponseFields; - this.tokenUsage = metadataAggregation.tokenUsage; - this.metrics = metadataAggregation.metrics; - this.trace = metadataAggregation.trace; - return this; - } - - public Builder withRole(String role) { - this.role = role; - return this; - } - - public Builder withStopReason(String stopReason) { - this.stopReason = stopReason; - return this; - } - - public Builder withAdditionalModelResponseFields(Document additionalModelResponseFields) { - this.additionalModelResponseFields = additionalModelResponseFields; - return this; - } - - public Builder withTokenUsage(TokenUsage tokenUsage) { - this.tokenUsage = tokenUsage; - return this; - } - - public Builder withMetrics(ConverseStreamMetrics metrics) { - this.metrics = metrics; - return this; - } - - public Builder withTrace(ConverseStreamTrace trace) { - this.trace = trace; - return this; - } - - public MetadataAggregation build() { - return new MetadataAggregation(role, stopReason, additionalModelResponseFields, tokenUsage, metrics, - trace); - } - - } + return event; } @SuppressWarnings("unchecked") @@ -496,4 +341,164 @@ public class ConverseApiUtils { return Document.fromMap(attr); } + public record Aggregation(MetadataAggregation metadataAggregation, ChatResponse chatResponse) { + public Aggregation() { + this(MetadataAggregation.builder().build(), EMPTY_CHAT_RESPONSE); + } + } + + /** + * Special event used to aggregate multiple tool use events into a single event with + * list of aggregated ContentBlockToolUse. + */ + public static class ToolUseAggregationEvent implements ConverseStreamOutput { + + private Integer index; + + private String id; + + private String name; + + private String partialJson = ""; + + private List toolUseEntries = new ArrayList<>(); + + private DefaultUsage usage; + + public List toolUseEntries() { + return this.toolUseEntries; + } + + public boolean isEmpty() { + return (this.index == null || this.id == null || this.name == null + || !StringUtils.hasText(this.partialJson)); + } + + ToolUseAggregationEvent withIndex(Integer index) { + this.index = index; + return this; + } + + ToolUseAggregationEvent withId(String id) { + this.id = id; + return this; + } + + ToolUseAggregationEvent withName(String name) { + this.name = name; + return this; + } + + ToolUseAggregationEvent withUsage(DefaultUsage usage) { + this.usage = usage; + return this; + } + + ToolUseAggregationEvent appendPartialJson(String partialJson) { + this.partialJson = this.partialJson + partialJson; + return this; + } + + void squashIntoContentBlock() { + this.toolUseEntries.add(new ToolUseEntry(this.index, this.id, this.name, this.partialJson)); + this.index = null; + this.id = null; + this.name = null; + this.partialJson = ""; + this.usage = null; + } + + @Override + public String toString() { + return "EventToolUseBuilder [index=" + this.index + ", id=" + this.id + ", name=" + this.name + + ", partialJson=" + this.partialJson + ", toolUseMap=" + "]"; + } + + @Override + public List> sdkFields() { + return List.of(); + } + + @Override + public void accept(Visitor visitor) { + throw new UnsupportedOperationException(); + } + + public record ToolUseEntry(Integer index, String id, String name, String input) { + } + + } + + public record MetadataAggregation(String role, String stopReason, Document additionalModelResponseFields, + TokenUsage tokenUsage, ConverseStreamMetrics metrics, ConverseStreamTrace trace) { + + public static Builder builder() { + return new Builder(); + } + + public final static class Builder { + + private String role; + + private String stopReason; + + private Document additionalModelResponseFields; + + private TokenUsage tokenUsage; + + private ConverseStreamMetrics metrics; + + private ConverseStreamTrace trace; + + private Builder() { + } + + public Builder copy(MetadataAggregation metadataAggregation) { + this.role = metadataAggregation.role; + this.stopReason = metadataAggregation.stopReason; + this.additionalModelResponseFields = metadataAggregation.additionalModelResponseFields; + this.tokenUsage = metadataAggregation.tokenUsage; + this.metrics = metadataAggregation.metrics; + this.trace = metadataAggregation.trace; + return this; + } + + public Builder withRole(String role) { + this.role = role; + return this; + } + + public Builder withStopReason(String stopReason) { + this.stopReason = stopReason; + return this; + } + + public Builder withAdditionalModelResponseFields(Document additionalModelResponseFields) { + this.additionalModelResponseFields = additionalModelResponseFields; + return this; + } + + public Builder withTokenUsage(TokenUsage tokenUsage) { + this.tokenUsage = tokenUsage; + return this; + } + + public Builder withMetrics(ConverseStreamMetrics metrics) { + this.metrics = metrics; + return this; + } + + public Builder withTrace(ConverseStreamTrace trace) { + this.trace = trace; + return this; + } + + public MetadataAggregation build() { + return new MetadataAggregation(this.role, this.stopReason, this.additionalModelResponseFields, + this.tokenUsage, this.metrics, this.trace); + } + + } + } + } diff --git a/models/spring-ai-bedrock-converse/src/main/java/org/springframework/ai/bedrock/converse/api/URLValidator.java b/models/spring-ai-bedrock-converse/src/main/java/org/springframework/ai/bedrock/converse/api/URLValidator.java index 342ce5ba5..121fe7487 100644 --- a/models/spring-ai-bedrock-converse/src/main/java/org/springframework/ai/bedrock/converse/api/URLValidator.java +++ b/models/spring-ai-bedrock-converse/src/main/java/org/springframework/ai/bedrock/converse/api/URLValidator.java @@ -1,18 +1,19 @@ /* -* Copyright 2024 - 2024 the original author or authors. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* https://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ + * Copyright 2023-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.springframework.ai.bedrock.converse.api; import java.net.MalformedURLException; @@ -27,7 +28,7 @@ import java.util.regex.Pattern; * @author Christian Tzolov * @since 1.0.0 */ -public class URLValidator { +public final class URLValidator { // Basic URL regex pattern // Protocol (http:// or https://) @@ -41,6 +42,10 @@ public class URLValidator { "(#[\\w-]*)?" + // Optional fragment "$"); + private URLValidator() { + + } + /** * Quick validation using regex pattern Good for basic checks but may not catch all * edge cases @@ -121,4 +126,4 @@ public class URLValidator { return normalized; } -} \ No newline at end of file +} diff --git a/models/spring-ai-bedrock-converse/src/test/java/org/springframework/ai/bedrock/converse/BedrockConverseChatClientIT.java b/models/spring-ai-bedrock-converse/src/test/java/org/springframework/ai/bedrock/converse/BedrockConverseChatClientIT.java index 3486abd9d..2719569dc 100644 --- a/models/spring-ai-bedrock-converse/src/test/java/org/springframework/ai/bedrock/converse/BedrockConverseChatClientIT.java +++ b/models/spring-ai-bedrock-converse/src/test/java/org/springframework/ai/bedrock/converse/BedrockConverseChatClientIT.java @@ -1,5 +1,5 @@ /* - * Copyright 2024-2024 the original author or authors. + * Copyright 2023-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,8 +16,6 @@ package org.springframework.ai.bedrock.converse; -import static org.assertj.core.api.Assertions.assertThat; - import java.io.IOException; import java.net.URL; import java.util.Arrays; @@ -31,6 +29,8 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import reactor.core.publisher.Flux; + import org.springframework.ai.chat.client.ChatClient; import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor; import org.springframework.ai.chat.model.ChatModel; @@ -47,7 +47,7 @@ import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.util.MimeTypeUtils; -import reactor.core.publisher.Flux; +import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest(classes = BedrockConverseTestConfiguration.class) @EnabledIfEnvironmentVariable(named = "AWS_ACCESS_KEY_ID", matches = ".*") @@ -88,7 +88,7 @@ class BedrockConverseChatClientIT { .user(u -> u.text("List five {subject}") .param("subject", "ice cream flavors")) .call() - .entity(new ParameterizedTypeReference>() {}); + .entity(new ParameterizedTypeReference>() { }); // @formatter:on logger.info(collection.toString()); @@ -211,7 +211,7 @@ class BedrockConverseChatClientIT { // @formatter:off String response = ChatClient.create(this.chatModel) - .prompt("What's the weather like in San Francisco, Tokyo, and Paris? Return the temperature in Celsius.") + .prompt("What's the weather like in San Francisco, Tokyo, and Paris? Return the temperature in Celsius.") .function("getCurrentWeather", "Get the weather in location", new MockWeatherService()) .call() .content(); diff --git a/models/spring-ai-bedrock-converse/src/test/java/org/springframework/ai/bedrock/converse/BedrockConverseTestConfiguration.java b/models/spring-ai-bedrock-converse/src/test/java/org/springframework/ai/bedrock/converse/BedrockConverseTestConfiguration.java index 4275e9fc7..eaf220fb2 100644 --- a/models/spring-ai-bedrock-converse/src/test/java/org/springframework/ai/bedrock/converse/BedrockConverseTestConfiguration.java +++ b/models/spring-ai-bedrock-converse/src/test/java/org/springframework/ai/bedrock/converse/BedrockConverseTestConfiguration.java @@ -18,13 +18,13 @@ package org.springframework.ai.bedrock.converse; import java.time.Duration; +import software.amazon.awssdk.auth.credentials.EnvironmentVariableCredentialsProvider; +import software.amazon.awssdk.regions.Region; + import org.springframework.ai.model.function.FunctionCallingOptions; import org.springframework.boot.SpringBootConfiguration; import org.springframework.context.annotation.Bean; -import software.amazon.awssdk.auth.credentials.EnvironmentVariableCredentialsProvider; -import software.amazon.awssdk.regions.Region; - @SpringBootConfiguration public class BedrockConverseTestConfiguration { diff --git a/models/spring-ai-bedrock-converse/src/test/java/org/springframework/ai/bedrock/converse/BedrockProxyChatModelIT.java b/models/spring-ai-bedrock-converse/src/test/java/org/springframework/ai/bedrock/converse/BedrockProxyChatModelIT.java index e02965f67..f2f5c19f2 100644 --- a/models/spring-ai-bedrock-converse/src/test/java/org/springframework/ai/bedrock/converse/BedrockProxyChatModelIT.java +++ b/models/spring-ai-bedrock-converse/src/test/java/org/springframework/ai/bedrock/converse/BedrockProxyChatModelIT.java @@ -16,8 +16,6 @@ package org.springframework.ai.bedrock.converse; -import static org.assertj.core.api.Assertions.assertThat; - import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; @@ -32,6 +30,8 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import reactor.core.publisher.Flux; + import org.springframework.ai.chat.client.ChatClient; import org.springframework.ai.chat.messages.AssistantMessage; import org.springframework.ai.chat.messages.Message; @@ -57,7 +57,7 @@ import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.util.MimeTypeUtils; -import reactor.core.publisher.Flux; +import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest(classes = BedrockConverseTestConfiguration.class, properties = "spring.ai.retry.on-http-codes=429") @EnabledIfEnvironmentVariable(named = "AWS_ACCESS_KEY_ID", matches = ".*") diff --git a/models/spring-ai-bedrock-converse/src/test/java/org/springframework/ai/bedrock/converse/BedrockProxyChatModelObservationIT.java b/models/spring-ai-bedrock-converse/src/test/java/org/springframework/ai/bedrock/converse/BedrockProxyChatModelObservationIT.java index 70c130bb2..1b2be8a27 100644 --- a/models/spring-ai-bedrock-converse/src/test/java/org/springframework/ai/bedrock/converse/BedrockProxyChatModelObservationIT.java +++ b/models/spring-ai-bedrock-converse/src/test/java/org/springframework/ai/bedrock/converse/BedrockProxyChatModelObservationIT.java @@ -16,8 +16,6 @@ package org.springframework.ai.bedrock.converse; -import static org.assertj.core.api.Assertions.assertThat; - import java.util.List; import java.util.stream.Collectors; @@ -45,6 +43,8 @@ import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Bean; +import static org.assertj.core.api.Assertions.assertThat; + /** * Integration tests for observation instrumentation in {@link BedrockProxyChatModel}. * diff --git a/models/spring-ai-bedrock-converse/src/test/java/org/springframework/ai/bedrock/converse/MockWeatherService.java b/models/spring-ai-bedrock-converse/src/test/java/org/springframework/ai/bedrock/converse/MockWeatherService.java index af62aaf85..8579aa443 100644 --- a/models/spring-ai-bedrock-converse/src/test/java/org/springframework/ai/bedrock/converse/MockWeatherService.java +++ b/models/spring-ai-bedrock-converse/src/test/java/org/springframework/ai/bedrock/converse/MockWeatherService.java @@ -1,5 +1,5 @@ /* - * Copyright 2024-2024 the original author or authors. + * Copyright 2023-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -65,7 +65,7 @@ public class MockWeatherService implements Function - false diff --git a/models/spring-ai-huggingface/pom.xml b/models/spring-ai-huggingface/pom.xml index d0fe55836..9a1d487db 100644 --- a/models/spring-ai-huggingface/pom.xml +++ b/models/spring-ai-huggingface/pom.xml @@ -36,7 +36,6 @@ - false diff --git a/models/spring-ai-minimax/pom.xml b/models/spring-ai-minimax/pom.xml index 198f47112..8a592901a 100644 --- a/models/spring-ai-minimax/pom.xml +++ b/models/spring-ai-minimax/pom.xml @@ -37,7 +37,6 @@ - false diff --git a/models/spring-ai-mistral-ai/pom.xml b/models/spring-ai-mistral-ai/pom.xml index b95c4a23f..07e45c48d 100644 --- a/models/spring-ai-mistral-ai/pom.xml +++ b/models/spring-ai-mistral-ai/pom.xml @@ -38,7 +38,6 @@ - false diff --git a/models/spring-ai-moonshot/pom.xml b/models/spring-ai-moonshot/pom.xml index 5d72d8583..40527b8a1 100644 --- a/models/spring-ai-moonshot/pom.xml +++ b/models/spring-ai-moonshot/pom.xml @@ -38,7 +38,6 @@ - false diff --git a/models/spring-ai-oci-genai/pom.xml b/models/spring-ai-oci-genai/pom.xml index 82c34d044..1355d4230 100644 --- a/models/spring-ai-oci-genai/pom.xml +++ b/models/spring-ai-oci-genai/pom.xml @@ -37,7 +37,6 @@ - false diff --git a/models/spring-ai-ollama/pom.xml b/models/spring-ai-ollama/pom.xml index 0e9fb5b94..9f8e340dd 100644 --- a/models/spring-ai-ollama/pom.xml +++ b/models/spring-ai-ollama/pom.xml @@ -34,7 +34,6 @@ 17 17 UTF-8 - false diff --git a/models/spring-ai-openai/pom.xml b/models/spring-ai-openai/pom.xml index aa52d0521..a69a0224c 100644 --- a/models/spring-ai-openai/pom.xml +++ b/models/spring-ai-openai/pom.xml @@ -37,7 +37,6 @@ - false diff --git a/models/spring-ai-postgresml/pom.xml b/models/spring-ai-postgresml/pom.xml index d205720f1..ff1d1eed4 100644 --- a/models/spring-ai-postgresml/pom.xml +++ b/models/spring-ai-postgresml/pom.xml @@ -37,7 +37,6 @@ - false diff --git a/models/spring-ai-qianfan/pom.xml b/models/spring-ai-qianfan/pom.xml index 750fe69fc..a2483861c 100644 --- a/models/spring-ai-qianfan/pom.xml +++ b/models/spring-ai-qianfan/pom.xml @@ -37,7 +37,6 @@ - false diff --git a/models/spring-ai-stability-ai/pom.xml b/models/spring-ai-stability-ai/pom.xml index b1a14b4c9..0307df28d 100644 --- a/models/spring-ai-stability-ai/pom.xml +++ b/models/spring-ai-stability-ai/pom.xml @@ -37,7 +37,6 @@ - false diff --git a/models/spring-ai-transformers/pom.xml b/models/spring-ai-transformers/pom.xml index 3351485ed..2b99d6a99 100644 --- a/models/spring-ai-transformers/pom.xml +++ b/models/spring-ai-transformers/pom.xml @@ -37,7 +37,6 @@ - false diff --git a/models/spring-ai-vertex-ai-embedding/pom.xml b/models/spring-ai-vertex-ai-embedding/pom.xml index dc61e8dfb..5327e48b4 100644 --- a/models/spring-ai-vertex-ai-embedding/pom.xml +++ b/models/spring-ai-vertex-ai-embedding/pom.xml @@ -37,7 +37,6 @@ - false diff --git a/models/spring-ai-vertex-ai-gemini/pom.xml b/models/spring-ai-vertex-ai-gemini/pom.xml index 0f503e4e7..cc184d54b 100644 --- a/models/spring-ai-vertex-ai-gemini/pom.xml +++ b/models/spring-ai-vertex-ai-gemini/pom.xml @@ -37,7 +37,6 @@ - false diff --git a/models/spring-ai-watsonx-ai/pom.xml b/models/spring-ai-watsonx-ai/pom.xml index ca14a148d..3b8d281d0 100644 --- a/models/spring-ai-watsonx-ai/pom.xml +++ b/models/spring-ai-watsonx-ai/pom.xml @@ -34,7 +34,6 @@ 17 17 UTF-8 - false diff --git a/models/spring-ai-zhipuai/pom.xml b/models/spring-ai-zhipuai/pom.xml index 10bb5cbfc..f0f6a920f 100644 --- a/models/spring-ai-zhipuai/pom.xml +++ b/models/spring-ai-zhipuai/pom.xml @@ -36,7 +36,6 @@ git@github.com:spring-projects/spring-ai.git - false diff --git a/spring-ai-core/pom.xml b/spring-ai-core/pom.xml index 1a58c4cf8..e278f72cc 100644 --- a/spring-ai-core/pom.xml +++ b/spring-ai-core/pom.xml @@ -38,7 +38,6 @@ 4.13.1 - false diff --git a/spring-ai-retry/pom.xml b/spring-ai-retry/pom.xml index e479fa220..596aef76a 100644 --- a/spring-ai-retry/pom.xml +++ b/spring-ai-retry/pom.xml @@ -36,7 +36,6 @@ - false diff --git a/spring-ai-spring-boot-autoconfigure/pom.xml b/spring-ai-spring-boot-autoconfigure/pom.xml index 2f6179bee..425674e77 100644 --- a/spring-ai-spring-boot-autoconfigure/pom.xml +++ b/spring-ai-spring-boot-autoconfigure/pom.xml @@ -21,7 +21,6 @@ - false diff --git a/spring-ai-spring-boot-docker-compose/pom.xml b/spring-ai-spring-boot-docker-compose/pom.xml index 70115f2a5..62d0d0de8 100644 --- a/spring-ai-spring-boot-docker-compose/pom.xml +++ b/spring-ai-spring-boot-docker-compose/pom.xml @@ -36,7 +36,6 @@ - false diff --git a/spring-ai-spring-boot-testcontainers/pom.xml b/spring-ai-spring-boot-testcontainers/pom.xml index 13acbba68..f60e6b34d 100644 --- a/spring-ai-spring-boot-testcontainers/pom.xml +++ b/spring-ai-spring-boot-testcontainers/pom.xml @@ -37,7 +37,6 @@ - false diff --git a/spring-ai-spring-cloud-bindings/pom.xml b/spring-ai-spring-cloud-bindings/pom.xml index 60de4a951..576e4bb33 100644 --- a/spring-ai-spring-cloud-bindings/pom.xml +++ b/spring-ai-spring-cloud-bindings/pom.xml @@ -36,7 +36,6 @@ - false diff --git a/spring-ai-test/pom.xml b/spring-ai-test/pom.xml index 81a928a26..3397a92ae 100644 --- a/spring-ai-test/pom.xml +++ b/spring-ai-test/pom.xml @@ -37,7 +37,6 @@ 17 17 - false diff --git a/src/checkstyle/checkstyle.xml b/src/checkstyle/checkstyle.xml index b19befaaa..c95fea1a1 100644 --- a/src/checkstyle/checkstyle.xml +++ b/src/checkstyle/checkstyle.xml @@ -100,7 +100,7 @@ + value="org.springframework.ai.autoconfigure.vectorstore.observation.ObservationTestUtil.*, org.awaitility.Awaitility.*, org.springframework.ai.aot.AiRuntimeHints.*, org.springframework.ai.openai.metadata.support.OpenAiApiResponseHeaders.*, org.springframework.ai.image.observation.ImageModelObservationDocumentation.*, org.springframework.ai.embedding.observation.EmbeddingModelObservationDocumentation.*, org.springframework.aot.hint.predicate.RuntimeHintsPredicates.*, org.springframework.ai.vectorstore.filter.Filter.ExpressionType.*, org.springframework.ai.chat.observation.ChatModelObservationDocumentation.*, org.assertj.core.groups.Tuple.*, org.assertj.core.api.AssertionsForClassTypes.*, org.junit.jupiter.api.Assertions.*, org.assertj.core.api.Assertions.*, org.junit.Assert.*, org.junit.Assume.*, org.junit.internal.matchers.ThrowableMessageMatcher.*, org.hamcrest.CoreMatchers.*, org.hamcrest.Matchers.*, org.springframework.boot.configurationprocessor.ConfigurationMetadataMatchers.*, org.springframework.boot.configurationprocessor.TestCompiler.*, org.springframework.boot.test.autoconfigure.AutoConfigurationImportedCondition.*, org.mockito.Mockito.*, org.mockito.BDDMockito.*, org.mockito.Matchers.*, org.mockito.ArgumentMatchers.*, org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.*, org.springframework.restdocs.hypermedia.HypermediaDocumentation.*, org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*, org.springframework.test.web.servlet.result.MockMvcResultMatchers.*, org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.*, org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.*, org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.*, org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo, org.springframework.test.web.client.match.MockRestRequestMatchers.*, org.springframework.test.web.client.response.MockRestResponseCreators.*, org.springframework.web.reactive.function.server.RequestPredicates.*, org.springframework.web.reactive.function.server.RouterFunctions.*, org.springframework.test.web.servlet.setup.MockMvcBuilders.*"/> diff --git a/vector-stores/spring-ai-azure-cosmos-db-store/pom.xml b/vector-stores/spring-ai-azure-cosmos-db-store/pom.xml index 4dc1ca30d..ca93a9ece 100644 --- a/vector-stores/spring-ai-azure-cosmos-db-store/pom.xml +++ b/vector-stores/spring-ai-azure-cosmos-db-store/pom.xml @@ -39,7 +39,6 @@ 17 17 - false diff --git a/vector-stores/spring-ai-azure-store/pom.xml b/vector-stores/spring-ai-azure-store/pom.xml index 015199de5..25bf7e5f1 100644 --- a/vector-stores/spring-ai-azure-store/pom.xml +++ b/vector-stores/spring-ai-azure-store/pom.xml @@ -39,7 +39,6 @@ 17 17 - false diff --git a/vector-stores/spring-ai-cassandra-store/pom.xml b/vector-stores/spring-ai-cassandra-store/pom.xml index ea9892b38..1032f3635 100644 --- a/vector-stores/spring-ai-cassandra-store/pom.xml +++ b/vector-stores/spring-ai-cassandra-store/pom.xml @@ -39,7 +39,6 @@ 17 17 - false diff --git a/vector-stores/spring-ai-elasticsearch-store/pom.xml b/vector-stores/spring-ai-elasticsearch-store/pom.xml index 824842bd0..440dc99b7 100644 --- a/vector-stores/spring-ai-elasticsearch-store/pom.xml +++ b/vector-stores/spring-ai-elasticsearch-store/pom.xml @@ -39,7 +39,6 @@ 17 17 - false 4.0.3 diff --git a/vector-stores/spring-ai-gemfire-store/pom.xml b/vector-stores/spring-ai-gemfire-store/pom.xml index 2d1f84a66..37d859f70 100644 --- a/vector-stores/spring-ai-gemfire-store/pom.xml +++ b/vector-stores/spring-ai-gemfire-store/pom.xml @@ -39,7 +39,6 @@ 17 17 - false diff --git a/vector-stores/spring-ai-hanadb-store/pom.xml b/vector-stores/spring-ai-hanadb-store/pom.xml index 0e7280597..430297bb7 100644 --- a/vector-stores/spring-ai-hanadb-store/pom.xml +++ b/vector-stores/spring-ai-hanadb-store/pom.xml @@ -40,7 +40,6 @@ 17 17 - false diff --git a/vector-stores/spring-ai-milvus-store/pom.xml b/vector-stores/spring-ai-milvus-store/pom.xml index c671083d4..fddad05b6 100644 --- a/vector-stores/spring-ai-milvus-store/pom.xml +++ b/vector-stores/spring-ai-milvus-store/pom.xml @@ -39,7 +39,6 @@ 17 17 - false diff --git a/vector-stores/spring-ai-mongodb-atlas-store/pom.xml b/vector-stores/spring-ai-mongodb-atlas-store/pom.xml index 753b5f9c8..b1b803005 100644 --- a/vector-stores/spring-ai-mongodb-atlas-store/pom.xml +++ b/vector-stores/spring-ai-mongodb-atlas-store/pom.xml @@ -38,7 +38,6 @@ 17 17 - false diff --git a/vector-stores/spring-ai-neo4j-store/pom.xml b/vector-stores/spring-ai-neo4j-store/pom.xml index 29697aaeb..a8acbfc8f 100644 --- a/vector-stores/spring-ai-neo4j-store/pom.xml +++ b/vector-stores/spring-ai-neo4j-store/pom.xml @@ -39,7 +39,6 @@ 17 17 - false diff --git a/vector-stores/spring-ai-opensearch-store/pom.xml b/vector-stores/spring-ai-opensearch-store/pom.xml index e8c5972f2..aa3ddfbbd 100644 --- a/vector-stores/spring-ai-opensearch-store/pom.xml +++ b/vector-stores/spring-ai-opensearch-store/pom.xml @@ -39,7 +39,6 @@ 4.0.3 - false diff --git a/vector-stores/spring-ai-oracle-store/pom.xml b/vector-stores/spring-ai-oracle-store/pom.xml index 3e56973eb..0f795fa89 100644 --- a/vector-stores/spring-ai-oracle-store/pom.xml +++ b/vector-stores/spring-ai-oracle-store/pom.xml @@ -39,7 +39,6 @@ 17 17 - false diff --git a/vector-stores/spring-ai-pgvector-store/pom.xml b/vector-stores/spring-ai-pgvector-store/pom.xml index c36221d7e..5b4a7b0df 100644 --- a/vector-stores/spring-ai-pgvector-store/pom.xml +++ b/vector-stores/spring-ai-pgvector-store/pom.xml @@ -39,7 +39,6 @@ 17 17 - false diff --git a/vector-stores/spring-ai-pinecone-store/pom.xml b/vector-stores/spring-ai-pinecone-store/pom.xml index 8603595fb..87b2722c5 100644 --- a/vector-stores/spring-ai-pinecone-store/pom.xml +++ b/vector-stores/spring-ai-pinecone-store/pom.xml @@ -38,7 +38,6 @@ 17 17 - false diff --git a/vector-stores/spring-ai-qdrant-store/pom.xml b/vector-stores/spring-ai-qdrant-store/pom.xml index d2938dcb5..2d9c598e5 100644 --- a/vector-stores/spring-ai-qdrant-store/pom.xml +++ b/vector-stores/spring-ai-qdrant-store/pom.xml @@ -39,7 +39,6 @@ 17 17 - false diff --git a/vector-stores/spring-ai-redis-store/pom.xml b/vector-stores/spring-ai-redis-store/pom.xml index 394f00aac..80c7c6874 100644 --- a/vector-stores/spring-ai-redis-store/pom.xml +++ b/vector-stores/spring-ai-redis-store/pom.xml @@ -41,7 +41,6 @@ 5.1.0 17 17 - false diff --git a/vector-stores/spring-ai-typesense-store/pom.xml b/vector-stores/spring-ai-typesense-store/pom.xml index 860758ec4..db03d7917 100644 --- a/vector-stores/spring-ai-typesense-store/pom.xml +++ b/vector-stores/spring-ai-typesense-store/pom.xml @@ -39,7 +39,6 @@ - false diff --git a/vector-stores/spring-ai-weaviate-store/pom.xml b/vector-stores/spring-ai-weaviate-store/pom.xml index 7a1b19ef5..c1ea5ff95 100644 --- a/vector-stores/spring-ai-weaviate-store/pom.xml +++ b/vector-stores/spring-ai-weaviate-store/pom.xml @@ -38,7 +38,6 @@ 17 17 - false