Skip to content

Commit 03d528e

Browse files
authored
Upgrade BWC version and fix neural search build (#868)
Signed-off-by: Varun Jain <varunudr@amazon.com>
1 parent 30a99fb commit 03d528e

7 files changed

+149
-26
lines changed

.github/workflows/backwards_compatibility_tests_workflow.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
matrix:
1616
java: [ 21 ]
1717
os: [ubuntu-latest,windows-latest]
18-
bwc_version : ["2.9.0","2.10.0","2.11.0","2.12.0","2.13.0","2.14.0","2.15.0","2.16.0-SNAPSHOT"]
18+
bwc_version : ["2.9.0","2.10.0","2.11.0","2.12.0","2.13.0","2.14.0","2.15.0","2.16.0","2.17.0-SNAPSHOT"]
1919
opensearch_version : [ "3.0.0-SNAPSHOT" ]
2020

2121
name: NeuralSearch Restart-Upgrade BWC Tests
@@ -42,7 +42,7 @@ jobs:
4242
matrix:
4343
java: [ 21 ]
4444
os: [ubuntu-latest,windows-latest]
45-
bwc_version: [ "2.16.0-SNAPSHOT" ]
45+
bwc_version: [ "2.17.0-SNAPSHOT" ]
4646
opensearch_version: [ "3.0.0-SNAPSHOT" ]
4747

4848
name: NeuralSearch Rolling-Upgrade BWC Tests

TRIAGING.md

+11-11
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
<img src="https://opensearch.org/assets/img/opensearch-logo-themed.svg" height="64px">
22

3-
The maintainers of the k-NN/neural-search Repo's seek to promote an inclusive and engaged community of contributors. In
4-
order to facilitate this, bi-weekly triage meetings are open-to-all and attendance is encouraged for anyone who hopes to
5-
contribute, discuss an issue, or learn more about the project. To learn more about contributing to the
3+
The maintainers of the k-NN/neural-search Repo's seek to promote an inclusive and engaged community of contributors. In
4+
order to facilitate this, bi-weekly triage meetings are open-to-all and attendance is encouraged for anyone who hopes to
5+
contribute, discuss an issue, or learn more about the project. To learn more about contributing to the
66
k-NN/neural-search Repo visit the [Contributing](./CONTRIBUTING.md) documentation.
77

88
### Do I need to attend for my issue to be addressed/triaged?
@@ -11,19 +11,19 @@ Attendance is not required for your issue to be triaged or addressed. All new is
1111

1212
### What happens if my issue does not get covered this time?
1313

14-
Each meeting we seek to address all new issues. However, should we run out of time before your issue is discussed, you
14+
Each meeting we seek to address all new issues. However, should we run out of time before your issue is discussed, you
1515
are always welcome to attend the next meeting or to follow up on the issue post itself.
1616

1717
### How do I join the Backlog & Triage meeting?
1818

19-
Meetings are hosted regularly at 5 PM Pacific Time on Tuesdays bi-weekly and can be joined via the links posted on the
20-
[OpenSearch Meetup Group](https://www.meetup.com/opensearch/events/) list of events. The event will be titled
19+
Meetings are hosted regularly at 5 PM Pacific Time on Tuesdays bi-weekly and can be joined via the links posted on the
20+
[OpenSearch Meetup Group](https://www.meetup.com/opensearch/events/) list of events. The event will be titled
2121
`Development Backlog & Triage Meeting - k-NN/neural-search`.
2222

23-
After joining the Chime meeting, you can enable your video / voice to join the discussion. If you do not have a webcam
23+
After joining the Chime meeting, you can enable your video / voice to join the discussion. If you do not have a webcam
2424
or microphone available, you can still join in via the text chat.
2525

26-
If you have an issue you'd like to bring forth please consider getting a link to the issue so it can be presented to
26+
If you have an issue you'd like to bring forth please consider getting a link to the issue so it can be presented to
2727
everyone in the meeting.
2828

2929
### Is there an agenda for each week?
@@ -48,13 +48,13 @@ No, all are welcome and encouraged to attend. Attending the Backlog & Triage mee
4848

4949
### What if I have an issue that is almost a duplicate, should I open a new one to be triaged?
5050

51-
You can always open an issue including one that you think may be a duplicate. However, in cases where you believe there
52-
is an important distinction to be made between an existing issue and your newly created one, you are encouraged to
51+
You can always open an issue including one that you think may be a duplicate. However, in cases where you believe there
52+
is an important distinction to be made between an existing issue and your newly created one, you are encouraged to
5353
attend the triaging meeting to explain.
5454

5555
### What if I have follow-up questions on an issue?
5656

57-
If you have an existing issue you would like to discuss, you can always comment on the issue itself. Alternatively, you
57+
If you have an existing issue you would like to discuss, you can always comment on the issue itself. Alternatively, you
5858
are welcome to come to the triage meeting to discuss.
5959

6060
### Is this meeting a good place to get help setting up k-NN/neural-search features on my OpenSearch instance?

gradle.properties

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
# https://github.com/opensearch-project/OpenSearch/blob/main/libs/core/src/main/java/org/opensearch/Version.java .
88
# Wired compatibility of OpenSearch works like 3.x version is compatible with 2.(latest-major) version.
99
# Therefore, to run rolling-upgrade BWC Test on local machine the BWC version here should be set 2.(latest-major).
10-
systemProp.bwc.version=2.16.0-SNAPSHOT
11-
systemProp.bwc.bundle.version=2.16.0
10+
systemProp.bwc.version=2.17.0-SNAPSHOT
11+
systemProp.bwc.bundle.version=2.17.0
1212

1313
# For fixing Spotless check with Java 17
1414
org.gradle.jvmargs=--add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED \

src/test/java/org/opensearch/neuralsearch/ValidateDependentPluginInstallationIT.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,8 @@ private void createBasicKnnIndex() throws IOException {
7575
.endObject()
7676
.toString();
7777
mapping = mapping.substring(1, mapping.length() - 1);
78-
createIndex(KNN_INDEX_NAME, Settings.EMPTY, mapping);
78+
Settings settings = Settings.builder().put("index.knn", true).build();
79+
createIndex(KNN_INDEX_NAME, settings, mapping);
7980
}
8081

8182
private Set<String> getAllInstalledPlugins() throws IOException {

src/test/java/org/opensearch/neuralsearch/query/HybridQueryBuilderTests.java

+63-6
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,27 @@
1717
import static org.opensearch.neuralsearch.query.NeuralQueryBuilder.MODEL_ID_FIELD;
1818
import static org.opensearch.neuralsearch.query.NeuralQueryBuilder.QUERY_TEXT_FIELD;
1919

20+
import java.util.HashSet;
2021
import java.util.Iterator;
2122
import java.util.List;
2223
import java.util.Map;
2324
import java.util.ArrayList;
25+
import java.util.Optional;
26+
import java.util.Set;
2427
import java.util.function.Supplier;
28+
import java.util.stream.Collectors;
2529

2630
import org.apache.lucene.search.MatchNoDocsQuery;
2731
import org.apache.lucene.search.Query;
2832
import org.apache.lucene.search.TermQuery;
33+
import org.mockito.Mock;
34+
import org.mockito.MockitoAnnotations;
2935
import org.opensearch.Version;
3036
import org.opensearch.cluster.service.ClusterService;
3137
import org.opensearch.common.io.stream.BytesStreamOutput;
38+
import org.opensearch.common.settings.ClusterSettings;
39+
import org.opensearch.common.settings.Setting;
40+
import org.opensearch.common.settings.Settings;
3241
import org.opensearch.common.xcontent.XContentFactory;
3342
import org.opensearch.core.ParseField;
3443
import org.opensearch.core.common.ParsingException;
@@ -47,8 +56,13 @@
4756
import org.opensearch.index.query.QueryBuilders;
4857
import org.opensearch.index.query.QueryShardContext;
4958
import org.opensearch.index.query.TermQueryBuilder;
59+
import org.opensearch.knn.index.KNNSettings;
5060
import org.opensearch.knn.index.SpaceType;
5161
import org.opensearch.knn.index.VectorDataType;
62+
import org.opensearch.knn.index.engine.KNNEngine;
63+
import org.opensearch.knn.index.engine.KNNMethodContext;
64+
import org.opensearch.knn.index.engine.MethodComponentContext;
65+
import org.opensearch.knn.index.mapper.KNNMappingConfig;
5266
import org.opensearch.knn.index.mapper.KNNVectorFieldType;
5367
import org.opensearch.knn.index.query.KNNQuery;
5468
import org.opensearch.knn.index.query.KNNQueryBuilder;
@@ -69,6 +83,26 @@ public class HybridQueryBuilderTests extends OpenSearchQueryTestCase {
6983
static final float BOOST = 1.8f;
7084
static final Supplier<float[]> TEST_VECTOR_SUPPLIER = () -> new float[4];
7185
static final QueryBuilder TEST_FILTER = new MatchAllQueryBuilder();
86+
@Mock
87+
private ClusterService clusterService;
88+
private AutoCloseable openMocks;
89+
90+
@Override
91+
public void setUp() throws Exception {
92+
super.setUp();
93+
openMocks = MockitoAnnotations.openMocks(this);
94+
// This is required to make sure that before every test we are initializing the KNNSettings. Not doing this
95+
// leads to failures of unit tests cases when a unit test is run separately. Try running this test:
96+
// ./gradlew ':test' --tests "org.opensearch.knn.training.TrainingJobTests.testRun_success" and see it fails
97+
// but if run along with other tests this test passes.
98+
initKNNSettings();
99+
}
100+
101+
@Override
102+
public void tearDown() throws Exception {
103+
super.tearDown();
104+
openMocks.close();
105+
}
72106

73107
@SneakyThrows
74108
public void testDoToQuery_whenNoSubqueries_thenBuildSuccessfully() {
@@ -86,11 +120,14 @@ public void testDoToQuery_whenOneSubquery_thenBuildSuccessfully() {
86120
Index dummyIndex = new Index("dummy", "dummy");
87121
QueryShardContext mockQueryShardContext = mock(QueryShardContext.class);
88122
KNNVectorFieldType mockKNNVectorField = mock(KNNVectorFieldType.class);
123+
KNNMappingConfig mockKNNMappingConfig = mock(KNNMappingConfig.class);
124+
KNNMethodContext knnMethodContext = new KNNMethodContext(KNNEngine.FAISS, SpaceType.L2, MethodComponentContext.EMPTY);
125+
when(mockKNNVectorField.getKnnMappingConfig()).thenReturn(mockKNNMappingConfig);
126+
when(mockKNNMappingConfig.getKnnMethodContext()).thenReturn(Optional.of(knnMethodContext));
89127
when(mockQueryShardContext.index()).thenReturn(dummyIndex);
90-
when(mockKNNVectorField.getDimension()).thenReturn(4);
128+
when(mockKNNVectorField.getKnnMappingConfig().getDimension()).thenReturn(4);
91129
when(mockKNNVectorField.getVectorDataType()).thenReturn(VectorDataType.FLOAT);
92130
when(mockQueryShardContext.fieldMapper(eq(VECTOR_FIELD_NAME))).thenReturn(mockKNNVectorField);
93-
when(mockKNNVectorField.getSpaceType()).thenReturn(SpaceType.L2);
94131

95132
NeuralQueryBuilder neuralQueryBuilder = new NeuralQueryBuilder().fieldName(VECTOR_FIELD_NAME)
96133
.queryText(QUERY_TEXT)
@@ -116,10 +153,13 @@ public void testDoToQuery_whenMultipleSubqueries_thenBuildSuccessfully() {
116153
Index dummyIndex = new Index("dummy", "dummy");
117154
QueryShardContext mockQueryShardContext = mock(QueryShardContext.class);
118155
KNNVectorFieldType mockKNNVectorField = mock(KNNVectorFieldType.class);
156+
KNNMappingConfig mockKNNMappingConfig = mock(KNNMappingConfig.class);
157+
KNNMethodContext knnMethodContext = new KNNMethodContext(KNNEngine.FAISS, SpaceType.L2, MethodComponentContext.EMPTY);
158+
when(mockKNNVectorField.getKnnMappingConfig()).thenReturn(mockKNNMappingConfig);
159+
when(mockKNNMappingConfig.getKnnMethodContext()).thenReturn(Optional.of(knnMethodContext));
119160
when(mockQueryShardContext.index()).thenReturn(dummyIndex);
120-
when(mockKNNVectorField.getDimension()).thenReturn(4);
161+
when(mockKNNVectorField.getKnnMappingConfig().getDimension()).thenReturn(4);
121162
when(mockKNNVectorField.getVectorDataType()).thenReturn(VectorDataType.FLOAT);
122-
when(mockKNNVectorField.getSpaceType()).thenReturn(SpaceType.L2);
123163
when(mockQueryShardContext.fieldMapper(eq(VECTOR_FIELD_NAME))).thenReturn(mockKNNVectorField);
124164

125165
NeuralQueryBuilder neuralQueryBuilder = new NeuralQueryBuilder().fieldName(VECTOR_FIELD_NAME)
@@ -367,8 +407,10 @@ public void testToXContent_whenIncomingJsonIsCorrect_thenSuccessful() {
367407
Index dummyIndex = new Index("dummy", "dummy");
368408
QueryShardContext mockQueryShardContext = mock(QueryShardContext.class);
369409
KNNVectorFieldType mockKNNVectorField = mock(KNNVectorFieldType.class);
410+
KNNMappingConfig mockKNNMappingConfig = mock(KNNMappingConfig.class);
411+
when(mockKNNVectorField.getKnnMappingConfig()).thenReturn(mockKNNMappingConfig);
370412
when(mockQueryShardContext.index()).thenReturn(dummyIndex);
371-
when(mockKNNVectorField.getDimension()).thenReturn(4);
413+
when(mockKNNVectorField.getKnnMappingConfig().getDimension()).thenReturn(4);
372414
when(mockQueryShardContext.fieldMapper(eq(VECTOR_FIELD_NAME))).thenReturn(mockKNNVectorField);
373415

374416
NeuralQueryBuilder neuralQueryBuilder = new NeuralQueryBuilder().fieldName(VECTOR_FIELD_NAME)
@@ -584,9 +626,11 @@ public void testRewrite_whenMultipleSubQueries_thenReturnBuilderForEachSubQuery(
584626

585627
QueryShardContext mockQueryShardContext = mock(QueryShardContext.class);
586628
KNNVectorFieldType mockKNNVectorField = mock(KNNVectorFieldType.class);
629+
KNNMappingConfig mockKNNMappingConfig = mock(KNNMappingConfig.class);
630+
when(mockKNNVectorField.getKnnMappingConfig()).thenReturn(mockKNNMappingConfig);
587631
Index dummyIndex = new Index("dummy", "dummy");
588632
when(mockQueryShardContext.index()).thenReturn(dummyIndex);
589-
when(mockKNNVectorField.getDimension()).thenReturn(4);
633+
when(mockKNNVectorField.getKnnMappingConfig().getDimension()).thenReturn(4);
590634
when(mockQueryShardContext.fieldMapper(eq(VECTOR_FIELD_NAME))).thenReturn(mockKNNVectorField);
591635

592636
TextFieldMapper.TextFieldType fieldType = (TextFieldMapper.TextFieldType) createMapperService().fieldType(TEXT_FIELD_NAME);
@@ -737,4 +781,17 @@ private void setUpClusterService() {
737781
ClusterService clusterService = NeuralSearchClusterTestUtils.mockClusterService(Version.CURRENT);
738782
NeuralSearchClusterUtil.instance().initialize(clusterService);
739783
}
784+
785+
private void initKNNSettings() {
786+
Set<Setting<?>> defaultClusterSettings = new HashSet<>(ClusterSettings.BUILT_IN_CLUSTER_SETTINGS);
787+
defaultClusterSettings.addAll(
788+
KNNSettings.state()
789+
.getSettings()
790+
.stream()
791+
.filter(s -> s.getProperties().contains(Setting.Property.NodeScope))
792+
.collect(Collectors.toList())
793+
);
794+
when(clusterService.getClusterSettings()).thenReturn(new ClusterSettings(Settings.EMPTY, defaultClusterSettings));
795+
KNNSettings.state().setClusterService(clusterService);
796+
}
740797
}

src/test/java/org/opensearch/neuralsearch/query/HybridQueryTests.java

+52-2
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,11 @@
1313

1414
import java.io.IOException;
1515
import java.util.Arrays;
16+
import java.util.HashSet;
1617
import java.util.Iterator;
1718
import java.util.List;
19+
import java.util.Optional;
20+
import java.util.Set;
1821
import java.util.stream.Collectors;
1922

2023
import org.apache.lucene.document.FieldType;
@@ -33,13 +36,24 @@
3336
import org.apache.lucene.store.Directory;
3437
import org.apache.lucene.tests.analysis.MockAnalyzer;
3538
import org.apache.lucene.tests.search.QueryUtils;
39+
import org.mockito.Mock;
40+
import org.mockito.MockitoAnnotations;
41+
import org.opensearch.cluster.service.ClusterService;
42+
import org.opensearch.common.settings.ClusterSettings;
43+
import org.opensearch.common.settings.Setting;
44+
import org.opensearch.common.settings.Settings;
3645
import org.opensearch.core.index.Index;
3746
import org.opensearch.index.mapper.TextFieldMapper;
3847
import org.opensearch.index.query.BoolQueryBuilder;
3948
import org.opensearch.index.query.QueryBuilders;
4049
import org.opensearch.index.query.QueryShardContext;
50+
import org.opensearch.knn.index.KNNSettings;
4151
import org.opensearch.knn.index.SpaceType;
4252
import org.opensearch.knn.index.VectorDataType;
53+
import org.opensearch.knn.index.engine.KNNEngine;
54+
import org.opensearch.knn.index.engine.KNNMethodContext;
55+
import org.opensearch.knn.index.engine.MethodComponentContext;
56+
import org.opensearch.knn.index.mapper.KNNMappingConfig;
4357
import org.opensearch.knn.index.mapper.KNNVectorFieldType;
4458
import org.opensearch.knn.index.query.KNNQueryBuilder;
4559

@@ -54,6 +68,26 @@ public class HybridQueryTests extends OpenSearchQueryTestCase {
5468
static final String TERM_ANOTHER_QUERY_TEXT = "anotherkeyword";
5569
static final float[] VECTOR_QUERY = new float[] { 1.0f, 2.0f, 2.1f, 0.6f };
5670
static final int K = 2;
71+
@Mock
72+
protected ClusterService clusterService;
73+
private AutoCloseable openMocks;
74+
75+
@Override
76+
public void setUp() throws Exception {
77+
super.setUp();
78+
openMocks = MockitoAnnotations.openMocks(this);
79+
// This is required to make sure that before every test we are initializing the KNNSettings. Not doing this
80+
// leads to failures of unit tests cases when a unit test is run separately. Try running this test:
81+
// ./gradlew ':test' --tests "org.opensearch.knn.training.TrainingJobTests.testRun_success" and see it fails
82+
// but if run along with other tests this test passes.
83+
initKNNSettings();
84+
}
85+
86+
@Override
87+
public void tearDown() throws Exception {
88+
super.tearDown();
89+
openMocks.close();
90+
}
5791

5892
@SneakyThrows
5993
public void testQueryBasics_whenMultipleDifferentQueries_thenSuccessful() {
@@ -116,10 +150,13 @@ public void testRewrite_whenRewriteQuery_thenSuccessful() {
116150

117151
Index dummyIndex = new Index("dummy", "dummy");
118152
KNNVectorFieldType mockKNNVectorField = mock(KNNVectorFieldType.class);
153+
KNNMappingConfig mockKNNMappingConfig = mock(KNNMappingConfig.class);
154+
KNNMethodContext mockKNNMethodContext = new KNNMethodContext(KNNEngine.FAISS, SpaceType.L2, MethodComponentContext.EMPTY);
155+
when(mockKNNVectorField.getKnnMappingConfig()).thenReturn(mockKNNMappingConfig);
156+
when(mockKNNMappingConfig.getKnnMethodContext()).thenReturn(Optional.ofNullable(mockKNNMethodContext));
119157
when(mockQueryShardContext.index()).thenReturn(dummyIndex);
120-
when(mockKNNVectorField.getDimension()).thenReturn(4);
158+
when(mockKNNVectorField.getKnnMappingConfig().getDimension()).thenReturn(4);
121159
when(mockQueryShardContext.fieldMapper(eq(VECTOR_FIELD_NAME))).thenReturn(mockKNNVectorField);
122-
when(mockKNNVectorField.getSpaceType()).thenReturn(SpaceType.L2);
123160
when(mockKNNVectorField.getVectorDataType()).thenReturn(VectorDataType.FLOAT);
124161
KNNQueryBuilder knnQueryBuilder = new KNNQueryBuilder(VECTOR_FIELD_NAME, VECTOR_QUERY, K);
125162
Query knnQuery = knnQueryBuilder.toQuery(mockQueryShardContext);
@@ -316,4 +353,17 @@ public void testFilter_whenSubQueriesWithFilterPassed_thenSuccessful() {
316353
}
317354
assertEquals(2, countOfQueries);
318355
}
356+
357+
private void initKNNSettings() {
358+
Set<Setting<?>> defaultClusterSettings = new HashSet<>(ClusterSettings.BUILT_IN_CLUSTER_SETTINGS);
359+
defaultClusterSettings.addAll(
360+
KNNSettings.state()
361+
.getSettings()
362+
.stream()
363+
.filter(s -> s.getProperties().contains(Setting.Property.NodeScope))
364+
.collect(Collectors.toList())
365+
);
366+
when(clusterService.getClusterSettings()).thenReturn(new ClusterSettings(Settings.EMPTY, defaultClusterSettings));
367+
KNNSettings.state().setClusterService(clusterService);
368+
}
319369
}

0 commit comments

Comments
 (0)