faiss 0.5.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -0
  3. data/README.md +2 -0
  4. data/ext/faiss/index.cpp +8 -0
  5. data/lib/faiss/version.rb +1 -1
  6. data/vendor/faiss/faiss/IVFlib.cpp +25 -49
  7. data/vendor/faiss/faiss/Index.cpp +11 -0
  8. data/vendor/faiss/faiss/Index.h +24 -1
  9. data/vendor/faiss/faiss/IndexAdditiveQuantizer.cpp +1 -0
  10. data/vendor/faiss/faiss/IndexBinaryHNSW.cpp +5 -1
  11. data/vendor/faiss/faiss/IndexFastScan.cpp +1 -1
  12. data/vendor/faiss/faiss/IndexFastScan.h +3 -8
  13. data/vendor/faiss/faiss/IndexFlat.cpp +374 -4
  14. data/vendor/faiss/faiss/IndexFlat.h +80 -0
  15. data/vendor/faiss/faiss/IndexHNSW.cpp +90 -1
  16. data/vendor/faiss/faiss/IndexHNSW.h +57 -1
  17. data/vendor/faiss/faiss/IndexIVFFlatPanorama.cpp +34 -149
  18. data/vendor/faiss/faiss/IndexIVFRaBitQ.cpp +86 -2
  19. data/vendor/faiss/faiss/IndexIVFRaBitQ.h +3 -1
  20. data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.cpp +293 -115
  21. data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.h +52 -16
  22. data/vendor/faiss/faiss/IndexPQ.cpp +4 -1
  23. data/vendor/faiss/faiss/IndexPreTransform.cpp +14 -0
  24. data/vendor/faiss/faiss/IndexPreTransform.h +9 -0
  25. data/vendor/faiss/faiss/IndexRaBitQ.cpp +96 -16
  26. data/vendor/faiss/faiss/IndexRaBitQ.h +5 -1
  27. data/vendor/faiss/faiss/IndexRaBitQFastScan.cpp +238 -93
  28. data/vendor/faiss/faiss/IndexRaBitQFastScan.h +35 -9
  29. data/vendor/faiss/faiss/IndexRefine.cpp +49 -0
  30. data/vendor/faiss/faiss/IndexRefine.h +17 -0
  31. data/vendor/faiss/faiss/clone_index.cpp +2 -0
  32. data/vendor/faiss/faiss/gpu/GpuClonerOptions.h +3 -1
  33. data/vendor/faiss/faiss/gpu/GpuIndexCagra.h +1 -1
  34. data/vendor/faiss/faiss/gpu/StandardGpuResources.cpp +1 -1
  35. data/vendor/faiss/faiss/impl/DistanceComputer.h +74 -3
  36. data/vendor/faiss/faiss/impl/HNSW.cpp +294 -15
  37. data/vendor/faiss/faiss/impl/HNSW.h +31 -2
  38. data/vendor/faiss/faiss/impl/IDSelector.h +3 -3
  39. data/vendor/faiss/faiss/impl/Panorama.cpp +193 -0
  40. data/vendor/faiss/faiss/impl/Panorama.h +204 -0
  41. data/vendor/faiss/faiss/impl/RaBitQStats.cpp +29 -0
  42. data/vendor/faiss/faiss/impl/RaBitQStats.h +56 -0
  43. data/vendor/faiss/faiss/impl/RaBitQUtils.cpp +54 -6
  44. data/vendor/faiss/faiss/impl/RaBitQUtils.h +183 -6
  45. data/vendor/faiss/faiss/impl/RaBitQuantizer.cpp +269 -84
  46. data/vendor/faiss/faiss/impl/RaBitQuantizer.h +71 -4
  47. data/vendor/faiss/faiss/impl/RaBitQuantizerMultiBit.cpp +362 -0
  48. data/vendor/faiss/faiss/impl/RaBitQuantizerMultiBit.h +112 -0
  49. data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +6 -9
  50. data/vendor/faiss/faiss/impl/ScalarQuantizer.h +1 -3
  51. data/vendor/faiss/faiss/impl/index_read.cpp +156 -12
  52. data/vendor/faiss/faiss/impl/index_write.cpp +142 -19
  53. data/vendor/faiss/faiss/impl/platform_macros.h +12 -0
  54. data/vendor/faiss/faiss/impl/svs_io.cpp +86 -0
  55. data/vendor/faiss/faiss/impl/svs_io.h +67 -0
  56. data/vendor/faiss/faiss/index_factory.cpp +182 -15
  57. data/vendor/faiss/faiss/invlists/BlockInvertedLists.h +1 -1
  58. data/vendor/faiss/faiss/invlists/DirectMap.cpp +1 -1
  59. data/vendor/faiss/faiss/invlists/InvertedLists.cpp +18 -109
  60. data/vendor/faiss/faiss/invlists/InvertedLists.h +2 -18
  61. data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +1 -1
  62. data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.h +1 -1
  63. data/vendor/faiss/faiss/svs/IndexSVSFaissUtils.h +261 -0
  64. data/vendor/faiss/faiss/svs/IndexSVSFlat.cpp +117 -0
  65. data/vendor/faiss/faiss/svs/IndexSVSFlat.h +66 -0
  66. data/vendor/faiss/faiss/svs/IndexSVSVamana.cpp +245 -0
  67. data/vendor/faiss/faiss/svs/IndexSVSVamana.h +137 -0
  68. data/vendor/faiss/faiss/svs/IndexSVSVamanaLVQ.cpp +39 -0
  69. data/vendor/faiss/faiss/svs/IndexSVSVamanaLVQ.h +42 -0
  70. data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.cpp +149 -0
  71. data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.h +58 -0
  72. data/vendor/faiss/faiss/utils/distances.cpp +0 -3
  73. data/vendor/faiss/faiss/utils/utils.cpp +4 -0
  74. metadata +18 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f3306dbb81c9168dcd82435c99d3404ab8501ac9b948adb2db7238ab89c01003
4
- data.tar.gz: b14a120e9cc67baba96816b52cf34388aae79fa690fc511918543921b64380d5
3
+ metadata.gz: 439ff96f613cd71e2a32197194d3814cf5ea516bd31489fdc2bd7a98747ec8ff
4
+ data.tar.gz: b2eaf07886acc74aaee4e6f1956a8c09f1d76da0ebaca14b6d4f3e889d728ef7
5
5
  SHA512:
6
- metadata.gz: b7af3f6540d283d886301137e5fed5dff32b0c0659e9c46d6c45808439e94a0a91f8c953d5897b480568169ec23cacc4224db523d6ab9b3737d7f0df1ce8190c
7
- data.tar.gz: fbe44473d9e3c61427aee597fed40264ba83a8184c0fe5280b6bf181d9bcc396583f033a69e8d3ec643ee0d41ef435dfeef4aa4441ade67703cbd8259326cb81
6
+ metadata.gz: 03d9a8aa01c86c176437adfab3038b91eb9b9991b2446f4b442114fac8e16133f213eec779d8bdedf80f13c643e96ec2ae39cfa9e1de4313148d53efa565d5c8
7
+ data.tar.gz: aa3ef7993a7411cbd480134e054528f069931c57ec55a8dd74c33642fa9debf203507f5744fa1ad178c04d142ac6efd482d63e6df1ced32e890fedd1def73769
data/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ ## 0.5.1 (2025-12-20)
2
+
3
+ - Updated Faiss to 1.13.2
4
+ - Added `reconstruct` method
5
+
1
6
  ## 0.5.0 (2025-11-12)
2
7
 
3
8
  - Updated Faiss to 1.13.0
data/README.md CHANGED
@@ -53,6 +53,8 @@ Search
53
53
  distances, ids = index.search(objects, 3)
54
54
  ```
55
55
 
56
+ > Use `index.freeze` to release the GVL for searches
57
+
56
58
  Save an index
57
59
 
58
60
  ```ruby
data/ext/faiss/index.cpp CHANGED
@@ -169,6 +169,14 @@ void init_index(Rice::Module& m) {
169
169
  auto &self = *Rice::Data_Object<faiss::Index>{rb_self};
170
170
  faiss::ParameterSpace().set_index_parameter(&self, "nprobe", val);
171
171
  })
172
+ .define_method(
173
+ "reconstruct",
174
+ [](faiss::Index &self, int64_t key) {
175
+ auto d = static_cast<std::size_t>(self.d);
176
+ auto recons = numo::SFloat({d});
177
+ self.reconstruct(key, recons.write_ptr());
178
+ return recons;
179
+ })
172
180
  .define_method(
173
181
  "save",
174
182
  [](faiss::Index &self, Rice::String fname) {
data/lib/faiss/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Faiss
2
- VERSION = "0.5.0"
2
+ VERSION = "0.5.1"
3
3
  end
@@ -558,19 +558,6 @@ void handle_ivf(
558
558
  const std::string& filename_template,
559
559
  ShardingFunction* sharding_function,
560
560
  bool generate_ids) {
561
- std::vector<faiss::IndexIVF*> sharded_indexes(shard_count);
562
- auto clone = static_cast<faiss::IndexIVF*>(faiss::clone_index(index));
563
- clone->quantizer->reset();
564
- for (int64_t i = 0; i < shard_count; i++) {
565
- sharded_indexes[i] =
566
- static_cast<faiss::IndexIVF*>(faiss::clone_index(clone));
567
- if (generate_ids) {
568
- // Assume the quantizer does not natively support add_with_ids.
569
- sharded_indexes[i]->quantizer =
570
- new IndexIDMap2(sharded_indexes[i]->quantizer);
571
- }
572
- }
573
-
574
561
  // assign centroids to each sharded Index based on sharding_function, and
575
562
  // add them to the quantizer of each sharded index
576
563
  std::vector<std::vector<float>> sharded_centroids(shard_count);
@@ -588,27 +575,29 @@ void handle_ivf(
588
575
  &reconstructed[index->quantizer->d]);
589
576
  delete[] reconstructed;
590
577
  }
578
+
579
+ auto clone = static_cast<faiss::IndexIVF*>(faiss::clone_index(index));
580
+ clone->quantizer->reset();
591
581
  for (int64_t i = 0; i < shard_count; i++) {
582
+ auto sharded_index =
583
+ static_cast<faiss::IndexIVF*>(faiss::clone_index(clone));
592
584
  if (generate_ids) {
593
- sharded_indexes[i]->quantizer->add_with_ids(
585
+ // Assume the quantizer does not natively support add_with_ids.
586
+ sharded_index->quantizer =
587
+ new IndexIDMap2(sharded_index->quantizer);
588
+ sharded_index->quantizer->add_with_ids(
594
589
  sharded_centroids[i].size() / index->quantizer->d,
595
590
  sharded_centroids[i].data(),
596
591
  xids[i].data());
597
592
  } else {
598
- sharded_indexes[i]->quantizer->add(
593
+ sharded_index->quantizer->add(
599
594
  sharded_centroids[i].size() / index->quantizer->d,
600
595
  sharded_centroids[i].data());
601
596
  }
602
- }
603
-
604
- for (int64_t i = 0; i < shard_count; i++) {
605
597
  char fname[256];
606
598
  snprintf(fname, 256, filename_template.c_str(), i);
607
- faiss::write_index(sharded_indexes[i], fname);
608
- }
609
-
610
- for (int64_t i = 0; i < shard_count; i++) {
611
- delete sharded_indexes[i];
599
+ faiss::write_index(sharded_index, fname);
600
+ delete sharded_index;
612
601
  }
613
602
  }
614
603
 
@@ -618,22 +607,6 @@ void handle_binary_ivf(
618
607
  const std::string& filename_template,
619
608
  ShardingFunction* sharding_function,
620
609
  bool generate_ids) {
621
- std::vector<faiss::IndexBinaryIVF*> sharded_indexes(shard_count);
622
-
623
- auto clone = static_cast<faiss::IndexBinaryIVF*>(
624
- faiss::clone_binary_index(index));
625
- clone->quantizer->reset();
626
-
627
- for (int64_t i = 0; i < shard_count; i++) {
628
- sharded_indexes[i] = static_cast<faiss::IndexBinaryIVF*>(
629
- faiss::clone_binary_index(clone));
630
- if (generate_ids) {
631
- // Assume the quantizer does not natively support add_with_ids.
632
- sharded_indexes[i]->quantizer =
633
- new IndexBinaryIDMap2(sharded_indexes[i]->quantizer);
634
- }
635
- }
636
-
637
610
  // assign centroids to each sharded Index based on sharding_function, and
638
611
  // add them to the quantizer of each sharded index
639
612
  int64_t reconstruction_size = index->quantizer->d / 8;
@@ -652,27 +625,30 @@ void handle_binary_ivf(
652
625
  &reconstructed[reconstruction_size]);
653
626
  delete[] reconstructed;
654
627
  }
628
+
629
+ auto clone = static_cast<faiss::IndexBinaryIVF*>(
630
+ faiss::clone_binary_index(index));
631
+ clone->quantizer->reset();
655
632
  for (int64_t i = 0; i < shard_count; i++) {
633
+ auto sharded_index = static_cast<faiss::IndexBinaryIVF*>(
634
+ faiss::clone_binary_index(clone));
656
635
  if (generate_ids) {
657
- sharded_indexes[i]->quantizer->add_with_ids(
636
+ // Assume the quantizer does not natively support add_with_ids.
637
+ sharded_index->quantizer =
638
+ new IndexBinaryIDMap2(sharded_index->quantizer);
639
+ sharded_index->quantizer->add_with_ids(
658
640
  sharded_centroids[i].size() / reconstruction_size,
659
641
  sharded_centroids[i].data(),
660
642
  xids[i].data());
661
643
  } else {
662
- sharded_indexes[i]->quantizer->add(
644
+ sharded_index->quantizer->add(
663
645
  sharded_centroids[i].size() / reconstruction_size,
664
646
  sharded_centroids[i].data());
665
647
  }
666
- }
667
-
668
- for (int64_t i = 0; i < shard_count; i++) {
669
648
  char fname[256];
670
649
  snprintf(fname, 256, filename_template.c_str(), i);
671
- faiss::write_index_binary(sharded_indexes[i], fname);
672
- }
673
-
674
- for (int64_t i = 0; i < shard_count; i++) {
675
- delete sharded_indexes[i];
650
+ faiss::write_index_binary(sharded_index, fname);
651
+ delete sharded_index;
676
652
  }
677
653
  }
678
654
 
@@ -104,6 +104,17 @@ void Index::search_and_reconstruct(
104
104
  }
105
105
  }
106
106
 
107
+ void Index::search_subset(
108
+ idx_t n,
109
+ const float* x,
110
+ idx_t k_base,
111
+ const idx_t* base_labels,
112
+ idx_t k,
113
+ float* distances,
114
+ idx_t* labels) const {
115
+ FAISS_THROW_MSG("search_subset not implemented for this type of index");
116
+ }
117
+
107
118
  void Index::compute_residual(const float* x, float* residual, idx_t key) const {
108
119
  reconstruct(key, residual);
109
120
  for (size_t i = 0; i < d; i++) {
@@ -18,7 +18,7 @@
18
18
 
19
19
  #define FAISS_VERSION_MAJOR 1
20
20
  #define FAISS_VERSION_MINOR 13
21
- #define FAISS_VERSION_PATCH 0
21
+ #define FAISS_VERSION_PATCH 2
22
22
 
23
23
  // Macro to combine the version components into a single string
24
24
  #ifndef FAISS_STRINGIFY
@@ -304,6 +304,29 @@ struct Index {
304
304
  float* recons,
305
305
  const SearchParameters* params = nullptr) const;
306
306
 
307
+ /** Similar to search, but operates on a potentially different subset
308
+ * of the dataset for each query.
309
+ *
310
+ * The default implementation fails with an assertion, as it is
311
+ * not supported by all indexes.
312
+ *
313
+ * @param n number of vectors
314
+ * @param x input vectors, size n * d
315
+ * @param k_base number of vectors to search from
316
+ * @param base_labels ids of the vectors to search from
317
+ * @param k desired number of results per query
318
+ * @param distances output pairwise distances, size n*k
319
+ * @param labels output labels of the NNs, size n*k
320
+ */
321
+ virtual void search_subset(
322
+ idx_t n,
323
+ const float* x,
324
+ idx_t k_base,
325
+ const idx_t* base_labels,
326
+ idx_t k,
327
+ float* distances,
328
+ idx_t* labels) const;
329
+
307
330
  /** Computes a residual vector after indexing encoding.
308
331
  *
309
332
  * The residual vector is the difference between a vector and the
@@ -86,6 +86,7 @@ struct AQDistanceComputerLUT : FlatCodesDistanceComputer {
86
86
 
87
87
  float bias;
88
88
  void set_query(const float* x) final {
89
+ q = x;
89
90
  // this is quite sub-optimal for multiple queries
90
91
  aq.compute_LUT(1, x, LUT.data());
91
92
  if (is_IP) {
@@ -227,7 +227,11 @@ void IndexBinaryHNSW::search(
227
227
  for (idx_t i = 0; i < n; i++) {
228
228
  res.begin(i);
229
229
  dis->set_query((float*)(x + i * code_size));
230
- hnsw.search(*dis, res, vt);
230
+ // Given that IndexBinaryHNSW is not an IndexHNSW, we pass nullptr
231
+ // as the index parameter. This state does not get used in the
232
+ // search function, as it is merely there to to enable Panorama
233
+ // execution for IndexHNSWFlatPanorama.
234
+ hnsw.search(*dis, nullptr, res, vt);
231
235
  res.end();
232
236
  }
233
237
  }
@@ -199,7 +199,7 @@ void estimators_from_tables_generic(
199
199
  } // anonymous namespace
200
200
 
201
201
  // Default implementation of make_knn_handler with centralized fallback logic
202
- void* IndexFastScan::make_knn_handler(
202
+ SIMDResultHandlerToFloat* IndexFastScan::make_knn_handler(
203
203
  bool is_max,
204
204
  int impl,
205
205
  idx_t n,
@@ -15,13 +15,8 @@ namespace faiss {
15
15
 
16
16
  struct CodePacker;
17
17
  struct NormTableScaler;
18
-
19
- // Forward declarations for result handlers
20
- namespace simd_result_handlers {
21
- template <class C, bool with_id_map>
22
- struct ResultHandlerCompare;
23
- }
24
18
  struct IDSelector;
19
+ struct SIMDResultHandlerToFloat;
25
20
 
26
21
  /** Fast scan version of IndexPQ and IndexAQ. Works for 4-bit PQ and AQ for now.
27
22
  *
@@ -141,10 +136,10 @@ struct IndexFastScan : Index {
141
136
  * @param distances output distances array
142
137
  * @param labels output labels array
143
138
  * @param sel optional ID selector
144
- * @param query_offset query offset for batch processing
139
+ * @param context processing context for distance post-processing
145
140
  * @return pointer to created handler (never returns nullptr)
146
141
  */
147
- virtual void* make_knn_handler(
142
+ virtual SIMDResultHandlerToFloat* make_knn_handler(
148
143
  bool is_max,
149
144
  int impl,
150
145
  idx_t n,