aboutsummaryrefslogtreecommitdiffstats
path: root/searchlib
diff options
context:
space:
mode:
authorTor Egge <Tor.Egge@online.no>2024-05-16 13:54:40 +0200
committerTor Egge <Tor.Egge@online.no>2024-05-16 13:54:40 +0200
commit7b386dd241870c6b1317cb85df1b16cc5f386d08 (patch)
tree1c1da155749cded0dca1d0ffa5608bf6802e90e5 /searchlib
parentcced1ff316a6960a0a6d091f43b0eafd3ba2a78e (diff)
Add second phase feature.
Diffstat (limited to 'searchlib')
-rw-r--r--searchlib/src/tests/features/prod_features_test.cpp27
-rw-r--r--searchlib/src/tests/ranksetup/ranksetup_test.cpp15
-rw-r--r--searchlib/src/vespa/searchlib/features/CMakeLists.txt1
-rw-r--r--searchlib/src/vespa/searchlib/features/second_phase_feature.cpp58
-rw-r--r--searchlib/src/vespa/searchlib/features/second_phase_feature.h35
-rw-r--r--searchlib/src/vespa/searchlib/features/setup.cpp2
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>());