Add IVF_HNSW index (#4613)

* Add IVF_HNSW index

Signed-off-by: sahuang <xiaohaix@student.unimelb.edu.au>

* Fix serialize-load bug

Signed-off-by: sahuang <xiaohaix@student.unimelb.edu.au>
pull/4654/head
Xiaohai Xu 2021-01-15 10:48:22 +08:00 committed by GitHub
parent 91a1494b57
commit df500c923e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 375 additions and 9 deletions

View File

@ -71,6 +71,7 @@ set(vector_index_srcs
knowhere/index/vector_index/IndexIVF.cpp
knowhere/index/vector_index/IndexIVFPQ.cpp
knowhere/index/vector_index/IndexIVFSQ.cpp
knowhere/index/vector_index/IndexIVFHNSW.cpp
knowhere/index/vector_index/IndexAnnoy.cpp
knowhere/index/vector_index/IndexRHNSW.cpp
knowhere/index/vector_index/IndexHNSW.cpp

View File

@ -25,6 +25,7 @@ const char* INDEX_FAISS_IVFFLAT = "IVF_FLAT";
const char* INDEX_FAISS_IVFPQ = "IVF_PQ";
const char* INDEX_FAISS_IVFSQ8 = "IVF_SQ8";
const char* INDEX_FAISS_IVFSQ8H = "IVF_SQ8_HYBRID";
const char* INDEX_FAISS_IVFHNSW = "IVF_HNSW";
const char* INDEX_FAISS_BIN_IDMAP = "BIN_FLAT";
const char* INDEX_FAISS_BIN_IVFFLAT = "BIN_IVF_FLAT";
const char* INDEX_NSG = "NSG";

View File

@ -54,6 +54,7 @@ extern const char* INDEX_FAISS_IVFFLAT;
extern const char* INDEX_FAISS_IVFPQ;
extern const char* INDEX_FAISS_IVFSQ8;
extern const char* INDEX_FAISS_IVFSQ8H;
extern const char* INDEX_FAISS_IVFHNSW;
extern const char* INDEX_FAISS_BIN_IDMAP;
extern const char* INDEX_FAISS_BIN_IVFFLAT;
extern const char* INDEX_NSG;

View File

@ -207,6 +207,34 @@ IVFPQConfAdapter::CheckCPUPQParams(int64_t dimension, int64_t m) {
return (dimension % m == 0);
}
bool
IVFHNSWConfAdapter::CheckTrain(Config& oricfg, const IndexMode mode) {
// HNSW param check
CheckIntByRange(knowhere::IndexParams::efConstruction, HNSW_MIN_EFCONSTRUCTION, HNSW_MAX_EFCONSTRUCTION);
CheckIntByRange(knowhere::IndexParams::M, HNSW_MIN_M, HNSW_MAX_M);
// IVF param check
CheckIntByRange(knowhere::IndexParams::nlist, MIN_NLIST, MAX_NLIST);
// auto tune params
auto rows = oricfg[knowhere::meta::ROWS].get<int64_t>();
auto nlist = oricfg[knowhere::IndexParams::nlist].get<int64_t>();
oricfg[knowhere::IndexParams::nlist] = MatchNlist(rows, nlist);
return ConfAdapter::CheckTrain(oricfg, mode);
}
bool
IVFHNSWConfAdapter::CheckSearch(Config& oricfg, const IndexType type, const IndexMode mode) {
// HNSW param check
CheckIntByRange(knowhere::IndexParams::ef, oricfg[knowhere::meta::TOPK], HNSW_MAX_EF);
// IVF param check
CheckIntByRange(knowhere::IndexParams::nprobe, MIN_NPROBE, MAX_NPROBE);
return ConfAdapter::CheckSearch(oricfg, type, mode);
}
bool
NSGConfAdapter::CheckTrain(Config& oricfg, const IndexMode mode) {
const int64_t MIN_KNNG = 5;

View File

@ -61,6 +61,15 @@ class IVFPQConfAdapter : public IVFConfAdapter {
CheckCPUPQParams(int64_t dimension, int64_t m);
};
class IVFHNSWConfAdapter : public ConfAdapter {
public:
bool
CheckTrain(Config& oricfg, const IndexMode mode) override;
bool
CheckSearch(Config& oricfg, const IndexType type, const IndexMode mode) override;
};
class NSGConfAdapter : public IVFConfAdapter {
public:
bool

View File

@ -41,6 +41,7 @@ AdapterMgr::RegisterAdapter() {
REGISTER_CONF_ADAPTER(IVFPQConfAdapter, IndexEnum::INDEX_FAISS_IVFPQ, ivfpq_adapter);
REGISTER_CONF_ADAPTER(IVFSQConfAdapter, IndexEnum::INDEX_FAISS_IVFSQ8, ivfsq8_adapter);
REGISTER_CONF_ADAPTER(IVFSQConfAdapter, IndexEnum::INDEX_FAISS_IVFSQ8H, ivfsq8h_adapter);
REGISTER_CONF_ADAPTER(IVFHNSWConfAdapter, IndexEnum::INDEX_FAISS_IVFHNSW, ivfhnsw_adapter);
REGISTER_CONF_ADAPTER(BinIDMAPConfAdapter, IndexEnum::INDEX_FAISS_BIN_IDMAP, idmap_bin_adapter);
REGISTER_CONF_ADAPTER(BinIVFConfAdapter, IndexEnum::INDEX_FAISS_BIN_IVFFLAT, ivf_bin_adapter);
REGISTER_CONF_ADAPTER(NSGConfAdapter, IndexEnum::INDEX_NSG, nsg_adapter);

View File

@ -0,0 +1,134 @@
// Copyright (C) 2019-2020 Zilliz. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the License
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
// or implied. See the License for the specific language governing permissions and limitations under the License
#include <algorithm>
#include <memory>
#include <string>
#include <faiss/IndexFlat.h>
#include <faiss/IndexIVFFlat.h>
#include <faiss/clone_index.h>
#include <faiss/index_io.h>
#include "faiss/IndexRHNSW.h"
#include "knowhere/common/Exception.h"
#include "knowhere/index/vector_index/IndexIVFHNSW.h"
#include "knowhere/index/vector_index/adapter/VectorAdapter.h"
#include "knowhere/index/vector_index/helpers/IndexParameter.h"
namespace milvus {
namespace knowhere {
BinarySet
IVFHNSW::Serialize(const Config& config) {
if (!index_ || !index_->is_trained) {
KNOWHERE_THROW_MSG("index not initialize or trained");
}
try {
// Serialize IVF index and HNSW data
auto res_set = SerializeImpl(index_type_);
auto index = dynamic_cast<faiss::IndexIVFFlat*>(index_.get());
auto real_idx = dynamic_cast<faiss::IndexRHNSWFlat*>(index->quantizer);
if (real_idx == nullptr) {
KNOWHERE_THROW_MSG("Quantizer index is not a faiss::IndexRHNSWFlat");
}
MemoryIOWriter writer;
faiss::write_index(real_idx->storage, &writer);
std::shared_ptr<uint8_t[]> data(writer.data_);
res_set.Append("HNSW_META", data, writer.rp);
if (config.contains(INDEX_FILE_SLICE_SIZE_IN_MEGABYTE)) {
Disassemble(config[INDEX_FILE_SLICE_SIZE_IN_MEGABYTE].get<int64_t>() * 1024 * 1024, res_set);
}
return res_set;
} catch (std::exception& e) {
KNOWHERE_THROW_MSG(e.what());
}
}
void
IVFHNSW::Load(const BinarySet& binary_set) {
try {
// Load IVF index and HNSW data
Assemble(const_cast<BinarySet&>(binary_set));
LoadImpl(binary_set, index_type_);
auto index = dynamic_cast<faiss::IndexIVFFlat*>(index_.get());
MemoryIOReader reader;
auto binary = binary_set.GetByName("HNSW_META");
reader.total = static_cast<size_t>(binary->size);
reader.data_ = binary->data.get();
auto idx = faiss::read_index(&reader);
auto real_idx = dynamic_cast<faiss::IndexRHNSWFlat*>(index->quantizer);
real_idx->storage = new faiss::IndexFlat(idx->d, idx->metric_type);
real_idx->storage->add(idx->ntotal,
reinterpret_cast<const float*>(dynamic_cast<faiss::IndexFlat*>(idx)->xb.data()));
real_idx->init_hnsw();
} catch (std::exception& e) {
KNOWHERE_THROW_MSG(e.what());
}
}
void
IVFHNSW::Train(const DatasetPtr& dataset_ptr, const Config& config) {
GET_TENSOR_DATA_DIM(dataset_ptr)
faiss::MetricType metric_type = GetMetricType(config[Metric::TYPE].get<std::string>());
auto coarse_quantizer = new faiss::IndexRHNSWFlat(dim, config[IndexParams::M], metric_type);
coarse_quantizer->hnsw.efConstruction = config[IndexParams::efConstruction];
auto index = std::make_shared<faiss::IndexIVFFlat>(coarse_quantizer, dim, config[IndexParams::nlist].get<int64_t>(),
metric_type);
index->own_fields = true;
index->train(rows, reinterpret_cast<const float*>(p_data));
index_ = index;
}
VecIndexPtr
IVFHNSW::CopyCpuToGpu(const int64_t device_id, const Config& config) {
KNOWHERE_THROW_MSG("IVFHNSW::CopyCpuToGpu not supported.");
}
void
IVFHNSW::UpdateIndexSize() {
if (!index_) {
KNOWHERE_THROW_MSG("index not initialize");
}
auto ivf_index = static_cast<faiss::IndexIVFFlat*>(index_.get());
auto nb = ivf_index->invlists->compute_ntotal();
auto code_size = ivf_index->code_size;
auto hnsw_quantizer = dynamic_cast<faiss::IndexRHNSWFlat*>(ivf_index->quantizer);
// ivf codes, ivf ids and hnsw_flat quantizer
index_size_ = nb * code_size + nb * sizeof(int64_t) + hnsw_quantizer->cal_size();
}
void
IVFHNSW::QueryImpl(int64_t n, const float* data, int64_t k, float* distances, int64_t* labels, const Config& config,
const faiss::BitsetView& bitset) {
auto params = GenParams(config);
auto ivf_index = dynamic_cast<faiss::IndexIVF*>(index_.get());
ivf_index->nprobe = std::min(params->nprobe, ivf_index->invlists->nlist);
if (params->nprobe > 1 && n <= 4) {
ivf_index->parallel_mode = 1;
} else {
ivf_index->parallel_mode = 0;
}
// Update HNSW quantizer search param
auto hnsw_quantizer = dynamic_cast<faiss::IndexRHNSWFlat*>(ivf_index->quantizer);
hnsw_quantizer->hnsw.efSearch = config[IndexParams::ef].get<int64_t>();
ivf_index->search(n, data, k, distances, labels, bitset);
}
} // namespace knowhere
} // namespace milvus

View File

@ -0,0 +1,56 @@
// Copyright (C) 2019-2020 Zilliz. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the License
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
// or implied. See the License for the specific language governing permissions and limitations under the License
#pragma once
#include <memory>
#include <utility>
#include "knowhere/index/vector_index/IndexIVF.h"
namespace milvus {
namespace knowhere {
class IVFHNSW : public IVF {
public:
IVFHNSW() : IVF() {
index_type_ = IndexEnum::INDEX_FAISS_IVFHNSW;
}
explicit IVFHNSW(std::shared_ptr<faiss::Index> index) : IVF(std::move(index)) {
index_type_ = IndexEnum::INDEX_FAISS_IVFHNSW;
}
BinarySet
Serialize(const Config&) override;
void
Load(const BinarySet&) override;
void
Train(const DatasetPtr&, const Config&) override;
VecIndexPtr
CopyCpuToGpu(const int64_t, const Config&) override;
void
UpdateIndexSize() override;
protected:
void
QueryImpl(int64_t n, const float* data, int64_t k, float* distances, int64_t* labels, const Config& config,
const faiss::BitsetView& bitset) override;
};
using IVFHNSWPtr = std::shared_ptr<IVFHNSW>;
} // namespace knowhere
} // namespace milvus

View File

@ -19,7 +19,6 @@
#include <faiss/IndexFlat.h>
#include <faiss/IndexScalarQuantizer.h>
#include <faiss/clone_index.h>
#include <faiss/index_factory.h>
#include "knowhere/common/Exception.h"
#include "knowhere/index/vector_index/IndexIVFSQ.h"

View File

@ -12,7 +12,6 @@
#include <faiss/IndexFlat.h>
#include <faiss/IndexScalarQuantizer.h>
#include <faiss/gpu/GpuCloner.h>
#include <faiss/index_factory.h>
#include <memory>
#include <string>

View File

@ -16,7 +16,6 @@
#include <faiss/IndexIVFFlat.h>
#include <faiss/IndexIVFPQ.h>
#include <faiss/clone_index.h>
#include <faiss/index_factory.h>
#include <faiss/index_io.h>
#ifdef MILVUS_GPU_VERSION
#include <faiss/gpu/GpuAutoTune.h>

View File

@ -277,7 +277,7 @@ IndexHNSW::~IndexHNSW() {
void IndexHNSW::train(idx_t n, const float* x)
{
FAISS_THROW_IF_NOT_MSG(storage,
"Please use IndexHSNWFlat (or variants) instead of IndexHNSW directly");
"Please use IndexHNSWFlat (or variants) instead of IndexHNSW directly");
// hnsw structure does not require training
storage->train (n, x);
is_trained = true;
@ -288,7 +288,7 @@ void IndexHNSW::search (idx_t n, const float *x, idx_t k,
{
FAISS_THROW_IF_NOT_MSG(storage,
"Please use IndexHSNWFlat (or variants) instead of IndexHNSW directly");
"Please use IndexHNSWFlat (or variants) instead of IndexHNSW directly");
size_t nreorder = 0;
idx_t check_period = InterruptCallback::get_period_hint (
@ -348,7 +348,7 @@ void IndexHNSW::search (idx_t n, const float *x, idx_t k,
void IndexHNSW::add(idx_t n, const float *x)
{
FAISS_THROW_IF_NOT_MSG(storage,
"Please use IndexHSNWFlat (or variants) instead of IndexHNSW directly");
"Please use IndexHNSWFlat (or variants) instead of IndexHNSW directly");
FAISS_THROW_IF_NOT(is_trained);
int n0 = ntotal;
storage->add(n, x);

View File

@ -230,7 +230,7 @@ IndexRHNSW::clear_stats() {
void IndexRHNSW::train(idx_t n, const float* x)
{
FAISS_THROW_IF_NOT_MSG(storage,
"Please use IndexHSNWFlat (or variants) instead of IndexRHNSW directly");
"Please use IndexRHNSWFlat (or variants) instead of IndexRHNSW directly");
// hnsw structure does not require training
storage->train (n, x);
is_trained = true;
@ -241,7 +241,7 @@ void IndexRHNSW::search (idx_t n, const float *x, idx_t k,
{
FAISS_THROW_IF_NOT_MSG(storage,
"Please use IndexHSNWFlat (or variants) instead of IndexRHNSW directly");
"Please use IndexRHNSWFlat (or variants) instead of IndexRHNSW directly");
size_t nreorder = 0;
idx_t check_period = InterruptCallback::get_period_hint (
@ -324,7 +324,7 @@ void IndexRHNSW::search (idx_t n, const float *x, idx_t k,
void IndexRHNSW::add(idx_t n, const float *x)
{
FAISS_THROW_IF_NOT_MSG(storage,
"Please use IndexHSNWFlat (or variants) instead of IndexRHNSW directly");
"Please use IndexRHNSWFlat (or variants) instead of IndexRHNSW directly");
FAISS_THROW_IF_NOT(is_trained);
int n0 = ntotal;
storage->add(n, x);

View File

@ -65,6 +65,7 @@ set(faiss_srcs
${INDEX_SOURCE_DIR}/knowhere/knowhere/index/vector_index/IndexIVF.cpp
${INDEX_SOURCE_DIR}/knowhere/knowhere/index/vector_index/IndexIVFSQ.cpp
${INDEX_SOURCE_DIR}/knowhere/knowhere/index/vector_index/IndexIVFPQ.cpp
${INDEX_SOURCE_DIR}/knowhere/knowhere/index/vector_index/IndexIVFHNSW.cpp
${INDEX_SOURCE_DIR}/knowhere/knowhere/index/vector_offset_index/OffsetBaseIndex.cpp
${INDEX_SOURCE_DIR}/knowhere/knowhere/index/vector_offset_index/IndexIVF_NM.cpp
)
@ -127,6 +128,14 @@ endif ()
target_link_libraries(test_ivf ${depend_libs} ${unittest_libs} ${basic_libs})
install(TARGETS test_ivf DESTINATION unittest)
################################################################################
#<IVFHNSW-TEST>
if (NOT TARGET test_ivf_hnsw)
add_executable(test_ivf_hnsw test_ivf_hnsw.cpp ${faiss_srcs} ${util_srcs})
endif ()
target_link_libraries(test_ivf_hnsw ${depend_libs} ${unittest_libs} ${basic_libs})
install(TARGETS test_ivf_hnsw DESTINATION unittest)
################################################################################
#<IVFNM-TEST-CPU>
if (NOT TARGET test_ivf_cpu_nm)

View File

@ -14,6 +14,7 @@
#include "knowhere/index/IndexType.h"
#include "knowhere/index/vector_index/IndexIVF.h"
#include "knowhere/index/vector_index/IndexIVFHNSW.h"
#include "knowhere/index/vector_index/IndexIVFPQ.h"
#include "knowhere/index/vector_index/IndexIVFSQ.h"
#include "knowhere/index/vector_index/helpers/IndexParameter.h"
@ -45,6 +46,8 @@ IndexFactory(const milvus::knowhere::IndexType& type, const milvus::knowhere::In
return std::make_shared<milvus::knowhere::IVFPQ>();
} else if (type == milvus::knowhere::IndexEnum::INDEX_FAISS_IVFSQ8) {
return std::make_shared<milvus::knowhere::IVFSQ>();
} else if (type == milvus::knowhere::IndexEnum::INDEX_FAISS_IVFHNSW) {
return std::make_shared<milvus::knowhere::IVFHNSW>();
} else if (type == milvus::knowhere::IndexEnum::INDEX_FAISS_IVFSQ8H) {
std::cout << "IVFSQ8H does not support MODE_CPU" << std::endl;
} else {
@ -124,6 +127,19 @@ class ParamGenerator {
{milvus::knowhere::INDEX_FILE_SLICE_SIZE_IN_MEGABYTE, 4},
{milvus::knowhere::meta::DEVICEID, DEVICEID},
};
} else if (type == milvus::knowhere::IndexEnum::INDEX_FAISS_IVFHNSW) {
return milvus::knowhere::Config{
{milvus::knowhere::meta::DIM, DIM},
{milvus::knowhere::meta::TOPK, K},
{milvus::knowhere::IndexParams::nlist, 100},
{milvus::knowhere::IndexParams::nprobe, 4},
{milvus::knowhere::IndexParams::M, 16},
{milvus::knowhere::IndexParams::efConstruction, 200},
{milvus::knowhere::IndexParams::ef, 200},
{milvus::knowhere::Metric::TYPE, milvus::knowhere::Metric::L2},
{milvus::knowhere::INDEX_FILE_SLICE_SIZE_IN_MEGABYTE, 4},
{milvus::knowhere::meta::DEVICEID, DEVICEID},
};
} else {
std::cout << "Invalid index type " << type << std::endl;
}

View File

@ -0,0 +1,96 @@
// Copyright (C) 2019-2020 Zilliz. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the License
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
// or implied. See the License for the specific language governing permissions and limitations under the License.
#include <gtest/gtest.h>
#include <fiu-control.h>
#include <fiu/fiu-local.h>
#include <iostream>
#include <thread>
#include "knowhere/common/Exception.h"
#include "knowhere/common/Timer.h"
#include "knowhere/index/IndexType.h"
#include "knowhere/index/vector_index/IndexIVF.h"
#include "knowhere/index/vector_index/IndexIVFHNSW.h"
#include "knowhere/index/vector_index/adapter/VectorAdapter.h"
#include "unittest/Helper.h"
#include "unittest/utils.h"
using ::testing::Combine;
using ::testing::TestWithParam;
using ::testing::Values;
class IVFHNSWTest : public DataGen,
public TestWithParam<::std::tuple<milvus::knowhere::IndexType, milvus::knowhere::IndexMode>> {
protected:
void
SetUp() override {
std::tie(index_type_, index_mode_) = GetParam();
Generate(dim, nb, nq);
index_ = IndexFactory(index_type_, index_mode_);
conf_ = ParamGenerator::GetInstance().Gen(index_type_);
}
void
TearDown() override {
#ifdef MILVUS_GPU_VERSION
milvus::knowhere::FaissGpuResourceMgr::GetInstance().Free();
#endif
}
protected:
milvus::knowhere::IndexType index_type_;
milvus::knowhere::IndexMode index_mode_;
milvus::knowhere::Config conf_;
milvus::knowhere::IVFPtr index_ = nullptr;
};
INSTANTIATE_TEST_CASE_P(
IVFParameters, IVFHNSWTest,
Values(
std::make_tuple(milvus::knowhere::IndexEnum::INDEX_FAISS_IVFHNSW, milvus::knowhere::IndexMode::MODE_CPU)));
TEST_P(IVFHNSWTest, ivfhnsw_basic_cpu) {
assert(!xb.empty());
if (index_mode_ != milvus::knowhere::IndexMode::MODE_CPU) {
return;
}
// null faiss index
ASSERT_ANY_THROW(index_->AddWithoutIds(base_dataset, conf_));
index_->Train(base_dataset, conf_);
index_->AddWithoutIds(base_dataset, conf_);
EXPECT_EQ(index_->Count(), nb);
EXPECT_EQ(index_->Dim(), dim);
auto result = index_->Query(query_dataset, conf_, nullptr);
AssertAnns(result, nq, k);
}
TEST_P(IVFHNSWTest, ivfhnsw_slice) {
fiu_init(0);
{
// serialize index
index_->Train(base_dataset, conf_);
index_->AddWithoutIds(base_dataset, conf_);
auto binaryset = index_->Serialize(conf_);
// load index
index_->Load(binaryset);
EXPECT_EQ(index_->Count(), nb);
EXPECT_EQ(index_->Dim(), dim);
auto result = index_->Query(query_dataset, conf_, nullptr);
AssertAnns(result, nq, k);
}
}

View File

@ -192,6 +192,7 @@ ValidateVectorIndexType(std::string& index_type, bool is_binary) {
knowhere::IndexEnum::INDEX_FAISS_IVFFLAT,
knowhere::IndexEnum::INDEX_FAISS_IVFPQ,
knowhere::IndexEnum::INDEX_FAISS_IVFSQ8,
knowhere::IndexEnum::INDEX_FAISS_IVFHNSW,
#ifdef MILVUS_GPU_VERSION
knowhere::IndexEnum::INDEX_FAISS_IVFSQ8H,
#endif
@ -354,6 +355,19 @@ ValidateIndexParams(const milvus::json& index_params, int64_t dimension, const s
if (!status.ok()) {
return status;
}
} else if (index_type == knowhere::IndexEnum::INDEX_FAISS_IVFHNSW) {
auto status = CheckParameterRange(index_params, knowhere::IndexParams::nlist, 1, 65536);
if (!status.ok()) {
return status;
}
status = CheckParameterRange(index_params, knowhere::IndexParams::M, 4, 64);
if (!status.ok()) {
return status;
}
status = CheckParameterRange(index_params, knowhere::IndexParams::efConstruction, 8, 512);
if (!status.ok()) {
return status;
}
}
return Status::OK();

View File

@ -21,6 +21,7 @@ const char* NAME_ENGINE_TYPE_IVFSQ8 = "IVF_SQ8";
const char* NAME_ENGINE_TYPE_IVFSQ8H = "IVF_SQ8H";
const char* NAME_ENGINE_TYPE_RNSG = "RNSG";
const char* NAME_ENGINE_TYPE_IVFPQ = "IVF_PQ";
const char* NAME_ENGINE_TYPE_IVFHNSW = "IVF_HNSW";
const char* NAME_ENGINE_TYPE_HNSW = "HNSW";
const char* NAME_ENGINE_TYPE_ANNOY = "ANNOY";
const char* NAME_ENGINE_TYPE_RHNSWFLAT = "RHNSW_FLAT";

View File

@ -24,6 +24,7 @@ extern const char* NAME_ENGINE_TYPE_IVFSQ8;
extern const char* NAME_ENGINE_TYPE_IVFSQ8H;
extern const char* NAME_ENGINE_TYPE_RNSG;
extern const char* NAME_ENGINE_TYPE_IVFPQ;
extern const char* NAME_ENGINE_TYPE_IVFHNSW;
extern const char* NAME_ENGINE_TYPE_HNSW;
extern const char* NAME_ENGINE_TYPE_ANNOY;
extern const char* NAME_ENGINE_TYPE_RHNSWFLAT;

View File

@ -46,6 +46,7 @@ enum class IndexType {
RHNSWSQ = 15,
NGTPANNG = 16,
NGTONNG = 17,
IVFHNSW = 18,
};
enum class MetricType {