From 0dcc7a16f6f4e1e86e855ae488fb5e67c96cdeae Mon Sep 17 00:00:00 2001 From: Xiangyu Wang Date: Wed, 22 Jan 2025 17:25:16 +0800 Subject: [PATCH] add update example Signed-off-by: Xiangyu Wang --- ...ture_remove.cpp => 303_feature_remove.cpp} | 0 .../cpp/todo_examples/303_feature_update.cpp | 14 -- .../cpp/todo_examples/305_feature_update.cpp | 129 ++++++++++++++++++ examples/cpp/todo_examples/CMakeLists.txt | 7 +- 4 files changed, 134 insertions(+), 16 deletions(-) rename examples/cpp/todo_examples/{305_feature_remove.cpp => 303_feature_remove.cpp} (100%) delete mode 100644 examples/cpp/todo_examples/303_feature_update.cpp create mode 100644 examples/cpp/todo_examples/305_feature_update.cpp diff --git a/examples/cpp/todo_examples/305_feature_remove.cpp b/examples/cpp/todo_examples/303_feature_remove.cpp similarity index 100% rename from examples/cpp/todo_examples/305_feature_remove.cpp rename to examples/cpp/todo_examples/303_feature_remove.cpp diff --git a/examples/cpp/todo_examples/303_feature_update.cpp b/examples/cpp/todo_examples/303_feature_update.cpp deleted file mode 100644 index 0d435f8c..00000000 --- a/examples/cpp/todo_examples/303_feature_update.cpp +++ /dev/null @@ -1,14 +0,0 @@ - -// Copyright 2024-present the vsag project -// -// 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. \ No newline at end of file diff --git a/examples/cpp/todo_examples/305_feature_update.cpp b/examples/cpp/todo_examples/305_feature_update.cpp new file mode 100644 index 00000000..7e05edf9 --- /dev/null +++ b/examples/cpp/todo_examples/305_feature_update.cpp @@ -0,0 +1,129 @@ + +// Copyright 2024-present the vsag project +// +// 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 + +#include + +int +main(int argc, char** argv) { + /******************* Prepare Base Dataset *****************/ + int64_t num_vectors = 10000; + int64_t dim = 64; + std::vector ids(num_vectors); + std::vector vectors(num_vectors * dim); + std::mt19937 rng(47); + std::uniform_real_distribution distrib_real; + for (int64_t i = 0; i < num_vectors; ++i) { + ids[i] = i; + } + for (int64_t i = 0; i < dim * num_vectors; ++i) { + vectors[i] = distrib_real(rng); + } + auto base = vsag::Dataset::Make(); + base->NumElements(num_vectors) + ->Dim(dim) + ->Ids(ids.data()) + ->Float32Vectors(vectors.data()) + ->Owner(false); + + /******************* Create HNSW Index *****************/ + auto hnsw_build_paramesters = R"( + { + "dtype": "float32", + "metric_type": "l2", + "dim": 64, + "hnsw": { + "max_degree": 16, + "ef_construction": 100 + } + } + )"; + auto index = vsag::Factory::CreateIndex("hnsw", hnsw_build_paramesters).value(); + + /******************* Build HNSW Index *****************/ + if (auto build_result = index->Build(base); build_result.has_value()) { + std::cout << "After Build(), Index Hnsw contains: " << index->GetNumElements() << std::endl; + } else { + std::cerr << "Failed to build index: " << build_result.error().message << std::endl; + exit(-1); + } + + /******************* Update Vector in Index *****************/ + int64_t update_id = 9527; + std::vector new_vector(dim); + for (int64_t i = 0; i < dim; ++i) { + new_vector[i] = distrib_real(rng); + } + auto update_dataset = vsag::Dataset::Make(); + update_dataset->NumElements(1)->Dim(dim)->Ids(&update_id)->Float32Vectors(new_vector.data())->Owner(false); + + // try to update determines by the distance between the new vector and the old vector + if (auto update_vector = index->UpdateVector(update_id, update_dataset, false); + not update_vector.has_value()) { /* update returns an error */ + std::cerr << "update vector failed: " << update_vector.error().message << std::endl; + abort(); + } else if (*update_vector) { /* updated, new vector is near to the old vector */ + std::cout << "updated, new vector is near to the old vector" << std::endl; + } else { /* not update, new vector is far away from the old vector */ + std::cout << "not update, new vector is far away from the old vector" << std::endl; + + // not good to update in-place, choose to delete and insert + if (auto remove = index->Remove(update_id); not remove.has_value()) { /* remove returns an error */ + std::cerr << "delete vector failed: " << remove.error().message << std::endl; + abort(); + } else if (not *remove) { /* id not exists, should NOT happend in this example */ + std::cerr << "example error" << std::endl; + abort(); + } else { /* delete vector success */ + std::cout << "delete old vector" << std::endl; + if (auto add = index->Add(update_dataset); not add.has_value()) { /* add returns an error */ + std::cout << "insert vector failed: " << add.error().message << std::endl; + abort(); + } else if (not add->empty()) { /* not insert, id is already exist in index, shoud NOT happend in this example */ + std::cerr << "example error" << std::endl; + abort(); + } else { + std::cout << "insert new vector" << std::endl; + } + } + } + + /******************* Search and Print Results *****************/ + auto topk = 10; + auto query_vector = new float[dim]; + for (uint64_t i = 0; i < dim; ++i) { + query_vector[i] = distrib_real(rng); + } + auto query = vsag::Dataset::Make(); + query->NumElements(1)->Dim(dim)->Float32Vectors(query_vector)->Owner(false); + auto search_parameters = R"( + { + "hnsw": { + "ef_search": 100 + } + } + )"; + if (auto knn_search = index->KnnSearch(query, topk, search_parameters); + not knn_search.has_value()) { + std::cerr << "search knn failed: " << knn_search.error().message << std::endl; + abort(); + } else { + auto result = *knn_search; + for (int64_t i = 0; i < result->GetDim(); ++i) { + std::cout << result->GetIds()[i] << " " << result->GetDistances()[i] << std::endl; + } + } +} diff --git a/examples/cpp/todo_examples/CMakeLists.txt b/examples/cpp/todo_examples/CMakeLists.txt index f5d7656e..063eb7ba 100644 --- a/examples/cpp/todo_examples/CMakeLists.txt +++ b/examples/cpp/todo_examples/CMakeLists.txt @@ -28,8 +28,11 @@ target_link_libraries (301_feature_filter vsag_static) add_executable(302_feature_range_search 302_feature_range_search.cpp) target_link_libraries(302_feature_range_search vsag) +add_executable (303_feature_remove 303_feature_remove.cpp) +target_link_libraries (303_feature_remove vsag_static) + add_executable(304_feature_enhance_graph 304_feature_enhance_graph.cpp) target_link_libraries(304_feature_enhance_graph vsag) -add_executable (305_feature_remove 305_feature_remove.cpp) -target_link_libraries (305_feature_remove vsag_static) +add_executable(305_feature_update 305_feature_update.cpp) +target_link_libraries(305_feature_update vsag)