Improve optional values handling in vector store observations

Vector store observations support several key-value pairs, coming from the Spring AI abstractions. Currently, whenever a value is not available (either because not configured by the user or not supported by the vector store provider), span/metrics attributes are generated anyway with value none.

That causes several issues, including an unneeded increase in time series, challenges in alerting/monitoring (especially for integer/double attributes that suddenly are populated with a string), and non-compliance with the OpenTelemetry Semantic Conventions (according to which, attributes should be excluded altogether if there's no value).

This pull request changes the conventions for vector store observations to exclude the generation of span/metrics attributes for optional values which don't have any value.

Signed-off-by: Thomas Vitale <ThomasVitale@users.noreply.github.com>
This commit is contained in:
Thomas Vitale
2024-10-06 10:21:54 +02:00
committed by Christian Tzolov
parent 3b1c68ac10
commit 50e11e3f46
35 changed files with 692 additions and 319 deletions

View File

@@ -56,6 +56,13 @@ public enum VectorStoreObservationAttributes {
*/
DB_SYSTEM("db.system"),
// DB Search
/**
* The metric used in similarity search.
*/
DB_SEARCH_SIMILARITY_METRIC("db.search.similarity_metric"),
// DB Vector
/**
@@ -68,11 +75,6 @@ public enum VectorStoreObservationAttributes {
*/
DB_VECTOR_FIELD_NAME("db.vector.field_name"),
/**
* The model used for the embedding.
*/
DB_VECTOR_MODEL("db.vector.model"),
/**
* The content of the search query being executed.
*/
@@ -98,12 +100,7 @@ public enum VectorStoreObservationAttributes {
/**
* The top-k most similar vectors returned by a query.
*/
DB_VECTOR_QUERY_TOP_K("db.vector.query.top_k"),
/**
* The metric used in similarity search.
*/
DB_VECTOR_SIMILARITY_METRIC("db.vector.similarity_metric");
DB_VECTOR_QUERY_TOP_K("db.vector.query.top_k");
private final String value;

View File

@@ -16,32 +16,42 @@
package org.springframework.ai.observation.conventions;
/**
* Collection of systems providing vector store functionality. Based on the OpenTelemetry
* Semantic Conventions for Vector Databases.
*
* @author Christian Tzolov
* @author Thomas Vitale
* @since 1.0.0
* @see <a href=
* "https://github.com/open-telemetry/semantic-conventions/tree/main/docs/database">DB
* Semantic Conventions</a>.
*/
public enum VectorStoreProvider {
// @formatter:off
PG_VECTOR("pg_vector"),
AZURE("azure"),
CASSANDRA("cassandra"),
CHROMA("chroma"),
ELASTICSEARCH("elasticsearch"),
MILVUS("milvus"),
NEO4J("neo4j"),
OPENSEARCH("opensearch"),
QDRANT("qdrant"),
REDIS("redis"),
TYPESENSE("typesense"),
WEAVIATE("weaviate"),
PINECONE("pinecone"),
ORACLE("oracle"),
MONGODB("mongodb"),
GEMFIRE("gemfire"),
HANA("hana"),
SIMPLE("simple");
// @formatter:on
// Please, keep the alphabetical sorting.
AZURE("azure"),
CASSANDRA("cassandra"),
CHROMA("chroma"),
ELASTICSEARCH("elasticsearch"),
GEMFIRE("gemfire"),
HANA("hana"),
MILVUS("milvus"),
MONGODB("mongodb"),
NEO4J("neo4j"),
OPENSEARCH("opensearch"),
ORACLE("oracle"),
PG_VECTOR("pg_vector"),
PINECONE("pinecone"),
QDRANT("qdrant"),
REDIS("redis"),
SIMPLE("simple"),
TYPESENSE("typesense"),
WEAVIATE("weaviate");
// @formatter:on
private final String value;
VectorStoreProvider(String value) {

View File

@@ -35,33 +35,6 @@ public class DefaultVectorStoreObservationConvention implements VectorStoreObser
public static final String DEFAULT_NAME = "db.vector.client.operation";
private static final KeyValue COLLECTION_NAME_NONE = KeyValue.of(HighCardinalityKeyNames.DB_COLLECTION_NAME,
KeyValue.NONE_VALUE);
private static final KeyValue DIMENSIONS_NONE = KeyValue.of(HighCardinalityKeyNames.DB_VECTOR_DIMENSION_COUNT,
KeyValue.NONE_VALUE);
private static final KeyValue METADATA_FILTER_NONE = KeyValue.of(HighCardinalityKeyNames.DB_VECTOR_QUERY_FILTER,
KeyValue.NONE_VALUE);
private static final KeyValue FIELD_NAME_NONE = KeyValue.of(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME,
KeyValue.NONE_VALUE);
private static final KeyValue NAMESPACE_NONE = KeyValue.of(HighCardinalityKeyNames.DB_NAMESPACE,
KeyValue.NONE_VALUE);
private static final KeyValue QUERY_CONTENT_NONE = KeyValue.of(HighCardinalityKeyNames.DB_VECTOR_QUERY_CONTENT,
KeyValue.NONE_VALUE);
private static final KeyValue SIMILARITY_METRIC_NONE = KeyValue
.of(HighCardinalityKeyNames.DB_VECTOR_SIMILARITY_METRIC, KeyValue.NONE_VALUE);
private static final KeyValue SIMILARITY_THRESHOLD_NONE = KeyValue
.of(HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD, KeyValue.NONE_VALUE);
private static final KeyValue TOP_K_NONE = KeyValue.of(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K,
KeyValue.NONE_VALUE);
private final String name;
public DefaultVectorStoreObservationConvention() {
@@ -102,74 +75,86 @@ public class DefaultVectorStoreObservationConvention implements VectorStoreObser
@Override
public KeyValues getHighCardinalityKeyValues(VectorStoreObservationContext context) {
return KeyValues.of(collectionName(context), dimensions(context), fieldName(context), metadataFilter(context),
namespace(context), queryContent(context), similarityMetric(context), similarityThreshold(context),
topK(context));
var keyValues = KeyValues.empty();
keyValues = collectionName(keyValues, context);
keyValues = dimensions(keyValues, context);
keyValues = fieldName(keyValues, context);
keyValues = metadataFilter(keyValues, context);
keyValues = namespace(keyValues, context);
keyValues = queryContent(keyValues, context);
keyValues = similarityMetric(keyValues, context);
keyValues = similarityThreshold(keyValues, context);
keyValues = topK(keyValues, context);
return keyValues;
}
protected KeyValue collectionName(VectorStoreObservationContext context) {
protected KeyValues collectionName(KeyValues keyValues, VectorStoreObservationContext context) {
if (StringUtils.hasText(context.getCollectionName())) {
return KeyValue.of(HighCardinalityKeyNames.DB_COLLECTION_NAME, context.getCollectionName());
return keyValues.and(HighCardinalityKeyNames.DB_COLLECTION_NAME.asString(), context.getCollectionName());
}
return COLLECTION_NAME_NONE;
return keyValues;
}
protected KeyValue dimensions(VectorStoreObservationContext context) {
protected KeyValues dimensions(KeyValues keyValues, VectorStoreObservationContext context) {
if (context.getDimensions() != null && context.getDimensions() > 0) {
return KeyValue.of(HighCardinalityKeyNames.DB_VECTOR_DIMENSION_COUNT, "" + context.getDimensions());
return keyValues.and(HighCardinalityKeyNames.DB_VECTOR_DIMENSION_COUNT.asString(),
"" + context.getDimensions());
}
return DIMENSIONS_NONE;
return keyValues;
}
protected KeyValue fieldName(VectorStoreObservationContext context) {
protected KeyValues fieldName(KeyValues keyValues, VectorStoreObservationContext context) {
if (StringUtils.hasText(context.getFieldName())) {
return KeyValue.of(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME, context.getFieldName());
return keyValues.and(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString(), context.getFieldName());
}
return FIELD_NAME_NONE;
return keyValues;
}
protected KeyValue metadataFilter(VectorStoreObservationContext context) {
protected KeyValues metadataFilter(KeyValues keyValues, VectorStoreObservationContext context) {
if (context.getQueryRequest() != null && context.getQueryRequest().getFilterExpression() != null) {
return KeyValue.of(HighCardinalityKeyNames.DB_VECTOR_QUERY_FILTER,
return keyValues.and(HighCardinalityKeyNames.DB_VECTOR_QUERY_FILTER.asString(),
context.getQueryRequest().getFilterExpression().toString());
}
return METADATA_FILTER_NONE;
return keyValues;
}
protected KeyValue namespace(VectorStoreObservationContext context) {
protected KeyValues namespace(KeyValues keyValues, VectorStoreObservationContext context) {
if (StringUtils.hasText(context.getNamespace())) {
return KeyValue.of(HighCardinalityKeyNames.DB_NAMESPACE, context.getNamespace());
return keyValues.and(HighCardinalityKeyNames.DB_NAMESPACE.asString(), context.getNamespace());
}
return NAMESPACE_NONE;
return keyValues;
}
protected KeyValue queryContent(VectorStoreObservationContext context) {
protected KeyValues queryContent(KeyValues keyValues, VectorStoreObservationContext context) {
if (context.getQueryRequest() != null && StringUtils.hasText(context.getQueryRequest().getQuery())) {
return KeyValue.of(HighCardinalityKeyNames.DB_VECTOR_QUERY_CONTENT, context.getQueryRequest().getQuery());
return keyValues.and(HighCardinalityKeyNames.DB_VECTOR_QUERY_CONTENT.asString(),
context.getQueryRequest().getQuery());
}
return QUERY_CONTENT_NONE;
return keyValues;
}
protected KeyValue similarityMetric(VectorStoreObservationContext context) {
protected KeyValues similarityMetric(KeyValues keyValues, VectorStoreObservationContext context) {
if (StringUtils.hasText(context.getSimilarityMetric())) {
return KeyValue.of(HighCardinalityKeyNames.DB_VECTOR_SIMILARITY_METRIC, context.getSimilarityMetric());
return keyValues.and(HighCardinalityKeyNames.DB_SEARCH_SIMILARITY_METRIC.asString(),
context.getSimilarityMetric());
}
return SIMILARITY_METRIC_NONE;
return keyValues;
}
protected KeyValue similarityThreshold(VectorStoreObservationContext context) {
protected KeyValues similarityThreshold(KeyValues keyValues, VectorStoreObservationContext context) {
if (context.getQueryRequest() != null && context.getQueryRequest().getSimilarityThreshold() >= 0) {
return KeyValue.of(HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD,
return keyValues.and(HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString(),
String.valueOf(context.getQueryRequest().getSimilarityThreshold()));
}
return SIMILARITY_THRESHOLD_NONE;
return keyValues;
}
protected KeyValue topK(VectorStoreObservationContext context) {
protected KeyValues topK(KeyValues keyValues, VectorStoreObservationContext context) {
if (context.getQueryRequest() != null && context.getQueryRequest().getTopK() > 0) {
return KeyValue.of(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K, "" + context.getQueryRequest().getTopK());
return keyValues.and(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString(),
"" + context.getQueryRequest().getTopK());
}
return TOP_K_NONE;
return keyValues;
}
}

View File

@@ -116,6 +116,18 @@ public enum VectorStoreObservationDocumentation implements ObservationDocumentat
}
},
// DB Search
/**
* The metric used in similarity search.
*/
DB_SEARCH_SIMILARITY_METRIC {
@Override
public String asString() {
return VectorStoreObservationAttributes.DB_SEARCH_SIMILARITY_METRIC.value();
}
},
// DB Vector
/**
@@ -188,16 +200,6 @@ public enum VectorStoreObservationDocumentation implements ObservationDocumentat
public String asString() {
return VectorStoreObservationAttributes.DB_VECTOR_QUERY_TOP_K.value();
}
},
/**
* The metric used in similarity search.
*/
DB_VECTOR_SIMILARITY_METRIC {
@Override
public String asString() {
return VectorStoreObservationAttributes.DB_VECTOR_SIMILARITY_METRIC.value();
}
};
}

View File

@@ -68,13 +68,13 @@ class DefaultVectorStoreObservationConventionTests {
.builder("my_database", VectorStoreObservationContext.Operation.QUERY)
.build();
assertThat(this.observationConvention.getLowCardinalityKeyValues(observationContext)).contains(
KeyValue.of(LowCardinalityKeyNames.SPRING_AI_KIND.asString(), SpringAiKind.VECTOR_STORE.value()),
KeyValue.of(LowCardinalityKeyNames.DB_OPERATION_NAME.asString(), "query"),
KeyValue.of(LowCardinalityKeyNames.DB_SYSTEM.asString(), "my_database"));
}
@Test
void shouldHaveOptionalKeyValues() {
VectorStoreObservationContext observationContext = VectorStoreObservationContext
.builder("my-database", VectorStoreObservationContext.Operation.QUERY)
.withCollectionName("COLLECTION_NAME")
@@ -102,26 +102,28 @@ class DefaultVectorStoreObservationConventionTests {
KeyValue.of(HighCardinalityKeyNames.DB_VECTOR_DIMENSION_COUNT.asString(), "696"),
KeyValue.of(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString(), "FIELD_NAME"),
KeyValue.of(HighCardinalityKeyNames.DB_NAMESPACE.asString(), "NAMESPACE"),
KeyValue.of(HighCardinalityKeyNames.DB_VECTOR_SIMILARITY_METRIC.asString(), "SIMILARITY_METRIC"),
KeyValue.of(HighCardinalityKeyNames.DB_SEARCH_SIMILARITY_METRIC.asString(), "SIMILARITY_METRIC"),
KeyValue.of(HighCardinalityKeyNames.DB_VECTOR_QUERY_CONTENT.asString(), "VDB QUERY"),
KeyValue.of(HighCardinalityKeyNames.DB_VECTOR_QUERY_FILTER.asString(),
"Expression[type=AND, left=Expression[type=EQ, left=Key[key=country], right=Value[value=UK]], right=Expression[type=GTE, left=Key[key=year], right=Value[value=2020]]]"));
}
@Test
void shouldHaveMissingKeyValues() {
void shouldNotHaveKeyValuesWhenMissing() {
VectorStoreObservationContext observationContext = VectorStoreObservationContext
.builder("my-database", VectorStoreObservationContext.Operation.QUERY)
.build();
assertThat(this.observationConvention.getHighCardinalityKeyValues(observationContext)).contains(
KeyValue.of(HighCardinalityKeyNames.DB_COLLECTION_NAME.asString(), KeyValue.NONE_VALUE),
KeyValue.of(HighCardinalityKeyNames.DB_VECTOR_DIMENSION_COUNT.asString(), KeyValue.NONE_VALUE),
KeyValue.of(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString(), KeyValue.NONE_VALUE),
KeyValue.of(HighCardinalityKeyNames.DB_NAMESPACE.asString(), KeyValue.NONE_VALUE),
KeyValue.of(HighCardinalityKeyNames.DB_VECTOR_SIMILARITY_METRIC.asString(), KeyValue.NONE_VALUE),
KeyValue.of(HighCardinalityKeyNames.DB_VECTOR_QUERY_CONTENT.asString(), KeyValue.NONE_VALUE),
KeyValue.of(HighCardinalityKeyNames.DB_VECTOR_QUERY_FILTER.asString(), KeyValue.NONE_VALUE));
assertThat(this.observationConvention.getHighCardinalityKeyValues(observationContext)
.stream()
.map(KeyValue::getKey)
.toList()).doesNotContain(HighCardinalityKeyNames.DB_COLLECTION_NAME.asString(),
HighCardinalityKeyNames.DB_VECTOR_DIMENSION_COUNT.asString(),
HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString(),
HighCardinalityKeyNames.DB_NAMESPACE.asString(),
HighCardinalityKeyNames.DB_SEARCH_SIMILARITY_METRIC.asString(),
HighCardinalityKeyNames.DB_VECTOR_QUERY_CONTENT.asString(),
HighCardinalityKeyNames.DB_VECTOR_QUERY_FILTER.asString());
}
}

View File

@@ -32,6 +32,8 @@ import org.springframework.ai.document.Document;
import org.springframework.ai.embedding.EmbeddingModel;
import org.springframework.ai.embedding.TokenCountBatchingStrategy;
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.SearchRequest;
import org.springframework.ai.vectorstore.VectorStore;
@@ -104,21 +106,23 @@ public class AzureVectorStoreObservationIT {
.doesNotHaveAnyRemainingCurrentObservation()
.hasObservationWithNameEqualTo(DefaultVectorStoreObservationConvention.DEFAULT_NAME)
.that()
.hasContextualNameEqualTo("azure add")
.hasContextualNameEqualTo("%s add".formatted(VectorStoreProvider.AZURE.value()))
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_OPERATION_NAME.asString(), "add")
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_SYSTEM.asString(), "azure")
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_SYSTEM.asString(),
VectorStoreProvider.AZURE.value())
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.SPRING_AI_KIND.asString(),
SpringAiKind.VECTOR_STORE.value())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_CONTENT.asString(), "none")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_QUERY_CONTENT.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_DIMENSION_COUNT.asString(), "384")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_COLLECTION_NAME.asString(),
AzureVectorStore.DEFAULT_INDEX_NAME)
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_NAMESPACE.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_SIMILARITY_METRIC.asString(), "cosine")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString(),
"none")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_NAMESPACE.asString())
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_SEARCH_SIMILARITY_METRIC.asString(),
VectorStoreSimilarityMetric.COSINE.value())
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString())
.doesNotHaveHighCardinalityKeyValueWithKey(
HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString())
.hasBeenStarted()
.hasBeenStopped();
@@ -134,9 +138,10 @@ public class AzureVectorStoreObservationIT {
.doesNotHaveAnyRemainingCurrentObservation()
.hasObservationWithNameEqualTo(DefaultVectorStoreObservationConvention.DEFAULT_NAME)
.that()
.hasContextualNameEqualTo("azure query")
.hasContextualNameEqualTo("%s query".formatted(VectorStoreProvider.AZURE.value()))
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_OPERATION_NAME.asString(), "query")
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_SYSTEM.asString(), "azure")
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_SYSTEM.asString(),
VectorStoreProvider.AZURE.value())
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.SPRING_AI_KIND.asString(),
SpringAiKind.VECTOR_STORE.value())
@@ -145,9 +150,10 @@ public class AzureVectorStoreObservationIT {
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_DIMENSION_COUNT.asString(), "384")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_COLLECTION_NAME.asString(),
AzureVectorStore.DEFAULT_INDEX_NAME)
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_NAMESPACE.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_SIMILARITY_METRIC.asString(), "cosine")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_NAMESPACE.asString())
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_SEARCH_SIMILARITY_METRIC.asString(),
VectorStoreSimilarityMetric.COSINE.value())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString(), "1")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString(),
"0.0")

View File

@@ -27,6 +27,8 @@ import org.springframework.ai.document.Document;
import org.springframework.ai.embedding.EmbeddingModel;
import org.springframework.ai.embedding.TokenCountBatchingStrategy;
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.CassandraVectorStoreConfig.SchemaColumn;
import org.springframework.ai.vectorstore.observation.DefaultVectorStoreObservationConvention;
@@ -95,21 +97,23 @@ public class CassandraVectorStoreObservationIT {
.doesNotHaveAnyRemainingCurrentObservation()
.hasObservationWithNameEqualTo(DefaultVectorStoreObservationConvention.DEFAULT_NAME)
.that()
.hasContextualNameEqualTo("cassandra add")
.hasContextualNameEqualTo("%s add".formatted(VectorStoreProvider.CASSANDRA.value()))
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_OPERATION_NAME.asString(), "add")
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_SYSTEM.asString(), "cassandra")
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_SYSTEM.asString(),
VectorStoreProvider.CASSANDRA.value())
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.SPRING_AI_KIND.asString(),
SpringAiKind.VECTOR_STORE.value())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_CONTENT.asString(), "none")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_QUERY_CONTENT.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_DIMENSION_COUNT.asString(), "384")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_COLLECTION_NAME.asString(),
CassandraVectorStoreConfig.DEFAULT_TABLE_NAME)
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_NAMESPACE.asString(), "test_springframework")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_SIMILARITY_METRIC.asString(), "cosine")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString(),
"none")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_SEARCH_SIMILARITY_METRIC.asString(),
VectorStoreSimilarityMetric.COSINE.value())
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString())
.doesNotHaveHighCardinalityKeyValueWithKey(
HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString())
.hasBeenStarted()
.hasBeenStopped();
@@ -125,9 +129,10 @@ public class CassandraVectorStoreObservationIT {
.doesNotHaveAnyRemainingCurrentObservation()
.hasObservationWithNameEqualTo(DefaultVectorStoreObservationConvention.DEFAULT_NAME)
.that()
.hasContextualNameEqualTo("cassandra query")
.hasContextualNameEqualTo("%s query".formatted(VectorStoreProvider.CASSANDRA.value()))
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_OPERATION_NAME.asString(), "query")
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_SYSTEM.asString(), "cassandra")
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_SYSTEM.asString(),
VectorStoreProvider.CASSANDRA.value())
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.SPRING_AI_KIND.asString(),
SpringAiKind.VECTOR_STORE.value())
@@ -137,8 +142,9 @@ public class CassandraVectorStoreObservationIT {
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_COLLECTION_NAME.asString(),
CassandraVectorStoreConfig.DEFAULT_TABLE_NAME)
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_NAMESPACE.asString(), "test_springframework")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_SIMILARITY_METRIC.asString(), "cosine")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_SEARCH_SIMILARITY_METRIC.asString(),
VectorStoreSimilarityMetric.COSINE.value())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString(), "1")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString(),
"0.0")

View File

@@ -0,0 +1,27 @@
/*
* Copyright 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;
import org.testcontainers.utility.DockerImageName;
/**
* @author Thomas Vitale
*/
public class ChromaImage {
public static final DockerImageName DEFAULT_IMAGE = DockerImageName.parse("ghcr.io/chroma-core/chroma:0.5.11");
}

View File

@@ -23,6 +23,7 @@ import java.util.List;
import java.util.Map;
import org.junit.jupiter.api.Test;
import org.springframework.ai.ChromaImage;
import org.springframework.ai.chroma.ChromaApi;
import org.springframework.ai.document.Document;
import org.springframework.ai.embedding.EmbeddingModel;
@@ -57,7 +58,7 @@ import io.micrometer.observation.tck.TestObservationRegistryAssert;
public class ChromaVectorStoreObservationIT {
@Container
static ChromaDBContainer chromaContainer = new ChromaDBContainer("ghcr.io/chroma-core/chroma:0.5.0");
static ChromaDBContainer chromaContainer = new ChromaDBContainer(ChromaImage.DEFAULT_IMAGE);
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withUserConfiguration(Config.class);
@@ -92,22 +93,23 @@ public class ChromaVectorStoreObservationIT {
.doesNotHaveAnyRemainingCurrentObservation()
.hasObservationWithNameEqualTo(DefaultVectorStoreObservationConvention.DEFAULT_NAME)
.that()
.hasContextualNameEqualTo("chroma add")
.hasContextualNameEqualTo("%s add".formatted(VectorStoreProvider.CHROMA.value()))
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_OPERATION_NAME.asString(), "add")
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_SYSTEM.asString(),
VectorStoreProvider.CHROMA.value())
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.SPRING_AI_KIND.asString(),
SpringAiKind.VECTOR_STORE.value())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_CONTENT.asString(), "none")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_QUERY_CONTENT.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_DIMENSION_COUNT.asString(), "1536")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_COLLECTION_NAME.asString(),
"TestCollection:" + vectorStore.getCollectionId())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_NAMESPACE.asString(), "none")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_NAMESPACE.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString(), "distance")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_SIMILARITY_METRIC.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString(),
"none")
.doesNotHaveHighCardinalityKeyValueWithKey(
HighCardinalityKeyNames.DB_SEARCH_SIMILARITY_METRIC.asString())
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString())
.doesNotHaveHighCardinalityKeyValueWithKey(
HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString())
.hasBeenStarted()
.hasBeenStopped();
@@ -123,7 +125,7 @@ public class ChromaVectorStoreObservationIT {
.doesNotHaveAnyRemainingCurrentObservation()
.hasObservationWithNameEqualTo(DefaultVectorStoreObservationConvention.DEFAULT_NAME)
.that()
.hasContextualNameEqualTo("chroma query")
.hasContextualNameEqualTo("%s query".formatted(VectorStoreProvider.CHROMA.value()))
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_OPERATION_NAME.asString(), "query")
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_SYSTEM.asString(),
VectorStoreProvider.CHROMA.value())
@@ -135,9 +137,10 @@ public class ChromaVectorStoreObservationIT {
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_DIMENSION_COUNT.asString(), "1536")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_COLLECTION_NAME.asString(),
"TestCollection:" + vectorStore.getCollectionId())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_NAMESPACE.asString(), "none")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_NAMESPACE.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString(), "distance")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_SIMILARITY_METRIC.asString(), "none")
.doesNotHaveHighCardinalityKeyValueWithKey(
HighCardinalityKeyNames.DB_SEARCH_SIMILARITY_METRIC.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString(), "1")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString(),
"0.0")

View File

@@ -0,0 +1,28 @@
/*
* Copyright 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.vectorstore;
import org.testcontainers.utility.DockerImageName;
/**
* @author Thomas Vitale
*/
public class ElasticsearchImage {
public static final DockerImageName DEFAULT_IMAGE = DockerImageName
.parse("docker.elastic.co/elasticsearch/elasticsearch:8.15.2");
}

View File

@@ -36,6 +36,7 @@ import org.springframework.ai.embedding.EmbeddingModel;
import org.springframework.ai.embedding.TokenCountBatchingStrategy;
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.openai.OpenAiEmbeddingModel;
import org.springframework.ai.openai.api.OpenAiApi;
import org.springframework.ai.vectorstore.observation.DefaultVectorStoreObservationConvention;
@@ -73,7 +74,7 @@ public class ElasticsearchVectorStoreObservationIT {
@Container
private static final ElasticsearchContainer elasticsearchContainer = new ElasticsearchContainer(
"docker.elastic.co/elasticsearch/elasticsearch:8.13.3")
ElasticsearchImage.DEFAULT_IMAGE)
.withEnv("xpack.security.enabled", "false");
List<Document> documents = List.of(
@@ -129,22 +130,23 @@ public class ElasticsearchVectorStoreObservationIT {
.doesNotHaveAnyRemainingCurrentObservation()
.hasObservationWithNameEqualTo(DefaultVectorStoreObservationConvention.DEFAULT_NAME)
.that()
.hasContextualNameEqualTo("elasticsearch add")
.hasContextualNameEqualTo("%s add".formatted(VectorStoreProvider.ELASTICSEARCH.value()))
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_OPERATION_NAME.asString(), "add")
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_SYSTEM.asString(),
VectorStoreProvider.ELASTICSEARCH.value())
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.SPRING_AI_KIND.asString(),
SpringAiKind.VECTOR_STORE.value())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_CONTENT.asString(), "none")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_QUERY_CONTENT.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_DIMENSION_COUNT.asString(), "1536")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_COLLECTION_NAME.asString(),
"spring-ai-document-index")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_NAMESPACE.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_SIMILARITY_METRIC.asString(), "cosine")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString(),
"none")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_NAMESPACE.asString())
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_SEARCH_SIMILARITY_METRIC.asString(),
VectorStoreSimilarityMetric.COSINE.value())
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString())
.doesNotHaveHighCardinalityKeyValueWithKey(
HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString())
.hasBeenStarted()
.hasBeenStopped();
@@ -165,7 +167,7 @@ public class ElasticsearchVectorStoreObservationIT {
.doesNotHaveAnyRemainingCurrentObservation()
.hasObservationWithNameEqualTo(DefaultVectorStoreObservationConvention.DEFAULT_NAME)
.that()
.hasContextualNameEqualTo("elasticsearch query")
.hasContextualNameEqualTo("%s query".formatted(VectorStoreProvider.ELASTICSEARCH.value()))
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_OPERATION_NAME.asString(), "query")
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_SYSTEM.asString(),
VectorStoreProvider.ELASTICSEARCH.value())
@@ -177,9 +179,10 @@ public class ElasticsearchVectorStoreObservationIT {
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_DIMENSION_COUNT.asString(), "1536")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_COLLECTION_NAME.asString(),
"spring-ai-document-index")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_NAMESPACE.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_SIMILARITY_METRIC.asString(), "cosine")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_NAMESPACE.asString())
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_SEARCH_SIMILARITY_METRIC.asString(),
VectorStoreSimilarityMetric.COSINE.value())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString(), "1")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString(),
"0.0")

View File

@@ -0,0 +1,27 @@
/*
* Copyright 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.vectorstore;
import org.testcontainers.utility.DockerImageName;
/**
* @author Thomas Vitale
*/
public class GemFireImage {
public static final DockerImageName DEFAULT_IMAGE = DockerImageName.parse("gemfire/gemfire-all:10.1-jdk17");
}

View File

@@ -80,7 +80,7 @@ public class GemFireVectorStoreObservationIT {
Ports.Binding hostPort = Ports.Binding.bindPort(HTTP_SERVICE_PORT);
ExposedPort exposedPort = new ExposedPort(HTTP_SERVICE_PORT);
PortBinding mappedPort = new PortBinding(hostPort, exposedPort);
gemFireCluster = new GemFireCluster("gemfire/gemfire-all:10.1-jdk17", LOCATOR_COUNT, SERVER_COUNT);
gemFireCluster = new GemFireCluster(GemFireImage.DEFAULT_IMAGE, LOCATOR_COUNT, SERVER_COUNT);
gemFireCluster.withConfiguration(GemFireCluster.SERVER_GLOB,
container -> container.withExposedPorts(HTTP_SERVICE_PORT)
.withCreateContainerCmdModifier(cmd -> cmd.getHostConfig().withPortBindings(mappedPort)));
@@ -125,21 +125,22 @@ public class GemFireVectorStoreObservationIT {
.doesNotHaveAnyRemainingCurrentObservation()
.hasObservationWithNameEqualTo(DefaultVectorStoreObservationConvention.DEFAULT_NAME)
.that()
.hasContextualNameEqualTo("gemfire add")
.hasContextualNameEqualTo("%s add".formatted(VectorStoreProvider.GEMFIRE.value()))
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_OPERATION_NAME.asString(), "add")
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_SYSTEM.asString(),
VectorStoreProvider.GEMFIRE.value())
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.SPRING_AI_KIND.asString(),
SpringAiKind.VECTOR_STORE.value())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_CONTENT.asString(), "none")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_QUERY_CONTENT.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_DIMENSION_COUNT.asString(), "384")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_COLLECTION_NAME.asString(), TEST_INDEX_NAME)
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_NAMESPACE.asString(), "none")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_NAMESPACE.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString(), "/embeddings")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_SIMILARITY_METRIC.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString(),
"none")
.doesNotHaveHighCardinalityKeyValueWithKey(
HighCardinalityKeyNames.DB_SEARCH_SIMILARITY_METRIC.asString())
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString())
.doesNotHaveHighCardinalityKeyValueWithKey(
HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString())
.hasBeenStarted()
.hasBeenStopped();
@@ -161,7 +162,7 @@ public class GemFireVectorStoreObservationIT {
.doesNotHaveAnyRemainingCurrentObservation()
.hasObservationWithNameEqualTo(DefaultVectorStoreObservationConvention.DEFAULT_NAME)
.that()
.hasContextualNameEqualTo("gemfire query")
.hasContextualNameEqualTo("%s query".formatted(VectorStoreProvider.GEMFIRE.value()))
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_OPERATION_NAME.asString(), "query")
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_SYSTEM.asString(),
VectorStoreProvider.GEMFIRE.value())
@@ -172,9 +173,10 @@ public class GemFireVectorStoreObservationIT {
"What is Great Depression")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_DIMENSION_COUNT.asString(), "384")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_COLLECTION_NAME.asString(), TEST_INDEX_NAME)
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_NAMESPACE.asString(), "none")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_NAMESPACE.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString(), "/embeddings")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_SIMILARITY_METRIC.asString(), "none")
.doesNotHaveHighCardinalityKeyValueWithKey(
HighCardinalityKeyNames.DB_SEARCH_SIMILARITY_METRIC.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString(), "1")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString(),
"0.0")

View File

@@ -30,6 +30,7 @@ import org.springframework.ai.document.Document;
import org.springframework.ai.embedding.EmbeddingModel;
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.openai.OpenAiEmbeddingModel;
import org.springframework.ai.openai.api.OpenAiApi;
import org.springframework.ai.vectorstore.observation.DefaultVectorStoreObservationConvention;
@@ -94,21 +95,22 @@ public class HanaVectorStoreObservationIT {
.doesNotHaveAnyRemainingCurrentObservation()
.hasObservationWithNameEqualTo(DefaultVectorStoreObservationConvention.DEFAULT_NAME)
.that()
.hasContextualNameEqualTo("hana add")
.hasContextualNameEqualTo("%s add".formatted(VectorStoreProvider.HANA.value()))
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_OPERATION_NAME.asString(), "add")
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_SYSTEM.asString(),
VectorStoreProvider.HANA.value())
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.SPRING_AI_KIND.asString(),
SpringAiKind.VECTOR_STORE.value())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_CONTENT.asString(), "none")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_QUERY_CONTENT.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_DIMENSION_COUNT.asString(), "1536")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_COLLECTION_NAME.asString(), TEST_TABLE_NAME)
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_NAMESPACE.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_SIMILARITY_METRIC.asString(), "cosine")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString(),
"none")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_NAMESPACE.asString())
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_SEARCH_SIMILARITY_METRIC.asString(),
VectorStoreSimilarityMetric.COSINE.value())
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString())
.doesNotHaveHighCardinalityKeyValueWithKey(
HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString())
.hasBeenStarted()
.hasBeenStopped();
@@ -124,7 +126,7 @@ public class HanaVectorStoreObservationIT {
.doesNotHaveAnyRemainingCurrentObservation()
.hasObservationWithNameEqualTo(DefaultVectorStoreObservationConvention.DEFAULT_NAME)
.that()
.hasContextualNameEqualTo("hana query")
.hasContextualNameEqualTo("%s query".formatted(VectorStoreProvider.HANA.value()))
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_OPERATION_NAME.asString(), "query")
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_SYSTEM.asString(),
VectorStoreProvider.HANA.value())
@@ -135,9 +137,10 @@ public class HanaVectorStoreObservationIT {
"What is Great Depression")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_DIMENSION_COUNT.asString(), "1536")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_COLLECTION_NAME.asString(), TEST_TABLE_NAME)
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_NAMESPACE.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_SIMILARITY_METRIC.asString(), "cosine")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_NAMESPACE.asString())
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_SEARCH_SIMILARITY_METRIC.asString(),
VectorStoreSimilarityMetric.COSINE.value())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString(), "1")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString(),
"0.0")

View File

@@ -0,0 +1,27 @@
/*
* Copyright 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.vectorstore;
import org.testcontainers.utility.DockerImageName;
/**
* @author Thomas Vitale
*/
public class MilvusImage {
public static final DockerImageName DEFAULT_IMAGE = DockerImageName.parse("milvusdb/milvus:v2.4.9");
}

View File

@@ -28,6 +28,7 @@ import org.springframework.ai.embedding.EmbeddingModel;
import org.springframework.ai.embedding.TokenCountBatchingStrategy;
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.openai.OpenAiEmbeddingModel;
import org.springframework.ai.openai.api.OpenAiApi;
import org.springframework.ai.vectorstore.MilvusVectorStore.MilvusVectorStoreConfig;
@@ -61,7 +62,7 @@ public class MilvusVectorStoreObservationIT {
private static final String TEST_COLLECTION_NAME = "test_vector_store";
@Container
private static MilvusContainer milvusContainer = new MilvusContainer("milvusdb/milvus:v2.3.8");
private static MilvusContainer milvusContainer = new MilvusContainer(MilvusImage.DEFAULT_IMAGE);
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withUserConfiguration(Config.class);
@@ -96,21 +97,22 @@ public class MilvusVectorStoreObservationIT {
.doesNotHaveAnyRemainingCurrentObservation()
.hasObservationWithNameEqualTo(DefaultVectorStoreObservationConvention.DEFAULT_NAME)
.that()
.hasContextualNameEqualTo("milvus add")
.hasContextualNameEqualTo("%s add".formatted(VectorStoreProvider.MILVUS.value()))
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_OPERATION_NAME.asString(), "add")
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_SYSTEM.asString(),
VectorStoreProvider.MILVUS.value())
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.SPRING_AI_KIND.asString(),
SpringAiKind.VECTOR_STORE.value())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_CONTENT.asString(), "none")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_QUERY_CONTENT.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_DIMENSION_COUNT.asString(), "1536")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_COLLECTION_NAME.asString(), TEST_COLLECTION_NAME)
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_NAMESPACE.asString(), "default")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_SIMILARITY_METRIC.asString(), "cosine")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString(),
"none")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_SEARCH_SIMILARITY_METRIC.asString(),
VectorStoreSimilarityMetric.COSINE.value())
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString())
.doesNotHaveHighCardinalityKeyValueWithKey(
HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString())
.hasBeenStarted()
.hasBeenStopped();
@@ -126,7 +128,7 @@ public class MilvusVectorStoreObservationIT {
.doesNotHaveAnyRemainingCurrentObservation()
.hasObservationWithNameEqualTo(DefaultVectorStoreObservationConvention.DEFAULT_NAME)
.that()
.hasContextualNameEqualTo("milvus query")
.hasContextualNameEqualTo("%s query".formatted(VectorStoreProvider.MILVUS.value()))
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_OPERATION_NAME.asString(), "query")
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_SYSTEM.asString(),
VectorStoreProvider.MILVUS.value())
@@ -138,8 +140,9 @@ public class MilvusVectorStoreObservationIT {
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_DIMENSION_COUNT.asString(), "1536")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_COLLECTION_NAME.asString(), TEST_COLLECTION_NAME)
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_NAMESPACE.asString(), "default")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_SIMILARITY_METRIC.asString(), "cosine")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_SEARCH_SIMILARITY_METRIC.asString(),
VectorStoreSimilarityMetric.COSINE.value())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString(), "1")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString(),
"0.0")

View File

@@ -0,0 +1,27 @@
/*
* Copyright 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.vectorstore;
import org.testcontainers.utility.DockerImageName;
/**
* @author Thomas Vitale
*/
public class MongoDbImage {
public static final DockerImageName DEFAULT_IMAGE = DockerImageName.parse("mongodb/mongodb-atlas-local:8.0.0");
}

View File

@@ -69,8 +69,7 @@ import org.testcontainers.mongodb.MongoDBAtlasLocalContainer;
public class MongoDbVectorStoreObservationIT {
@Container
private static MongoDBAtlasLocalContainer container = new MongoDBAtlasLocalContainer(
"mongodb/mongodb-atlas-local:7.0.9");
private static MongoDBAtlasLocalContainer container = new MongoDBAtlasLocalContainer(MongoDbImage.DEFAULT_IMAGE);
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withUserConfiguration(Config.class)
@@ -117,22 +116,23 @@ public class MongoDbVectorStoreObservationIT {
.doesNotHaveAnyRemainingCurrentObservation()
.hasObservationWithNameEqualTo(DefaultVectorStoreObservationConvention.DEFAULT_NAME)
.that()
.hasContextualNameEqualTo("mongodb add")
.hasContextualNameEqualTo("%s add".formatted(VectorStoreProvider.MONGODB.value()))
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_OPERATION_NAME.asString(), "add")
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_SYSTEM.asString(),
VectorStoreProvider.MONGODB.value())
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.SPRING_AI_KIND.asString(),
SpringAiKind.VECTOR_STORE.value())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_CONTENT.asString(), "none")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_QUERY_CONTENT.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_DIMENSION_COUNT.asString(), "1536")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_COLLECTION_NAME.asString(),
MongoDBAtlasVectorStore.DEFAULT_VECTOR_COLLECTION_NAME)
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_NAMESPACE.asString(), "none")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_NAMESPACE.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString(), "embedding")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_SIMILARITY_METRIC.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString(),
"none")
.doesNotHaveHighCardinalityKeyValueWithKey(
HighCardinalityKeyNames.DB_SEARCH_SIMILARITY_METRIC.asString())
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString())
.doesNotHaveHighCardinalityKeyValueWithKey(
HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString())
.hasBeenStarted()
.hasBeenStopped();
@@ -148,7 +148,7 @@ public class MongoDbVectorStoreObservationIT {
.doesNotHaveAnyRemainingCurrentObservation()
.hasObservationWithNameEqualTo(DefaultVectorStoreObservationConvention.DEFAULT_NAME)
.that()
.hasContextualNameEqualTo("mongodb query")
.hasContextualNameEqualTo("%s query".formatted(VectorStoreProvider.MONGODB.value()))
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_OPERATION_NAME.asString(), "query")
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_SYSTEM.asString(),
VectorStoreProvider.MONGODB.value())
@@ -160,9 +160,10 @@ public class MongoDbVectorStoreObservationIT {
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_DIMENSION_COUNT.asString(), "1536")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_COLLECTION_NAME.asString(),
MongoDBAtlasVectorStore.DEFAULT_VECTOR_COLLECTION_NAME)
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_NAMESPACE.asString(), "none")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_NAMESPACE.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString(), "embedding")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_SIMILARITY_METRIC.asString(), "none")
.doesNotHaveHighCardinalityKeyValueWithKey(
HighCardinalityKeyNames.DB_SEARCH_SIMILARITY_METRIC.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString(), "1")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString(),
"0.0")

View File

@@ -0,0 +1,27 @@
/*
* Copyright 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.vectorstore;
import org.testcontainers.utility.DockerImageName;
/**
* @author Thomas Vitale
*/
public class Neo4jImage {
public static final DockerImageName DEFAULT_IMAGE = DockerImageName.parse("neo4j:5.24");
}

View File

@@ -34,6 +34,7 @@ import org.springframework.ai.embedding.EmbeddingModel;
import org.springframework.ai.embedding.TokenCountBatchingStrategy;
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.openai.OpenAiEmbeddingModel;
import org.springframework.ai.openai.api.OpenAiApi;
import org.springframework.ai.vectorstore.observation.DefaultVectorStoreObservationConvention;
@@ -48,7 +49,6 @@ import org.springframework.core.io.DefaultResourceLoader;
import org.testcontainers.containers.Neo4jContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.testcontainers.utility.DockerImageName;
import io.micrometer.observation.ObservationRegistry;
import io.micrometer.observation.tck.TestObservationRegistry;
@@ -63,8 +63,7 @@ import io.micrometer.observation.tck.TestObservationRegistryAssert;
public class Neo4jVectorStoreObservationIT {
@Container
static Neo4jContainer<?> neo4jContainer = new Neo4jContainer<>(DockerImageName.parse("neo4j:5.18"))
.withRandomPassword();
static Neo4jContainer<?> neo4jContainer = new Neo4jContainer<>(Neo4jImage.DEFAULT_IMAGE).withRandomPassword();
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withUserConfiguration(Config.class);
@@ -105,22 +104,23 @@ public class Neo4jVectorStoreObservationIT {
.doesNotHaveAnyRemainingCurrentObservation()
.hasObservationWithNameEqualTo(DefaultVectorStoreObservationConvention.DEFAULT_NAME)
.that()
.hasContextualNameEqualTo("neo4j add")
.hasContextualNameEqualTo("%s add".formatted(VectorStoreProvider.NEO4J.value()))
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_OPERATION_NAME.asString(), "add")
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_SYSTEM.asString(),
VectorStoreProvider.NEO4J.value())
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.SPRING_AI_KIND.asString(),
SpringAiKind.VECTOR_STORE.value())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_CONTENT.asString(), "none")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_QUERY_CONTENT.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_DIMENSION_COUNT.asString(), "1536")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_COLLECTION_NAME.asString(),
SchemaNames.sanitize(Neo4jVectorStore.DEFAULT_INDEX_NAME).orElseThrow())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_NAMESPACE.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_SIMILARITY_METRIC.asString(), "cosine")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString(),
"none")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_NAMESPACE.asString())
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_SEARCH_SIMILARITY_METRIC.asString(),
VectorStoreSimilarityMetric.COSINE.value())
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString())
.doesNotHaveHighCardinalityKeyValueWithKey(
HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString())
.hasBeenStarted()
.hasBeenStopped();
@@ -136,7 +136,7 @@ public class Neo4jVectorStoreObservationIT {
.doesNotHaveAnyRemainingCurrentObservation()
.hasObservationWithNameEqualTo(DefaultVectorStoreObservationConvention.DEFAULT_NAME)
.that()
.hasContextualNameEqualTo("neo4j query")
.hasContextualNameEqualTo("%s query".formatted(VectorStoreProvider.NEO4J.value()))
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_OPERATION_NAME.asString(), "query")
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_SYSTEM.asString(),
VectorStoreProvider.NEO4J.value())
@@ -148,9 +148,10 @@ public class Neo4jVectorStoreObservationIT {
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_DIMENSION_COUNT.asString(), "1536")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_COLLECTION_NAME.asString(),
SchemaNames.sanitize(Neo4jVectorStore.DEFAULT_INDEX_NAME).orElseThrow())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_NAMESPACE.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_SIMILARITY_METRIC.asString(), "cosine")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_NAMESPACE.asString())
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_SEARCH_SIMILARITY_METRIC.asString(),
VectorStoreSimilarityMetric.COSINE.value())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString(), "1")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString(),
"0.0")

View File

@@ -0,0 +1,27 @@
/*
* Copyright 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.vectorstore;
import org.testcontainers.utility.DockerImageName;
/**
* @author Thomas Vitale
*/
public class OpenSearchImage {
public static final DockerImageName DEFAULT_IMAGE = DockerImageName.parse("opensearchproject/opensearch:2.17.1");
}

View File

@@ -39,6 +39,7 @@ import org.springframework.ai.embedding.EmbeddingModel;
import org.springframework.ai.embedding.TokenCountBatchingStrategy;
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.openai.OpenAiEmbeddingModel;
import org.springframework.ai.openai.api.OpenAiApi;
import org.springframework.ai.vectorstore.observation.DefaultVectorStoreObservationConvention;
@@ -52,7 +53,6 @@ import org.springframework.context.annotation.Bean;
import org.springframework.core.io.DefaultResourceLoader;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.testcontainers.utility.DockerImageName;
import io.micrometer.observation.ObservationRegistry;
import io.micrometer.observation.tck.TestObservationRegistry;
@@ -70,7 +70,7 @@ public class OpenSearchVectorStoreObservationIT {
@Container
private static final OpensearchContainer<?> opensearchContainer = new OpensearchContainer<>(
DockerImageName.parse("opensearchproject/opensearch:2.13.0"));
OpenSearchImage.DEFAULT_IMAGE);
List<Document> documents = List.of(
new Document(getText("classpath:/test/data/spring.ai.txt"), Map.of("meta1", "meta1")),
@@ -121,22 +121,23 @@ public class OpenSearchVectorStoreObservationIT {
.doesNotHaveAnyRemainingCurrentObservation()
.hasObservationWithNameEqualTo(DefaultVectorStoreObservationConvention.DEFAULT_NAME)
.that()
.hasContextualNameEqualTo("opensearch add")
.hasContextualNameEqualTo("%s add".formatted(VectorStoreProvider.OPENSEARCH.value()))
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_OPERATION_NAME.asString(), "add")
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_SYSTEM.asString(),
VectorStoreProvider.OPENSEARCH.value())
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.SPRING_AI_KIND.asString(),
SpringAiKind.VECTOR_STORE.value())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_CONTENT.asString(), "none")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_QUERY_CONTENT.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_DIMENSION_COUNT.asString(), "1536")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_COLLECTION_NAME.asString(),
OpenSearchVectorStore.DEFAULT_INDEX_NAME)
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_NAMESPACE.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_SIMILARITY_METRIC.asString(), "cosine")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString(),
"none")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_NAMESPACE.asString())
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_SEARCH_SIMILARITY_METRIC.asString(),
VectorStoreSimilarityMetric.COSINE.value())
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString())
.doesNotHaveHighCardinalityKeyValueWithKey(
HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString())
.hasBeenStarted()
.hasBeenStopped();
@@ -156,7 +157,7 @@ public class OpenSearchVectorStoreObservationIT {
.doesNotHaveAnyRemainingCurrentObservation()
.hasObservationWithNameEqualTo(DefaultVectorStoreObservationConvention.DEFAULT_NAME)
.that()
.hasContextualNameEqualTo("opensearch query")
.hasContextualNameEqualTo("%s query".formatted(VectorStoreProvider.OPENSEARCH.value()))
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_OPERATION_NAME.asString(), "query")
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_SYSTEM.asString(),
VectorStoreProvider.OPENSEARCH.value())
@@ -168,9 +169,10 @@ public class OpenSearchVectorStoreObservationIT {
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_DIMENSION_COUNT.asString(), "1536")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_COLLECTION_NAME.asString(),
OpenSearchVectorStore.DEFAULT_INDEX_NAME)
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_NAMESPACE.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_SIMILARITY_METRIC.asString(), "cosine")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_NAMESPACE.asString())
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_SEARCH_SIMILARITY_METRIC.asString(),
VectorStoreSimilarityMetric.COSINE.value())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString(), "1")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString(),
"0.0")

View File

@@ -0,0 +1,27 @@
/*
* Copyright 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.vectorstore;
import org.testcontainers.utility.DockerImageName;
/**
* @author Thomas Vitale
*/
public class OracleImage {
public static final DockerImageName DEFAULT_IMAGE = DockerImageName.parse("gvenzl/oracle-free:23-slim");
}

View File

@@ -30,6 +30,7 @@ import org.springframework.ai.embedding.EmbeddingModel;
import org.springframework.ai.embedding.TokenCountBatchingStrategy;
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.OracleVectorStore.OracleVectorStoreDistanceType;
import org.springframework.ai.vectorstore.observation.DefaultVectorStoreObservationConvention;
@@ -64,9 +65,8 @@ import oracle.jdbc.pool.OracleDataSource;
public class OracleVectorStoreObservationIT {
@Container
static OracleContainer oracle23aiContainer = new OracleContainer("gvenzl/oracle-free:23-slim")
.withCopyFileToContainer(MountableFile.forClasspathResource("/initialize.sql"),
"/container-entrypoint-initdb.d/initialize.sql");
static OracleContainer oracle23aiContainer = new OracleContainer(OracleImage.DEFAULT_IMAGE).withCopyFileToContainer(
MountableFile.forClasspathResource("/initialize.sql"), "/container-entrypoint-initdb.d/initialize.sql");
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withUserConfiguration(Config.class)
@@ -112,22 +112,23 @@ public class OracleVectorStoreObservationIT {
.doesNotHaveAnyRemainingCurrentObservation()
.hasObservationWithNameEqualTo(DefaultVectorStoreObservationConvention.DEFAULT_NAME)
.that()
.hasContextualNameEqualTo("oracle add")
.hasContextualNameEqualTo("%s add".formatted(VectorStoreProvider.ORACLE.value()))
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_OPERATION_NAME.asString(), "add")
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_SYSTEM.asString(),
VectorStoreProvider.ORACLE.value())
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.SPRING_AI_KIND.asString(),
SpringAiKind.VECTOR_STORE.value())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_CONTENT.asString(), "none")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_QUERY_CONTENT.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_DIMENSION_COUNT.asString(), "384")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_COLLECTION_NAME.asString(),
OracleVectorStore.DEFAULT_TABLE_NAME)
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_NAMESPACE.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_SIMILARITY_METRIC.asString(), "cosine")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString(),
"none")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_NAMESPACE.asString())
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_SEARCH_SIMILARITY_METRIC.asString(),
VectorStoreSimilarityMetric.COSINE.value())
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString())
.doesNotHaveHighCardinalityKeyValueWithKey(
HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString())
.hasBeenStarted()
.hasBeenStopped();
@@ -143,7 +144,7 @@ public class OracleVectorStoreObservationIT {
.doesNotHaveAnyRemainingCurrentObservation()
.hasObservationWithNameEqualTo(DefaultVectorStoreObservationConvention.DEFAULT_NAME)
.that()
.hasContextualNameEqualTo("oracle query")
.hasContextualNameEqualTo("%s query".formatted(VectorStoreProvider.ORACLE.value()))
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_OPERATION_NAME.asString(), "query")
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_SYSTEM.asString(),
VectorStoreProvider.ORACLE.value())
@@ -155,9 +156,10 @@ public class OracleVectorStoreObservationIT {
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_DIMENSION_COUNT.asString(), "384")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_COLLECTION_NAME.asString(),
OracleVectorStore.DEFAULT_TABLE_NAME)
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_NAMESPACE.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_SIMILARITY_METRIC.asString(), "cosine")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_NAMESPACE.asString())
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_SEARCH_SIMILARITY_METRIC.asString(),
VectorStoreSimilarityMetric.COSINE.value())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString(), "1")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString(),
"0.0")

View File

@@ -0,0 +1,27 @@
/*
* Copyright 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.vectorstore;
import org.testcontainers.utility.DockerImageName;
/**
* @author Thomas Vitale
*/
public class PgVectorImage {
public static final DockerImageName DEFAULT_IMAGE = DockerImageName.parse("pgvector/pgvector:pg17");
}

View File

@@ -29,6 +29,8 @@ import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
import org.springframework.ai.document.Document;
import org.springframework.ai.embedding.EmbeddingModel;
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.openai.OpenAiChatModel;
import org.springframework.ai.openai.OpenAiEmbeddingModel;
import org.springframework.ai.openai.api.OpenAiApi;
@@ -69,7 +71,7 @@ public class PgVectorStoreObservationIT {
@Container
@SuppressWarnings("resource")
static PostgreSQLContainer<?> postgresContainer = new PostgreSQLContainer<>("pgvector/pgvector:pg16")
static PostgreSQLContainer<?> postgresContainer = new PostgreSQLContainer<>(PgVectorImage.DEFAULT_IMAGE)
.withUsername("postgres")
.withPassword("postgres");
@@ -113,21 +115,23 @@ public class PgVectorStoreObservationIT {
.doesNotHaveAnyRemainingCurrentObservation()
.hasObservationWithNameEqualTo(DefaultVectorStoreObservationConvention.DEFAULT_NAME)
.that()
.hasContextualNameEqualTo("pg_vector add")
.hasContextualNameEqualTo("%s add".formatted(VectorStoreProvider.PG_VECTOR.value()))
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_OPERATION_NAME.asString(), "add")
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_SYSTEM.asString(), "pg_vector")
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_SYSTEM.asString(),
VectorStoreProvider.PG_VECTOR.value())
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.SPRING_AI_KIND.asString(),
SpringAiKind.VECTOR_STORE.value())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_CONTENT.asString(), "none")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_QUERY_CONTENT.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_DIMENSION_COUNT.asString(), "1536")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_COLLECTION_NAME.asString(),
PgVectorStore.DEFAULT_TABLE_NAME)
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_NAMESPACE.asString(), "public")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_SIMILARITY_METRIC.asString(), "cosine")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString(),
"none")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_SEARCH_SIMILARITY_METRIC.asString(),
VectorStoreSimilarityMetric.COSINE.value())
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString())
.doesNotHaveHighCardinalityKeyValueWithKey(
HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString())
.hasBeenStarted()
.hasBeenStopped();
@@ -143,9 +147,10 @@ public class PgVectorStoreObservationIT {
.doesNotHaveAnyRemainingCurrentObservation()
.hasObservationWithNameEqualTo(DefaultVectorStoreObservationConvention.DEFAULT_NAME)
.that()
.hasContextualNameEqualTo("pg_vector query")
.hasContextualNameEqualTo("%s query".formatted(VectorStoreProvider.PG_VECTOR.value()))
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_OPERATION_NAME.asString(), "query")
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_SYSTEM.asString(), "pg_vector")
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_SYSTEM.asString(),
VectorStoreProvider.PG_VECTOR.value())
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.SPRING_AI_KIND.asString(),
SpringAiKind.VECTOR_STORE.value())
@@ -155,8 +160,9 @@ public class PgVectorStoreObservationIT {
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_COLLECTION_NAME.asString(),
PgVectorStore.DEFAULT_TABLE_NAME)
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_NAMESPACE.asString(), "public")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_SIMILARITY_METRIC.asString(), "cosine")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_SEARCH_SIMILARITY_METRIC.asString(),
VectorStoreSimilarityMetric.COSINE.value())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString(), "1")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString(),
"0.0")

View File

@@ -107,21 +107,22 @@ public class PineconeVectorStoreObservationIT {
.doesNotHaveAnyRemainingCurrentObservation()
.hasObservationWithNameEqualTo(DefaultVectorStoreObservationConvention.DEFAULT_NAME)
.that()
.hasContextualNameEqualTo("pinecone add")
.hasContextualNameEqualTo("%s add".formatted(VectorStoreProvider.PINECONE.value()))
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_OPERATION_NAME.asString(), "add")
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_SYSTEM.asString(),
VectorStoreProvider.PINECONE.value())
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.SPRING_AI_KIND.asString(),
SpringAiKind.VECTOR_STORE.value())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_CONTENT.asString(), "none")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_QUERY_CONTENT.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_DIMENSION_COUNT.asString(), "384")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_COLLECTION_NAME.asString(), PINECONE_INDEX_NAME)
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_NAMESPACE.asString(), "none")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_NAMESPACE.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString(), "article")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_SIMILARITY_METRIC.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString(),
"none")
.doesNotHaveHighCardinalityKeyValueWithKey(
HighCardinalityKeyNames.DB_SEARCH_SIMILARITY_METRIC.asString())
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString())
.doesNotHaveHighCardinalityKeyValueWithKey(
HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString())
.hasBeenStarted()
.hasBeenStopped();
@@ -141,7 +142,7 @@ public class PineconeVectorStoreObservationIT {
.doesNotHaveAnyRemainingCurrentObservation()
.hasObservationWithNameEqualTo(DefaultVectorStoreObservationConvention.DEFAULT_NAME)
.that()
.hasContextualNameEqualTo("pinecone query")
.hasContextualNameEqualTo("%s query".formatted(VectorStoreProvider.PINECONE.value()))
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_OPERATION_NAME.asString(), "query")
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_SYSTEM.asString(),
VectorStoreProvider.PINECONE.value())
@@ -152,9 +153,10 @@ public class PineconeVectorStoreObservationIT {
"What is Great Depression")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_DIMENSION_COUNT.asString(), "384")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_COLLECTION_NAME.asString(), PINECONE_INDEX_NAME)
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_NAMESPACE.asString(), "none")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_NAMESPACE.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString(), "article")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_SIMILARITY_METRIC.asString(), "none")
.doesNotHaveHighCardinalityKeyValueWithKey(
HighCardinalityKeyNames.DB_SEARCH_SIMILARITY_METRIC.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString(), "1")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString(),
"0.0")

View File

@@ -0,0 +1,27 @@
/*
* Copyright 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.vectorstore.qdrant;
import org.testcontainers.utility.DockerImageName;
/**
* @author Thomas Vitale
*/
public class QdrantImage {
public static final DockerImageName DEFAULT_IMAGE = DockerImageName.parse("qdrant/qdrant:v1.9.7");
}

View File

@@ -68,7 +68,7 @@ public class QdrantVectorStoreObservationIT {
private static final int EMBEDDING_DIMENSION = 1024;
@Container
static QdrantContainer qdrantContainer = new QdrantContainer("qdrant/qdrant:v1.9.2");
static QdrantContainer qdrantContainer = new QdrantContainer(QdrantImage.DEFAULT_IMAGE);
List<Document> documents = List.of(
new Document(getText("classpath:/test/data/spring.ai.txt"), Map.of("meta1", "meta1")),
@@ -118,21 +118,22 @@ public class QdrantVectorStoreObservationIT {
.doesNotHaveAnyRemainingCurrentObservation()
.hasObservationWithNameEqualTo(DefaultVectorStoreObservationConvention.DEFAULT_NAME)
.that()
.hasContextualNameEqualTo("qdrant add")
.hasContextualNameEqualTo("%s add".formatted(VectorStoreProvider.QDRANT.value()))
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_OPERATION_NAME.asString(), "add")
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_SYSTEM.asString(),
VectorStoreProvider.QDRANT.value())
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.SPRING_AI_KIND.asString(),
SpringAiKind.VECTOR_STORE.value())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_CONTENT.asString(), "none")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_QUERY_CONTENT.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_DIMENSION_COUNT.asString(), "1024")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_COLLECTION_NAME.asString(), COLLECTION_NAME)
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_NAMESPACE.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_SIMILARITY_METRIC.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString(),
"none")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_NAMESPACE.asString())
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString())
.doesNotHaveHighCardinalityKeyValueWithKey(
HighCardinalityKeyNames.DB_SEARCH_SIMILARITY_METRIC.asString())
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString())
.doesNotHaveHighCardinalityKeyValueWithKey(
HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString())
.hasBeenStarted()
.hasBeenStopped();
@@ -148,7 +149,7 @@ public class QdrantVectorStoreObservationIT {
.doesNotHaveAnyRemainingCurrentObservation()
.hasObservationWithNameEqualTo(DefaultVectorStoreObservationConvention.DEFAULT_NAME)
.that()
.hasContextualNameEqualTo("qdrant query")
.hasContextualNameEqualTo("%s query".formatted(VectorStoreProvider.QDRANT.value()))
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_OPERATION_NAME.asString(), "query")
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_SYSTEM.asString(),
VectorStoreProvider.QDRANT.value())
@@ -159,9 +160,10 @@ public class QdrantVectorStoreObservationIT {
"What is Great Depression")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_DIMENSION_COUNT.asString(), "1024")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_COLLECTION_NAME.asString(), COLLECTION_NAME)
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_NAMESPACE.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_SIMILARITY_METRIC.asString(), "none")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_NAMESPACE.asString())
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString())
.doesNotHaveHighCardinalityKeyValueWithKey(
HighCardinalityKeyNames.DB_SEARCH_SIMILARITY_METRIC.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString(), "1")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString(),
"0.0")

View File

@@ -35,6 +35,7 @@ import org.springframework.ai.embedding.EmbeddingModel;
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.vectorstore.filter.FilterExpressionConverter;
import org.springframework.ai.vectorstore.observation.AbstractObservationVectorStore;
import org.springframework.ai.vectorstore.observation.VectorStoreObservationContext;
@@ -491,7 +492,8 @@ public class RedisVectorStore extends AbstractObservationVectorStore implements
.withCollectionName(this.config.indexName)
.withDimensions(this.embeddingModel.dimensions())
.withFieldName(this.config.embeddingFieldName)
.withSimilarityMetric(vectorAlgorithm().name());
.withSimilarityMetric(
"COSINE".equals(DEFAULT_DISTANCE_METRIC) ? VectorStoreSimilarityMetric.COSINE.value() : "");
}

View File

@@ -29,6 +29,7 @@ import org.springframework.ai.embedding.EmbeddingModel;
import org.springframework.ai.embedding.TokenCountBatchingStrategy;
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.RedisVectorStore.MetadataField;
import org.springframework.ai.vectorstore.RedisVectorStore.RedisVectorStoreConfig;
@@ -104,22 +105,23 @@ public class RedisVectorStoreObservationIT {
.doesNotHaveAnyRemainingCurrentObservation()
.hasObservationWithNameEqualTo(DefaultVectorStoreObservationConvention.DEFAULT_NAME)
.that()
.hasContextualNameEqualTo("redis add")
.hasContextualNameEqualTo("%s add".formatted(VectorStoreProvider.REDIS.value()))
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_OPERATION_NAME.asString(), "add")
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_SYSTEM.asString(),
VectorStoreProvider.REDIS.value())
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.SPRING_AI_KIND.asString(),
SpringAiKind.VECTOR_STORE.value())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_CONTENT.asString(), "none")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_QUERY_CONTENT.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_DIMENSION_COUNT.asString(), "384")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_COLLECTION_NAME.asString(),
RedisVectorStore.DEFAULT_INDEX_NAME)
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_NAMESPACE.asString(), "none")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_NAMESPACE.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString(), "embedding")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_SIMILARITY_METRIC.asString(), "HNSW")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString(),
"none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_SEARCH_SIMILARITY_METRIC.asString(),
VectorStoreSimilarityMetric.COSINE.value())
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString())
.doesNotHaveHighCardinalityKeyValueWithKey(
HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString())
.hasBeenStarted()
.hasBeenStopped();
@@ -135,7 +137,7 @@ public class RedisVectorStoreObservationIT {
.doesNotHaveAnyRemainingCurrentObservation()
.hasObservationWithNameEqualTo(DefaultVectorStoreObservationConvention.DEFAULT_NAME)
.that()
.hasContextualNameEqualTo("redis query")
.hasContextualNameEqualTo("%s query".formatted(VectorStoreProvider.REDIS.value()))
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_OPERATION_NAME.asString(), "query")
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_SYSTEM.asString(),
VectorStoreProvider.REDIS.value())
@@ -147,9 +149,10 @@ public class RedisVectorStoreObservationIT {
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_DIMENSION_COUNT.asString(), "384")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_COLLECTION_NAME.asString(),
RedisVectorStore.DEFAULT_INDEX_NAME)
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_NAMESPACE.asString(), "none")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_NAMESPACE.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString(), "embedding")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_SIMILARITY_METRIC.asString(), "HNSW")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_SEARCH_SIMILARITY_METRIC.asString(),
VectorStoreSimilarityMetric.COSINE.value())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString(), "1")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString(),
"0.0")

View File

@@ -0,0 +1,27 @@
/*
* Copyright 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.vectorstore;
import org.testcontainers.utility.DockerImageName;
/**
* @author Thomas Vitale
*/
public class TypesenseImage {
public static final DockerImageName DEFAULT_IMAGE = DockerImageName.parse("typesense/typesense:27.1");
}

View File

@@ -30,6 +30,7 @@ import org.springframework.ai.embedding.EmbeddingModel;
import org.springframework.ai.embedding.TokenCountBatchingStrategy;
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.TypesenseVectorStore.TypesenseVectorStoreConfig;
import org.springframework.ai.vectorstore.observation.DefaultVectorStoreObservationConvention;
@@ -61,7 +62,7 @@ public class TypesenseVectorStoreObservationIT {
private static final String TEST_COLLECTION_NAME = "test_vector_store";
@Container
private static GenericContainer<?> typesenseContainer = new GenericContainer<>("typesense/typesense:26.0")
private static GenericContainer<?> typesenseContainer = new GenericContainer<>(TypesenseImage.DEFAULT_IMAGE)
.withExposedPorts(8108)
.withCommand("--data-dir", "/tmp", "--api-key=xyz", "--enable-cors");
@@ -98,21 +99,22 @@ public class TypesenseVectorStoreObservationIT {
.doesNotHaveAnyRemainingCurrentObservation()
.hasObservationWithNameEqualTo(DefaultVectorStoreObservationConvention.DEFAULT_NAME)
.that()
.hasContextualNameEqualTo("typesense add")
.hasContextualNameEqualTo("%s add".formatted(VectorStoreProvider.TYPESENSE.value()))
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_OPERATION_NAME.asString(), "add")
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_SYSTEM.asString(),
VectorStoreProvider.TYPESENSE.value())
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.SPRING_AI_KIND.asString(),
SpringAiKind.VECTOR_STORE.value())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_CONTENT.asString(), "none")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_QUERY_CONTENT.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_DIMENSION_COUNT.asString(), "384")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_COLLECTION_NAME.asString(), TEST_COLLECTION_NAME)
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_NAMESPACE.asString(), "none")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_NAMESPACE.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString(), "embedding")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_SIMILARITY_METRIC.asString(), "cosine")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString(),
"none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_SEARCH_SIMILARITY_METRIC.asString(),
VectorStoreSimilarityMetric.COSINE.value())
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString())
.doesNotHaveHighCardinalityKeyValueWithKey(
HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString())
.hasBeenStarted()
.hasBeenStopped();
@@ -128,7 +130,7 @@ public class TypesenseVectorStoreObservationIT {
.doesNotHaveAnyRemainingCurrentObservation()
.hasObservationWithNameEqualTo(DefaultVectorStoreObservationConvention.DEFAULT_NAME)
.that()
.hasContextualNameEqualTo("typesense query")
.hasContextualNameEqualTo("%s query".formatted(VectorStoreProvider.TYPESENSE.value()))
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_OPERATION_NAME.asString(), "query")
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_SYSTEM.asString(),
VectorStoreProvider.TYPESENSE.value())
@@ -139,9 +141,10 @@ public class TypesenseVectorStoreObservationIT {
"What is Great Depression")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_DIMENSION_COUNT.asString(), "384")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_COLLECTION_NAME.asString(), TEST_COLLECTION_NAME)
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_NAMESPACE.asString(), "none")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_NAMESPACE.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString(), "embedding")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_SIMILARITY_METRIC.asString(), "cosine")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_SEARCH_SIMILARITY_METRIC.asString(),
VectorStoreSimilarityMetric.COSINE.value())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString(), "1")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString(),
"0.0")

View File

@@ -0,0 +1,27 @@
/*
* Copyright 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.vectorstore;
import org.testcontainers.utility.DockerImageName;
/**
* @author Thomas Vitale
*/
public class WeaviateImage {
public static final DockerImageName DEFAULT_IMAGE = DockerImageName.parse("semitechnologies/weaviate:1.25.9");
}

View File

@@ -56,7 +56,7 @@ import io.weaviate.client.WeaviateClient;
public class WeaviateVectorStoreObservationIT {
@Container
static WeaviateContainer weaviateContainer = new WeaviateContainer("semitechnologies/weaviate:1.25.4")
static WeaviateContainer weaviateContainer = new WeaviateContainer(WeaviateImage.DEFAULT_IMAGE)
.waitingFor(Wait.forHttp("/v1/.well-known/ready").forPort(8080));
List<Document> documents = List.of(
@@ -92,21 +92,22 @@ public class WeaviateVectorStoreObservationIT {
.doesNotHaveAnyRemainingCurrentObservation()
.hasObservationWithNameEqualTo(DefaultVectorStoreObservationConvention.DEFAULT_NAME)
.that()
.hasContextualNameEqualTo("weaviate add")
.hasContextualNameEqualTo("%s add".formatted(VectorStoreProvider.WEAVIATE.value()))
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_OPERATION_NAME.asString(), "add")
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_SYSTEM.asString(),
VectorStoreProvider.WEAVIATE.value())
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.SPRING_AI_KIND.asString(),
SpringAiKind.VECTOR_STORE.value())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_CONTENT.asString(), "none")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_QUERY_CONTENT.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_DIMENSION_COUNT.asString(), "384")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_COLLECTION_NAME.asString(), "SpringAiWeaviate")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_NAMESPACE.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_SIMILARITY_METRIC.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString(),
"none")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_NAMESPACE.asString())
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString())
.doesNotHaveHighCardinalityKeyValueWithKey(
HighCardinalityKeyNames.DB_SEARCH_SIMILARITY_METRIC.asString())
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString())
.doesNotHaveHighCardinalityKeyValueWithKey(
HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString())
.hasBeenStarted()
.hasBeenStopped();
@@ -122,7 +123,7 @@ public class WeaviateVectorStoreObservationIT {
.doesNotHaveAnyRemainingCurrentObservation()
.hasObservationWithNameEqualTo(DefaultVectorStoreObservationConvention.DEFAULT_NAME)
.that()
.hasContextualNameEqualTo("weaviate query")
.hasContextualNameEqualTo("%s query".formatted(VectorStoreProvider.WEAVIATE.value()))
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_OPERATION_NAME.asString(), "query")
.hasLowCardinalityKeyValue(LowCardinalityKeyNames.DB_SYSTEM.asString(),
VectorStoreProvider.WEAVIATE.value())
@@ -133,9 +134,10 @@ public class WeaviateVectorStoreObservationIT {
"What is Great Depression")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_DIMENSION_COUNT.asString(), "384")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_COLLECTION_NAME.asString(), "SpringAiWeaviate")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_NAMESPACE.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString(), "none")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_SIMILARITY_METRIC.asString(), "none")
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_NAMESPACE.asString())
.doesNotHaveHighCardinalityKeyValueWithKey(HighCardinalityKeyNames.DB_VECTOR_FIELD_NAME.asString())
.doesNotHaveHighCardinalityKeyValueWithKey(
HighCardinalityKeyNames.DB_SEARCH_SIMILARITY_METRIC.asString())
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_TOP_K.asString(), "1")
.hasHighCardinalityKeyValue(HighCardinalityKeyNames.DB_VECTOR_QUERY_SIMILARITY_THRESHOLD.asString(),
"0.0")