Skip to content

Commit 3563ddb

Browse files
authored
[8.18] [8.19] Semantic Text Rolling Upgrade Tests (#126548) (#127748) (#127868)
1 parent 48c7aad commit 3563ddb

File tree

5 files changed

+388
-3
lines changed

5 files changed

+388
-3
lines changed
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the "Elastic License
4+
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
5+
* Public License v 1"; you may not use this file except in compliance with, at
6+
* your election, the "Elastic License 2.0", the "GNU Affero General Public
7+
* License v3.0 only", or the "Server Side Public License, v 1".
8+
*/
9+
10+
package org.elasticsearch.index.mapper.vectors;
11+
12+
import com.carrotsearch.randomizedtesting.RandomizedContext;
13+
import com.carrotsearch.randomizedtesting.generators.RandomNumbers;
14+
15+
import org.elasticsearch.inference.SimilarityMeasure;
16+
17+
import java.util.List;
18+
import java.util.Random;
19+
20+
public class DenseVectorFieldMapperTestUtils {
21+
private DenseVectorFieldMapperTestUtils() {}
22+
23+
public static List<SimilarityMeasure> getSupportedSimilarities(DenseVectorFieldMapper.ElementType elementType) {
24+
return switch (elementType) {
25+
case FLOAT, BYTE -> List.of(SimilarityMeasure.values());
26+
case BIT -> List.of(SimilarityMeasure.L2_NORM);
27+
};
28+
}
29+
30+
public static int getEmbeddingLength(DenseVectorFieldMapper.ElementType elementType, int dimensions) {
31+
return switch (elementType) {
32+
case FLOAT, BYTE -> dimensions;
33+
case BIT -> {
34+
assert dimensions % Byte.SIZE == 0;
35+
yield dimensions / Byte.SIZE;
36+
}
37+
};
38+
}
39+
40+
public static int randomCompatibleDimensions(DenseVectorFieldMapper.ElementType elementType, int max) {
41+
if (max < 1) {
42+
throw new IllegalArgumentException("max must be at least 1");
43+
}
44+
45+
return switch (elementType) {
46+
case FLOAT, BYTE -> RandomNumbers.randomIntBetween(random(), 1, max);
47+
case BIT -> {
48+
if (max < 8) {
49+
throw new IllegalArgumentException("max must be at least 8 for bit vectors");
50+
}
51+
52+
// Generate a random dimension count that is a multiple of 8
53+
int maxEmbeddingLength = max / 8;
54+
yield RandomNumbers.randomIntBetween(random(), 1, maxEmbeddingLength) * 8;
55+
}
56+
};
57+
}
58+
59+
private static Random random() {
60+
return RandomizedContext.current().getRandom();
61+
}
62+
}

x-pack/plugin/inference/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import org.elasticsearch.gradle.internal.info.BuildParams
99
apply plugin: 'elasticsearch.internal-es-plugin'
1010
apply plugin: 'elasticsearch.internal-cluster-test'
1111
apply plugin: 'elasticsearch.internal-yaml-rest-test'
12+
apply plugin: 'elasticsearch.internal-test-artifact'
1213

1314
restResources {
1415
restApi {

x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/model/TestModel.java

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import org.elasticsearch.common.io.stream.StreamInput;
1313
import org.elasticsearch.common.io.stream.StreamOutput;
1414
import org.elasticsearch.index.mapper.vectors.DenseVectorFieldMapper;
15+
import org.elasticsearch.index.mapper.vectors.DenseVectorFieldMapperTestUtils;
1516
import org.elasticsearch.inference.Model;
1617
import org.elasticsearch.inference.ModelConfigurations;
1718
import org.elasticsearch.inference.ModelSecrets;
@@ -25,9 +26,13 @@
2526
import org.elasticsearch.xpack.inference.services.ServiceUtils;
2627

2728
import java.io.IOException;
29+
import java.util.ArrayList;
30+
import java.util.Arrays;
2831
import java.util.HashMap;
32+
import java.util.List;
2933
import java.util.Map;
3034

35+
import static org.elasticsearch.index.mapper.vectors.DenseVectorFieldMapper.BBQ_MIN_DIMS;
3136
import static org.elasticsearch.test.ESTestCase.randomAlphaOfLength;
3237
import static org.elasticsearch.test.ESTestCase.randomFrom;
3338
import static org.elasticsearch.test.ESTestCase.randomInt;
@@ -39,9 +44,60 @@ public static TestModel createRandomInstance() {
3944
}
4045

4146
public static TestModel createRandomInstance(TaskType taskType) {
42-
var dimensions = taskType == TaskType.TEXT_EMBEDDING ? randomInt(64) : null;
43-
var similarity = taskType == TaskType.TEXT_EMBEDDING ? randomFrom(SimilarityMeasure.values()) : null;
44-
var elementType = taskType == TaskType.TEXT_EMBEDDING ? randomFrom(DenseVectorFieldMapper.ElementType.values()) : null;
47+
return createRandomInstance(taskType, null, null);
48+
}
49+
50+
public static TestModel createRandomInstance(
51+
TaskType taskType,
52+
List<DenseVectorFieldMapper.ElementType> excludedElementTypes,
53+
List<SimilarityMeasure> excludedSimilarities
54+
) {
55+
// Use a max dimension count that has a reasonable probability of being compatible with BBQ
56+
return createRandomInstance(taskType, excludedElementTypes, excludedSimilarities, BBQ_MIN_DIMS * 2);
57+
}
58+
59+
public static TestModel createRandomInstance(
60+
TaskType taskType,
61+
List<DenseVectorFieldMapper.ElementType> excludedElementTypes,
62+
List<SimilarityMeasure> excludedSimilarities,
63+
int maxDimensions
64+
) {
65+
List<DenseVectorFieldMapper.ElementType> supportedElementTypes = new ArrayList<>(
66+
Arrays.asList(DenseVectorFieldMapper.ElementType.values())
67+
);
68+
if (excludedElementTypes != null) {
69+
supportedElementTypes.removeAll(excludedElementTypes);
70+
if (supportedElementTypes.isEmpty()) {
71+
throw new IllegalArgumentException("No supported element types with excluded element types " + excludedElementTypes);
72+
}
73+
}
74+
75+
var elementType = taskType == TaskType.TEXT_EMBEDDING ? randomFrom(supportedElementTypes) : null;
76+
var dimensions = taskType == TaskType.TEXT_EMBEDDING
77+
? DenseVectorFieldMapperTestUtils.randomCompatibleDimensions(elementType, maxDimensions)
78+
: null;
79+
80+
SimilarityMeasure similarity = null;
81+
if (taskType == TaskType.TEXT_EMBEDDING) {
82+
List<SimilarityMeasure> supportedSimilarities = new ArrayList<>(
83+
DenseVectorFieldMapperTestUtils.getSupportedSimilarities(elementType)
84+
);
85+
if (excludedSimilarities != null) {
86+
supportedSimilarities.removeAll(excludedSimilarities);
87+
}
88+
89+
if (supportedSimilarities.isEmpty()) {
90+
throw new IllegalArgumentException(
91+
"No supported similarities for combination of element type ["
92+
+ elementType
93+
+ "] and excluded similarities "
94+
+ (excludedSimilarities == null ? List.of() : excludedSimilarities)
95+
);
96+
}
97+
98+
similarity = randomFrom(supportedSimilarities);
99+
}
100+
45101
return new TestModel(
46102
randomAlphaOfLength(4),
47103
taskType,

x-pack/qa/rolling-upgrade/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@ apply plugin: 'elasticsearch.bwc-test'
88
apply plugin: 'elasticsearch.rest-resources'
99

1010
dependencies {
11+
testImplementation testArtifact(project(':server'))
1112
testImplementation testArtifact(project(xpackModule('core')))
1213
testImplementation project(':x-pack:qa')
1314
testImplementation project(':modules:reindex')
15+
testImplementation testArtifact(project(xpackModule('inference')))
1416
}
1517

1618
restResources {

0 commit comments

Comments
 (0)