Fix checkstyle errors
This commit is contained in:
@@ -29,8 +29,6 @@ import io.micrometer.observation.ObservationRegistry;
|
||||
import io.micrometer.observation.contextpropagation.ObservationThreadLocalAccessor;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.ai.model.Media;
|
||||
import org.springframework.util.MimeType;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
@@ -62,6 +60,7 @@ import org.springframework.ai.mistralai.api.MistralAiApi.ChatCompletionMessage.C
|
||||
import org.springframework.ai.mistralai.api.MistralAiApi.ChatCompletionMessage.ToolCall;
|
||||
import org.springframework.ai.mistralai.api.MistralAiApi.ChatCompletionRequest;
|
||||
import org.springframework.ai.mistralai.metadata.MistralAiUsage;
|
||||
import org.springframework.ai.model.Media;
|
||||
import org.springframework.ai.model.ModelOptionsUtils;
|
||||
import org.springframework.ai.model.function.FunctionCallback;
|
||||
import org.springframework.ai.model.function.FunctionCallbackResolver;
|
||||
@@ -71,6 +70,7 @@ import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.retry.support.RetryTemplate;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.MimeType;
|
||||
|
||||
/**
|
||||
* Represents a Mistral AI Chat Model.
|
||||
|
||||
@@ -16,12 +16,22 @@
|
||||
|
||||
package org.springframework.ai.mistralai;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
|
||||
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.messages.AssistantMessage;
|
||||
import org.springframework.ai.chat.messages.Message;
|
||||
import org.springframework.ai.chat.messages.UserMessage;
|
||||
@@ -46,15 +56,6 @@ import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.util.MimeTypeUtils;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@ import java.util.function.Function;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
@@ -672,15 +672,15 @@ public class OllamaApi {
|
||||
}
|
||||
|
||||
public Duration getTotalDuration() {
|
||||
return (this.totalDuration() != null)? Duration.ofNanos(this.totalDuration()) : null;
|
||||
return (this.totalDuration() != null) ? Duration.ofNanos(this.totalDuration()) : null;
|
||||
}
|
||||
|
||||
public Duration getLoadDuration() {
|
||||
return (this.loadDuration() != null)? Duration.ofNanos(this.loadDuration()) : null;
|
||||
return (this.loadDuration() != null) ? Duration.ofNanos(this.loadDuration()) : null;
|
||||
}
|
||||
|
||||
public Duration getPromptEvalDuration() {
|
||||
return (this.promptEvalDuration() != null)? Duration.ofNanos(this.promptEvalDuration()) : null;
|
||||
return (this.promptEvalDuration() != null) ? Duration.ofNanos(this.promptEvalDuration()) : null;
|
||||
}
|
||||
|
||||
public Duration getEvalDuration() {
|
||||
|
||||
@@ -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 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.
|
||||
*/
|
||||
|
||||
package org.springframework.ai.ollama.api;
|
||||
|
||||
import java.time.Instant;
|
||||
@@ -28,6 +29,10 @@ import org.springframework.util.CollectionUtils;
|
||||
*/
|
||||
public final class OllamaApiHelper {
|
||||
|
||||
private OllamaApiHelper() {
|
||||
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ollamaChatResponse the Ollama chat response chunk to check
|
||||
* @return true if the chunk is a streaming tool call.
|
||||
|
||||
@@ -117,7 +117,7 @@ public class OllamaModelManager {
|
||||
logger.info("Pulling the '{}' model - Status: {}", modelName, progressResponses.get(progressResponses.size() - 1).status());
|
||||
}
|
||||
})
|
||||
.takeUntil(progressResponses ->
|
||||
.takeUntil(progressResponses ->
|
||||
progressResponses.get(0) != null && "success".equals(progressResponses.get(0).status()))
|
||||
.timeout(this.options.timeout())
|
||||
.retryWhen(Retry.backoff(this.options.maxRetries(), Duration.ofSeconds(5)))
|
||||
|
||||
@@ -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 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.
|
||||
*/
|
||||
|
||||
package org.springframework.ai.ollama.api;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
|
||||
@@ -325,7 +325,7 @@ public class OpenAiChatOptions implements FunctionCallingOptions {
|
||||
}
|
||||
|
||||
public List<String> getOutputModalities() {
|
||||
return outputModalities;
|
||||
return this.outputModalities;
|
||||
}
|
||||
|
||||
public void setOutputModalities(List<String> modalities) {
|
||||
@@ -333,7 +333,7 @@ public class OpenAiChatOptions implements FunctionCallingOptions {
|
||||
}
|
||||
|
||||
public AudioParameters getOutputAudio() {
|
||||
return outputAudio;
|
||||
return this.outputAudio;
|
||||
}
|
||||
|
||||
public void setOutputAudio(AudioParameters audio) {
|
||||
|
||||
@@ -16,11 +16,12 @@
|
||||
|
||||
package org.springframework.ai.openai;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import org.springframework.ai.image.ImageOptions;
|
||||
|
||||
import java.util.Objects;
|
||||
import org.springframework.ai.image.ImageOptions;
|
||||
|
||||
/**
|
||||
* OpenAI Image API options. OpenAiImageOptions.java
|
||||
|
||||
@@ -960,7 +960,7 @@ public class OpenAiApi {
|
||||
@JsonProperty("mp3") MP3,
|
||||
/** FLAC format */
|
||||
@JsonProperty("flac") FLAC,
|
||||
/** OPUS format */
|
||||
/** OPUS format */
|
||||
@JsonProperty("opus") OPUS,
|
||||
/** PCM16 format */
|
||||
@JsonProperty("pcm16") PCM16,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2024 the original author or authors.
|
||||
* 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.
|
||||
|
||||
@@ -47,7 +47,6 @@ import com.google.protobuf.util.JsonFormat;
|
||||
import io.micrometer.observation.Observation;
|
||||
import io.micrometer.observation.ObservationRegistry;
|
||||
import io.micrometer.observation.contextpropagation.ObservationThreadLocalAccessor;
|
||||
import org.springframework.ai.vertexai.gemini.common.VertexAiGeminiSafetySetting;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import org.springframework.ai.chat.messages.AssistantMessage;
|
||||
@@ -77,6 +76,7 @@ import org.springframework.ai.model.function.FunctionCallbackResolver;
|
||||
import org.springframework.ai.model.function.FunctionCallingOptions;
|
||||
import org.springframework.ai.retry.RetryUtils;
|
||||
import org.springframework.ai.vertexai.gemini.common.VertexAiGeminiConstants;
|
||||
import org.springframework.ai.vertexai.gemini.common.VertexAiGeminiSafetySetting;
|
||||
import org.springframework.ai.vertexai.gemini.metadata.VertexAiUsage;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.lang.NonNull;
|
||||
|
||||
@@ -273,7 +273,7 @@ public class VertexAiGeminiChatOptions implements FunctionCallingOptions {
|
||||
}
|
||||
|
||||
public List<VertexAiGeminiSafetySetting> getSafetySettings() {
|
||||
return safetySettings;
|
||||
return this.safetySettings;
|
||||
}
|
||||
|
||||
public void setSafetySettings(List<VertexAiGeminiSafetySetting> safetySettings) {
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2024-2025 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.vertexai.gemini.common;
|
||||
|
||||
public class VertexAiGeminiSafetySetting {
|
||||
@@ -17,7 +33,7 @@ public class VertexAiGeminiSafetySetting {
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return value;
|
||||
return this.value;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -36,7 +52,7 @@ public class VertexAiGeminiSafetySetting {
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return value;
|
||||
return this.value;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -56,7 +72,7 @@ public class VertexAiGeminiSafetySetting {
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return value;
|
||||
return this.value;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -83,7 +99,7 @@ public class VertexAiGeminiSafetySetting {
|
||||
|
||||
// Getters and setters
|
||||
public HarmCategory getCategory() {
|
||||
return category;
|
||||
return this.category;
|
||||
}
|
||||
|
||||
public void setCategory(HarmCategory category) {
|
||||
@@ -91,7 +107,7 @@ public class VertexAiGeminiSafetySetting {
|
||||
}
|
||||
|
||||
public HarmBlockThreshold getThreshold() {
|
||||
return threshold;
|
||||
return this.threshold;
|
||||
}
|
||||
|
||||
public void setThreshold(HarmBlockThreshold threshold) {
|
||||
@@ -99,7 +115,7 @@ public class VertexAiGeminiSafetySetting {
|
||||
}
|
||||
|
||||
public HarmBlockMethod getMethod() {
|
||||
return method;
|
||||
return this.method;
|
||||
}
|
||||
|
||||
public void setMethod(HarmBlockMethod method) {
|
||||
@@ -108,30 +124,35 @@ public class VertexAiGeminiSafetySetting {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SafetySetting{" + "category=" + category + ", threshold=" + threshold + ", method=" + method + '}';
|
||||
return "SafetySetting{" + "category=" + this.category + ", threshold=" + this.threshold + ", method="
|
||||
+ this.method + '}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o)
|
||||
if (this == o) {
|
||||
return true;
|
||||
if (o == null || getClass() != o.getClass())
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
VertexAiGeminiSafetySetting that = (VertexAiGeminiSafetySetting) o;
|
||||
|
||||
if (category != that.category)
|
||||
if (this.category != that.category) {
|
||||
return false;
|
||||
if (threshold != that.threshold)
|
||||
}
|
||||
if (this.threshold != that.threshold) {
|
||||
return false;
|
||||
return method == that.method;
|
||||
}
|
||||
return this.method == that.method;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = category != null ? category.hashCode() : 0;
|
||||
result = 31 * result + (threshold != null ? threshold.hashCode() : 0);
|
||||
result = 31 * result + (method != null ? method.hashCode() : 0);
|
||||
int result = this.category != null ? this.category.hashCode() : 0;
|
||||
result = 31 * result + (this.threshold != null ? this.threshold.hashCode() : 0);
|
||||
result = 31 * result + (this.method != null ? this.method.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -159,7 +180,7 @@ public class VertexAiGeminiSafetySetting {
|
||||
}
|
||||
|
||||
public VertexAiGeminiSafetySetting build() {
|
||||
return new VertexAiGeminiSafetySetting(category, threshold, method);
|
||||
return new VertexAiGeminiSafetySetting(this.category, this.threshold, this.method);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.ai.embedding.EmbeddingOptions;
|
||||
import org.springframework.ai.embedding.EmbeddingOptionsBuilder;
|
||||
import org.springframework.ai.embedding.EmbeddingResponse;
|
||||
import org.springframework.ai.watsonx.api.WatsonxAiApi;
|
||||
|
||||
@@ -140,7 +140,7 @@ public final class RetrievalAugmentationAdvisor implements BaseAdvisor {
|
||||
* documents.
|
||||
*/
|
||||
private Map.Entry<Query, List<Document>> getDocumentsForQuery(Query query) {
|
||||
List<Document> documents = documentRetriever.retrieve(query);
|
||||
List<Document> documents = this.documentRetriever.retrieve(query);
|
||||
return Map.entry(query, documents);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.springframework.ai.chat.model.ChatModel;
|
||||
import org.springframework.ai.chat.model.ChatResponse;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -23,7 +23,11 @@ import org.springframework.ai.chat.model.ChatResponse;
|
||||
*
|
||||
* @author Ilayaperumal Gopinathan
|
||||
*/
|
||||
public class UsageUtils {
|
||||
public final class UsageUtils {
|
||||
|
||||
private UsageUtils() {
|
||||
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
|
||||
}
|
||||
|
||||
/**
|
||||
* Accumulate usage tokens from the previous chat response to the current usage
|
||||
|
||||
@@ -49,7 +49,7 @@ public enum DocumentMetadata {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return value;
|
||||
return this.value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.springframework.ai.document.Document;
|
||||
import org.springframework.ai.model.Content;
|
||||
|
||||
/**
|
||||
* Represents an evaluation request, which includes the user's text, a list of content
|
||||
|
||||
@@ -20,7 +20,6 @@ import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.ai.document.Document;
|
||||
import org.springframework.ai.model.Content;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@FunctionalInterface
|
||||
|
||||
@@ -127,7 +127,7 @@ public class FactCheckingEvaluator implements Evaluator {
|
||||
|
||||
String evaluationResponse = this.chatClientBuilder.build()
|
||||
.prompt()
|
||||
.user(userSpec -> userSpec.text(evaluationPrompt).param("document", context).param("claim", response))
|
||||
.user(userSpec -> userSpec.text(this.evaluationPrompt).param("document", context).param("claim", response))
|
||||
.call()
|
||||
.content();
|
||||
|
||||
|
||||
@@ -1,17 +1,41 @@
|
||||
package org.springframework.ai.model;
|
||||
/*
|
||||
* Copyright 2024-2025 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.
|
||||
*/
|
||||
|
||||
import com.github.victools.jsonschema.generator.*;
|
||||
import com.github.victools.jsonschema.generator.Module;
|
||||
import kotlin.jvm.JvmClassMappingKt;
|
||||
import kotlin.reflect.*;
|
||||
import kotlin.reflect.full.KClasses;
|
||||
import kotlin.reflect.jvm.ReflectJvmMapping;
|
||||
import org.springframework.core.KotlinDetector;
|
||||
package org.springframework.ai.model;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.github.victools.jsonschema.generator.FieldScope;
|
||||
import com.github.victools.jsonschema.generator.MemberScope;
|
||||
import com.github.victools.jsonschema.generator.Module;
|
||||
import com.github.victools.jsonschema.generator.SchemaGeneratorConfigBuilder;
|
||||
import com.github.victools.jsonschema.generator.SchemaGeneratorConfigPart;
|
||||
import kotlin.jvm.JvmClassMappingKt;
|
||||
import kotlin.reflect.KClass;
|
||||
import kotlin.reflect.KFunction;
|
||||
import kotlin.reflect.KParameter;
|
||||
import kotlin.reflect.KProperty;
|
||||
import kotlin.reflect.KType;
|
||||
import kotlin.reflect.full.KClasses;
|
||||
import kotlin.reflect.jvm.ReflectJvmMapping;
|
||||
|
||||
import org.springframework.core.KotlinDetector;
|
||||
|
||||
public class KotlinModule implements Module {
|
||||
|
||||
@Override
|
||||
|
||||
@@ -161,7 +161,7 @@ public class Media {
|
||||
* Creates a new Media builder.
|
||||
* @return a new Media builder instance
|
||||
*/
|
||||
public static Builder builder() {
|
||||
public static final Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
@@ -228,7 +228,7 @@ public class Media {
|
||||
/**
|
||||
* Builder class for Media.
|
||||
*/
|
||||
public static class Builder {
|
||||
public static final class Builder {
|
||||
|
||||
private String id;
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.springframework.ai.model;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public interface MediaContent extends Content {
|
||||
|
||||
@@ -1,3 +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.
|
||||
*/
|
||||
|
||||
package org.springframework.ai.model.function;
|
||||
|
||||
import java.util.function.Function;
|
||||
@@ -112,4 +128,4 @@ public class DefaultCommonCallbackInvokingSpec<B extends CommonCallbackInvokingS
|
||||
return this.objectMapper;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package org.springframework.ai.moderation;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A builder class for creating instances of ModerationOptions. Use the builder() method
|
||||
* to obtain a new instance of ModerationOptionsBuilder. Use the withModel() method to set
|
||||
|
||||
@@ -16,12 +16,12 @@
|
||||
|
||||
package org.springframework.ai.rag;
|
||||
|
||||
import org.springframework.ai.chat.messages.Message;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.ai.chat.messages.Message;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Represents a query in the context of a Retrieval Augmented Generation (RAG) flow.
|
||||
*
|
||||
@@ -53,7 +53,7 @@ public record Query(String text, List<Message> history, Map<String, Object> cont
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
public static final class Builder {
|
||||
|
||||
private String text;
|
||||
|
||||
@@ -85,7 +85,7 @@ public record Query(String text, List<Message> history, Map<String, Object> cont
|
||||
}
|
||||
|
||||
public Query build() {
|
||||
return new Query(text, history, context);
|
||||
return new Query(this.text, this.history, this.context);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.ai.chat.prompt.PromptTemplate;
|
||||
import org.springframework.ai.document.Document;
|
||||
import org.springframework.ai.model.Content;
|
||||
import org.springframework.ai.rag.Query;
|
||||
import org.springframework.ai.util.PromptAssert;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
@@ -16,8 +16,12 @@
|
||||
|
||||
package org.springframework.ai.rag.preretrieval.query.transformation;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.ai.chat.client.ChatClient;
|
||||
import org.springframework.ai.chat.messages.Message;
|
||||
import org.springframework.ai.chat.messages.MessageType;
|
||||
@@ -29,9 +33,6 @@ import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Uses a large language model to compress a conversation history and a follow-up query
|
||||
* into a standalone query that captures the essence of the conversation.
|
||||
@@ -132,7 +133,7 @@ public class CompressionQueryTransformer implements QueryTransformer {
|
||||
}
|
||||
|
||||
public CompressionQueryTransformer build() {
|
||||
return new CompressionQueryTransformer(chatClientBuilder, promptTemplate);
|
||||
return new CompressionQueryTransformer(this.chatClientBuilder, this.promptTemplate);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.ai.rag.preretrieval.query.transformation;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.ai.chat.client.ChatClient;
|
||||
import org.springframework.ai.chat.prompt.ChatOptions;
|
||||
import org.springframework.ai.chat.prompt.PromptTemplate;
|
||||
@@ -79,7 +80,7 @@ public class RewriteQueryTransformer implements QueryTransformer {
|
||||
|
||||
var rewrittenQueryText = this.chatClient.prompt()
|
||||
.user(user -> user.text(this.promptTemplate.getTemplate())
|
||||
.param("target", targetSearchSystem)
|
||||
.param("target", this.targetSearchSystem)
|
||||
.param("query", query.text()))
|
||||
.options(ChatOptions.builder().temperature(0.0).build())
|
||||
.call()
|
||||
@@ -126,7 +127,7 @@ public class RewriteQueryTransformer implements QueryTransformer {
|
||||
}
|
||||
|
||||
public RewriteQueryTransformer build() {
|
||||
return new RewriteQueryTransformer(chatClientBuilder, promptTemplate, targetSearchSystem);
|
||||
return new RewriteQueryTransformer(this.chatClientBuilder, this.promptTemplate, this.targetSearchSystem);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.ai.rag.preretrieval.query.transformation;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.ai.chat.client.ChatClient;
|
||||
import org.springframework.ai.chat.prompt.ChatOptions;
|
||||
import org.springframework.ai.chat.prompt.PromptTemplate;
|
||||
|
||||
@@ -92,6 +92,109 @@ public final class SearchRequest {
|
||||
return new Builder().topK(DEFAULT_TOP_K).similarityThresholdAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link Builder#query(String)} instead.
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "1.0.0-M5")
|
||||
public SearchRequest withQuery(String query) {
|
||||
Assert.notNull(query, "Query can not be null.");
|
||||
this.query = query;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link Builder#topK(int)} instead.
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "1.0.0-M5")
|
||||
public SearchRequest withTopK(int topK) {
|
||||
Assert.isTrue(topK >= 0, "TopK should be positive.");
|
||||
this.topK = topK;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link Builder#similarityThreshold(double)} instead.
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "1.0.0-M5")
|
||||
public SearchRequest withSimilarityThreshold(double threshold) {
|
||||
Assert.isTrue(threshold >= 0 && threshold <= 1, "Similarity threshold must be in [0,1] range.");
|
||||
this.similarityThreshold = threshold;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link Builder#similarityThresholdAll()} instead.
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "1.0.0-M5")
|
||||
public SearchRequest withSimilarityThresholdAll() {
|
||||
return withSimilarityThreshold(SIMILARITY_THRESHOLD_ACCEPT_ALL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link Builder#filterExpression(Filter.Expression)} instead.
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "1.0.0-M5")
|
||||
public SearchRequest withFilterExpression(@Nullable Filter.Expression expression) {
|
||||
this.filterExpression = expression;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link Builder#filterExpression(String)} instead.
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "1.0.0-M5")
|
||||
public SearchRequest withFilterExpression(@Nullable String textExpression) {
|
||||
this.filterExpression = (textExpression != null) ? new FilterExpressionTextParser().parse(textExpression)
|
||||
: null;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getQuery() {
|
||||
return this.query;
|
||||
}
|
||||
|
||||
public int getTopK() {
|
||||
return this.topK;
|
||||
}
|
||||
|
||||
public double getSimilarityThreshold() {
|
||||
return this.similarityThreshold;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Filter.Expression getFilterExpression() {
|
||||
return this.filterExpression;
|
||||
}
|
||||
|
||||
public boolean hasFilterExpression() {
|
||||
return this.filterExpression != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SearchRequest{" + "query='" + this.query + '\'' + ", topK=" + this.topK + ", similarityThreshold="
|
||||
+ this.similarityThreshold + ", filterExpression=" + this.filterExpression + '}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
SearchRequest that = (SearchRequest) o;
|
||||
return this.topK == that.topK && Double.compare(that.similarityThreshold, this.similarityThreshold) == 0
|
||||
&& Objects.equals(this.query, that.query)
|
||||
&& Objects.equals(this.filterExpression, that.filterExpression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(this.query, this.topK, this.similarityThreshold, this.filterExpression);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder for creating the SearchRequest instance.
|
||||
* @return the builder.
|
||||
@@ -258,107 +361,4 @@ public final class SearchRequest {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link Builder#query(String)} instead.
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "1.0.0-M5")
|
||||
public SearchRequest withQuery(String query) {
|
||||
Assert.notNull(query, "Query can not be null.");
|
||||
this.query = query;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link Builder#topK(int)} instead.
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "1.0.0-M5")
|
||||
public SearchRequest withTopK(int topK) {
|
||||
Assert.isTrue(topK >= 0, "TopK should be positive.");
|
||||
this.topK = topK;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link Builder#similarityThreshold(double)} instead.
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "1.0.0-M5")
|
||||
public SearchRequest withSimilarityThreshold(double threshold) {
|
||||
Assert.isTrue(threshold >= 0 && threshold <= 1, "Similarity threshold must be in [0,1] range.");
|
||||
this.similarityThreshold = threshold;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link Builder#similarityThresholdAll()} instead.
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "1.0.0-M5")
|
||||
public SearchRequest withSimilarityThresholdAll() {
|
||||
return withSimilarityThreshold(SIMILARITY_THRESHOLD_ACCEPT_ALL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link Builder#filterExpression(Filter.Expression)} instead.
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "1.0.0-M5")
|
||||
public SearchRequest withFilterExpression(@Nullable Filter.Expression expression) {
|
||||
this.filterExpression = expression;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link Builder#filterExpression(String)} instead.
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "1.0.0-M5")
|
||||
public SearchRequest withFilterExpression(@Nullable String textExpression) {
|
||||
this.filterExpression = (textExpression != null) ? new FilterExpressionTextParser().parse(textExpression)
|
||||
: null;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getQuery() {
|
||||
return this.query;
|
||||
}
|
||||
|
||||
public int getTopK() {
|
||||
return this.topK;
|
||||
}
|
||||
|
||||
public double getSimilarityThreshold() {
|
||||
return this.similarityThreshold;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Filter.Expression getFilterExpression() {
|
||||
return this.filterExpression;
|
||||
}
|
||||
|
||||
public boolean hasFilterExpression() {
|
||||
return this.filterExpression != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SearchRequest{" + "query='" + this.query + '\'' + ", topK=" + this.topK + ", similarityThreshold="
|
||||
+ this.similarityThreshold + ", filterExpression=" + this.filterExpression + '}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
SearchRequest that = (SearchRequest) o;
|
||||
return this.topK == that.topK && Double.compare(that.similarityThreshold, this.similarityThreshold) == 0
|
||||
&& Objects.equals(this.query, that.query)
|
||||
&& Objects.equals(this.filterExpression, that.filterExpression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(this.query, this.topK, this.similarityThreshold, this.filterExpression);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,8 +16,11 @@
|
||||
|
||||
package org.springframework.ai.chat.client.advisor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
||||
import org.springframework.ai.chat.client.ChatClient;
|
||||
import org.springframework.ai.chat.messages.AssistantMessage;
|
||||
import org.springframework.ai.chat.model.ChatModel;
|
||||
@@ -29,8 +32,6 @@ import org.springframework.ai.rag.Query;
|
||||
import org.springframework.ai.rag.preretrieval.query.transformation.QueryTransformer;
|
||||
import org.springframework.ai.rag.retrieval.search.DocumentRetriever;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.springframework.ai.chat.prompt;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -43,12 +42,12 @@ public class ChatOptionsBuilderTests {
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
builder = ChatOptions.builder();
|
||||
this.builder = ChatOptions.builder();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldBuildWithAllOptions() {
|
||||
ChatOptions options = builder.model("gpt-4")
|
||||
ChatOptions options = this.builder.model("gpt-4")
|
||||
.maxTokens(100)
|
||||
.temperature(0.7)
|
||||
.topP(1.0)
|
||||
@@ -66,7 +65,7 @@ public class ChatOptionsBuilderTests {
|
||||
|
||||
@Test
|
||||
void shouldBuildWithMinimalOptions() {
|
||||
ChatOptions options = builder.model("gpt-4").build();
|
||||
ChatOptions options = this.builder.model("gpt-4").build();
|
||||
|
||||
assertThat(options.getModel()).isEqualTo("gpt-4");
|
||||
assertThat(options.getMaxTokens()).isNull();
|
||||
@@ -78,7 +77,7 @@ public class ChatOptionsBuilderTests {
|
||||
|
||||
@Test
|
||||
void shouldCopyOptions() {
|
||||
ChatOptions original = builder.model("gpt-4")
|
||||
ChatOptions original = this.builder.model("gpt-4")
|
||||
.maxTokens(100)
|
||||
.temperature(0.7)
|
||||
.topP(1.0)
|
||||
@@ -129,8 +128,8 @@ public class ChatOptionsBuilderTests {
|
||||
@Test
|
||||
void shouldAllowBuilderReuse() {
|
||||
// When
|
||||
ChatOptions options1 = builder.model("model1").temperature(0.7).build();
|
||||
ChatOptions options2 = builder.model("model2").build();
|
||||
ChatOptions options1 = this.builder.model("model1").temperature(0.7).build();
|
||||
ChatOptions options2 = this.builder.model("model2").build();
|
||||
|
||||
// Then
|
||||
assertThat(options1.getModel()).isEqualTo("model1");
|
||||
@@ -142,16 +141,16 @@ public class ChatOptionsBuilderTests {
|
||||
@Test
|
||||
void shouldReturnSameBuilderInstanceOnEachMethod() {
|
||||
// When
|
||||
ChatOptions.Builder returnedBuilder = builder.model("test");
|
||||
ChatOptions.Builder returnedBuilder = this.builder.model("test");
|
||||
|
||||
// Then
|
||||
assertThat(returnedBuilder).isSameAs(builder);
|
||||
assertThat(returnedBuilder).isSameAs(this.builder);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldHaveExpectedDefaultValues() {
|
||||
// When
|
||||
ChatOptions options = builder.build();
|
||||
ChatOptions options = this.builder.build();
|
||||
|
||||
// Then
|
||||
assertThat(options.getModel()).isNull();
|
||||
@@ -168,7 +167,7 @@ public class ChatOptionsBuilderTests {
|
||||
void shouldBeImmutableAfterBuild() {
|
||||
// Given
|
||||
List<String> stopSequences = new ArrayList<>(List.of("stop1", "stop2"));
|
||||
ChatOptions options = builder.stopSequences(stopSequences).build();
|
||||
ChatOptions options = this.builder.stopSequences(stopSequences).build();
|
||||
|
||||
// Then
|
||||
assertThatThrownBy(() -> options.getStopSequences().add("stop3"))
|
||||
|
||||
@@ -1,3 +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.
|
||||
*/
|
||||
|
||||
package org.springframework.ai.model;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -8,7 +24,6 @@ import java.util.UUID;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.core.io.ByteArrayResource;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.util.MimeType;
|
||||
|
||||
|
||||
@@ -16,9 +16,6 @@
|
||||
|
||||
package org.springframework.ai.model.function;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
@@ -26,6 +23,9 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.ai.chat.prompt.ChatOptions;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -41,7 +41,7 @@ class DefaultFunctionCallingOptionsBuilderTests {
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
builder = new DefaultFunctionCallingOptionsBuilder();
|
||||
this.builder = new DefaultFunctionCallingOptionsBuilder();
|
||||
}
|
||||
|
||||
// Tests for inherited ChatOptions properties
|
||||
@@ -49,7 +49,7 @@ class DefaultFunctionCallingOptionsBuilderTests {
|
||||
@Test
|
||||
void shouldBuildWithModel() {
|
||||
// When
|
||||
ChatOptions options = builder.model("gpt-4").build();
|
||||
ChatOptions options = this.builder.model("gpt-4").build();
|
||||
|
||||
// Then
|
||||
assertThat(options.getModel()).isEqualTo("gpt-4");
|
||||
@@ -58,7 +58,7 @@ class DefaultFunctionCallingOptionsBuilderTests {
|
||||
@Test
|
||||
void shouldBuildWithFrequencyPenalty() {
|
||||
// When
|
||||
ChatOptions options = builder.frequencyPenalty(0.5).build();
|
||||
ChatOptions options = this.builder.frequencyPenalty(0.5).build();
|
||||
|
||||
// Then
|
||||
assertThat(options.getFrequencyPenalty()).isEqualTo(0.5);
|
||||
@@ -67,7 +67,7 @@ class DefaultFunctionCallingOptionsBuilderTests {
|
||||
@Test
|
||||
void shouldBuildWithMaxTokens() {
|
||||
// When
|
||||
ChatOptions options = builder.maxTokens(100).build();
|
||||
ChatOptions options = this.builder.maxTokens(100).build();
|
||||
|
||||
// Then
|
||||
assertThat(options.getMaxTokens()).isEqualTo(100);
|
||||
@@ -76,7 +76,7 @@ class DefaultFunctionCallingOptionsBuilderTests {
|
||||
@Test
|
||||
void shouldBuildWithPresencePenalty() {
|
||||
// When
|
||||
ChatOptions options = builder.presencePenalty(0.7).build();
|
||||
ChatOptions options = this.builder.presencePenalty(0.7).build();
|
||||
|
||||
// Then
|
||||
assertThat(options.getPresencePenalty()).isEqualTo(0.7);
|
||||
@@ -88,7 +88,7 @@ class DefaultFunctionCallingOptionsBuilderTests {
|
||||
List<String> stopSequences = List.of("stop1", "stop2");
|
||||
|
||||
// When
|
||||
ChatOptions options = builder.stopSequences(stopSequences).build();
|
||||
ChatOptions options = this.builder.stopSequences(stopSequences).build();
|
||||
|
||||
// Then
|
||||
assertThat(options.getStopSequences()).hasSize(2).containsExactlyElementsOf(stopSequences);
|
||||
@@ -97,7 +97,7 @@ class DefaultFunctionCallingOptionsBuilderTests {
|
||||
@Test
|
||||
void shouldBuildWithTemperature() {
|
||||
// When
|
||||
ChatOptions options = builder.temperature(0.8).build();
|
||||
ChatOptions options = this.builder.temperature(0.8).build();
|
||||
|
||||
// Then
|
||||
assertThat(options.getTemperature()).isEqualTo(0.8);
|
||||
@@ -106,7 +106,7 @@ class DefaultFunctionCallingOptionsBuilderTests {
|
||||
@Test
|
||||
void shouldBuildWithTopK() {
|
||||
// When
|
||||
ChatOptions options = builder.topK(5).build();
|
||||
ChatOptions options = this.builder.topK(5).build();
|
||||
|
||||
// Then
|
||||
assertThat(options.getTopK()).isEqualTo(5);
|
||||
@@ -115,7 +115,7 @@ class DefaultFunctionCallingOptionsBuilderTests {
|
||||
@Test
|
||||
void shouldBuildWithTopP() {
|
||||
// When
|
||||
ChatOptions options = builder.topP(0.9).build();
|
||||
ChatOptions options = this.builder.topP(0.9).build();
|
||||
|
||||
// Then
|
||||
assertThat(options.getTopP()).isEqualTo(0.9);
|
||||
@@ -124,7 +124,7 @@ class DefaultFunctionCallingOptionsBuilderTests {
|
||||
@Test
|
||||
void shouldBuildWithAllInheritedOptions() {
|
||||
// When
|
||||
ChatOptions options = builder.model("gpt-4")
|
||||
ChatOptions options = this.builder.model("gpt-4")
|
||||
.frequencyPenalty(0.5)
|
||||
.maxTokens(100)
|
||||
.presencePenalty(0.7)
|
||||
@@ -163,7 +163,7 @@ class DefaultFunctionCallingOptionsBuilderTests {
|
||||
List<FunctionCallback> callbacks = List.of(callback1, callback2);
|
||||
|
||||
// When
|
||||
FunctionCallingOptions options = builder.functionCallbacks(callbacks).build();
|
||||
FunctionCallingOptions options = this.builder.functionCallbacks(callbacks).build();
|
||||
|
||||
// Then
|
||||
assertThat(options.getFunctionCallbacks()).hasSize(2).containsExactlyElementsOf(callbacks);
|
||||
@@ -184,7 +184,7 @@ class DefaultFunctionCallingOptionsBuilderTests {
|
||||
.build();
|
||||
|
||||
// When
|
||||
FunctionCallingOptions options = builder.functionCallbacks(callback1, callback2).build();
|
||||
FunctionCallingOptions options = this.builder.functionCallbacks(callback1, callback2).build();
|
||||
|
||||
// Then
|
||||
assertThat(options.getFunctionCallbacks()).hasSize(2).containsExactly(callback1, callback2);
|
||||
@@ -192,7 +192,7 @@ class DefaultFunctionCallingOptionsBuilderTests {
|
||||
|
||||
@Test
|
||||
void shouldThrowExceptionWhenFunctionCallbacksVarargsIsNull() {
|
||||
assertThatThrownBy(() -> builder.functionCallbacks((FunctionCallback[]) null))
|
||||
assertThatThrownBy(() -> this.builder.functionCallbacks((FunctionCallback[]) null))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("FunctionCallbacks must not be null");
|
||||
}
|
||||
@@ -203,7 +203,7 @@ class DefaultFunctionCallingOptionsBuilderTests {
|
||||
Set<String> functions = Set.of("function1", "function2");
|
||||
|
||||
// When
|
||||
FunctionCallingOptions options = builder.functions(functions).build();
|
||||
FunctionCallingOptions options = this.builder.functions(functions).build();
|
||||
|
||||
// Then
|
||||
assertThat(options.getFunctions()).hasSize(2).containsExactlyInAnyOrderElementsOf(functions);
|
||||
@@ -212,7 +212,7 @@ class DefaultFunctionCallingOptionsBuilderTests {
|
||||
@Test
|
||||
void shouldBuildWithSingleFunction() {
|
||||
// When
|
||||
FunctionCallingOptions options = builder.function("function1").function("function2").build();
|
||||
FunctionCallingOptions options = this.builder.function("function1").function("function2").build();
|
||||
|
||||
// Then
|
||||
assertThat(options.getFunctions()).hasSize(2).containsExactlyInAnyOrder("function1", "function2");
|
||||
@@ -220,14 +220,14 @@ class DefaultFunctionCallingOptionsBuilderTests {
|
||||
|
||||
@Test
|
||||
void shouldThrowExceptionWhenFunctionIsNull() {
|
||||
assertThatThrownBy(() -> builder.function(null)).isInstanceOf(IllegalArgumentException.class)
|
||||
assertThatThrownBy(() -> this.builder.function(null)).isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Function must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldBuildWithProxyToolCalls() {
|
||||
// When
|
||||
FunctionCallingOptions options = builder.proxyToolCalls(true).build();
|
||||
FunctionCallingOptions options = this.builder.proxyToolCalls(true).build();
|
||||
|
||||
// Then
|
||||
assertThat(options.getProxyToolCalls()).isTrue();
|
||||
@@ -239,7 +239,7 @@ class DefaultFunctionCallingOptionsBuilderTests {
|
||||
Map<String, Object> context = Map.of("key1", "value1", "key2", 42);
|
||||
|
||||
// When
|
||||
FunctionCallingOptions options = builder.toolContext(context).build();
|
||||
FunctionCallingOptions options = this.builder.toolContext(context).build();
|
||||
|
||||
// Then
|
||||
assertThat(options.getToolContext()).hasSize(2).containsAllEntriesOf(context);
|
||||
@@ -247,7 +247,7 @@ class DefaultFunctionCallingOptionsBuilderTests {
|
||||
|
||||
@Test
|
||||
void shouldThrowExceptionWhenToolContextMapIsNull() {
|
||||
assertThatThrownBy(() -> builder.toolContext((Map<String, Object>) null))
|
||||
assertThatThrownBy(() -> this.builder.toolContext((Map<String, Object>) null))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Tool context must not be null");
|
||||
}
|
||||
@@ -255,7 +255,7 @@ class DefaultFunctionCallingOptionsBuilderTests {
|
||||
@Test
|
||||
void shouldBuildWithToolContextKeyValue() {
|
||||
// When
|
||||
FunctionCallingOptions options = builder.toolContext("key1", "value1").toolContext("key2", 42).build();
|
||||
FunctionCallingOptions options = this.builder.toolContext("key1", "value1").toolContext("key2", 42).build();
|
||||
|
||||
// Then
|
||||
assertThat(options.getToolContext()).hasSize(2).containsEntry("key1", "value1").containsEntry("key2", 42);
|
||||
@@ -263,13 +263,13 @@ class DefaultFunctionCallingOptionsBuilderTests {
|
||||
|
||||
@Test
|
||||
void shouldThrowExceptionWhenToolContextKeyIsNull() {
|
||||
assertThatThrownBy(() -> builder.toolContext(null, "value")).isInstanceOf(IllegalArgumentException.class)
|
||||
assertThatThrownBy(() -> this.builder.toolContext(null, "value")).isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Key must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldThrowExceptionWhenToolContextValueIsNull() {
|
||||
assertThatThrownBy(() -> builder.toolContext("key", null)).isInstanceOf(IllegalArgumentException.class)
|
||||
assertThatThrownBy(() -> this.builder.toolContext("key", null)).isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Value must not be null");
|
||||
}
|
||||
|
||||
@@ -280,7 +280,7 @@ class DefaultFunctionCallingOptionsBuilderTests {
|
||||
Map<String, Object> context2 = Map.of("key2", "updated", "key3", true);
|
||||
|
||||
// When
|
||||
FunctionCallingOptions options = builder.toolContext(context1).toolContext(context2).build();
|
||||
FunctionCallingOptions options = this.builder.toolContext(context1).toolContext(context2).build();
|
||||
|
||||
// Then
|
||||
assertThat(options.getToolContext()).hasSize(3)
|
||||
@@ -301,7 +301,7 @@ class DefaultFunctionCallingOptionsBuilderTests {
|
||||
Map<String, Object> context = Map.of("key1", "value1");
|
||||
|
||||
// When
|
||||
FunctionCallingOptions options = builder.model("gpt-4")
|
||||
FunctionCallingOptions options = this.builder.model("gpt-4")
|
||||
.frequencyPenalty(0.5)
|
||||
.maxTokens(100)
|
||||
.presencePenalty(0.7)
|
||||
@@ -335,7 +335,7 @@ class DefaultFunctionCallingOptionsBuilderTests {
|
||||
@Test
|
||||
void shouldBuildWithEmptyFunctionCallbacks() {
|
||||
// When
|
||||
FunctionCallingOptions options = builder.functionCallbacks(List.of()).build();
|
||||
FunctionCallingOptions options = this.builder.functionCallbacks(List.of()).build();
|
||||
|
||||
// Then
|
||||
assertThat(options.getFunctionCallbacks()).isEmpty();
|
||||
@@ -344,7 +344,7 @@ class DefaultFunctionCallingOptionsBuilderTests {
|
||||
@Test
|
||||
void shouldBuildWithEmptyFunctions() {
|
||||
// When
|
||||
FunctionCallingOptions options = builder.functions(Set.of()).build();
|
||||
FunctionCallingOptions options = this.builder.functions(Set.of()).build();
|
||||
|
||||
// Then
|
||||
assertThat(options.getFunctions()).isEmpty();
|
||||
@@ -353,7 +353,7 @@ class DefaultFunctionCallingOptionsBuilderTests {
|
||||
@Test
|
||||
void shouldBuildWithEmptyToolContext() {
|
||||
// When
|
||||
FunctionCallingOptions options = builder.toolContext(Map.of()).build();
|
||||
FunctionCallingOptions options = this.builder.toolContext(Map.of()).build();
|
||||
|
||||
// Then
|
||||
assertThat(options.getToolContext()).isEmpty();
|
||||
@@ -362,7 +362,7 @@ class DefaultFunctionCallingOptionsBuilderTests {
|
||||
@Test
|
||||
void shouldDeduplicateFunctions() {
|
||||
// When
|
||||
FunctionCallingOptions options = builder.function("function1")
|
||||
FunctionCallingOptions options = this.builder.function("function1")
|
||||
.function("function1") // Duplicate
|
||||
.function("function2")
|
||||
.build();
|
||||
@@ -379,7 +379,7 @@ class DefaultFunctionCallingOptionsBuilderTests {
|
||||
.description("Test function")
|
||||
.inputType(String.class)
|
||||
.build();
|
||||
FunctionCallingOptions original = builder.model("gpt-4")
|
||||
FunctionCallingOptions original = this.builder.model("gpt-4")
|
||||
.frequencyPenalty(0.5)
|
||||
.maxTokens(100)
|
||||
.presencePenalty(0.7)
|
||||
@@ -418,7 +418,7 @@ class DefaultFunctionCallingOptionsBuilderTests {
|
||||
.inputType(String.class)
|
||||
.build();
|
||||
|
||||
DefaultFunctionCallingOptions options1 = (DefaultFunctionCallingOptions) builder.model("gpt-4")
|
||||
DefaultFunctionCallingOptions options1 = (DefaultFunctionCallingOptions) this.builder.model("gpt-4")
|
||||
.temperature(0.8)
|
||||
.functionCallbacks(callback1)
|
||||
.function("function1")
|
||||
@@ -457,7 +457,7 @@ class DefaultFunctionCallingOptionsBuilderTests {
|
||||
.inputType(String.class)
|
||||
.build();
|
||||
|
||||
DefaultFunctionCallingOptions options1 = (DefaultFunctionCallingOptions) builder.model("gpt-4")
|
||||
DefaultFunctionCallingOptions options1 = (DefaultFunctionCallingOptions) this.builder.model("gpt-4")
|
||||
.temperature(0.8)
|
||||
.functionCallbacks(callback)
|
||||
.function("function1")
|
||||
@@ -496,9 +496,12 @@ class DefaultFunctionCallingOptionsBuilderTests {
|
||||
.build();
|
||||
|
||||
// When
|
||||
FunctionCallingOptions options1 = builder.model("model1").temperature(0.7).functionCallbacks(callback1).build();
|
||||
FunctionCallingOptions options1 = this.builder.model("model1")
|
||||
.temperature(0.7)
|
||||
.functionCallbacks(callback1)
|
||||
.build();
|
||||
|
||||
FunctionCallingOptions options2 = builder.model("model2").functionCallbacks(callback2).build();
|
||||
FunctionCallingOptions options2 = this.builder.model("model2").functionCallbacks(callback2).build();
|
||||
|
||||
// Then
|
||||
assertThat(options1.getModel()).isEqualTo("model1");
|
||||
@@ -515,16 +518,16 @@ class DefaultFunctionCallingOptionsBuilderTests {
|
||||
@Test
|
||||
void shouldReturnSameBuilderInstanceOnEachMethod() {
|
||||
// When
|
||||
FunctionCallingOptions.Builder returnedBuilder = builder.model("test");
|
||||
FunctionCallingOptions.Builder returnedBuilder = this.builder.model("test");
|
||||
|
||||
// Then
|
||||
assertThat(returnedBuilder).isSameAs(builder);
|
||||
assertThat(returnedBuilder).isSameAs(this.builder);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldHaveExpectedDefaultValues() {
|
||||
// When
|
||||
FunctionCallingOptions options = builder.build();
|
||||
FunctionCallingOptions options = this.builder.build();
|
||||
|
||||
// Then
|
||||
// ChatOptions defaults
|
||||
@@ -557,7 +560,7 @@ class DefaultFunctionCallingOptionsBuilderTests {
|
||||
Set<String> functions = new HashSet<>(Set.of("function1", "function2"));
|
||||
Map<String, Object> context = new HashMap<>(Map.of("key1", "value1"));
|
||||
|
||||
FunctionCallingOptions options = builder.stopSequences(stopSequences)
|
||||
FunctionCallingOptions options = this.builder.stopSequences(stopSequences)
|
||||
.functionCallbacks(callback)
|
||||
.functions(functions)
|
||||
.toolContext(context)
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.ai.rag.preretrieval.query.transformation;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.ai.chat.client.ChatClient;
|
||||
import org.springframework.ai.chat.prompt.PromptTemplate;
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.ai.rag.preretrieval.query.transformation;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.ai.chat.client.ChatClient;
|
||||
import org.springframework.ai.chat.prompt.PromptTemplate;
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.ai.document.Document;
|
||||
import org.springframework.ai.rag.Query;
|
||||
|
||||
|
||||
@@ -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 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.
|
||||
*/
|
||||
|
||||
package org.springframework.ai.utils;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
@@ -28,7 +29,11 @@ import javax.sound.sampled.Clip;
|
||||
* @author Christian Tzolov
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class AudioPlayer {
|
||||
public final class AudioPlayer {
|
||||
|
||||
private AudioPlayer() {
|
||||
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
|
||||
@@ -34,6 +34,20 @@
|
||||
<suppress files="MethodInvokingFunctionCallbackTests.java" checks="RegexpSinglelineJava"/>
|
||||
<suppress files="DefaultFunctionCallbackBuilderTests.java" checks="RegexpSinglelineJava"/>
|
||||
<suppress files="ClientIT.java" checks="RegexpSinglelineJava"/>
|
||||
<suppress files="MistralAiApi.java" checks="RegexpSinglelineJava"/>
|
||||
<suppress files="MariaDBSchemaValidator.java" checks="RegexpSinglelineJava"/>
|
||||
<suppress files="OpenAiApi.java" checks="AnnotationLocation"/>
|
||||
|
||||
<suppress files="AzureVectorStore.java" checks="FinalClass"/>
|
||||
<suppress files="CassandraVectorStore.java" checks="FinalClass"/>
|
||||
<suppress files="MilvusVectorStore.java" checks="FinalClass"/>
|
||||
<suppress files="HanaCloudVectorStore.java" checks="FinalClass"/>
|
||||
<suppress files="PineconeVectorStore.java" checks="FinalClass"/>
|
||||
<suppress files="TypesenseVectorStore.java" checks="FinalClass"/>
|
||||
<suppress files="WeaviateVectorStore.java" checks="FinalClass"/>
|
||||
<suppress files="ChromaVectorStore.java" checks="FinalClass"/>
|
||||
<suppress files="QdrantVectorStore.java" checks="FinalClass"/>
|
||||
<suppress files="RedisVectorStore.java" checks="FinalClass"/>
|
||||
|
||||
|
||||
</suppressions>
|
||||
|
||||
@@ -203,7 +203,7 @@ public class AzureVectorStore extends AbstractObservationVectorStore implements
|
||||
this.defaultTopK = builder.defaultTopK;
|
||||
this.defaultSimilarityThreshold = builder.defaultSimilarityThreshold;
|
||||
this.indexName = builder.indexName;
|
||||
this.filterExpressionConverter = new AzureAiSearchFilterExpressionConverter(filterMetadataFields);
|
||||
this.filterExpressionConverter = new AzureAiSearchFilterExpressionConverter(this.filterMetadataFields);
|
||||
}
|
||||
|
||||
public static Builder builder(SearchIndexClient searchIndexClient, EmbeddingModel embeddingModel) {
|
||||
|
||||
@@ -270,10 +270,10 @@ public class CassandraVectorStore extends AbstractObservationVectorStore impleme
|
||||
prepareAddStatement(Set.of());
|
||||
this.deleteStmt = prepareDeleteStatement();
|
||||
|
||||
TableMetadata cassandraMetadata = session.getMetadata()
|
||||
.getKeyspace(schema.keyspace())
|
||||
TableMetadata cassandraMetadata = this.session.getMetadata()
|
||||
.getKeyspace(this.schema.keyspace())
|
||||
.get()
|
||||
.getTable(schema.table())
|
||||
.getTable(this.schema.table())
|
||||
.get();
|
||||
|
||||
this.similarity = getIndexSimilarity(cassandraMetadata);
|
||||
@@ -870,11 +870,11 @@ public class CassandraVectorStore extends AbstractObservationVectorStore impleme
|
||||
* @throws IllegalStateException if session is already set
|
||||
*/
|
||||
public Builder contactPoint(InetSocketAddress contactPoint) {
|
||||
Assert.state(session == null, "Cannot call addContactPoint(..) when session is already set");
|
||||
if (sessionBuilder == null) {
|
||||
sessionBuilder = new CqlSessionBuilder();
|
||||
Assert.state(this.session == null, "Cannot call addContactPoint(..) when session is already set");
|
||||
if (this.sessionBuilder == null) {
|
||||
this.sessionBuilder = new CqlSessionBuilder();
|
||||
}
|
||||
sessionBuilder.addContactPoint(contactPoint);
|
||||
this.sessionBuilder.addContactPoint(contactPoint);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -885,11 +885,11 @@ public class CassandraVectorStore extends AbstractObservationVectorStore impleme
|
||||
* @throws IllegalStateException if session is already set
|
||||
*/
|
||||
public Builder localDatacenter(String localDatacenter) {
|
||||
Assert.state(session == null, "Cannot call withLocalDatacenter(..) when session is already set");
|
||||
if (sessionBuilder == null) {
|
||||
sessionBuilder = new CqlSessionBuilder();
|
||||
Assert.state(this.session == null, "Cannot call withLocalDatacenter(..) when session is already set");
|
||||
if (this.sessionBuilder == null) {
|
||||
this.sessionBuilder = new CqlSessionBuilder();
|
||||
}
|
||||
sessionBuilder.withLocalDatacenter(localDatacenter);
|
||||
this.sessionBuilder.withLocalDatacenter(localDatacenter);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -1035,49 +1035,49 @@ public class CassandraVectorStore extends AbstractObservationVectorStore impleme
|
||||
|
||||
Schema buildSchema() {
|
||||
if (this.indexName == null) {
|
||||
this.indexName = String.format("%s_%s_%s", table, embeddingColumnName, DEFAULT_INDEX_SUFFIX);
|
||||
this.indexName = String.format("%s_%s_%s", this.table, this.embeddingColumnName, DEFAULT_INDEX_SUFFIX);
|
||||
}
|
||||
|
||||
validateSchema();
|
||||
|
||||
return new Schema(keyspace, table, partitionKeys, clusteringKeys, contentColumnName, embeddingColumnName,
|
||||
indexName, metadataColumns);
|
||||
return new Schema(this.keyspace, this.table, this.partitionKeys, this.clusteringKeys,
|
||||
this.contentColumnName, this.embeddingColumnName, this.indexName, this.metadataColumns);
|
||||
}
|
||||
|
||||
private void validateSchema() {
|
||||
for (SchemaColumn metadata : metadataColumns) {
|
||||
Assert.isTrue(!partitionKeys.stream().anyMatch(c -> c.name().equals(metadata.name())),
|
||||
for (SchemaColumn metadata : this.metadataColumns) {
|
||||
Assert.isTrue(!this.partitionKeys.stream().anyMatch(c -> c.name().equals(metadata.name())),
|
||||
"metadataColumn " + metadata.name() + " cannot have same name as a partition key");
|
||||
|
||||
Assert.isTrue(!clusteringKeys.stream().anyMatch(c -> c.name().equals(metadata.name())),
|
||||
Assert.isTrue(!this.clusteringKeys.stream().anyMatch(c -> c.name().equals(metadata.name())),
|
||||
"metadataColumn " + metadata.name() + " cannot have same name as a clustering key");
|
||||
|
||||
Assert.isTrue(!metadata.name().equals(contentColumnName),
|
||||
Assert.isTrue(!metadata.name().equals(this.contentColumnName),
|
||||
"metadataColumn " + metadata.name() + " cannot have same name as content column name");
|
||||
|
||||
Assert.isTrue(!metadata.name().equals(embeddingColumnName),
|
||||
Assert.isTrue(!metadata.name().equals(this.embeddingColumnName),
|
||||
"metadataColumn " + metadata.name() + " cannot have same name as embedding column name");
|
||||
}
|
||||
|
||||
int primaryKeyColumnsCount = partitionKeys.size() + clusteringKeys.size();
|
||||
String exampleId = primaryKeyTranslator.apply(Collections.emptyList());
|
||||
List<Object> testIdTranslation = documentIdTranslator.apply(exampleId);
|
||||
int primaryKeyColumnsCount = this.partitionKeys.size() + this.clusteringKeys.size();
|
||||
String exampleId = this.primaryKeyTranslator.apply(Collections.emptyList());
|
||||
List<Object> testIdTranslation = this.documentIdTranslator.apply(exampleId);
|
||||
|
||||
Assert.isTrue(testIdTranslation.size() == primaryKeyColumnsCount,
|
||||
"documentIdTranslator results length " + testIdTranslation.size()
|
||||
+ " doesn't match number of primary key columns " + primaryKeyColumnsCount);
|
||||
|
||||
Assert.isTrue(exampleId.equals(primaryKeyTranslator.apply(documentIdTranslator.apply(exampleId))),
|
||||
Assert.isTrue(exampleId.equals(this.primaryKeyTranslator.apply(this.documentIdTranslator.apply(exampleId))),
|
||||
"primaryKeyTranslator is not an inverse function to documentIdTranslator");
|
||||
}
|
||||
|
||||
@Override
|
||||
public CassandraVectorStore build() {
|
||||
if (session == null && sessionBuilder != null) {
|
||||
session = sessionBuilder.build();
|
||||
closeSessionOnClose = true;
|
||||
if (this.session == null && this.sessionBuilder != null) {
|
||||
this.session = this.sessionBuilder.build();
|
||||
this.closeSessionOnClose = true;
|
||||
}
|
||||
Assert.notNull(session, "Either session must be set directly or configured via sessionBuilder");
|
||||
Assert.notNull(this.session, "Either session must be set directly or configured via sessionBuilder");
|
||||
return new CassandraVectorStore(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,6 @@ import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.ai.document.DocumentMetadata;
|
||||
import org.testcontainers.containers.CassandraContainer;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
@@ -45,6 +44,7 @@ import org.testcontainers.shaded.org.apache.commons.lang3.RandomStringUtils;
|
||||
|
||||
import org.springframework.ai.cassandra.CassandraImage;
|
||||
import org.springframework.ai.document.Document;
|
||||
import org.springframework.ai.document.DocumentMetadata;
|
||||
import org.springframework.ai.embedding.EmbeddingModel;
|
||||
import org.springframework.ai.transformers.TransformersEmbeddingModel;
|
||||
import org.springframework.ai.vectorstore.SearchRequest;
|
||||
|
||||
@@ -30,13 +30,13 @@ import com.datastax.oss.driver.api.core.servererrors.SyntaxError;
|
||||
import com.datastax.oss.driver.api.core.type.DataTypes;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.ai.document.DocumentMetadata;
|
||||
import org.testcontainers.containers.CassandraContainer;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
|
||||
import org.springframework.ai.cassandra.CassandraImage;
|
||||
import org.springframework.ai.document.Document;
|
||||
import org.springframework.ai.document.DocumentMetadata;
|
||||
import org.springframework.ai.embedding.EmbeddingModel;
|
||||
import org.springframework.ai.transformers.TransformersEmbeddingModel;
|
||||
import org.springframework.ai.vectorstore.SearchRequest;
|
||||
|
||||
@@ -21,9 +21,11 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.mariadb.jdbc.Driver;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
||||
@@ -151,8 +153,9 @@ public class MariaDBSchemaValidator {
|
||||
try {
|
||||
String quotedId = Driver.enquoteIdentifier(identifier, alwaysQuote);
|
||||
// force use of simple table name
|
||||
if (Pattern.compile("`?[\\p{Alnum}_]*`?").matcher(identifier).matches())
|
||||
if (Pattern.compile("`?[\\p{Alnum}_]*`?").matcher(identifier).matches()) {
|
||||
return quotedId;
|
||||
}
|
||||
throw new IllegalArgumentException(String
|
||||
.format("Identifier '%s' should only contain alphanumeric characters and underscores", quotedId));
|
||||
}
|
||||
|
||||
@@ -16,16 +16,22 @@
|
||||
|
||||
package org.springframework.ai.vectorstore.mariadb;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.json.JsonMapper;
|
||||
import io.micrometer.observation.ObservationRegistry;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.*;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.ai.document.Document;
|
||||
import org.springframework.ai.embedding.BatchingStrategy;
|
||||
import org.springframework.ai.embedding.EmbeddingModel;
|
||||
@@ -33,7 +39,6 @@ import org.springframework.ai.embedding.EmbeddingOptionsBuilder;
|
||||
import org.springframework.ai.embedding.TokenCountBatchingStrategy;
|
||||
import org.springframework.ai.observation.conventions.VectorStoreProvider;
|
||||
import org.springframework.ai.observation.conventions.VectorStoreSimilarityMetric;
|
||||
import org.springframework.ai.observation.conventions.VectorStoreSimilarityMetric;
|
||||
import org.springframework.ai.util.JacksonUtils;
|
||||
import org.springframework.ai.vectorstore.AbstractVectorStoreBuilder;
|
||||
import org.springframework.ai.vectorstore.SearchRequest;
|
||||
@@ -305,7 +310,7 @@ public class MariaDBVectorStore extends AbstractObservationVectorStore implement
|
||||
this.distanceType = builder.distanceType;
|
||||
this.removeExistingVectorStoreTable = builder.removeExistingVectorStoreTable;
|
||||
this.initializeSchema = builder.initializeSchema;
|
||||
this.schemaValidator = new MariaDBSchemaValidator(jdbcTemplate);
|
||||
this.schemaValidator = new MariaDBSchemaValidator(this.jdbcTemplate);
|
||||
this.batchingStrategy = builder.batchingStrategy;
|
||||
this.maxDocumentBatchSize = builder.maxDocumentBatchSize;
|
||||
|
||||
@@ -314,7 +319,7 @@ public class MariaDBVectorStore extends AbstractObservationVectorStore implement
|
||||
false);
|
||||
this.idFieldName = MariaDBSchemaValidator.validateAndEnquoteIdentifier(builder.idFieldName, false);
|
||||
this.metadataFieldName = MariaDBSchemaValidator.validateAndEnquoteIdentifier(builder.metadataFieldName, false);
|
||||
filterExpressionConverter = new MariaDBFilterExpressionConverter(this.metadataFieldName);
|
||||
this.filterExpressionConverter = new MariaDBFilterExpressionConverter(this.metadataFieldName);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -447,8 +452,8 @@ public class MariaDBVectorStore extends AbstractObservationVectorStore implement
|
||||
logger.info("vectorTableValidationsEnabled {}", this.schemaValidation);
|
||||
|
||||
if (this.schemaValidation) {
|
||||
this.schemaValidator.validateTableSchema(this.schemaName, this.vectorTableName, idFieldName,
|
||||
contentFieldName, metadataFieldName, embeddingFieldName, this.embeddingDimensions());
|
||||
this.schemaValidator.validateTableSchema(this.schemaName, this.vectorTableName, this.idFieldName,
|
||||
this.contentFieldName, this.metadataFieldName, this.embeddingFieldName, this.embeddingDimensions());
|
||||
}
|
||||
|
||||
if (!this.initializeSchema) {
|
||||
@@ -456,8 +461,9 @@ public class MariaDBVectorStore extends AbstractObservationVectorStore implement
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.schemaName != null)
|
||||
if (this.schemaName != null) {
|
||||
this.jdbcTemplate.execute(String.format("CREATE SCHEMA IF NOT EXISTS %s", this.schemaName));
|
||||
}
|
||||
|
||||
// Remove existing VectorStoreTable
|
||||
if (this.removeExistingVectorStoreTable) {
|
||||
@@ -472,15 +478,16 @@ public class MariaDBVectorStore extends AbstractObservationVectorStore implement
|
||||
%s VECTOR(%d) NOT NULL,
|
||||
VECTOR INDEX %s_idx (%s)
|
||||
) ENGINE=InnoDB
|
||||
""", this.getFullyQualifiedTableName(), idFieldName, contentFieldName, metadataFieldName,
|
||||
embeddingFieldName, this.embeddingDimensions(),
|
||||
(vectorTableName + "_" + embeddingFieldName).replaceAll("[^\\n\\r\\t\\p{Print}]", ""),
|
||||
embeddingFieldName));
|
||||
""", this.getFullyQualifiedTableName(), this.idFieldName, this.contentFieldName, this.metadataFieldName,
|
||||
this.embeddingFieldName, this.embeddingDimensions(),
|
||||
(this.vectorTableName + "_" + this.embeddingFieldName).replaceAll("[^\\n\\r\\t\\p{Print}]", ""),
|
||||
this.embeddingFieldName));
|
||||
}
|
||||
|
||||
private String getFullyQualifiedTableName() {
|
||||
if (this.schemaName != null)
|
||||
if (this.schemaName != null) {
|
||||
return this.schemaName + "." + this.vectorTableName;
|
||||
}
|
||||
return this.vectorTableName;
|
||||
}
|
||||
|
||||
@@ -522,7 +529,7 @@ public class MariaDBVectorStore extends AbstractObservationVectorStore implement
|
||||
|
||||
public enum MariaDBDistanceType {
|
||||
|
||||
EUCLIDEAN, COSINE;
|
||||
EUCLIDEAN, COSINE
|
||||
|
||||
}
|
||||
|
||||
@@ -530,7 +537,7 @@ public class MariaDBVectorStore extends AbstractObservationVectorStore implement
|
||||
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
public DocumentRowMapper(ObjectMapper objectMapper) {
|
||||
DocumentRowMapper(ObjectMapper objectMapper) {
|
||||
this.objectMapper = objectMapper;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,20 +16,20 @@
|
||||
|
||||
package org.springframework.ai.vectorstore.mariadb;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import org.springframework.ai.embedding.EmbeddingModel;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.only;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.ai.embedding.EmbeddingModel;
|
||||
import org.springframework.ai.vectorstore.mariadb.MariaDBVectorStore;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
||||
/**
|
||||
* @author Diego Dupin
|
||||
*/
|
||||
|
||||
@@ -16,6 +16,16 @@
|
||||
|
||||
package org.springframework.ai.vectorstore.mariadb;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.ai.vectorstore.filter.Filter.Expression;
|
||||
import org.springframework.ai.vectorstore.filter.Filter.Group;
|
||||
import org.springframework.ai.vectorstore.filter.Filter.Key;
|
||||
import org.springframework.ai.vectorstore.filter.Filter.Value;
|
||||
import org.springframework.ai.vectorstore.filter.FilterExpressionConverter;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.ai.vectorstore.filter.Filter.ExpressionType.AND;
|
||||
import static org.springframework.ai.vectorstore.filter.Filter.ExpressionType.EQ;
|
||||
@@ -26,15 +36,6 @@ import static org.springframework.ai.vectorstore.filter.Filter.ExpressionType.NE
|
||||
import static org.springframework.ai.vectorstore.filter.Filter.ExpressionType.NIN;
|
||||
import static org.springframework.ai.vectorstore.filter.Filter.ExpressionType.OR;
|
||||
|
||||
import java.util.List;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.ai.vectorstore.filter.Filter.Expression;
|
||||
import org.springframework.ai.vectorstore.filter.Filter.Group;
|
||||
import org.springframework.ai.vectorstore.filter.Filter.Key;
|
||||
import org.springframework.ai.vectorstore.filter.Filter.Value;
|
||||
import org.springframework.ai.vectorstore.mariadb.MariaDBFilterExpressionConverter;
|
||||
import org.springframework.ai.vectorstore.filter.FilterExpressionConverter;
|
||||
|
||||
/**
|
||||
* @author Diego Dupin
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023-2024 the original author or authors.
|
||||
* 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.
|
||||
@@ -21,8 +21,12 @@ import org.testcontainers.utility.DockerImageName;
|
||||
/**
|
||||
* @author Diego Dupin
|
||||
*/
|
||||
public class MariaDBImage {
|
||||
public final class MariaDBImage {
|
||||
|
||||
public static final DockerImageName DEFAULT_IMAGE = DockerImageName.parse("mariadb:11.7-rc");
|
||||
|
||||
private MariaDBImage() {
|
||||
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,16 +16,18 @@
|
||||
|
||||
package org.springframework.ai.vectorstore.mariadb;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
import javax.sql.DataSource;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.testcontainers.containers.MariaDBContainer;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
|
||||
import org.springframework.ai.embedding.EmbeddingModel;
|
||||
import org.springframework.ai.openai.OpenAiEmbeddingModel;
|
||||
import org.springframework.ai.openai.api.OpenAiApi;
|
||||
import org.springframework.ai.vectorstore.VectorStore;
|
||||
import org.springframework.ai.vectorstore.mariadb.MariaDBVectorStore;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.SpringBootConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
@@ -37,9 +39,8 @@ import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.testcontainers.containers.MariaDBContainer;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author Diego Dupin
|
||||
@@ -91,8 +92,9 @@ public class MariaDBStoreCustomNamesIT {
|
||||
boolean fieldsExists = jdbcTemplate
|
||||
.queryForObject("SELECT EXISTS (SELECT * FROM information_schema.columns WHERE table_schema= ? AND"
|
||||
+ " table_name = ? AND column_name = ?)", Boolean.class, schemaName, tableName, field);
|
||||
if (!fieldsExists)
|
||||
if (!fieldsExists) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -16,9 +16,6 @@
|
||||
|
||||
package org.springframework.ai.vectorstore.mariadb;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Collections;
|
||||
@@ -27,13 +24,20 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
import org.junit.Assert;
|
||||
import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
import org.testcontainers.containers.MariaDBContainer;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
|
||||
import org.springframework.ai.document.Document;
|
||||
import org.springframework.ai.embedding.EmbeddingModel;
|
||||
import org.springframework.ai.openai.OpenAiEmbeddingModel;
|
||||
@@ -54,9 +58,8 @@ import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.core.io.DefaultResourceLoader;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.testcontainers.containers.MariaDBContainer;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author Diego Dupin
|
||||
@@ -121,7 +124,8 @@ public class MariaDBStoreIT {
|
||||
}
|
||||
|
||||
Iterator<Float> iter = distances.iterator();
|
||||
Float current, previous = iter.next();
|
||||
Float current;
|
||||
Float previous = iter.next();
|
||||
while (iter.hasNext()) {
|
||||
current = iter.next();
|
||||
if (previous > current) {
|
||||
|
||||
@@ -16,20 +16,23 @@
|
||||
|
||||
package org.springframework.ai.vectorstore.mariadb;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
import io.micrometer.observation.ObservationRegistry;
|
||||
import io.micrometer.observation.tck.TestObservationRegistry;
|
||||
import io.micrometer.observation.tck.TestObservationRegistryAssert;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
|
||||
import org.testcontainers.containers.MariaDBContainer;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
|
||||
import org.springframework.ai.document.Document;
|
||||
import org.springframework.ai.embedding.EmbeddingModel;
|
||||
import org.springframework.ai.observation.conventions.SpringAiKind;
|
||||
@@ -52,9 +55,8 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.core.io.DefaultResourceLoader;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.testcontainers.containers.MariaDBContainer;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author Diego Dupin
|
||||
|
||||
@@ -26,8 +26,6 @@ import org.mockito.ArgumentCaptor;
|
||||
|
||||
import org.springframework.ai.document.Document;
|
||||
import org.springframework.ai.embedding.EmbeddingModel;
|
||||
import org.springframework.ai.vectorstore.mariadb.MariaDBSchemaValidator;
|
||||
import org.springframework.ai.vectorstore.mariadb.MariaDBVectorStore;
|
||||
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
||||
|
||||
@@ -16,15 +16,16 @@
|
||||
|
||||
package org.springframework.ai.vectorstore.mariadb;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.ai.embedding.EmbeddingModel;
|
||||
import org.springframework.ai.vectorstore.mariadb.MariaDBVectorStore.MariaDBDistanceType;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link MariaDBVectorStore.MariaDBBuilder}.
|
||||
*
|
||||
@@ -38,21 +39,21 @@ class MariaDBVectorStoreBuilderTests {
|
||||
|
||||
@Test
|
||||
void shouldFailOnMissingEmbeddingModel() {
|
||||
assertThatThrownBy(() -> MariaDBVectorStore.builder(jdbcTemplate, null).build())
|
||||
assertThatThrownBy(() -> MariaDBVectorStore.builder(this.jdbcTemplate, null).build())
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessageContaining("EmbeddingModel must be configured");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldFailOnMissingJdbcTemplate() {
|
||||
assertThatThrownBy(() -> MariaDBVectorStore.builder(null, embeddingModel).build())
|
||||
assertThatThrownBy(() -> MariaDBVectorStore.builder(null, this.embeddingModel).build())
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessageContaining("JdbcTemplate must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldUseDefaultValues() {
|
||||
MariaDBVectorStore vectorStore = MariaDBVectorStore.builder(jdbcTemplate, embeddingModel).build();
|
||||
MariaDBVectorStore vectorStore = MariaDBVectorStore.builder(this.jdbcTemplate, this.embeddingModel).build();
|
||||
|
||||
assertThat(vectorStore).hasFieldOrPropertyWithValue("vectorTableName", "vector_store")
|
||||
.hasFieldOrPropertyWithValue("schemaName", null)
|
||||
@@ -70,7 +71,7 @@ class MariaDBVectorStoreBuilderTests {
|
||||
|
||||
@Test
|
||||
void shouldConfigureCustomValues() {
|
||||
MariaDBVectorStore vectorStore = MariaDBVectorStore.builder(jdbcTemplate, embeddingModel)
|
||||
MariaDBVectorStore vectorStore = MariaDBVectorStore.builder(this.jdbcTemplate, this.embeddingModel)
|
||||
.schemaName("custom_schema")
|
||||
.vectorTableName("custom_vectors")
|
||||
.schemaValidation(true)
|
||||
@@ -101,40 +102,44 @@ class MariaDBVectorStoreBuilderTests {
|
||||
|
||||
@Test
|
||||
void shouldValidateFieldNames() {
|
||||
assertThatThrownBy(() -> MariaDBVectorStore.builder(jdbcTemplate, embeddingModel).contentFieldName("").build())
|
||||
assertThatThrownBy(
|
||||
() -> MariaDBVectorStore.builder(this.jdbcTemplate, this.embeddingModel).contentFieldName("").build())
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessageContaining("ContentFieldName must not be empty");
|
||||
|
||||
assertThatThrownBy(
|
||||
() -> MariaDBVectorStore.builder(jdbcTemplate, embeddingModel).embeddingFieldName("").build())
|
||||
() -> MariaDBVectorStore.builder(this.jdbcTemplate, this.embeddingModel).embeddingFieldName("").build())
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessageContaining("EmbeddingFieldName must not be empty");
|
||||
|
||||
assertThatThrownBy(() -> MariaDBVectorStore.builder(jdbcTemplate, embeddingModel).idFieldName("").build())
|
||||
assertThatThrownBy(
|
||||
() -> MariaDBVectorStore.builder(this.jdbcTemplate, this.embeddingModel).idFieldName("").build())
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessageContaining("IdFieldName must not be empty");
|
||||
|
||||
assertThatThrownBy(() -> MariaDBVectorStore.builder(jdbcTemplate, embeddingModel).metadataFieldName("").build())
|
||||
assertThatThrownBy(
|
||||
() -> MariaDBVectorStore.builder(this.jdbcTemplate, this.embeddingModel).metadataFieldName("").build())
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessageContaining("MetadataFieldName must not be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldValidateMaxDocumentBatchSize() {
|
||||
assertThatThrownBy(
|
||||
() -> MariaDBVectorStore.builder(jdbcTemplate, embeddingModel).maxDocumentBatchSize(0).build())
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
assertThatThrownBy(() -> MariaDBVectorStore.builder(this.jdbcTemplate, this.embeddingModel)
|
||||
.maxDocumentBatchSize(0)
|
||||
.build()).isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessageContaining("MaxDocumentBatchSize must be positive");
|
||||
|
||||
assertThatThrownBy(
|
||||
() -> MariaDBVectorStore.builder(jdbcTemplate, embeddingModel).maxDocumentBatchSize(-1).build())
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
assertThatThrownBy(() -> MariaDBVectorStore.builder(this.jdbcTemplate, this.embeddingModel)
|
||||
.maxDocumentBatchSize(-1)
|
||||
.build()).isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessageContaining("MaxDocumentBatchSize must be positive");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldValidateDistanceType() {
|
||||
assertThatThrownBy(() -> MariaDBVectorStore.builder(jdbcTemplate, embeddingModel).distanceType(null).build())
|
||||
assertThatThrownBy(
|
||||
() -> MariaDBVectorStore.builder(this.jdbcTemplate, this.embeddingModel).distanceType(null).build())
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessageContaining("DistanceType must not be null");
|
||||
}
|
||||
@@ -142,7 +147,7 @@ class MariaDBVectorStoreBuilderTests {
|
||||
@Test
|
||||
void shouldValidateBatchingStrategy() {
|
||||
assertThatThrownBy(
|
||||
() -> MariaDBVectorStore.builder(jdbcTemplate, embeddingModel).batchingStrategy(null).build())
|
||||
() -> MariaDBVectorStore.builder(this.jdbcTemplate, this.embeddingModel).batchingStrategy(null).build())
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessageContaining("BatchingStrategy must not be null");
|
||||
}
|
||||
|
||||
@@ -572,7 +572,7 @@ public class MilvusVectorStore extends AbstractObservationVectorStore implements
|
||||
return SIMILARITY_TYPE_MAPPING.get(this.metricType).value();
|
||||
}
|
||||
|
||||
public static final class Builder extends AbstractVectorStoreBuilder<Builder> {
|
||||
public static class Builder extends AbstractVectorStoreBuilder<Builder> {
|
||||
|
||||
private final MilvusServiceClient milvusClient;
|
||||
|
||||
|
||||
@@ -30,12 +30,12 @@ import io.milvus.param.MetricType;
|
||||
import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
import org.springframework.ai.document.DocumentMetadata;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
import org.testcontainers.milvus.MilvusContainer;
|
||||
|
||||
import org.springframework.ai.document.Document;
|
||||
import org.springframework.ai.document.DocumentMetadata;
|
||||
import org.springframework.ai.embedding.EmbeddingModel;
|
||||
import org.springframework.ai.embedding.TokenCountBatchingStrategy;
|
||||
import org.springframework.ai.openai.OpenAiEmbeddingModel;
|
||||
|
||||
@@ -32,13 +32,13 @@ import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.CsvSource;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
import org.springframework.ai.document.DocumentMetadata;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
import org.testcontainers.oracle.OracleContainer;
|
||||
import org.testcontainers.utility.MountableFile;
|
||||
|
||||
import org.springframework.ai.document.Document;
|
||||
import org.springframework.ai.document.DocumentMetadata;
|
||||
import org.springframework.ai.embedding.EmbeddingModel;
|
||||
import org.springframework.ai.transformers.TransformersEmbeddingModel;
|
||||
import org.springframework.ai.vectorstore.SearchRequest;
|
||||
@@ -328,9 +328,9 @@ public class OracleVectorStoreIT {
|
||||
return OracleVectorStore.builder(jdbcTemplate, embeddingModel)
|
||||
.tableName(OracleVectorStore.DEFAULT_TABLE_NAME)
|
||||
.indexType(OracleVectorStore.OracleVectorStoreIndexType.IVF)
|
||||
.distanceType(distanceType)
|
||||
.distanceType(this.distanceType)
|
||||
.dimensions(384)
|
||||
.searchAccuracy(searchAccuracy)
|
||||
.searchAccuracy(this.searchAccuracy)
|
||||
.initializeSchema(true)
|
||||
.removeExistingVectorStoreTable(true)
|
||||
.forcedNormalization(true)
|
||||
|
||||
@@ -42,10 +42,10 @@ import org.springframework.ai.observation.conventions.VectorStoreSimilarityMetri
|
||||
import org.springframework.ai.transformers.TransformersEmbeddingModel;
|
||||
import org.springframework.ai.vectorstore.SearchRequest;
|
||||
import org.springframework.ai.vectorstore.VectorStore;
|
||||
import org.springframework.ai.vectorstore.oracle.OracleVectorStore.OracleVectorStoreDistanceType;
|
||||
import org.springframework.ai.vectorstore.observation.DefaultVectorStoreObservationConvention;
|
||||
import org.springframework.ai.vectorstore.observation.VectorStoreObservationDocumentation.HighCardinalityKeyNames;
|
||||
import org.springframework.ai.vectorstore.observation.VectorStoreObservationDocumentation.LowCardinalityKeyNames;
|
||||
import org.springframework.ai.vectorstore.oracle.OracleVectorStore.OracleVectorStoreDistanceType;
|
||||
import org.springframework.boot.SpringBootConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||
|
||||
@@ -617,7 +617,7 @@ public class PgVectorStore extends AbstractObservationVectorStore implements Ini
|
||||
|
||||
}
|
||||
|
||||
public static class PgVectorStoreBuilder extends AbstractVectorStoreBuilder<PgVectorStoreBuilder> {
|
||||
public static final class PgVectorStoreBuilder extends AbstractVectorStoreBuilder<PgVectorStoreBuilder> {
|
||||
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
|
||||
|
||||
@@ -30,8 +30,8 @@ import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
import org.springframework.ai.embedding.EmbeddingModel;
|
||||
import org.springframework.ai.openai.OpenAiEmbeddingModel;
|
||||
import org.springframework.ai.openai.api.OpenAiApi;
|
||||
import org.springframework.ai.vectorstore.pgvector.PgVectorStore.PgIndexType;
|
||||
import org.springframework.ai.vectorstore.VectorStore;
|
||||
import org.springframework.ai.vectorstore.pgvector.PgVectorStore.PgIndexType;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.SpringBootConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
|
||||
@@ -34,19 +34,19 @@ import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
import org.springframework.ai.document.DocumentMetadata;
|
||||
import org.testcontainers.containers.PostgreSQLContainer;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
|
||||
import org.springframework.ai.document.Document;
|
||||
import org.springframework.ai.document.DocumentMetadata;
|
||||
import org.springframework.ai.embedding.EmbeddingModel;
|
||||
import org.springframework.ai.openai.OpenAiEmbeddingModel;
|
||||
import org.springframework.ai.openai.api.OpenAiApi;
|
||||
import org.springframework.ai.vectorstore.pgvector.PgVectorStore.PgIndexType;
|
||||
import org.springframework.ai.vectorstore.SearchRequest;
|
||||
import org.springframework.ai.vectorstore.VectorStore;
|
||||
import org.springframework.ai.vectorstore.filter.FilterExpressionTextParser.FilterExpressionParseException;
|
||||
import org.springframework.ai.vectorstore.pgvector.PgVectorStore.PgIndexType;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.SpringBootConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
|
||||
@@ -41,12 +41,12 @@ import org.springframework.ai.observation.conventions.VectorStoreSimilarityMetri
|
||||
import org.springframework.ai.openai.OpenAiChatModel;
|
||||
import org.springframework.ai.openai.OpenAiEmbeddingModel;
|
||||
import org.springframework.ai.openai.api.OpenAiApi;
|
||||
import org.springframework.ai.vectorstore.pgvector.PgVectorStore.PgIndexType;
|
||||
import org.springframework.ai.vectorstore.SearchRequest;
|
||||
import org.springframework.ai.vectorstore.VectorStore;
|
||||
import org.springframework.ai.vectorstore.observation.DefaultVectorStoreObservationConvention;
|
||||
import org.springframework.ai.vectorstore.observation.VectorStoreObservationDocumentation.HighCardinalityKeyNames;
|
||||
import org.springframework.ai.vectorstore.observation.VectorStoreObservationDocumentation.LowCardinalityKeyNames;
|
||||
import org.springframework.ai.vectorstore.pgvector.PgVectorStore.PgIndexType;
|
||||
import org.springframework.boot.SpringBootConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||
|
||||
@@ -146,9 +146,9 @@ class PgVectorStoreWithChatMemoryAdvisorIT {
|
||||
private @NotNull EmbeddingModel embeddingNModelShouldAlwaysReturnFakedEmbed() {
|
||||
EmbeddingModel embeddingModel = mock(EmbeddingModel.class);
|
||||
|
||||
Mockito.doAnswer(invocationOnMock -> {
|
||||
return List.of(this.embed, this.embed);
|
||||
}).when(embeddingModel).embed(ArgumentMatchers.any(), any(), any());
|
||||
Mockito.doAnswer(invocationOnMock -> List.of(this.embed, this.embed))
|
||||
.when(embeddingModel)
|
||||
.embed(ArgumentMatchers.any(), any(), any());
|
||||
given(embeddingModel.embed(any(String.class))).willReturn(this.embed);
|
||||
return embeddingModel;
|
||||
}
|
||||
|
||||
@@ -36,7 +36,6 @@ import org.springframework.ai.embedding.EmbeddingModel;
|
||||
import org.springframework.ai.transformers.TransformersEmbeddingModel;
|
||||
import org.springframework.ai.vectorstore.SearchRequest;
|
||||
import org.springframework.ai.vectorstore.VectorStore;
|
||||
import org.springframework.ai.vectorstore.pinecone.PineconeVectorStore.PineconeVectorStoreConfig;
|
||||
import org.springframework.boot.SpringBootConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
|
||||
@@ -39,7 +39,6 @@ import org.springframework.ai.observation.conventions.VectorStoreProvider;
|
||||
import org.springframework.ai.transformers.TransformersEmbeddingModel;
|
||||
import org.springframework.ai.vectorstore.SearchRequest;
|
||||
import org.springframework.ai.vectorstore.VectorStore;
|
||||
import org.springframework.ai.vectorstore.pinecone.PineconeVectorStore.PineconeVectorStoreConfig;
|
||||
import org.springframework.ai.vectorstore.observation.DefaultVectorStoreObservationConvention;
|
||||
import org.springframework.ai.vectorstore.observation.VectorStoreObservationDocumentation.HighCardinalityKeyNames;
|
||||
import org.springframework.ai.vectorstore.observation.VectorStoreObservationDocumentation.LowCardinalityKeyNames;
|
||||
|
||||
@@ -368,7 +368,7 @@ public class QdrantVectorStore extends AbstractObservationVectorStore implements
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static final class Builder extends AbstractVectorStoreBuilder<Builder> {
|
||||
public static class Builder extends AbstractVectorStoreBuilder<Builder> {
|
||||
|
||||
private final QdrantClient qdrantClient;
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ class QdrantVectorStoreBuilderTests {
|
||||
|
||||
@Test
|
||||
void defaultConfiguration() {
|
||||
QdrantVectorStore vectorStore = QdrantVectorStore.builder(qdrantClient, embeddingModel).build();
|
||||
QdrantVectorStore vectorStore = QdrantVectorStore.builder(this.qdrantClient, this.embeddingModel).build();
|
||||
|
||||
// Verify default values
|
||||
assertThat(vectorStore).hasFieldOrPropertyWithValue("collectionName", "vector_store");
|
||||
@@ -56,7 +56,7 @@ class QdrantVectorStoreBuilderTests {
|
||||
|
||||
@Test
|
||||
void customConfiguration() {
|
||||
QdrantVectorStore vectorStore = QdrantVectorStore.builder(qdrantClient, embeddingModel)
|
||||
QdrantVectorStore vectorStore = QdrantVectorStore.builder(this.qdrantClient, this.embeddingModel)
|
||||
.collectionName("custom_collection")
|
||||
.initializeSchema(true)
|
||||
.batchingStrategy(new TokenCountBatchingStrategy())
|
||||
@@ -75,21 +75,23 @@ class QdrantVectorStoreBuilderTests {
|
||||
|
||||
@Test
|
||||
void nullEmbeddingModelShouldThrowException() {
|
||||
assertThatThrownBy(() -> QdrantVectorStore.builder(qdrantClient, null).build())
|
||||
assertThatThrownBy(() -> QdrantVectorStore.builder(this.qdrantClient, null).build())
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("EmbeddingModel must be configured");
|
||||
}
|
||||
|
||||
@Test
|
||||
void emptyCollectionNameShouldThrowException() {
|
||||
assertThatThrownBy(() -> QdrantVectorStore.builder(qdrantClient, embeddingModel).collectionName("").build())
|
||||
assertThatThrownBy(
|
||||
() -> QdrantVectorStore.builder(this.qdrantClient, this.embeddingModel).collectionName("").build())
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("collectionName must not be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
void nullBatchingStrategyShouldThrowException() {
|
||||
assertThatThrownBy(() -> QdrantVectorStore.builder(qdrantClient, embeddingModel).batchingStrategy(null).build())
|
||||
assertThatThrownBy(
|
||||
() -> QdrantVectorStore.builder(this.qdrantClient, this.embeddingModel).batchingStrategy(null).build())
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("BatchingStrategy must not be null");
|
||||
}
|
||||
|
||||
@@ -22,13 +22,13 @@ import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.ai.vectorstore.redis.RedisVectorStore.MetadataField;
|
||||
import org.springframework.ai.vectorstore.filter.Filter.Expression;
|
||||
import org.springframework.ai.vectorstore.filter.Filter.ExpressionType;
|
||||
import org.springframework.ai.vectorstore.filter.Filter.Group;
|
||||
import org.springframework.ai.vectorstore.filter.Filter.Key;
|
||||
import org.springframework.ai.vectorstore.filter.Filter.Value;
|
||||
import org.springframework.ai.vectorstore.filter.converter.AbstractFilterExpressionConverter;
|
||||
import org.springframework.ai.vectorstore.redis.RedisVectorStore.MetadataField;
|
||||
|
||||
/**
|
||||
* Converts {@link Expression} into Redis search filter expression format.
|
||||
|
||||
@@ -30,7 +30,6 @@ import java.util.stream.Collectors;
|
||||
import io.micrometer.observation.ObservationRegistry;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.ai.document.DocumentMetadata;
|
||||
import redis.clients.jedis.JedisPooled;
|
||||
import redis.clients.jedis.Pipeline;
|
||||
import redis.clients.jedis.json.Path2;
|
||||
@@ -48,6 +47,7 @@ import redis.clients.jedis.search.schemafields.VectorField;
|
||||
import redis.clients.jedis.search.schemafields.VectorField.VectorAlgorithm;
|
||||
|
||||
import org.springframework.ai.document.Document;
|
||||
import org.springframework.ai.document.DocumentMetadata;
|
||||
import org.springframework.ai.embedding.BatchingStrategy;
|
||||
import org.springframework.ai.embedding.EmbeddingModel;
|
||||
import org.springframework.ai.embedding.EmbeddingOptionsBuilder;
|
||||
@@ -458,6 +458,10 @@ public class RedisVectorStore extends AbstractObservationVectorStore implements
|
||||
|
||||
}
|
||||
|
||||
public static Builder builder(JedisPooled jedis, EmbeddingModel embeddingModel) {
|
||||
return new Builder(jedis, embeddingModel);
|
||||
}
|
||||
|
||||
public enum Algorithm {
|
||||
|
||||
FLAT, HSNW
|
||||
@@ -480,10 +484,6 @@ public class RedisVectorStore extends AbstractObservationVectorStore implements
|
||||
|
||||
}
|
||||
|
||||
public static Builder builder(JedisPooled jedis, EmbeddingModel embeddingModel) {
|
||||
return new Builder(jedis, embeddingModel);
|
||||
}
|
||||
|
||||
public static class Builder extends AbstractVectorStoreBuilder<Builder> {
|
||||
|
||||
private final JedisPooled jedis;
|
||||
|
||||
@@ -21,11 +21,11 @@ import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.ai.vectorstore.redis.RedisVectorStore.MetadataField;
|
||||
import org.springframework.ai.vectorstore.filter.Filter.Expression;
|
||||
import org.springframework.ai.vectorstore.filter.Filter.Group;
|
||||
import org.springframework.ai.vectorstore.filter.Filter.Key;
|
||||
import org.springframework.ai.vectorstore.filter.Filter.Value;
|
||||
import org.springframework.ai.vectorstore.redis.RedisVectorStore.MetadataField;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.ai.vectorstore.filter.Filter.ExpressionType.AND;
|
||||
|
||||
@@ -26,17 +26,17 @@ import java.util.UUID;
|
||||
import com.redis.testcontainers.RedisStackContainer;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.ai.document.DocumentMetadata;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
import redis.clients.jedis.JedisPooled;
|
||||
|
||||
import org.springframework.ai.document.Document;
|
||||
import org.springframework.ai.document.DocumentMetadata;
|
||||
import org.springframework.ai.embedding.EmbeddingModel;
|
||||
import org.springframework.ai.transformers.TransformersEmbeddingModel;
|
||||
import org.springframework.ai.vectorstore.redis.RedisVectorStore.MetadataField;
|
||||
import org.springframework.ai.vectorstore.SearchRequest;
|
||||
import org.springframework.ai.vectorstore.VectorStore;
|
||||
import org.springframework.ai.vectorstore.redis.RedisVectorStore.MetadataField;
|
||||
import org.springframework.boot.SpringBootConfiguration;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
|
||||
@@ -38,12 +38,12 @@ import org.springframework.ai.observation.conventions.SpringAiKind;
|
||||
import org.springframework.ai.observation.conventions.VectorStoreProvider;
|
||||
import org.springframework.ai.observation.conventions.VectorStoreSimilarityMetric;
|
||||
import org.springframework.ai.transformers.TransformersEmbeddingModel;
|
||||
import org.springframework.ai.vectorstore.redis.RedisVectorStore.MetadataField;
|
||||
import org.springframework.ai.vectorstore.SearchRequest;
|
||||
import org.springframework.ai.vectorstore.VectorStore;
|
||||
import org.springframework.ai.vectorstore.observation.DefaultVectorStoreObservationConvention;
|
||||
import org.springframework.ai.vectorstore.observation.VectorStoreObservationDocumentation.HighCardinalityKeyNames;
|
||||
import org.springframework.ai.vectorstore.observation.VectorStoreObservationDocumentation.LowCardinalityKeyNames;
|
||||
import org.springframework.ai.vectorstore.redis.RedisVectorStore.MetadataField;
|
||||
import org.springframework.boot.SpringBootConfiguration;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
|
||||
@@ -393,7 +393,7 @@ public class TypesenseVectorStore extends AbstractObservationVectorStore impleme
|
||||
.similarityMetric(VectorStoreSimilarityMetric.COSINE.value());
|
||||
}
|
||||
|
||||
public static final class Builder extends AbstractVectorStoreBuilder<Builder> {
|
||||
public static class Builder extends AbstractVectorStoreBuilder<Builder> {
|
||||
|
||||
private String collectionName = DEFAULT_COLLECTION_NAME;
|
||||
|
||||
|
||||
@@ -531,7 +531,7 @@ public class WeaviateVectorStore extends AbstractObservationVectorStore {
|
||||
}
|
||||
}
|
||||
|
||||
public static final class Builder extends AbstractVectorStoreBuilder<Builder> {
|
||||
public static class Builder extends AbstractVectorStoreBuilder<Builder> {
|
||||
|
||||
private String weaviateObjectClass = "SpringAiWeaviate";
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.ai.vectorstore.weaviate;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import io.weaviate.client.Config;
|
||||
import io.weaviate.client.WeaviateClient;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -27,8 +29,6 @@ import org.springframework.ai.embedding.EmbeddingModel;
|
||||
import org.springframework.ai.vectorstore.weaviate.WeaviateVectorStore.ConsistentLevel;
|
||||
import org.springframework.ai.vectorstore.weaviate.WeaviateVectorStore.MetadataField;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
@@ -47,7 +47,7 @@ class WeaviateVectorStoreBuilderTests {
|
||||
void shouldBuildWithMinimalConfiguration() {
|
||||
WeaviateClient weaviateClient = new WeaviateClient(new Config("http", "localhost:8080"));
|
||||
|
||||
WeaviateVectorStore vectorStore = WeaviateVectorStore.builder(weaviateClient, embeddingModel).build();
|
||||
WeaviateVectorStore vectorStore = WeaviateVectorStore.builder(weaviateClient, this.embeddingModel).build();
|
||||
|
||||
assertThat(vectorStore).isNotNull();
|
||||
}
|
||||
@@ -56,7 +56,7 @@ class WeaviateVectorStoreBuilderTests {
|
||||
void shouldBuildWithCustomConfiguration() {
|
||||
WeaviateClient weaviateClient = new WeaviateClient(new Config("http", "localhost:8080"));
|
||||
|
||||
WeaviateVectorStore vectorStore = WeaviateVectorStore.builder(weaviateClient, embeddingModel)
|
||||
WeaviateVectorStore vectorStore = WeaviateVectorStore.builder(weaviateClient, this.embeddingModel)
|
||||
.objectClass("CustomClass")
|
||||
.consistencyLevel(ConsistentLevel.QUORUM)
|
||||
.filterMetadataFields(List.of(MetadataField.text("country"), MetadataField.number("year")))
|
||||
@@ -67,7 +67,7 @@ class WeaviateVectorStoreBuilderTests {
|
||||
|
||||
@Test
|
||||
void shouldFailWithoutWeaviateClient() {
|
||||
assertThatThrownBy(() -> WeaviateVectorStore.builder(null, embeddingModel).build())
|
||||
assertThatThrownBy(() -> WeaviateVectorStore.builder(null, this.embeddingModel).build())
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("WeaviateClient must not be null");
|
||||
}
|
||||
@@ -85,7 +85,8 @@ class WeaviateVectorStoreBuilderTests {
|
||||
void shouldFailWithInvalidObjectClass() {
|
||||
WeaviateClient weaviateClient = new WeaviateClient(new Config("http", "localhost:8080"));
|
||||
|
||||
assertThatThrownBy(() -> WeaviateVectorStore.builder(weaviateClient, embeddingModel).objectClass("").build())
|
||||
assertThatThrownBy(
|
||||
() -> WeaviateVectorStore.builder(weaviateClient, this.embeddingModel).objectClass("").build())
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("objectClass must not be empty");
|
||||
}
|
||||
@@ -95,7 +96,7 @@ class WeaviateVectorStoreBuilderTests {
|
||||
WeaviateClient weaviateClient = new WeaviateClient(new Config("http", "localhost:8080"));
|
||||
|
||||
assertThatThrownBy(
|
||||
() -> WeaviateVectorStore.builder(weaviateClient, embeddingModel).consistencyLevel(null).build())
|
||||
() -> WeaviateVectorStore.builder(weaviateClient, this.embeddingModel).consistencyLevel(null).build())
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("consistencyLevel must not be null");
|
||||
}
|
||||
@@ -104,10 +105,9 @@ class WeaviateVectorStoreBuilderTests {
|
||||
void shouldFailWithNullFilterMetadataFields() {
|
||||
WeaviateClient weaviateClient = new WeaviateClient(new Config("http", "localhost:8080"));
|
||||
|
||||
assertThatThrownBy(
|
||||
() -> WeaviateVectorStore.builder(weaviateClient, embeddingModel).filterMetadataFields(null).build())
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("filterMetadataFields must not be null");
|
||||
assertThatThrownBy(() -> WeaviateVectorStore.builder(weaviateClient, this.embeddingModel)
|
||||
.filterMetadataFields(null)
|
||||
.build()).isInstanceOf(IllegalArgumentException.class).hasMessage("filterMetadataFields must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -26,13 +26,13 @@ import java.util.UUID;
|
||||
import io.weaviate.client.Config;
|
||||
import io.weaviate.client.WeaviateClient;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.ai.document.DocumentMetadata;
|
||||
import org.testcontainers.containers.wait.strategy.Wait;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
import org.testcontainers.weaviate.WeaviateContainer;
|
||||
|
||||
import org.springframework.ai.document.Document;
|
||||
import org.springframework.ai.document.DocumentMetadata;
|
||||
import org.springframework.ai.embedding.EmbeddingModel;
|
||||
import org.springframework.ai.transformers.TransformersEmbeddingModel;
|
||||
import org.springframework.ai.vectorstore.SearchRequest;
|
||||
|
||||
Reference in New Issue
Block a user