diff options
author | Tor Egge <Tor.Egge@online.no> | 2024-05-16 13:54:40 +0200 |
---|---|---|
committer | Tor Egge <Tor.Egge@online.no> | 2024-05-16 13:54:40 +0200 |
commit | 7b386dd241870c6b1317cb85df1b16cc5f386d08 (patch) | |
tree | 1c1da155749cded0dca1d0ffa5608bf6802e90e5 /searchlib | |
parent | cced1ff316a6960a0a6d091f43b0eafd3ba2a78e (diff) |
Add second phase feature.
Diffstat (limited to 'searchlib')
6 files changed, 138 insertions, 0 deletions
diff --git a/searchlib/src/tests/features/prod_features_test.cpp b/searchlib/src/tests/features/prod_features_test.cpp index 22105533895..fb00b4ff5e6 100644 --- a/searchlib/src/tests/features/prod_features_test.cpp +++ b/searchlib/src/tests/features/prod_features_test.cpp @@ -33,6 +33,7 @@ #include <vespa/searchlib/features/random_normal_stable_feature.h> #include <vespa/searchlib/features/randomfeature.h> #include <vespa/searchlib/features/rankingexpressionfeature.h> +#include <vespa/searchlib/features/second_phase_feature.h> #include <vespa/searchlib/features/setup.h> #include <vespa/searchlib/features/termfeature.h> #include <vespa/searchlib/features/utils.h> @@ -614,6 +615,32 @@ TEST_F(ProdFeaturesTest, test_first_phase) } } +TEST_F(ProdFeaturesTest, test_second_phase) +{ + { // Test blueprint. + SecondPhaseBlueprint pt; + + EXPECT_TRUE(assertCreateInstance(pt, "secondPhase")); + + FtIndexEnvironment ie; + ie.getProperties().add(indexproperties::rank::SecondPhase::NAME, "random"); + + StringList params, in, out; + FT_SETUP_OK(pt, ie, params, in.add("random"), out.add("score")); + FT_SETUP_FAIL(pt, params.add("foo")); + params.clear(); + + FT_DUMP_EMPTY(_factory, "secondPhase", ie); + } + + { // Test executor. + FtFeatureTest ft(_factory, "secondPhase"); + ft.getIndexEnv().getProperties().add(indexproperties::rank::SecondPhase::NAME, "value(11)"); + ASSERT_TRUE(ft.setup()); + ASSERT_TRUE(ft.execute(11.0f)); + } +} + TEST_F(ProdFeaturesTest, test_foreach) { { // Test blueprint. diff --git a/searchlib/src/tests/ranksetup/ranksetup_test.cpp b/searchlib/src/tests/ranksetup/ranksetup_test.cpp index 53224425a04..348326c3936 100644 --- a/searchlib/src/tests/ranksetup/ranksetup_test.cpp +++ b/searchlib/src/tests/ranksetup/ranksetup_test.cpp @@ -26,6 +26,7 @@ #include <vespa/searchlib/fef/test/rankresult.h> #include <vespa/searchlib/features/rankingexpressionfeature.h> +#include <vespa/searchlib/features/second_phase_feature.h> #include <vespa/searchlib/features/setup.h> #include <vespa/searchlib/features/valuefeature.h> #include <vespa/searchlib/fef/test/plugin/chain.h> @@ -787,6 +788,19 @@ RankSetupTest::testFeatureDump() exp.addScore("test_cfgvalue(foo)", 1.0); EXPECT_EQUAL(exp, dumper.dump()); } + { // Dump secondPhase feature + IndexEnvironment indexEnv; + indexEnv.getProperties().add(indexproperties::rank::FirstPhase::NAME, "value(2)"); + indexEnv.getProperties().add(indexproperties::rank::SecondPhase::NAME, "value(4)"); + RankEnvironment rankEnv(_factory, indexEnv, _queryEnv); + FeatureDumper dumper(rankEnv); + dumper.configure(); + dumper.addDumpFeature("secondPhase"); + EXPECT_TRUE(dumper.setup()); + RankResult exp; + exp.addScore("secondPhase", 4.0); + EXPECT_EQUAL(exp, dumper.dump()); + } } void @@ -939,6 +953,7 @@ RankSetupTest::RankSetupTest() : setup_fef_test_plugin(_factory); _factory.addPrototype(Blueprint::SP(new ValueBlueprint())); _factory.addPrototype(Blueprint::SP(new RankingExpressionBlueprint())); + _factory.addPrototype(std::make_shared<SecondPhaseBlueprint>()); // setup an original attribute manager with two attributes search::attribute::Config cfg(search::attribute::BasicType::INT32, diff --git a/searchlib/src/vespa/searchlib/features/CMakeLists.txt b/searchlib/src/vespa/searchlib/features/CMakeLists.txt index 0690801ee61..4736dbecb86 100644 --- a/searchlib/src/vespa/searchlib/features/CMakeLists.txt +++ b/searchlib/src/vespa/searchlib/features/CMakeLists.txt @@ -57,6 +57,7 @@ vespa_add_library(searchlib_features OBJECT rankingexpressionfeature.cpp raw_score_feature.cpp reverseproximityfeature.cpp + second_phase_feature.cpp setup.cpp subqueries_feature.cpp tensor_attribute_executor.cpp diff --git a/searchlib/src/vespa/searchlib/features/second_phase_feature.cpp b/searchlib/src/vespa/searchlib/features/second_phase_feature.cpp new file mode 100644 index 00000000000..ea72365e174 --- /dev/null +++ b/searchlib/src/vespa/searchlib/features/second_phase_feature.cpp @@ -0,0 +1,58 @@ +// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#include "second_phase_feature.h" +#include <vespa/searchlib/fef/featureexecutor.h> +#include <vespa/searchlib/fef/indexproperties.h> +#include <vespa/searchlib/fef/properties.h> +#include <vespa/vespalib/util/stash.h> + +using namespace search::fef; + +namespace search::features { + +void +SecondPhaseExecutor::execute(uint32_t) +{ + outputs().set_number(0, inputs().get_number(0)); +} + + +SecondPhaseBlueprint::SecondPhaseBlueprint() + : Blueprint("secondPhase") +{ + // empty +} + +void +SecondPhaseBlueprint::visitDumpFeatures(const IIndexEnvironment&, + IDumpFeatureVisitor&) const +{ +} + +Blueprint::UP +SecondPhaseBlueprint::createInstance() const +{ + return std::make_unique<SecondPhaseBlueprint>(); +} + +bool +SecondPhaseBlueprint::setup(const IIndexEnvironment& env, + const ParameterList&) +{ + if (auto maybe_input = defineInput(indexproperties::rank::SecondPhase::lookup(env.getProperties()), + AcceptInput::ANY)) + { + describeOutput("score", "The ranking score for second phase.", maybe_input.value()); + return true; + } else { + return false; + } +} + +FeatureExecutor & +SecondPhaseBlueprint::createExecutor(const IQueryEnvironment&, vespalib::Stash& stash) const +{ + return stash.create<SecondPhaseExecutor>(); +} + +} diff --git a/searchlib/src/vespa/searchlib/features/second_phase_feature.h b/searchlib/src/vespa/searchlib/features/second_phase_feature.h new file mode 100644 index 00000000000..61805186453 --- /dev/null +++ b/searchlib/src/vespa/searchlib/features/second_phase_feature.h @@ -0,0 +1,35 @@ +// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#pragma once + +#include <vespa/searchlib/fef/blueprint.h> + +namespace search::features { + +/** + * Implements the executor outputting the second phase ranking. + */ +class SecondPhaseExecutor : public fef::FeatureExecutor { +public: + bool isPure() override { return true; } + void execute(uint32_t docId) override; +}; + +/** + * Implements the blueprint for the second phase feature. + */ +class SecondPhaseBlueprint : public fef::Blueprint { +public: + SecondPhaseBlueprint(); + void visitDumpFeatures(const fef::IIndexEnvironment & env, fef::IDumpFeatureVisitor & visitor) const override; + fef::Blueprint::UP createInstance() const override; + + fef::ParameterDescriptions getDescriptions() const override { + return fef::ParameterDescriptions().desc(); + } + bool setup(const fef::IIndexEnvironment & env, const fef::ParameterList & params) override; + + fef::FeatureExecutor &createExecutor(const fef::IQueryEnvironment &env, vespalib::Stash &stash) const override; +}; + +} diff --git a/searchlib/src/vespa/searchlib/features/setup.cpp b/searchlib/src/vespa/searchlib/features/setup.cpp index 71e083e2326..bdffbd1c6aa 100644 --- a/searchlib/src/vespa/searchlib/features/setup.cpp +++ b/searchlib/src/vespa/searchlib/features/setup.cpp @@ -48,6 +48,7 @@ #include "rankingexpressionfeature.h" #include "raw_score_feature.h" #include "reverseproximityfeature.h" +#include "second_phase_feature.h" #include "subqueries_feature.h" #include "tensor_from_labels_feature.h" #include "tensor_from_weighted_set_feature.h" @@ -109,6 +110,7 @@ void setup_search_features(fef::IBlueprintRegistry & registry) registry.addPrototype(std::make_shared<RandomNormalBlueprint>()); registry.addPrototype(std::make_shared<RandomNormalStableBlueprint>()); registry.addPrototype(std::make_shared<RawScoreBlueprint>()); + registry.addPrototype(std::make_shared<SecondPhaseBlueprint>()); registry.addPrototype(std::make_shared<SubqueriesBlueprint>()); registry.addPrototype(std::make_shared<TensorFromLabelsBlueprint>()); registry.addPrototype(std::make_shared<TensorFromWeightedSetBlueprint>()); |