Skip to content

Commit 1870f57

Browse files
committed
refactor raw storage; impl bin for lemur
Signed-off-by: SpadeA <tangchenjie1210@gmail.com>
1 parent a747e18 commit 1870f57

15 files changed

Lines changed: 1468 additions & 158 deletions

include/knowhere/index/emb_list_strategy.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
#include <cstring>
1616
#include <memory>
17+
#include <optional>
1718
#include <string>
1819

1920
#include "knowhere/bitsetview.h"
@@ -47,6 +48,37 @@ struct EmbListMetricInfo {
4748
bool is_cosine;
4849
};
4950

51+
// Some strategies build ANN data whose physical type differs from the raw vectors.
52+
// This target tells IndexNode whether that ANN data can use the current index node
53+
// or needs a separate index with a different data type.
54+
enum class EmbListAnnIndexTarget {
55+
// Build the ANN dataset directly into this IndexNode's own ANN index. This is used when
56+
// the ANN dataset has the same data type as the current index node, such as TokenANN and MUVERA.
57+
BaseIndex,
58+
// Build the ANN dataset into a separately allocated Index<IndexNode>. This is used when
59+
// the strategy's ANN representation has a different data type from the current index node,
60+
// such as bin1 LEMUR producing fp32 learned representations.
61+
SeparateIndex,
62+
};
63+
64+
enum class EmbListAnnIndexDataType {
65+
// Valid for BaseIndex: the current IndexNode data type is reused.
66+
// SeparateIndex must request a concrete data type instead.
67+
SameAsBaseIndex,
68+
Fp32,
69+
Fp16,
70+
Bf16,
71+
Int8,
72+
Bin1,
73+
};
74+
75+
struct EmbListAnnIndexSpec {
76+
EmbListAnnIndexTarget target;
77+
EmbListAnnIndexDataType data_type;
78+
// nullopt means the ANN index uses the raw sub metric parsed from the outer emb-list metric.
79+
std::optional<std::string> ann_metric_type;
80+
};
81+
5082
/**
5183
* @brief Parse metric type from config into a shared struct.
5284
*
@@ -206,6 +238,16 @@ class EmbListStrategy {
206238
return false;
207239
}
208240

241+
/**
242+
* @brief Describe how the strategy's ANN dataset should be indexed.
243+
*
244+
* BaseIndex means the ANN data is indexed by this IndexNode itself. SeparateIndex means IndexNode must create
245+
* a child Index<IndexNode> with the requested data type. nullopt ann_metric_type means the ANN index uses the
246+
* raw sub metric parsed from the outer emb-list metric; a value means the strategy overrides it.
247+
*/
248+
[[nodiscard]] virtual EmbListAnnIndexSpec
249+
AnnIndexSpec(const BaseConfig& config) const = 0;
250+
209251
/**
210252
* @brief Execute search with full control over the search flow.
211253
*

include/knowhere/index/index_node.h

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#define INDEX_NODE_H
1414

1515
#include <functional>
16+
#include <memory>
1617
#include <mutex>
1718
#include <queue>
1819
#include <utility>
@@ -46,13 +47,11 @@ struct OpContext;
4647
class ThreadPool;
4748
#endif
4849

49-
namespace faiss {
50-
class IndexFlat;
51-
} // namespace faiss
52-
5350
namespace knowhere {
5451

5552
class Interrupt;
53+
class EmbListRawStorage;
54+
struct EmbListSeparateAnnIndexHolder;
5655

5756
class IndexNode : public Object {
5857
public:
@@ -318,6 +317,23 @@ class IndexNode : public Object {
318317
virtual int64_t
319318
Count() const = 0;
320319

320+
// Returns the ANN index that currently serves vector-level metadata/search.
321+
// EmbList strategies normally use this node itself, but a strategy may build
322+
// a child ANN index when its ANN representation has a different data type.
323+
virtual IndexNode*
324+
AnnIndexNode();
325+
326+
virtual const IndexNode*
327+
AnnIndexNode() const;
328+
329+
virtual int64_t
330+
CountForSearchBitset() const {
331+
if (emb_list_strategy_ != nullptr && emb_list_strategy_->GetDocCount() >= 0) {
332+
return emb_list_strategy_->GetDocCount();
333+
}
334+
return Count();
335+
}
336+
321337
virtual std::string
322338
Type() const = 0;
323339

@@ -496,6 +512,10 @@ class IndexNode : public Object {
496512
SearchEmbListIfNeed(const DataSetPtr dataset, std::unique_ptr<Config> config, const BitsetView& bitset,
497513
milvus::OpContext* op_context = nullptr) const;
498514

515+
virtual expected<DataSetPtr>
516+
SearchEmbListAnnIndex(const DataSetPtr dataset, std::unique_ptr<Config> config, const BitsetView& bitset,
517+
milvus::OpContext* op_context = nullptr) const;
518+
499519
/**
500520
* @brief Returns the code size (in bytes) of a single query vector, which varies depending on the data type (e.g.,
501521
* fp32, bf16, etc).
@@ -619,10 +639,10 @@ class IndexNode : public Object {
619639

620640
protected:
621641
/**
622-
* @brief Compute distances using emb_list_raw_index_ (raw vector storage).
642+
* @brief Compute distances using emb_list raw vector storage.
623643
*
624-
* Used by CalcDistByIDs implementations when emb_list_raw_index_ is present
625-
* (MUVERA/LEMUR strategies). The raw index stores original vectors indexed by
644+
* Used by CalcDistByIDs implementations when emb_list raw storage is present
645+
* (MUVERA/LEMUR strategies). The raw storage keeps original vectors indexed by
626646
* global vector IDs, so no ID translation is needed.
627647
*
628648
* @param pool Thread pool for parallel computation
@@ -637,14 +657,14 @@ class IndexNode : public Object {
637657
std::string el_metric_type_;
638658
EmbListStrategyPtr emb_list_strategy_; // emb_list encoding strategy (tokenann/muvera)
639659
// Raw vector storage for EmbList strategies (MUVERA/LEMUR) that encode documents
640-
// into different representations for ANN search. Since the base index holds encoded
641-
// vectors (not raw), this IndexFlat stores original vectors for exact distance
642-
// computation during MaxSim reranking.
643-
// Baseline type so that the same shared_ptr can hold either the knowhere
644-
// Jaccard-aware IndexFlat subclass (fresh build path, if ever needed) or
645-
// a plain ::faiss::IndexFlat{,IP,L2} restored by the deserialization
646-
// factory in cppcontrib/knowhere/impl/index_read.cpp.
647-
std::shared_ptr<::faiss::IndexFlat> emb_list_raw_index_;
660+
// into different representations for ANN search. The ANN index may be this node's
661+
// BaseIndex or a SeparateIndex, so raw storage keeps the original vectors available
662+
// for exact distance computation during MaxSim reranking.
663+
std::shared_ptr<EmbListRawStorage> emb_list_raw_storage_;
664+
// Optional child ANN index used when a strategy's ANN representation has a different
665+
// data type from this IndexNode, for example binary LEMUR producing fp32 vectors.
666+
std::shared_ptr<EmbListSeparateAnnIndexHolder> emb_list_separate_ann_index_;
667+
std::string emb_list_raw_metric_type_;
648668

649669
#if defined(NOT_COMPILE_FOR_SWIG) && !defined(KNOWHERE_WITH_LIGHT)
650670
struct PrometheusMetrics {

0 commit comments

Comments
 (0)