nidx-binding 6.9.0.post567__tar.gz → 6.9.0.post576__tar.gz

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 (263) hide show
  1. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/PKG-INFO +1 -1
  2. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_protos/pyproject.toml +1 -1
  3. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_vector/src/hnsw/ops_hnsw.rs +83 -34
  4. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_vector/src/hnsw/params.rs +6 -14
  5. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_vector/src/hnsw.rs +1 -4
  6. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_vector/src/segment.rs +32 -31
  7. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_vector/src/vector_types/rabitq.rs +42 -1
  8. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/pyproject.toml +1 -1
  9. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.config/nextest.toml +0 -0
  10. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-0cfce9b29547f8f5bafa6e440f86103be7b8c4ad2fd92db9ac223f4efbe23d10.json +0 -0
  11. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-1a561eed00f3dbe868bf5030059793300209179dc8fb73e4b57a54b5e81262fe.json +0 -0
  12. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-1d3fca2682e25a01143da92285297f134a6a105a96f64d87e0db3abb219855e4.json +0 -0
  13. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-249b3b57c27a71baa823f1fe0f0bba9c9af36f61c28f731e58beea60ec48e687.json +0 -0
  14. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-24cb6b683daa42d7125f862e25943ab4be7bf275cd8739f8da4859d701795e1a.json +0 -0
  15. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-263c8fce6db5b03bbd012fafdba6943cbee6ed7eb8976cdef4f5b01dde7ca6fd.json +0 -0
  16. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-2a5d92fb1638df830a4477a7cdf24e6db6b43034b7bbe74fdfb63e8afe2c4071.json +0 -0
  17. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-2b065a363f58caed60e3706603c1260dbf5a4c795604a5b68edda22eb07fec1b.json +0 -0
  18. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-3fc3cb39934683de8cd475ce1368c8373453eb1e01f81587d66b9d14b109ce6e.json +0 -0
  19. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-48f33b77b7c1633467b0b2efcaa1d3c207e7757e4f1d83b40d15e6ca365f7771.json +0 -0
  20. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-4ae09f2c08e2f324bee01bb8487a8f37678a1c5e9d327339235c50d4921a8949.json +0 -0
  21. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-4d7a76fa413c9ef0ce2a47ac7bb7e01d3e6a2aabded9487d21010a53efee8852.json +0 -0
  22. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-4fcbdd6657c7dc9b60b3a563dd41711b3dbcf72ce063427b7a01f8cddf34c244.json +0 -0
  23. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-577109ac00ccfbd38ecaccab94116f2f46a4caf5612afa372cded197123c1e08.json +0 -0
  24. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-5db25f97d8578d6d78f2f6bd4b72cc82a9b1b82805c6422d967ac63b20d99db4.json +0 -0
  25. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-5ec3233a3a23e926055056d46bdde17836a633066dbb5f349502648cd3ea9a60.json +0 -0
  26. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-66edb6ea424d8681927dcddb6bac5f1239175f4775d1f40417ba15054b0c6f19.json +0 -0
  27. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-6f9c6d201c1b5712efb68c363bffd3e0169c11f2a8f925e8cd4e8808599ff7b4.json +0 -0
  28. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-733c3ebacc86f444bf5e2dd79ade660c291e88a00fc09b722f6e2e191545874c.json +0 -0
  29. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-7a3bf27c330c468a596e8a297cf7d8b192e31e67ecc5177c1267f579e8e247c7.json +0 -0
  30. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-7a7e59e47b30b12237511fd3d7da2d17b0471ad2b006af48d6a6f587c779692b.json +0 -0
  31. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-7dcbb33312cc9f11ae3a6d73b1ace017a9f19a8bf8f10304fc57977c8efeadff.json +0 -0
  32. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-7efa7c0d747afc4b6aed0586ff846c27839c3213ff7ee9f30c89b0d0f17e60e3.json +0 -0
  33. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-8493140d788604d498a4e48da4158708572ccc9d60185290a00d549cc84533db.json +0 -0
  34. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-8493bb0059b013eaca42fd10cd7d04f0d06a8acaed379eff0d23f3229edde9ee.json +0 -0
  35. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-87996b3d6c7a2195438d7038015b06949102bce8c7b8cd8db1f83aaf23cbe489.json +0 -0
  36. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-8d33717587c6ee8f5fc339a80b1212a73d6c03e45856b1d55457fc8074709dd0.json +0 -0
  37. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-8f096d8171b89f9615d18f95d696dc9e4fb3674e103161a713cdc806f7a68506.json +0 -0
  38. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-917732a56ee04bf3a6e127319dda8225210869c82f9828d878162394dba4e078.json +0 -0
  39. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-95fe4ef93ee90733db1b67ed7987f80b5aac792f1590b979c68b418d1599eb98.json +0 -0
  40. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-9b67658569b343d8b4b61ae0a7dc721f367f2ba33c7b69b9e68bfd5c9bff5206.json +0 -0
  41. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-9c8062ea55d070afef68309e58fa987eb37fda44e1efbf68c8ba2af7846cc968.json +0 -0
  42. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-a06e1d9f6f95e4c4c2b98310ebddcc9d963cc033582bf2e945e8bf3a301b4247.json +0 -0
  43. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-a55265c9b07bd1399961a6f1e757201fd0eebe868ddaf96437111113d80fce92.json +0 -0
  44. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-a60ec2f66f1e7b84189e5b089f2087a29ff6a64326a3743dea935bbc58ee77fa.json +0 -0
  45. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-a891a37be5c2d7cce775c2dd33726b0318fd3839beab222a1b22bc6174604207.json +0 -0
  46. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-a945191bb4b3e37d6823ed3ad499339d007d69983105de8567777d9daf517b28.json +0 -0
  47. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-abe9f7832f2bd799ac44008da031e8d8ab52d4f5fbfc2a7e3974e8873bae55b2.json +0 -0
  48. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-aca588cca57a85e4d7fcc40c23cd87e57d53d11ca550d78e7e3d5e39e524fcd3.json +0 -0
  49. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-b02f8aafc00a7724510772ac41269e368c5bccf03ef7b4590e0ef6fd1a1bf64f.json +0 -0
  50. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-b742e17cabe2d64617e9aa64bafc782172f7a4f8023d1b54f952a0fb39f6b2b8.json +0 -0
  51. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-b94e349dbc0daec57f8f8f6e9e2dffb06100b1bb2b41d297c9f3b191da37a83d.json +0 -0
  52. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-bd9afa22994aba671dbf7b5f89b53c2ee02f53c0442a81265786a6d52d08512f.json +0 -0
  53. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-be60554eca98a5899efc6b49785cecd6444a6d39afed9e4a884ce2dbf162012c.json +0 -0
  54. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-bf49702b506c9a1650ece1f8e8d9f14834a902f8caefafe30ded55e2790f2188.json +0 -0
  55. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-bfcd21ed704cd305db5c17fcdec7d92aa4ac501913c9c9514d8ff92928c0c7e7.json +0 -0
  56. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-c3ab694650f49a75b146fb877a92e48c4f20f0d99f70f8ec859fbb763b01a1e5.json +0 -0
  57. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-c55542bb9fae544d87fae6f30e0fe8a9088d12075f4442ab4fe2fcd05e472234.json +0 -0
  58. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-cb29a6556d35ac630ee0aa885dd7341cf9573bd3efd216ff8a887b87686b03db.json +0 -0
  59. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-d0a1f341a89f5f14696b10baa72db9d95551c2b7e5fc67308fd52dc03dd98a92.json +0 -0
  60. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-d2ad0a0ca2649c9e4873cfcc1fc66d2d07cc45d0f65c560b06d7b5f592f4fa8a.json +0 -0
  61. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-d6cfe78eb635ba0b89ca4021a4dc8182d18ab5b197f30149cd28488eba4c1df5.json +0 -0
  62. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-d729b56dea00e49dcdba8cf0001e2811da27351eabe98212db3b589f18fc6f32.json +0 -0
  63. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-d9658bfd4e7170b41d03f2ddf2446d0bf54171c0d39d53bf20af2b8437f2ec48.json +0 -0
  64. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-dbba7b3d3289425bae711aedbf73fbc3699f857f86f84d95c3b556d05c5658b0.json +0 -0
  65. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-dcb96b649d6d63a58efd5d445453a4f3d7869a56ff714b69bedf3d616a0473ca.json +0 -0
  66. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-ebd876fbf5362a5900e75bc05f2f11c73c406ef7da4e95097fc6a1c3d1b8bc54.json +0 -0
  67. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-eef5cc6bce1cc14eba8f3e68971724ef181e88cffcedd74673615f2026b89a62.json +0 -0
  68. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/.sqlx/query-ef56d5fefc5774040d1ee397beadb475f6af02768c22f0e583c74062e2e821ce.json +0 -0
  69. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/Cargo.lock +0 -0
  70. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/Cargo.toml +0 -0
  71. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/README.md +0 -0
  72. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/migrations/20241007163501_initial.sql +0 -0
  73. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/migrations/20241211120039_merge_job_priority.sql +0 -0
  74. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/migrations/20241211121159_basic_indexes.sql +0 -0
  75. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/migrations/20241212151105_check_segment_records.sql +0 -0
  76. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/migrations/20250110145554_in_flight_messages.sql +0 -0
  77. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_binding/Cargo.toml +0 -0
  78. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_binding/src/lib.rs +0 -0
  79. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_paragraph/Cargo.toml +0 -0
  80. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_paragraph/src/fuzzy_query.rs +0 -0
  81. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_paragraph/src/lib.rs +0 -0
  82. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_paragraph/src/query_io.rs +0 -0
  83. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_paragraph/src/query_parser/fuzzy_parser.rs +0 -0
  84. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_paragraph/src/query_parser/keyword_parser.rs +0 -0
  85. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_paragraph/src/query_parser/stop_words.rs +0 -0
  86. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_paragraph/src/query_parser/tokenizer.rs +0 -0
  87. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_paragraph/src/query_parser.rs +0 -0
  88. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_paragraph/src/reader.rs +0 -0
  89. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_paragraph/src/request_types.rs +0 -0
  90. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_paragraph/src/resource_indexer.rs +0 -0
  91. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_paragraph/src/schema.rs +0 -0
  92. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_paragraph/src/search_query.rs +0 -0
  93. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_paragraph/src/search_response.rs +0 -0
  94. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_paragraph/src/set_query.rs +0 -0
  95. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_paragraph/stop_words/README.md +0 -0
  96. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_paragraph/stop_words/ar.json +0 -0
  97. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_paragraph/stop_words/az.json +0 -0
  98. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_paragraph/stop_words/bn.json +0 -0
  99. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_paragraph/stop_words/ca.json +0 -0
  100. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_paragraph/stop_words/ch.json +0 -0
  101. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_paragraph/stop_words/da.json +0 -0
  102. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_paragraph/stop_words/de.json +0 -0
  103. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_paragraph/stop_words/el.json +0 -0
  104. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_paragraph/stop_words/en.json +0 -0
  105. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_paragraph/stop_words/es.json +0 -0
  106. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_paragraph/stop_words/eu.json +0 -0
  107. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_paragraph/stop_words/extract.py +0 -0
  108. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_paragraph/stop_words/fi.json +0 -0
  109. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_paragraph/stop_words/fr.json +0 -0
  110. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_paragraph/stop_words/he.json +0 -0
  111. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_paragraph/stop_words/hu.json +0 -0
  112. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_paragraph/stop_words/id.json +0 -0
  113. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_paragraph/stop_words/it.json +0 -0
  114. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_paragraph/stop_words/kk.json +0 -0
  115. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_paragraph/stop_words/ne.json +0 -0
  116. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_paragraph/stop_words/nl.json +0 -0
  117. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_paragraph/stop_words/no.json +0 -0
  118. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_paragraph/stop_words/pt.json +0 -0
  119. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_paragraph/stop_words/ro.json +0 -0
  120. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_paragraph/stop_words/ru.json +0 -0
  121. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_paragraph/stop_words/sl.json +0 -0
  122. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_paragraph/stop_words/sv.json +0 -0
  123. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_paragraph/stop_words/tg.json +0 -0
  124. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_paragraph/stop_words/tr.json +0 -0
  125. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_paragraph/tests/common/mod.rs +0 -0
  126. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_paragraph/tests/reader.rs +0 -0
  127. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_protos/Cargo.toml +0 -0
  128. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_protos/build.py +0 -0
  129. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_protos/build.rs +0 -0
  130. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_protos/nidx.proto +0 -0
  131. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_protos/nodereader.proto +0 -0
  132. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_protos/noderesources.proto +0 -0
  133. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_protos/nodewriter.proto +0 -0
  134. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_protos/src/lib.rs +0 -0
  135. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_relation/Cargo.toml +0 -0
  136. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_relation/src/graph_collector.rs +0 -0
  137. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_relation/src/graph_query_parser.rs +0 -0
  138. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_relation/src/io_maps.rs +0 -0
  139. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_relation/src/lib.rs +0 -0
  140. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_relation/src/reader.rs +0 -0
  141. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_relation/src/resource_indexer.rs +0 -0
  142. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_relation/src/schema.rs +0 -0
  143. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_relation/src/top_unique_n.rs +0 -0
  144. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_relation/tests/common/mod.rs +0 -0
  145. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_relation/tests/test_graph_query_parser_search.rs +0 -0
  146. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_relation/tests/test_graph_search.rs +0 -0
  147. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_relation/tests/test_writer.rs +0 -0
  148. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_tantivy/Cargo.toml +0 -0
  149. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_tantivy/src/index_reader.rs +0 -0
  150. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_tantivy/src/lib.rs +0 -0
  151. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_tantivy/src/utils.rs +0 -0
  152. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_tests/Cargo.toml +0 -0
  153. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_tests/src/graph.rs +0 -0
  154. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_tests/src/lib.rs +0 -0
  155. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_text/Cargo.toml +0 -0
  156. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_text/src/lib.rs +0 -0
  157. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_text/src/prefilter.rs +0 -0
  158. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_text/src/query_io.rs +0 -0
  159. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_text/src/reader.rs +0 -0
  160. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_text/src/request_types.rs +0 -0
  161. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_text/src/resource_indexer.rs +0 -0
  162. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_text/src/schema.rs +0 -0
  163. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_text/src/search_query.rs +0 -0
  164. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_text/tests/common/mod.rs +0 -0
  165. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_text/tests/test_deletions.rs +0 -0
  166. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_text/tests/test_flow.rs +0 -0
  167. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_text/tests/test_search.rs +0 -0
  168. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_text/tests/test_streaming.rs +0 -0
  169. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_types/Cargo.toml +0 -0
  170. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_types/src/lib.rs +0 -0
  171. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_types/src/prefilter.rs +0 -0
  172. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_types/src/query_language.rs +0 -0
  173. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_vector/Cargo.toml +0 -0
  174. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_vector/src/config.rs +0 -0
  175. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_vector/src/data_store/v1/node.rs +0 -0
  176. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_vector/src/data_store/v1/store.rs +0 -0
  177. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_vector/src/data_store/v1/trie.rs +0 -0
  178. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_vector/src/data_store/v1/trie_ram.rs +0 -0
  179. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_vector/src/data_store/v1.rs +0 -0
  180. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_vector/src/data_store/v2/paragraph_store.rs +0 -0
  181. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_vector/src/data_store/v2/quant_vector_store.rs +0 -0
  182. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_vector/src/data_store/v2/vector_store.rs +0 -0
  183. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_vector/src/data_store/v2.rs +0 -0
  184. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_vector/src/data_store.rs +0 -0
  185. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_vector/src/data_types.rs +0 -0
  186. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_vector/src/formula.rs +0 -0
  187. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_vector/src/hnsw/disk_hnsw.rs +0 -0
  188. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_vector/src/hnsw/ram_hnsw.rs +0 -0
  189. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_vector/src/indexer.rs +0 -0
  190. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_vector/src/inverted_index/fst_index.rs +0 -0
  191. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_vector/src/inverted_index/map.rs +0 -0
  192. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_vector/src/inverted_index.rs +0 -0
  193. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_vector/src/lib.rs +0 -0
  194. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_vector/src/multivector.rs +0 -0
  195. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_vector/src/query_io.rs +0 -0
  196. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_vector/src/request_types.rs +0 -0
  197. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_vector/src/searcher.rs +0 -0
  198. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_vector/src/segment/tests.rs +0 -0
  199. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_vector/src/utils.rs +0 -0
  200. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_vector/src/vector_types/dense_f32.rs +0 -0
  201. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_vector/src/vector_types/mod.rs +0 -0
  202. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_vector/tests/common/mod.rs +0 -0
  203. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_vector/tests/test_basic_search.rs +0 -0
  204. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_vector/tests/test_hidden.rs +0 -0
  205. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/nidx_vector/tests/test_maxsim.rs +0 -0
  206. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/src/api/grpc.rs +0 -0
  207. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/src/api/shards.rs +0 -0
  208. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/src/api.rs +0 -0
  209. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/src/control.rs +0 -0
  210. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/src/errors.rs +0 -0
  211. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/src/grpc_server.rs +0 -0
  212. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/src/import_export.rs +0 -0
  213. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/src/indexer.rs +0 -0
  214. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/src/lib.rs +0 -0
  215. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/src/main.rs +0 -0
  216. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/src/metadata/deletion.rs +0 -0
  217. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/src/metadata/index.rs +0 -0
  218. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/src/metadata/index_request.rs +0 -0
  219. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/src/metadata/merge_job.rs +0 -0
  220. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/src/metadata/segment.rs +0 -0
  221. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/src/metadata/shard.rs +0 -0
  222. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/src/metadata.rs +0 -0
  223. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/src/metrics.rs +0 -0
  224. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/src/scheduler/audit_task.rs +0 -0
  225. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/src/scheduler/log_merge.rs +0 -0
  226. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/src/scheduler/merge_task.rs +0 -0
  227. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/src/scheduler/metrics_task.rs +0 -0
  228. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/src/scheduler/purge_tasks.rs +0 -0
  229. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/src/scheduler/vector_merge.rs +0 -0
  230. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/src/scheduler.rs +0 -0
  231. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/src/searcher/grpc.rs +0 -0
  232. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/src/searcher/index_cache.rs +0 -0
  233. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/src/searcher/query_language.rs +0 -0
  234. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/src/searcher/query_planner.rs +0 -0
  235. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/src/searcher/shard_search.rs +0 -0
  236. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/src/searcher/shard_selector.rs +0 -0
  237. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/src/searcher/shard_suggest.rs +0 -0
  238. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/src/searcher/streams.rs +0 -0
  239. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/src/searcher/sync.rs +0 -0
  240. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/src/searcher.rs +0 -0
  241. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/src/segment_store.rs +0 -0
  242. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/src/settings.rs +0 -0
  243. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/src/telemetry/duration_layer.rs +0 -0
  244. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/src/telemetry/log_format.rs +0 -0
  245. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/src/telemetry/middleware.rs +0 -0
  246. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/src/telemetry.rs +0 -0
  247. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/src/tool.rs +0 -0
  248. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/src/utilization_tracker.rs +0 -0
  249. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/src/worker.rs +0 -0
  250. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/tests/common/mod.rs +0 -0
  251. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/tests/common/services.rs +0 -0
  252. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/tests/test_date_range_search.rs +0 -0
  253. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/tests/test_search_filtering.rs +0 -0
  254. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/tests/test_search_relations.rs +0 -0
  255. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/tests/test_search_sorting.rs +0 -0
  256. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/tests/test_searcher_cluster.rs +0 -0
  257. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/tests/test_security_search.rs +0 -0
  258. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/tests/test_shards.rs +0 -0
  259. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/tests/test_shards_api.rs +0 -0
  260. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/tests/test_suggest.rs +0 -0
  261. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/tests/test_synced_searcher.rs +0 -0
  262. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/tests/test_vector_normalization.rs +0 -0
  263. {nidx_binding-6.9.0.post567 → nidx_binding-6.9.0.post576}/tests/test_vectorsets.rs +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nidx_binding
3
- Version: 6.9.0.post567
3
+ Version: 6.9.0.post576
4
4
  Classifier: Programming Language :: Rust
5
5
  Classifier: Programming Language :: Python :: Implementation :: CPython
6
6
  Classifier: Programming Language :: Python :: Implementation :: PyPy
@@ -10,7 +10,7 @@ build-backend = "pdm.backend"
10
10
 
11
11
  [project]
12
12
  name = "nidx_protos"
13
- version = "6.9.0.post567"
13
+ version = "6.9.0.post576"
14
14
  license = "AGPL-3.0-or-later"
15
15
  description = "Protobuf definitions for nucliadb/nidx"
16
16
  authors = [{ name = "Nuclia", email = "nucliadb@nuclia.com" }]
@@ -37,7 +37,7 @@ use super::*;
37
37
  /// Implementors of this trait can guide the hnsw search
38
38
  pub trait DataRetriever: std::marker::Sync {
39
39
  fn similarity(&self, x: VectorAddr, y: &SearchVector) -> f32;
40
- fn similarity_upper_bound(&self, x: VectorAddr, y: &SearchVector) -> f32;
40
+ fn similarity_upper_bound(&self, x: VectorAddr, y: &SearchVector) -> EstimatedScore;
41
41
  fn paragraph(&self, x: VectorAddr) -> ParagraphAddr;
42
42
  fn get_vector(&self, x: VectorAddr) -> &[u8];
43
43
  /// Embeddings with smaller similarity should not be considered.
@@ -67,6 +67,28 @@ pub trait Hnsw {
67
67
  fn get_layer(&self, i: usize) -> Self::L;
68
68
  }
69
69
 
70
+ #[derive(Clone, Copy)]
71
+ pub struct EstimatedScore {
72
+ pub score: f32,
73
+ pub upper_bound: f32,
74
+ }
75
+
76
+ impl EstimatedScore {
77
+ pub fn new_with_error(score: f32, error: f32) -> Self {
78
+ Self {
79
+ score,
80
+ upper_bound: score + error,
81
+ }
82
+ }
83
+
84
+ pub fn new_exact(score: f32) -> Self {
85
+ Self {
86
+ score,
87
+ upper_bound: score,
88
+ }
89
+ }
90
+ }
91
+
70
92
  /// Tuples ([`VectorAddr`], [`f32`]) can not be stored in a [`BinaryHeap`] because [`f32`] does not
71
93
  /// implement [`Ord`]. [`Cnx`] is an application of the new-type pattern that lets us bypass the
72
94
  /// orphan rules and store such tuples in a [`BinaryHeap`].
@@ -89,6 +111,25 @@ impl PartialOrd for Cnx {
89
111
  }
90
112
  }
91
113
 
114
+ #[derive(Clone, Copy)]
115
+ pub struct CnxWithBound(VectorAddr, EstimatedScore);
116
+ impl Eq for CnxWithBound {}
117
+ impl Ord for CnxWithBound {
118
+ fn cmp(&self, other: &Self) -> Ordering {
119
+ f32::total_cmp(&self.1.score, &other.1.score)
120
+ }
121
+ }
122
+ impl PartialEq for CnxWithBound {
123
+ fn eq(&self, other: &Self) -> bool {
124
+ f32::eq(&self.1.score, &other.1.score)
125
+ }
126
+ }
127
+ impl PartialOrd for CnxWithBound {
128
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
129
+ Some(self.cmp(other))
130
+ }
131
+ }
132
+
92
133
  /// A list of neighbours containing a pointer to the embedding and their similarity.
93
134
  pub type Neighbours = Vec<(VectorAddr, f32)>;
94
135
 
@@ -243,7 +284,7 @@ impl<'a, DR: DataRetriever> HnswOps<'a, DR> {
243
284
  layer: L,
244
285
  k_neighbours: usize,
245
286
  entry_points: &[VectorAddr],
246
- ) -> Neighbours {
287
+ ) -> impl Iterator<Item = (VectorAddr, EstimatedScore)> {
247
288
  // Nodes already visited
248
289
  let mut visited = FxHashSet::default();
249
290
  // Nodes to visit
@@ -254,9 +295,9 @@ impl<'a, DR: DataRetriever> HnswOps<'a, DR> {
254
295
  // The initial candidates are the entry points
255
296
  for ep in entry_points.iter().copied() {
256
297
  visited.insert(ep);
257
- let similarity = self.retriever.similarity(ep, query);
258
- candidates.push(Cnx(ep, similarity));
259
- ms_neighbours.push(Reverse(Cnx(ep, similarity)));
298
+ let similarity = self.retriever.similarity_upper_bound(ep, query);
299
+ candidates.push(CnxWithBound(ep, similarity));
300
+ ms_neighbours.push(Reverse(CnxWithBound(ep, similarity)));
260
301
  }
261
302
 
262
303
  loop {
@@ -264,9 +305,14 @@ impl<'a, DR: DataRetriever> HnswOps<'a, DR> {
264
305
  // No more candidates, done
265
306
  (None, _) => break,
266
307
  // Candidate is worse than worse result, done
267
- (Some(Cnx(_, cs)), Some(Reverse(Cnx(_, ws)))) if cs < ws => break,
308
+ (
309
+ Some(CnxWithBound(_, EstimatedScore { score: cs, .. })),
310
+ Some(Reverse(CnxWithBound(_, EstimatedScore { score: ws, .. }))),
311
+ ) if cs < ws => {
312
+ break;
313
+ }
268
314
  // Candidate is better than worse result
269
- (Some(Cnx(cn, _)), Some(Reverse(Cnx(_, mut ws)))) => {
315
+ (Some(CnxWithBound(cn, _)), Some(Reverse(CnxWithBound(_, mut ws)))) => {
270
316
  for (y, _) in layer.get_out_edges(cn) {
271
317
  if self.preload_nodes && !visited.contains(&y) {
272
318
  self.retriever.will_need_vector(y);
@@ -275,10 +321,10 @@ impl<'a, DR: DataRetriever> HnswOps<'a, DR> {
275
321
  for (y, _) in layer.get_out_edges(cn) {
276
322
  if !visited.contains(&y) {
277
323
  visited.insert(y);
278
- let similarity = self.retriever.similarity(y, query);
279
- if similarity > ws || ms_neighbours.len() < k_neighbours {
280
- candidates.push(Cnx(y, similarity));
281
- ms_neighbours.push(Reverse(Cnx(y, similarity)));
324
+ let similarity = self.retriever.similarity_upper_bound(y, query);
325
+ if similarity.score > ws.score || ms_neighbours.len() < k_neighbours {
326
+ candidates.push(CnxWithBound(y, similarity));
327
+ ms_neighbours.push(Reverse(CnxWithBound(y, similarity)));
282
328
  if ms_neighbours.len() > k_neighbours {
283
329
  ms_neighbours.pop();
284
330
  }
@@ -290,11 +336,7 @@ impl<'a, DR: DataRetriever> HnswOps<'a, DR> {
290
336
  _ => (),
291
337
  }
292
338
  }
293
- ms_neighbours
294
- .into_sorted_vec()
295
- .into_iter()
296
- .map(|Reverse(Cnx(n, d))| (n, d))
297
- .collect()
339
+ ms_neighbours.into_iter().map(|Reverse(CnxWithBound(n, d))| (n, d))
298
340
  }
299
341
 
300
342
  fn layer_insert(
@@ -305,9 +347,11 @@ impl<'a, DR: DataRetriever> HnswOps<'a, DR> {
305
347
  mmax: usize,
306
348
  ) -> Vec<VectorAddr> {
307
349
  use params::*;
308
- let neighbours =
309
- self.layer_search::<&RAMLayer>(&SearchVector::Stored(x), layer, ef_construction(), entry_points);
310
- let neighbours = self.select_neighbours_heuristic(m(), neighbours, layer);
350
+ let search_neighbours = self
351
+ .layer_search::<&RAMLayer>(&SearchVector::Stored(x), layer, EF_CONSTRUCTION, entry_points)
352
+ .map(|(addr, score)| (addr, score.score))
353
+ .collect();
354
+ let neighbours = self.select_neighbours_heuristic(M, search_neighbours, layer);
311
355
  let mut needs_repair = HashSet::new();
312
356
  let mut result = Vec::with_capacity(neighbours.len());
313
357
  layer.add_node(x);
@@ -343,7 +387,11 @@ impl<'a, DR: DataRetriever> HnswOps<'a, DR> {
343
387
  for l in (0..=top_layer).rev() {
344
388
  if l > level {
345
389
  // Above insertion point, just search
346
- eps[0] = self.layer_search(&SearchVector::Stored(x), &hnsw.layers[l], 1, &eps)[0].0;
390
+ let new_ep = self
391
+ .layer_search(&SearchVector::Stored(x), &hnsw.layers[l], 1, &eps)
392
+ .next()
393
+ .unwrap();
394
+ eps[0] = new_ep.0;
347
395
  } else {
348
396
  eps = self.layer_insert(x, &mut hnsw.layers[l], &eps, params::m_max_for_layer(l));
349
397
  }
@@ -370,13 +418,13 @@ impl<'a, DR: DataRetriever> HnswOps<'a, DR> {
370
418
  };
371
419
 
372
420
  let mut crnt_layer = entry_point.layer;
373
- let mut neighbours = vec![(entry_point.node, 0.)];
421
+ let mut entry_points = vec![entry_point.node];
374
422
 
423
+ // Traverse upper layer finding the best match on each one
375
424
  while crnt_layer != 0 {
376
425
  let layer = hnsw.get_layer(crnt_layer);
377
- let entry_points: Vec<_> = neighbours.into_iter().map(|(node, _)| node).collect();
378
426
  let layer_res = self.layer_search(query, layer, 1, &entry_points);
379
- neighbours = layer_res;
427
+ entry_points = layer_res.map(|(addr, _)| addr).collect();
380
428
  crnt_layer -= 1;
381
429
  }
382
430
 
@@ -387,23 +435,24 @@ impl<'a, DR: DataRetriever> HnswOps<'a, DR> {
387
435
  None
388
436
  };
389
437
  let last_layer_k = if original_query.is_some() {
390
- std::cmp::min(k_neighbours * 100, 2000)
438
+ std::cmp::min(k_neighbours * rabitq::RERANKING_FACTOR, rabitq::RERANKING_LIMIT)
391
439
  } else {
392
440
  k_neighbours
393
441
  };
394
442
 
395
- let entry_points: Vec<_> = neighbours.into_iter().map(|(node, _)| node).collect();
443
+ // Find the best k nodes in the last layer
396
444
  let layer = hnsw.get_layer(crnt_layer);
397
- let mut neighbors = self.layer_search(query, layer, last_layer_k, &entry_points);
445
+ let neighbours = self.layer_search(query, layer, last_layer_k, &entry_points);
398
446
 
399
- // If using RabitQ, rerank using the original vectors
400
- if let Some(query) = original_query {
401
- neighbors = neighbors
447
+ let entry_points = if let Some(query) = original_query {
448
+ // If using RabitQ, rerank using the original vectors
449
+ rabitq::rerank_top(neighbours.collect(), k_neighbours, self.retriever, query)
402
450
  .into_iter()
403
- .map(|(addr, _)| (addr, self.retriever.similarity(addr, query)))
404
- .collect();
405
- neighbors.sort_unstable_by(|x, y| y.1.partial_cmp(&x.1).unwrap_or(Ordering::Equal));
406
- }
451
+ .map(|Reverse(Cnx(addr, _))| addr)
452
+ .collect()
453
+ } else {
454
+ neighbours.map(|(addr, _)| addr).collect()
455
+ };
407
456
 
408
457
  let filter = NodeFilter {
409
458
  filter: with_filter,
@@ -412,8 +461,8 @@ impl<'a, DR: DataRetriever> HnswOps<'a, DR> {
412
461
  vec_counter: RepCounter::new(!with_duplicates),
413
462
  };
414
463
  let layer_zero = hnsw.get_layer(0);
415
- let entry_points: Vec<_> = neighbors.into_iter().take(k_neighbours).map(|(node, _)| node).collect();
416
464
 
465
+ // Find k nodes that match the filter in the last layer
417
466
  let mut filtered_result = self.closest_up_nodes(
418
467
  entry_points,
419
468
  original_query.unwrap_or(query),
@@ -23,11 +23,11 @@
23
23
 
24
24
  /// Factor by which the layer distribution should deviate.
25
25
  pub fn level_factor() -> f64 {
26
- 1.0 / (m() as f64).ln()
26
+ 1.0 / (M as f64).ln()
27
27
  }
28
28
 
29
29
  pub const fn m_max_for_layer(layer: usize) -> usize {
30
- if layer == 0 { m_max0() } else { m_max() }
30
+ if layer == 0 { M_MAX_0 } else { M_MAX }
31
31
  }
32
32
 
33
33
  /// M to use when pruning neighbours
@@ -36,21 +36,13 @@ pub const fn prune_m(m: usize) -> usize {
36
36
  }
37
37
 
38
38
  /// Upper limit to the number of out-edges a embedding can have.
39
- pub const fn m_max0() -> usize {
40
- 60
41
- }
39
+ pub const M_MAX_0: usize = 60;
42
40
 
43
41
  /// Upper limit to the number of out-edges a embedding can have.
44
- pub const fn m_max() -> usize {
45
- 30
46
- }
42
+ pub const M_MAX: usize = 30;
47
43
 
48
44
  /// Number of bi-directional links created for every new element.
49
- pub const fn m() -> usize {
50
- 30
51
- }
45
+ pub const M: usize = 30;
52
46
 
53
47
  /// Number of neighbours that are searched for before adding a new embedding.
54
- pub const fn ef_construction() -> usize {
55
- 100
56
- }
48
+ pub const EF_CONSTRUCTION: usize = 100;
@@ -24,8 +24,5 @@ mod params;
24
24
  mod ram_hnsw;
25
25
 
26
26
  pub use disk_hnsw::DiskHnsw;
27
- pub use ops_hnsw::Cnx;
28
- pub use ops_hnsw::DataRetriever;
29
- pub use ops_hnsw::HnswOps;
30
- pub use ops_hnsw::SearchVector;
27
+ pub use ops_hnsw::{Cnx, DataRetriever, EstimatedScore, HnswOps, SearchVector};
31
28
  pub use ram_hnsw::RAMHnsw;
@@ -352,14 +352,14 @@ impl<DS: DataStore> DataRetriever for Retriever<'_, DS> {
352
352
  }
353
353
  }
354
354
 
355
- fn similarity_upper_bound(&self, x: VectorAddr, y: &SearchVector) -> f32 {
355
+ fn similarity_upper_bound(&self, x: VectorAddr, y: &SearchVector) -> EstimatedScore {
356
356
  match y {
357
357
  SearchVector::RabitQ(query) => {
358
358
  let x = self.data_store.get_quantized_vector(x);
359
359
  let (est, err) = query.similarity(x);
360
- est + err
360
+ EstimatedScore::new_with_error(est, err)
361
361
  }
362
- _ => self.similarity(x, y),
362
+ _ => EstimatedScore::new_exact(self.similarity(x, y)),
363
363
  }
364
364
  }
365
365
 
@@ -492,16 +492,16 @@ impl OpenSegment {
492
492
  }
493
493
 
494
494
  #[allow(clippy::too_many_arguments)]
495
- fn _search<DS: DataStore>(
496
- &self,
497
- data_store: &DS,
495
+ fn _search<'a, DS: DataStore>(
496
+ &'a self,
497
+ data_store: &'a DS,
498
498
  query: &[f32],
499
499
  filter: &Formula,
500
500
  with_duplicates: bool,
501
501
  results: usize,
502
502
  config: &VectorConfig,
503
503
  min_score: f32,
504
- ) -> Box<dyn Iterator<Item = ScoredVector<'_>> + '_> {
504
+ ) -> Box<dyn Iterator<Item = ScoredVector<'a>> + '_> {
505
505
  let raw_query = SearchVector::Query(config.vector_type.encode(query));
506
506
  let rabitq = data_store.has_quantized() && !config.flags.contains(&flags::DISABLE_RABITQ_SEARCH.to_string());
507
507
  let encoded_query = if rabitq {
@@ -539,49 +539,50 @@ impl OpenSegment {
539
539
  }
540
540
  }
541
541
 
542
- fn brute_force_search<DS: DataStore>(
543
- &self,
542
+ fn brute_force_search<'a, DS: DataStore>(
543
+ &'a self,
544
544
  bitset: &FilterBitSet,
545
545
  results: usize,
546
- retriever: Retriever<DS>,
546
+ retriever: Retriever<'a, DS>,
547
547
  encoded_query: &SearchVector,
548
548
  raw_query: &SearchVector,
549
- ) -> Box<dyn Iterator<Item = ScoredVector<'_>> + '_> {
549
+ ) -> Box<dyn Iterator<Item = ScoredVector<'a>> + '_> {
550
550
  let mut scored_results = Vec::new();
551
551
  for paragraph_addr in bitset.iter() {
552
552
  let paragraph = retriever.data_store.get_paragraph(paragraph_addr);
553
553
 
554
- // Only return the best vector match per paragraph
554
+ // Only return the best vector match per paragraph (only relevant with multi-vectors)
555
555
  let best_vector_score = paragraph
556
556
  .vectors(&paragraph_addr)
557
557
  .map(|va| {
558
558
  let score = retriever.similarity_upper_bound(va, encoded_query);
559
- Cnx(va, score)
559
+ (va, score)
560
560
  })
561
- .max_by(|v, w| v.1.total_cmp(&w.1))
561
+ .max_by(|v, w| v.1.score.total_cmp(&w.1.score))
562
562
  .unwrap();
563
563
 
564
- if best_vector_score.1 >= retriever.min_score {
565
- scored_results.push(Reverse(best_vector_score));
564
+ if best_vector_score.1.upper_bound >= retriever.min_score {
565
+ scored_results.push(best_vector_score);
566
566
  }
567
567
  }
568
- scored_results.sort_unstable();
569
- // If using RabitQ, rerank top results using the raw vectors
568
+
570
569
  if matches!(encoded_query, SearchVector::RabitQ(_)) {
571
- scored_results = scored_results
572
- .into_iter()
573
- .take(std::cmp::min(results * 100, 2000))
574
- .map(|Reverse(Cnx(addr, _))| Reverse(Cnx(addr, retriever.similarity(addr, raw_query))))
575
- .collect();
576
- scored_results.sort_unstable();
570
+ // If using RabitQ, rerank top results using the raw vectors
571
+ Box::new(
572
+ rabitq::rerank_top(scored_results, results, &retriever, raw_query)
573
+ .into_iter()
574
+ .map(|Reverse(Cnx(addr, score))| ScoredVector::new(addr, self.data_store.as_ref(), score)),
575
+ )
576
+ } else {
577
+ // If using raw vectors, sort by score and take top_k
578
+ scored_results.sort_unstable_by(|a, b| b.1.score.total_cmp(&a.1.score));
579
+ Box::new(
580
+ scored_results
581
+ .into_iter()
582
+ .map(|a| ScoredVector::new(a.0, self.data_store.as_ref(), a.1.score))
583
+ .take(results),
584
+ )
577
585
  }
578
-
579
- Box::new(
580
- scored_results
581
- .into_iter()
582
- .map(|Reverse(a)| ScoredVector::new(a.0, self.data_store.as_ref(), a.1))
583
- .take(results),
584
- )
585
586
  }
586
587
  }
587
588
 
@@ -18,12 +18,28 @@
18
18
  // along with this program. If not, see <http://www.gnu.org/licenses/>.
19
19
  //
20
20
 
21
+ use std::{cmp::Reverse, collections::BinaryHeap};
22
+
21
23
  use simsimd::SpatialSimilarity;
22
24
 
23
- use crate::config::VectorType;
25
+ use crate::{
26
+ VectorAddr,
27
+ config::VectorType,
28
+ hnsw::{Cnx, DataRetriever, EstimatedScore, SearchVector},
29
+ };
24
30
 
31
+ /// Constant to adjust the error bound of the estimated similarity.
32
+ // The paper recommends 1.9, reasonable values are from 0.0 to 4.0
33
+ // Higher numbers give more error bound so we need to load more raw
34
+ // vectors but provide slightly better recall.
25
35
  const EPSILON: f32 = 1.9;
26
36
 
37
+ /// How many vectors to evaluate per each expected result.
38
+ /// This is multiplied by top_k to get the number of vectors to search for.
39
+ pub const RERANKING_FACTOR: usize = 100;
40
+ /// The maximum number of vectors to evaluate during reranking.
41
+ pub const RERANKING_LIMIT: usize = 2000;
42
+
27
43
  pub struct EncodedVector<'a> {
28
44
  data: &'a [u8],
29
45
  }
@@ -207,6 +223,31 @@ impl QueryVector {
207
223
  }
208
224
  }
209
225
 
226
+ /// Rerank results from RabitQ search using the raw vectors. Uses the error bound to know when to stop reranking
227
+ pub fn rerank_top(
228
+ candidates: Vec<(VectorAddr, EstimatedScore)>,
229
+ top_k: usize,
230
+ retriever: &impl DataRetriever,
231
+ query: &SearchVector,
232
+ ) -> BinaryHeap<Reverse<Cnx>> {
233
+ let mut best = BinaryHeap::new();
234
+ let mut best_k = 0.0;
235
+ for (addr, EstimatedScore { upper_bound, .. }) in candidates {
236
+ if best.len() < top_k || best_k < upper_bound {
237
+ // If the candidate score could be better than what we have so far, calculate the accurate similarity
238
+ let real_score = retriever.similarity(addr, query);
239
+ if best.len() < top_k || best_k < real_score {
240
+ best.push(Reverse(Cnx(addr, real_score)));
241
+ if best.len() > top_k {
242
+ best.pop();
243
+ }
244
+ best_k = best.peek().unwrap().0.1;
245
+ }
246
+ }
247
+ }
248
+ best
249
+ }
250
+
210
251
  #[cfg(test)]
211
252
  mod tests {
212
253
  use rand::{Rng, SeedableRng, rngs::SmallRng};
@@ -13,7 +13,7 @@ classifiers = [
13
13
  "Programming Language :: Python :: Implementation :: CPython",
14
14
  "Programming Language :: Python :: Implementation :: PyPy",
15
15
  ]
16
- version = "6.9.0.post567"
16
+ version = "6.9.0.post576"
17
17
 
18
18
  [project.urls]
19
19
  Homepage = "https://nuclia.com"