Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEATURE] Add rescoreContext for neuralsparse query's two-phase speed up. #695

Closed
wants to merge 37 commits into from
Closed
Show file tree
Hide file tree
Changes from 34 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
746458d
Add rescoreContext for neuralsparse query's two-phase speed up.
Apr 9, 2024
55eeb31
enhancements: support neural sparse query by tokens
zhichao-aws Apr 16, 2024
826eabe
add empty string logics for streams
zhichao-aws Apr 16, 2024
7824216
fix fromXContent error case logic
zhichao-aws Apr 17, 2024
a8267bb
add ut
zhichao-aws Apr 17, 2024
835929f
ut it
zhichao-aws Apr 18, 2024
fb771cd
updates for comments
zhichao-aws Apr 19, 2024
3027c3b
add settings & parameters
zhichao-aws Apr 19, 2024
3bea3ea
change int to float
zhichao-aws Apr 19, 2024
3f9c076
hashcode & equals
zhichao-aws Apr 19, 2024
03d24cc
nit
zhichao-aws Apr 19, 2024
c95ef12
merge query_by_tokens
zhichao-aws Apr 19, 2024
485668f
Set windowSizeExpansion in twoPhase.
Apr 19, 2024
211d508
add ut
zhichao-aws Apr 19, 2024
63340cb
Merge pull request #2 from zhichao-aws/rescore-zhichao-branch
conggguan Apr 20, 2024
d19132a
Add default boundary for neuralsparse twophase settings, and compleme…
Apr 21, 2024
607ff2d
Change some name of functiion to provide a clearer and more precise d…
Apr 22, 2024
0aa1a44
Add description of neural sparse two-phase enhancement in CHANGLOG.md.
Apr 22, 2024
17d7916
merge main branch & resolve conflicts (#3)
zhichao-aws Apr 22, 2024
86a11dd
Fix conflict and optimize some function.
Apr 22, 2024
a511b0a
Fix the forbiddenApisMain check.
Apr 22, 2024
df0c9fc
Simplify a function name.
Apr 22, 2024
2f1183e
Add some java documentation.
Apr 22, 2024
0ac9245
Change the comment and logic of rewrite and visit.
Apr 23, 2024
1d28441
Return the original all token query if there has no low score token.
Apr 23, 2024
d37d73e
Merge remote-tracking branch 'origin' into rescore-context
Apr 23, 2024
aec35b6
Add a version check to disable two-phase.
Apr 23, 2024
6857ef2
Some update for comments.
Apr 23, 2024
31c349e
Merge branch 'main' into rescore-context
conggguan Apr 23, 2024
feb9606
Add some IT, optimized the get tokens logic in NeuralSparseQueryBuilder.
Apr 24, 2024
69c3b0d
Replace some NeuralSparseIT test case's model inference with fixed qu…
Apr 25, 2024
3a9da75
Merge remote-tracking branch 'origin' into rescore-context
Apr 25, 2024
37646cb
Refactor NeuralSparseTwoPhaseUtil.
Apr 25, 2024
cacbdab
Change the version check to current to pass bwc test.
Apr 25, 2024
0f089cb
Change the parameter's to private, change the way that two-phase supp…
Apr 26, 2024
57966f6
Use index setting for two phase.
Apr 29, 2024
5ede643
Merge branch 'opensearch-project:main' into rescore-context
conggguan Apr 29, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
## [Unreleased 2.x](https://github.com/opensearch-project/neural-search/compare/2.13...2.x)
### Features
- Support k-NN radial search parameters in neural search([#697](https://github.com/opensearch-project/neural-search/pull/697))
- Enhance neural_sparse query's latency performance with two-phase rescore query([#695](https://github.com/opensearch-project/neural-search/pull/695)).
### Enhancements
- BWC tests for text chunking processor ([#661](https://github.com/opensearch-project/neural-search/pull/661))
- Allowing execution of hybrid query on index alias with filters ([#670](https://github.com/opensearch-project/neural-search/pull/670))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
package org.opensearch.neuralsearch.plugin;

import static org.opensearch.neuralsearch.settings.NeuralSearchSettings.NEURAL_SEARCH_HYBRID_SEARCH_DISABLED;
import static org.opensearch.neuralsearch.settings.NeuralSearchSettings.NEURAL_SPARSE_TWO_PHASE_DEFAULT_ENABLED;
import static org.opensearch.neuralsearch.settings.NeuralSearchSettings.NEURAL_SPARSE_TWO_PHASE_DEFAULT_PRUNING_RATIO;
import static org.opensearch.neuralsearch.settings.NeuralSearchSettings.NEURAL_SPARSE_TWO_PHASE_DEFAULT_WINDOW_SIZE_EXPANSION;
import static org.opensearch.neuralsearch.settings.NeuralSearchSettings.NEURAL_SPARSE_TWO_PHASE_MAX_WINDOW_SIZE;
import static org.opensearch.neuralsearch.settings.NeuralSearchSettings.RERANKER_MAX_DOC_FIELDS;

import java.util.Arrays;
Expand All @@ -18,13 +22,15 @@
import org.opensearch.cluster.metadata.IndexNameExpressionResolver;
import org.opensearch.cluster.service.ClusterService;
import org.opensearch.common.settings.Setting;
import org.opensearch.common.settings.Settings;
import org.opensearch.common.util.FeatureFlags;
import org.opensearch.core.common.io.stream.NamedWriteableRegistry;
import org.opensearch.core.xcontent.NamedXContentRegistry;
import org.opensearch.env.Environment;
import org.opensearch.env.NodeEnvironment;
import org.opensearch.ingest.Processor;
import org.opensearch.ml.client.MachineLearningNodeClient;
import org.opensearch.ml.repackage.com.google.common.collect.ImmutableList;
import org.opensearch.neuralsearch.ml.MLCommonsClientAccessor;
import org.opensearch.neuralsearch.processor.NeuralQueryEnricherProcessor;
import org.opensearch.neuralsearch.processor.NormalizationProcessor;
Expand All @@ -47,6 +53,7 @@
import org.opensearch.neuralsearch.query.HybridQueryBuilder;
import org.opensearch.neuralsearch.query.NeuralQueryBuilder;
import org.opensearch.neuralsearch.query.NeuralSparseQueryBuilder;
import org.opensearch.neuralsearch.query.NeuralSparseTwoPhaseParameters;
import org.opensearch.neuralsearch.query.ext.RerankSearchExtBuilder;
import org.opensearch.neuralsearch.search.query.HybridQueryPhaseSearcher;
import org.opensearch.neuralsearch.util.NeuralSearchClusterUtil;
Expand Down Expand Up @@ -91,9 +98,11 @@ public Collection<Object> createComponents(
final IndexNameExpressionResolver indexNameExpressionResolver,
final Supplier<RepositoriesService> repositoriesServiceSupplier
) {
Settings settings = environment.settings();
NeuralSearchClusterUtil.instance().initialize(clusterService);
NeuralQueryBuilder.initialize(clientAccessor);
NeuralSparseQueryBuilder.initialize(clientAccessor);
NeuralSparseTwoPhaseParameters.initialize(clusterService, settings);
normalizationProcessorWorkflow = new NormalizationProcessorWorkflow(new ScoreNormalizer(), new ScoreCombiner());
return List.of(clientAccessor);
}
Expand Down Expand Up @@ -155,7 +164,14 @@ public Map<String, org.opensearch.search.pipeline.Processor.Factory<SearchPhaseR

@Override
public List<Setting<?>> getSettings() {
return List.of(NEURAL_SEARCH_HYBRID_SEARCH_DISABLED, RERANKER_MAX_DOC_FIELDS);
return ImmutableList.of(
NEURAL_SEARCH_HYBRID_SEARCH_DISABLED,
RERANKER_MAX_DOC_FIELDS,
NEURAL_SPARSE_TWO_PHASE_DEFAULT_ENABLED,
NEURAL_SPARSE_TWO_PHASE_DEFAULT_WINDOW_SIZE_EXPANSION,
NEURAL_SPARSE_TWO_PHASE_DEFAULT_PRUNING_RATIO,
NEURAL_SPARSE_TWO_PHASE_MAX_WINDOW_SIZE
);
}

@Override
Expand Down Expand Up @@ -185,4 +201,5 @@ public List<SearchPlugin.SearchExtSpec<?>> getSearchExts() {
)
);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/
package org.opensearch.neuralsearch.query;

import java.io.IOException;
import java.util.Locale;
import java.util.Objects;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NonNull;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.QueryVisitor;
import org.apache.lucene.search.ScoreMode;
import org.apache.lucene.search.Weight;

/**
* Implementation of Query interface for type NeuralSparseQuery when TwoPhaseNeuralSparse Enabled.
* Initialized, it currentQuery include all tokenQuery. After call setCurrentQueryToHighScoreTokenQuery,
* it will perform highScoreTokenQuery.
*/
@AllArgsConstructor
@Getter
@NonNull
public final class NeuralSparseQuery extends Query {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

earlier NeuralSparseQuery was getting executed via RankFeature Query. Now we are changing to some other query clause? How we are ensuring that the changes are backward compatible?

Copy link
Contributor Author

@conggguan conggguan Apr 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For earlier node, it perform the original query and logic, for new node, it perform the updated logic and build a NeuralSpraseQuery.
Besides, we add version check, only enabled two-phase if it's on or after 2.14.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need to have BWC test for higher confidence, can you add it @conggguan? I think there was same ask from Varun in this PR


private Query currentQuery;
private final Query highScoreTokenQuery;
private final Query lowScoreTokenQuery;
private final Float rescoreWindowSizeExpansion;

/**
*
* @param field The field of this query.
* @return String of NeuralSparseQuery object.
*/
@Override
public String toString(String field) {
return String.format(
Locale.ROOT,
"NeuralSparseQuery(%s,%s,%s)",
currentQuery.toString(field),
highScoreTokenQuery.toString(field),
lowScoreTokenQuery.toString(field)
);
}

public Query rewrite(IndexSearcher indexSearcher) throws IOException {
Query rewrittenCurrentQuery = currentQuery.rewrite(indexSearcher);
Query rewrittenFirstStepQuery = highScoreTokenQuery.rewrite(indexSearcher);
Query rewrittenSecondPhaseQuery = lowScoreTokenQuery.rewrite(indexSearcher);
if (rewrittenCurrentQuery == currentQuery
&& rewrittenFirstStepQuery == highScoreTokenQuery
&& rewrittenSecondPhaseQuery == lowScoreTokenQuery) {
return this;
}
return new NeuralSparseQuery(rewrittenCurrentQuery, rewrittenFirstStepQuery, rewrittenSecondPhaseQuery, rescoreWindowSizeExpansion);
}

/**
* This interface is let the lucene to visit this query.
* Briefly, the query to be performed always be a subset of current query.
* So in this function use currentQuery.visit().
* @param queryVisitor a QueryVisitor to be called by each query in the tree
*/
@Override
public void visit(QueryVisitor queryVisitor) {
currentQuery.visit(queryVisitor);
}

@Override
public boolean equals(Object other) {
return sameClassAs(other) && equalsTo(getClass().cast(other));
}

private boolean equalsTo(NeuralSparseQuery other) {
return Objects.equals(currentQuery, other.currentQuery)
&& Objects.equals(highScoreTokenQuery, other.highScoreTokenQuery)
&& Objects.equals(lowScoreTokenQuery, other.lowScoreTokenQuery)
&& Objects.equals(rescoreWindowSizeExpansion, other.rescoreWindowSizeExpansion);
}

@Override
public int hashCode() {
int h = classHash();
h = 31 * h + Objects.hashCode(highScoreTokenQuery) + Objects.hashCode(lowScoreTokenQuery) + Objects.hashCode(currentQuery) + Objects
.hashCode(rescoreWindowSizeExpansion);
return h;
}

/**
* This function is always performed after setCurrentQueryToHighScoreTokenQuery. And determine which query's weight to score docs.
* @param searcher The searcher that execute the neural_sparse query.
* @param scoreMode How the produced scorers will be consumed.
* @param boost The boost that is propagated by the parent queries.
* @return The weight of currentQuery.
* @throws IOException If creteWeight failed.
*/
@Override
public Weight createWeight(IndexSearcher searcher, ScoreMode scoreMode, float boost) throws IOException {
return currentQuery.createWeight(searcher, scoreMode, boost);
}

/**
* Before call this function, the currentQuery of this object is a BooleanQuery include all tokens FeatureFiledQuery.
* After call this function, the currentQuery of this object change to a BooleanQuery include high score tokens FeatureFiledQuery.
*/
public void setCurrentQueryToHighScoreTokenQuery() {
this.currentQuery = highScoreTokenQuery;
}
}
Loading
Loading