nidx-binding 6.9.2.post622__tar.gz → 6.9.3.post624__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.

Potentially problematic release.


This version of nidx-binding might be problematic. Click here for more details.

Files changed (265) hide show
  1. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/PKG-INFO +1 -1
  2. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_protos/pyproject.toml +1 -1
  3. nidx_binding-6.9.3.post624/nidx_vector/src/hnsw/build.rs +172 -0
  4. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_vector/src/hnsw/disk_hnsw.rs +62 -52
  5. nidx_binding-6.9.3.post624/nidx_vector/src/hnsw/ram_hnsw.rs +178 -0
  6. nidx_binding-6.9.2.post622/nidx_vector/src/hnsw/ops_hnsw.rs → nidx_binding-6.9.3.post624/nidx_vector/src/hnsw/search.rs +18 -142
  7. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_vector/src/hnsw.rs +4 -2
  8. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_vector/src/segment/tests.rs +1 -1
  9. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_vector/src/segment.rs +14 -9
  10. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/pyproject.toml +1 -1
  11. nidx_binding-6.9.2.post622/nidx_vector/src/hnsw/ram_hnsw.rs +0 -128
  12. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.config/nextest.toml +0 -0
  13. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-0cfce9b29547f8f5bafa6e440f86103be7b8c4ad2fd92db9ac223f4efbe23d10.json +0 -0
  14. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-1a561eed00f3dbe868bf5030059793300209179dc8fb73e4b57a54b5e81262fe.json +0 -0
  15. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-1d3fca2682e25a01143da92285297f134a6a105a96f64d87e0db3abb219855e4.json +0 -0
  16. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-249b3b57c27a71baa823f1fe0f0bba9c9af36f61c28f731e58beea60ec48e687.json +0 -0
  17. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-24cb6b683daa42d7125f862e25943ab4be7bf275cd8739f8da4859d701795e1a.json +0 -0
  18. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-263c8fce6db5b03bbd012fafdba6943cbee6ed7eb8976cdef4f5b01dde7ca6fd.json +0 -0
  19. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-2a5d92fb1638df830a4477a7cdf24e6db6b43034b7bbe74fdfb63e8afe2c4071.json +0 -0
  20. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-2b065a363f58caed60e3706603c1260dbf5a4c795604a5b68edda22eb07fec1b.json +0 -0
  21. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-3fc3cb39934683de8cd475ce1368c8373453eb1e01f81587d66b9d14b109ce6e.json +0 -0
  22. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-48f33b77b7c1633467b0b2efcaa1d3c207e7757e4f1d83b40d15e6ca365f7771.json +0 -0
  23. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-4ae09f2c08e2f324bee01bb8487a8f37678a1c5e9d327339235c50d4921a8949.json +0 -0
  24. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-4d7a76fa413c9ef0ce2a47ac7bb7e01d3e6a2aabded9487d21010a53efee8852.json +0 -0
  25. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-4fcbdd6657c7dc9b60b3a563dd41711b3dbcf72ce063427b7a01f8cddf34c244.json +0 -0
  26. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-577109ac00ccfbd38ecaccab94116f2f46a4caf5612afa372cded197123c1e08.json +0 -0
  27. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-5db25f97d8578d6d78f2f6bd4b72cc82a9b1b82805c6422d967ac63b20d99db4.json +0 -0
  28. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-5ec3233a3a23e926055056d46bdde17836a633066dbb5f349502648cd3ea9a60.json +0 -0
  29. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-66edb6ea424d8681927dcddb6bac5f1239175f4775d1f40417ba15054b0c6f19.json +0 -0
  30. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-6f9c6d201c1b5712efb68c363bffd3e0169c11f2a8f925e8cd4e8808599ff7b4.json +0 -0
  31. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-733c3ebacc86f444bf5e2dd79ade660c291e88a00fc09b722f6e2e191545874c.json +0 -0
  32. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-7a3bf27c330c468a596e8a297cf7d8b192e31e67ecc5177c1267f579e8e247c7.json +0 -0
  33. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-7a7e59e47b30b12237511fd3d7da2d17b0471ad2b006af48d6a6f587c779692b.json +0 -0
  34. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-7dcbb33312cc9f11ae3a6d73b1ace017a9f19a8bf8f10304fc57977c8efeadff.json +0 -0
  35. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-7efa7c0d747afc4b6aed0586ff846c27839c3213ff7ee9f30c89b0d0f17e60e3.json +0 -0
  36. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-8493140d788604d498a4e48da4158708572ccc9d60185290a00d549cc84533db.json +0 -0
  37. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-8493bb0059b013eaca42fd10cd7d04f0d06a8acaed379eff0d23f3229edde9ee.json +0 -0
  38. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-87996b3d6c7a2195438d7038015b06949102bce8c7b8cd8db1f83aaf23cbe489.json +0 -0
  39. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-8d33717587c6ee8f5fc339a80b1212a73d6c03e45856b1d55457fc8074709dd0.json +0 -0
  40. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-8f096d8171b89f9615d18f95d696dc9e4fb3674e103161a713cdc806f7a68506.json +0 -0
  41. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-917732a56ee04bf3a6e127319dda8225210869c82f9828d878162394dba4e078.json +0 -0
  42. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-95fe4ef93ee90733db1b67ed7987f80b5aac792f1590b979c68b418d1599eb98.json +0 -0
  43. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-9b67658569b343d8b4b61ae0a7dc721f367f2ba33c7b69b9e68bfd5c9bff5206.json +0 -0
  44. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-9c8062ea55d070afef68309e58fa987eb37fda44e1efbf68c8ba2af7846cc968.json +0 -0
  45. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-a06e1d9f6f95e4c4c2b98310ebddcc9d963cc033582bf2e945e8bf3a301b4247.json +0 -0
  46. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-a55265c9b07bd1399961a6f1e757201fd0eebe868ddaf96437111113d80fce92.json +0 -0
  47. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-a60ec2f66f1e7b84189e5b089f2087a29ff6a64326a3743dea935bbc58ee77fa.json +0 -0
  48. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-a891a37be5c2d7cce775c2dd33726b0318fd3839beab222a1b22bc6174604207.json +0 -0
  49. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-a945191bb4b3e37d6823ed3ad499339d007d69983105de8567777d9daf517b28.json +0 -0
  50. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-abe9f7832f2bd799ac44008da031e8d8ab52d4f5fbfc2a7e3974e8873bae55b2.json +0 -0
  51. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-aca588cca57a85e4d7fcc40c23cd87e57d53d11ca550d78e7e3d5e39e524fcd3.json +0 -0
  52. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-b02f8aafc00a7724510772ac41269e368c5bccf03ef7b4590e0ef6fd1a1bf64f.json +0 -0
  53. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-b742e17cabe2d64617e9aa64bafc782172f7a4f8023d1b54f952a0fb39f6b2b8.json +0 -0
  54. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-b94e349dbc0daec57f8f8f6e9e2dffb06100b1bb2b41d297c9f3b191da37a83d.json +0 -0
  55. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-bd9afa22994aba671dbf7b5f89b53c2ee02f53c0442a81265786a6d52d08512f.json +0 -0
  56. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-be60554eca98a5899efc6b49785cecd6444a6d39afed9e4a884ce2dbf162012c.json +0 -0
  57. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-bf49702b506c9a1650ece1f8e8d9f14834a902f8caefafe30ded55e2790f2188.json +0 -0
  58. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-bfcd21ed704cd305db5c17fcdec7d92aa4ac501913c9c9514d8ff92928c0c7e7.json +0 -0
  59. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-c3ab694650f49a75b146fb877a92e48c4f20f0d99f70f8ec859fbb763b01a1e5.json +0 -0
  60. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-c55542bb9fae544d87fae6f30e0fe8a9088d12075f4442ab4fe2fcd05e472234.json +0 -0
  61. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-cb29a6556d35ac630ee0aa885dd7341cf9573bd3efd216ff8a887b87686b03db.json +0 -0
  62. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-d0a1f341a89f5f14696b10baa72db9d95551c2b7e5fc67308fd52dc03dd98a92.json +0 -0
  63. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-d2ad0a0ca2649c9e4873cfcc1fc66d2d07cc45d0f65c560b06d7b5f592f4fa8a.json +0 -0
  64. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-d6cfe78eb635ba0b89ca4021a4dc8182d18ab5b197f30149cd28488eba4c1df5.json +0 -0
  65. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-d729b56dea00e49dcdba8cf0001e2811da27351eabe98212db3b589f18fc6f32.json +0 -0
  66. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-d9658bfd4e7170b41d03f2ddf2446d0bf54171c0d39d53bf20af2b8437f2ec48.json +0 -0
  67. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-dbba7b3d3289425bae711aedbf73fbc3699f857f86f84d95c3b556d05c5658b0.json +0 -0
  68. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-dcb96b649d6d63a58efd5d445453a4f3d7869a56ff714b69bedf3d616a0473ca.json +0 -0
  69. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-ebd876fbf5362a5900e75bc05f2f11c73c406ef7da4e95097fc6a1c3d1b8bc54.json +0 -0
  70. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-eef5cc6bce1cc14eba8f3e68971724ef181e88cffcedd74673615f2026b89a62.json +0 -0
  71. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/.sqlx/query-ef56d5fefc5774040d1ee397beadb475f6af02768c22f0e583c74062e2e821ce.json +0 -0
  72. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/Cargo.lock +0 -0
  73. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/Cargo.toml +0 -0
  74. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/README.md +0 -0
  75. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/migrations/20241007163501_initial.sql +0 -0
  76. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/migrations/20241211120039_merge_job_priority.sql +0 -0
  77. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/migrations/20241211121159_basic_indexes.sql +0 -0
  78. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/migrations/20241212151105_check_segment_records.sql +0 -0
  79. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/migrations/20250110145554_in_flight_messages.sql +0 -0
  80. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_binding/Cargo.toml +0 -0
  81. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_binding/src/lib.rs +0 -0
  82. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_paragraph/Cargo.toml +0 -0
  83. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_paragraph/src/fuzzy_query.rs +0 -0
  84. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_paragraph/src/lib.rs +0 -0
  85. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_paragraph/src/query_io.rs +0 -0
  86. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_paragraph/src/query_parser/fuzzy_parser.rs +0 -0
  87. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_paragraph/src/query_parser/keyword_parser.rs +0 -0
  88. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_paragraph/src/query_parser/stop_words.rs +0 -0
  89. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_paragraph/src/query_parser/tokenizer.rs +0 -0
  90. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_paragraph/src/query_parser.rs +0 -0
  91. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_paragraph/src/reader.rs +0 -0
  92. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_paragraph/src/request_types.rs +0 -0
  93. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_paragraph/src/resource_indexer.rs +0 -0
  94. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_paragraph/src/schema.rs +0 -0
  95. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_paragraph/src/search_query.rs +0 -0
  96. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_paragraph/src/search_response.rs +0 -0
  97. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_paragraph/src/set_query.rs +0 -0
  98. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_paragraph/stop_words/README.md +0 -0
  99. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_paragraph/stop_words/ar.json +0 -0
  100. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_paragraph/stop_words/az.json +0 -0
  101. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_paragraph/stop_words/bn.json +0 -0
  102. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_paragraph/stop_words/ca.json +0 -0
  103. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_paragraph/stop_words/ch.json +0 -0
  104. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_paragraph/stop_words/da.json +0 -0
  105. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_paragraph/stop_words/de.json +0 -0
  106. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_paragraph/stop_words/el.json +0 -0
  107. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_paragraph/stop_words/en.json +0 -0
  108. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_paragraph/stop_words/es.json +0 -0
  109. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_paragraph/stop_words/eu.json +0 -0
  110. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_paragraph/stop_words/extract.py +0 -0
  111. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_paragraph/stop_words/fi.json +0 -0
  112. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_paragraph/stop_words/fr.json +0 -0
  113. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_paragraph/stop_words/he.json +0 -0
  114. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_paragraph/stop_words/hu.json +0 -0
  115. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_paragraph/stop_words/id.json +0 -0
  116. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_paragraph/stop_words/it.json +0 -0
  117. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_paragraph/stop_words/kk.json +0 -0
  118. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_paragraph/stop_words/ne.json +0 -0
  119. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_paragraph/stop_words/nl.json +0 -0
  120. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_paragraph/stop_words/no.json +0 -0
  121. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_paragraph/stop_words/pt.json +0 -0
  122. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_paragraph/stop_words/ro.json +0 -0
  123. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_paragraph/stop_words/ru.json +0 -0
  124. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_paragraph/stop_words/sl.json +0 -0
  125. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_paragraph/stop_words/sv.json +0 -0
  126. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_paragraph/stop_words/tg.json +0 -0
  127. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_paragraph/stop_words/tr.json +0 -0
  128. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_paragraph/tests/common/mod.rs +0 -0
  129. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_paragraph/tests/reader.rs +0 -0
  130. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_protos/Cargo.toml +0 -0
  131. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_protos/build.py +0 -0
  132. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_protos/build.rs +0 -0
  133. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_protos/nidx.proto +0 -0
  134. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_protos/nodereader.proto +0 -0
  135. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_protos/noderesources.proto +0 -0
  136. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_protos/nodewriter.proto +0 -0
  137. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_protos/src/lib.rs +0 -0
  138. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_relation/Cargo.toml +0 -0
  139. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_relation/src/graph_collector.rs +0 -0
  140. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_relation/src/graph_query_parser.rs +0 -0
  141. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_relation/src/io_maps.rs +0 -0
  142. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_relation/src/lib.rs +0 -0
  143. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_relation/src/reader.rs +0 -0
  144. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_relation/src/resource_indexer.rs +0 -0
  145. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_relation/src/schema.rs +0 -0
  146. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_relation/src/top_unique_n.rs +0 -0
  147. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_relation/tests/common/mod.rs +0 -0
  148. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_relation/tests/test_graph_query_parser_search.rs +0 -0
  149. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_relation/tests/test_graph_search.rs +0 -0
  150. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_relation/tests/test_writer.rs +0 -0
  151. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_tantivy/Cargo.toml +0 -0
  152. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_tantivy/src/index_reader.rs +0 -0
  153. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_tantivy/src/lib.rs +0 -0
  154. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_tantivy/src/utils.rs +0 -0
  155. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_tests/Cargo.toml +0 -0
  156. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_tests/src/graph.rs +0 -0
  157. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_tests/src/lib.rs +0 -0
  158. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_text/Cargo.toml +0 -0
  159. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_text/src/lib.rs +0 -0
  160. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_text/src/prefilter.rs +0 -0
  161. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_text/src/query_io.rs +0 -0
  162. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_text/src/reader.rs +0 -0
  163. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_text/src/request_types.rs +0 -0
  164. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_text/src/resource_indexer.rs +0 -0
  165. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_text/src/schema.rs +0 -0
  166. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_text/src/search_query.rs +0 -0
  167. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_text/tests/common/mod.rs +0 -0
  168. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_text/tests/test_deletions.rs +0 -0
  169. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_text/tests/test_flow.rs +0 -0
  170. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_text/tests/test_search.rs +0 -0
  171. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_text/tests/test_streaming.rs +0 -0
  172. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_types/Cargo.toml +0 -0
  173. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_types/src/lib.rs +0 -0
  174. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_types/src/prefilter.rs +0 -0
  175. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_types/src/query_language.rs +0 -0
  176. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_vector/Cargo.toml +0 -0
  177. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_vector/src/config.rs +0 -0
  178. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_vector/src/data_store/v1/node.rs +0 -0
  179. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_vector/src/data_store/v1/store.rs +0 -0
  180. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_vector/src/data_store/v1/trie.rs +0 -0
  181. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_vector/src/data_store/v1/trie_ram.rs +0 -0
  182. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_vector/src/data_store/v1.rs +0 -0
  183. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_vector/src/data_store/v2/paragraph_store.rs +0 -0
  184. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_vector/src/data_store/v2/quant_vector_store.rs +0 -0
  185. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_vector/src/data_store/v2/vector_store.rs +0 -0
  186. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_vector/src/data_store/v2.rs +0 -0
  187. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_vector/src/data_store.rs +0 -0
  188. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_vector/src/data_types.rs +0 -0
  189. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_vector/src/formula.rs +0 -0
  190. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_vector/src/hnsw/params.rs +0 -0
  191. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_vector/src/indexer.rs +0 -0
  192. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_vector/src/inverted_index/fst_index.rs +0 -0
  193. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_vector/src/inverted_index/map.rs +0 -0
  194. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_vector/src/inverted_index.rs +0 -0
  195. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_vector/src/lib.rs +0 -0
  196. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_vector/src/multivector.rs +0 -0
  197. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_vector/src/query_io.rs +0 -0
  198. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_vector/src/request_types.rs +0 -0
  199. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_vector/src/searcher.rs +0 -0
  200. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_vector/src/utils.rs +0 -0
  201. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_vector/src/vector_types/dense_f32.rs +0 -0
  202. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_vector/src/vector_types/mod.rs +0 -0
  203. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_vector/src/vector_types/rabitq.rs +0 -0
  204. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_vector/tests/common/mod.rs +0 -0
  205. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_vector/tests/test_basic_search.rs +0 -0
  206. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_vector/tests/test_hidden.rs +0 -0
  207. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/nidx_vector/tests/test_maxsim.rs +0 -0
  208. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/src/api/grpc.rs +0 -0
  209. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/src/api/shards.rs +0 -0
  210. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/src/api.rs +0 -0
  211. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/src/control.rs +0 -0
  212. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/src/errors.rs +0 -0
  213. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/src/grpc_server.rs +0 -0
  214. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/src/import_export.rs +0 -0
  215. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/src/indexer.rs +0 -0
  216. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/src/lib.rs +0 -0
  217. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/src/main.rs +0 -0
  218. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/src/metadata/deletion.rs +0 -0
  219. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/src/metadata/index.rs +0 -0
  220. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/src/metadata/index_request.rs +0 -0
  221. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/src/metadata/merge_job.rs +0 -0
  222. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/src/metadata/segment.rs +0 -0
  223. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/src/metadata/shard.rs +0 -0
  224. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/src/metadata.rs +0 -0
  225. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/src/metrics.rs +0 -0
  226. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/src/scheduler/audit_task.rs +0 -0
  227. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/src/scheduler/log_merge.rs +0 -0
  228. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/src/scheduler/merge_task.rs +0 -0
  229. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/src/scheduler/metrics_task.rs +0 -0
  230. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/src/scheduler/purge_tasks.rs +0 -0
  231. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/src/scheduler/vector_merge.rs +0 -0
  232. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/src/scheduler.rs +0 -0
  233. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/src/searcher/grpc.rs +0 -0
  234. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/src/searcher/index_cache.rs +0 -0
  235. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/src/searcher/query_language.rs +0 -0
  236. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/src/searcher/query_planner.rs +0 -0
  237. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/src/searcher/shard_search.rs +0 -0
  238. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/src/searcher/shard_selector.rs +0 -0
  239. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/src/searcher/shard_suggest.rs +0 -0
  240. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/src/searcher/streams.rs +0 -0
  241. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/src/searcher/sync.rs +0 -0
  242. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/src/searcher.rs +0 -0
  243. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/src/segment_store.rs +0 -0
  244. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/src/settings.rs +0 -0
  245. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/src/telemetry/duration_layer.rs +0 -0
  246. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/src/telemetry/log_format.rs +0 -0
  247. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/src/telemetry/middleware.rs +0 -0
  248. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/src/telemetry.rs +0 -0
  249. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/src/tool.rs +0 -0
  250. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/src/utilization_tracker.rs +0 -0
  251. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/src/worker.rs +0 -0
  252. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/tests/common/mod.rs +0 -0
  253. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/tests/common/services.rs +0 -0
  254. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/tests/test_date_range_search.rs +0 -0
  255. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/tests/test_search_filtering.rs +0 -0
  256. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/tests/test_search_relations.rs +0 -0
  257. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/tests/test_search_sorting.rs +0 -0
  258. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/tests/test_searcher_cluster.rs +0 -0
  259. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/tests/test_security_search.rs +0 -0
  260. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/tests/test_shards.rs +0 -0
  261. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/tests/test_shards_api.rs +0 -0
  262. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/tests/test_suggest.rs +0 -0
  263. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/tests/test_synced_searcher.rs +0 -0
  264. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/tests/test_vector_normalization.rs +0 -0
  265. {nidx_binding-6.9.2.post622 → nidx_binding-6.9.3.post624}/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.2.post622
3
+ Version: 6.9.3.post624
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.2.post622"
13
+ version = "6.9.3.post624"
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" }]
@@ -0,0 +1,172 @@
1
+ // Copyright (C) 2021 Bosutech XXI S.L.
2
+ //
3
+ // nucliadb is offered under the AGPL v3.0 and as commercial software.
4
+ // For commercial licensing, contact us at info@nuclia.com.
5
+ //
6
+ // AGPL:
7
+ // This program is free software: you can redistribute it and/or modify
8
+ // it under the terms of the GNU Affero General Public License as
9
+ // published by the Free Software Foundation, either version 3 of the
10
+ // License, or (at your option) any later version.
11
+ //
12
+ // This program is distributed in the hope that it will be useful,
13
+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ // GNU Affero General Public License for more details.
16
+ //
17
+ // You should have received a copy of the GNU Affero General Public License
18
+ // along with this program. If not, see <http://www.gnu.org/licenses/>.
19
+ //
20
+
21
+ use std::collections::BinaryHeap;
22
+
23
+ use rand::{Rng, SeedableRng, distributions::Uniform, rngs::SmallRng};
24
+
25
+ use crate::{
26
+ VectorAddr,
27
+ hnsw::{
28
+ Cnx, DataRetriever, HnswSearcher, RAMHnsw, SearchVector, params,
29
+ ram_hnsw::{Edge, RAMLayer},
30
+ },
31
+ };
32
+
33
+ pub struct HnswBuilder<'a, DR> {
34
+ distribution: Uniform<f64>,
35
+ layer_rng: SmallRng,
36
+ retriever: &'a DR,
37
+ searcher: HnswSearcher<'a, DR>,
38
+ }
39
+
40
+ impl<'a, DR: DataRetriever> HnswBuilder<'a, DR> {
41
+ pub fn new(retriever: &DR) -> HnswBuilder<'_, DR> {
42
+ HnswBuilder {
43
+ retriever,
44
+ distribution: Uniform::new(0.0, 1.0),
45
+ layer_rng: SmallRng::seed_from_u64(2),
46
+ searcher: HnswSearcher::new(retriever, false),
47
+ }
48
+ }
49
+
50
+ /// Initialize the graph holding the specified number of vectors
51
+ /// Each vector is assigned to a random amount of layers but no
52
+ /// edges are built yet. If the node is preinitialized, you can skip
53
+ /// an initial amount of nodes so they aren't recreated
54
+ pub fn initialize_graph(&mut self, hnsw: &mut RAMHnsw, skip_nodes: u32, total_nodes: u32) {
55
+ for node_id in skip_nodes..total_nodes {
56
+ let top_layer = self.get_random_layer();
57
+ hnsw.add_node(VectorAddr(node_id), top_layer);
58
+ }
59
+ hnsw.update_entry_point();
60
+ }
61
+
62
+ fn select_neighbours_heuristic(
63
+ &self,
64
+ k_neighbours: usize,
65
+ candidates: &[(VectorAddr, Edge)],
66
+ ) -> Vec<(VectorAddr, Edge)> {
67
+ let mut results = Vec::new();
68
+ let mut discarded = BinaryHeap::new();
69
+
70
+ // First, select the best candidates to link, trying to connect from all directions
71
+ // i.e: avoid linking to all nodes in a single cluster
72
+ for (x, sim) in candidates.iter().copied() {
73
+ if results.len() == k_neighbours {
74
+ break;
75
+ }
76
+ // Keep if x is more similar to the new node than it is similar to other results
77
+ // i.e: similarity(x, new) > similarity(x, y) for all y in result
78
+ let check = results
79
+ .iter()
80
+ .map(|&(y, _)| self.retriever.similarity(x, &SearchVector::Stored(y)))
81
+ .all(|inter_sim| sim > inter_sim);
82
+ if check {
83
+ results.push((x, sim));
84
+ } else {
85
+ discarded.push(Cnx(x, sim));
86
+ }
87
+ }
88
+
89
+ // keepPrunedConnections: keep some other connections to fill M
90
+ if results.len() < k_neighbours {
91
+ while results.len() < k_neighbours {
92
+ let Some(Cnx(n, d)) = discarded.pop() else { break };
93
+ results.push((n, d));
94
+ }
95
+ // Sort the list since the newly added connections might be out of order
96
+ results.sort_unstable_by(|y, x| x.1.total_cmp(&y.1));
97
+ }
98
+
99
+ results
100
+ }
101
+
102
+ fn get_random_layer(&mut self) -> usize {
103
+ let sample: f64 = self.layer_rng.sample(self.distribution);
104
+ let picked_level = -sample.ln() * params::level_factor();
105
+ picked_level.round() as usize
106
+ }
107
+
108
+ /// Insert a node into a layer, calculating all edges
109
+ fn layer_insert(&self, x: VectorAddr, layer: &RAMLayer, search_neighbours: Vec<(VectorAddr, Edge)>, mmax: usize) {
110
+ let neighbours = self.select_neighbours_heuristic(params::M, &search_neighbours);
111
+
112
+ // Set edges from this node to neighbours
113
+ *layer.out.get(&x).unwrap().write().unwrap() = neighbours.clone();
114
+
115
+ // Set edges from neighbours to this node
116
+ for (y, dist) in neighbours.iter().copied() {
117
+ let other_node = layer.out.get(&y).unwrap();
118
+ let mut other_edges = other_node.write().unwrap();
119
+ other_edges.push((x, dist));
120
+ if other_edges.len() > mmax {
121
+ *other_edges = self.select_neighbours_heuristic(params::prune_m(mmax), &other_edges);
122
+ }
123
+ }
124
+ }
125
+
126
+ /// Insert a node into all corresponding layers.
127
+ /// The node must be created first by calling initialize_graph()
128
+ pub fn insert(&self, node: VectorAddr, hnsw: &RAMHnsw) {
129
+ debug_assert!(!hnsw.layers.is_empty());
130
+ debug_assert!(node.0 < hnsw.layers[0].out.len() as u32);
131
+
132
+ let mut search_ep = vec![hnsw.entry_point.node];
133
+ let vector = SearchVector::Stored(node);
134
+
135
+ // The neighbours of the node at each layer, for insertion
136
+ let mut layer_neighbours = Vec::with_capacity(hnsw.no_layers());
137
+ let mut node_in_layer = false;
138
+
139
+ // First, find the neighbours for each layer the node appears in.
140
+ for l in (0..hnsw.no_layers()).rev() {
141
+ if !node_in_layer && (l == 0 || hnsw.layers[l].contains(&node)) {
142
+ node_in_layer = true;
143
+ }
144
+
145
+ // On upper layers, find 1 neighbour (as entrypoint to next layer)
146
+ // On layers where the inserted node appears, find efC neighbours for creating links
147
+ let k_neighbours = if node_in_layer { params::EF_CONSTRUCTION } else { 1 };
148
+
149
+ let search_results: Vec<_> = self
150
+ .searcher
151
+ .layer_search(&vector, &hnsw.layers[l], k_neighbours, &search_ep)
152
+ .map(|x| (x.0, x.1.score))
153
+ .collect();
154
+
155
+ search_ep = search_results.iter().map(|x| x.0).collect();
156
+ if node_in_layer {
157
+ // If finding neighbours, store them for insertion later
158
+ layer_neighbours.push(search_results);
159
+ }
160
+ }
161
+
162
+ // Insert all neighbours from the bottom layer up. This is done so that it's not possible to
163
+ // find a node on a top layer before the edges are set on the lower layers because this can cause
164
+ // problems during parallel insertion.
165
+ // If edges are inserted from top to bottom, another worker might find the node in layer N and
166
+ // follow it down to layer N-1 where edges are not yet set. Then, it cannot find neighbours in this
167
+ // layer and the search gets stuck (no links to follow) resulting in a node with low connectivity.
168
+ for (layer, neighbours) in layer_neighbours.into_iter().rev().enumerate() {
169
+ self.layer_insert(node, &hnsw.layers[layer], neighbours, params::m_max_for_layer(layer));
170
+ }
171
+ }
172
+ }
@@ -46,8 +46,8 @@
46
46
  use std::collections::HashMap;
47
47
  use std::io;
48
48
 
49
- use super::ops_hnsw::{Hnsw, Layer};
50
49
  use super::ram_hnsw::{Edge, EntryPoint, RAMHnsw, RAMLayer};
50
+ use super::search::{SearchableHnsw, SearchableLayer};
51
51
  use crate::VectorAddr;
52
52
  use crate::data_types::usize_utils::*;
53
53
 
@@ -66,7 +66,7 @@ pub struct DiskLayer<'a> {
66
66
  layer: usize,
67
67
  }
68
68
 
69
- impl<'a> Layer for &'a DiskLayer<'a> {
69
+ impl<'a> SearchableLayer for &'a DiskLayer<'a> {
70
70
  type EdgeIt = EdgeIter<'a>;
71
71
  fn get_out_edges(&self, address: VectorAddr) -> Self::EdgeIt {
72
72
  let node = DiskHnsw::get_node(self.hnsw, address);
@@ -74,7 +74,7 @@ impl<'a> Layer for &'a DiskLayer<'a> {
74
74
  }
75
75
  }
76
76
 
77
- impl<'a> Layer for DiskLayer<'a> {
77
+ impl<'a> SearchableLayer for DiskLayer<'a> {
78
78
  type EdgeIt = EdgeIter<'a>;
79
79
  fn get_out_edges(&self, address: VectorAddr) -> Self::EdgeIt {
80
80
  let node = DiskHnsw::get_node(self.hnsw, address);
@@ -82,9 +82,9 @@ impl<'a> Layer for DiskLayer<'a> {
82
82
  }
83
83
  }
84
84
 
85
- impl<'a> Hnsw for &'a [u8] {
85
+ impl<'a> SearchableHnsw for &'a [u8] {
86
86
  type L = DiskLayer<'a>;
87
- fn get_entry_point(&self) -> Option<EntryPoint> {
87
+ fn get_entry_point(&self) -> EntryPoint {
88
88
  DiskHnsw::get_entry_point(self)
89
89
  }
90
90
  fn get_layer(&self, i: usize) -> Self::L {
@@ -124,14 +124,16 @@ impl DiskHnsw {
124
124
  let mut length = offset;
125
125
  let mut indexing = HashMap::new();
126
126
  for layer in 0..hnsw.no_layers() {
127
- let no_edges = hnsw.get_layer(layer).no_out_edges(node);
127
+ let num_edges = hnsw.get_layer(layer).num_out_edges(&node);
128
128
  indexing.insert(layer, length);
129
- buf.write_all(&no_edges.to_le_bytes())?;
129
+ buf.write_all(&num_edges.to_le_bytes())?;
130
130
  length += USIZE_LEN;
131
- for (cnx, edge) in hnsw.get_layer(layer).get_out_edges(node) {
132
- buf.write_all(&(cnx.0 as usize).to_le_bytes())?;
133
- buf.write_all(&edge.to_le_bytes())?;
134
- length += CNX_LEN;
131
+ if num_edges > 0 {
132
+ for (cnx, edge) in hnsw.get_layer(layer).get_out_edges(node) {
133
+ buf.write_all(&(cnx.0 as usize).to_le_bytes())?;
134
+ buf.write_all(&edge.to_le_bytes())?;
135
+ length += CNX_LEN;
136
+ }
135
137
  }
136
138
  }
137
139
  for layer in (0..hnsw.no_layers()).rev() {
@@ -158,38 +160,40 @@ impl DiskHnsw {
158
160
  }
159
161
  }
160
162
  pub fn serialize_into<W: io::Write>(mut buf: W, no_nodes: u32, hnsw: RAMHnsw) -> io::Result<()> {
161
- if let Some(entry_point) = hnsw.entry_point {
162
- let mut length = 0;
163
- let mut nodes_end = vec![];
164
- for node in 0..no_nodes {
165
- length = DiskHnsw::serialize_node(&mut buf, length, node, &hnsw)?;
166
- nodes_end.push(length)
167
- }
168
- for ends_at in nodes_end.into_iter().rev() {
169
- buf.write_all(&ends_at.to_le_bytes())?;
170
- length += USIZE_LEN;
171
- }
172
- let EntryPoint { node, layer } = entry_point;
173
- buf.write_all(&layer.to_le_bytes())?;
174
- buf.write_all(&(node.0 as usize).to_le_bytes())?;
175
- let _length = length + 2 * USIZE_LEN;
176
- buf.flush()?;
163
+ if no_nodes == 0 {
164
+ // Empty graph, nothing to serialize
165
+ return Ok(());
166
+ }
167
+
168
+ let mut length = 0;
169
+ let mut nodes_end = vec![];
170
+ for node in 0..no_nodes {
171
+ length = DiskHnsw::serialize_node(&mut buf, length, node, &hnsw)?;
172
+ nodes_end.push(length)
173
+ }
174
+ for ends_at in nodes_end.into_iter().rev() {
175
+ buf.write_all(&ends_at.to_le_bytes())?;
176
+ length += USIZE_LEN;
177
177
  }
178
+ let EntryPoint { node, layer } = hnsw.entry_point;
179
+ buf.write_all(&layer.to_le_bytes())?;
180
+ buf.write_all(&(node.0 as usize).to_le_bytes())?;
181
+ let _length = length + 2 * USIZE_LEN;
182
+ buf.flush()?;
183
+
178
184
  Ok(())
179
185
  }
180
186
  // hnsw must be serialized using DiskHnsw, may have trailing bytes at the start.
181
- pub fn get_entry_point(hnsw: &[u8]) -> Option<EntryPoint> {
182
- if !hnsw.is_empty() {
183
- let node_start = hnsw.len() - USIZE_LEN;
184
- let layer_start = node_start - USIZE_LEN;
185
- let node_addr = usize_from_slice_le(&hnsw[node_start..(node_start + NODE_LEN)]);
186
- let layer = usize_from_slice_le(&hnsw[layer_start..(layer_start + USIZE_LEN)]);
187
- Some(EntryPoint {
188
- node: VectorAddr(node_addr as u32),
189
- layer,
190
- })
191
- } else {
192
- None
187
+ pub fn get_entry_point(hnsw: &[u8]) -> EntryPoint {
188
+ assert!(!hnsw.is_empty());
189
+
190
+ let node_start = hnsw.len() - USIZE_LEN;
191
+ let layer_start = node_start - USIZE_LEN;
192
+ let node_addr = usize_from_slice_le(&hnsw[node_start..(node_start + NODE_LEN)]);
193
+ let layer = usize_from_slice_le(&hnsw[layer_start..(layer_start + USIZE_LEN)]);
194
+ EntryPoint {
195
+ node: VectorAddr(node_addr as u32),
196
+ layer,
193
197
  }
194
198
  }
195
199
  // hnsw must be serialized using MHnsw, may have trailing bytes at the start.
@@ -231,7 +235,12 @@ impl DiskHnsw {
231
235
  let cnx_end = cnx_start + number_edges * CNX_LEN;
232
236
 
233
237
  if number_edges > 0 {
234
- let ram_edges = ram.layers[layer_index].out.entry(VectorAddr(node_index)).or_default();
238
+ let mut ram_edges = ram.layers[layer_index]
239
+ .out
240
+ .entry(VectorAddr(node_index))
241
+ .or_default()
242
+ .write()
243
+ .unwrap();
235
244
  let edges = EdgeIter {
236
245
  crnt: 0,
237
246
  buf: &hnsw[cnx_start..cnx_end],
@@ -259,9 +268,11 @@ impl DiskHnsw {
259
268
 
260
269
  #[cfg(test)]
261
270
  mod tests {
271
+ use std::sync::RwLock;
272
+
262
273
  use super::*;
263
274
  use crate::hnsw::ram_hnsw::RAMLayer;
264
- fn layer_check<L: Layer>(buf: L, no_nodes: u32, cnx: &[Vec<(VectorAddr, Edge)>]) {
275
+ fn layer_check<L: SearchableLayer>(buf: L, no_nodes: u32, cnx: &[Vec<(VectorAddr, Edge)>]) {
265
276
  let no_cnx = vec![];
266
277
  for i in 0..no_nodes {
267
278
  let expected = cnx.get(i as usize).unwrap_or(&no_cnx);
@@ -274,8 +285,7 @@ mod tests {
274
285
  let hnsw = RAMHnsw::new();
275
286
  let mut buf = vec![];
276
287
  DiskHnsw::serialize_into(&mut buf, 0, hnsw).unwrap();
277
- let ep = DiskHnsw::get_entry_point(&buf);
278
- assert_eq!(ep, None);
288
+ assert!(buf.is_empty());
279
289
  }
280
290
 
281
291
  #[test]
@@ -290,7 +300,7 @@ mod tests {
290
300
  out: cnx0
291
301
  .iter()
292
302
  .enumerate()
293
- .map(|(i, c)| (VectorAddr(i as u32), c.clone()))
303
+ .map(|(i, c)| (VectorAddr(i as u32), RwLock::new(c.clone())))
294
304
  .collect(),
295
305
  };
296
306
  let cnx1 = vec![vec![(VectorAddr(1), 4.0)], vec![(VectorAddr(2), 5.0)]];
@@ -298,7 +308,7 @@ mod tests {
298
308
  out: cnx1
299
309
  .iter()
300
310
  .enumerate()
301
- .map(|(i, c)| (VectorAddr(i as u32), c.clone()))
311
+ .map(|(i, c)| (VectorAddr(i as u32), RwLock::new(c.clone())))
302
312
  .collect(),
303
313
  };
304
314
  let cnx2 = vec![vec![(VectorAddr(1), 6.0)]];
@@ -306,7 +316,7 @@ mod tests {
306
316
  out: cnx2
307
317
  .iter()
308
318
  .enumerate()
309
- .map(|(i, c)| (VectorAddr(i as u32), c.clone()))
319
+ .map(|(i, c)| (VectorAddr(i as u32), RwLock::new(c.clone())))
310
320
  .collect(),
311
321
  };
312
322
  let entry_point = EntryPoint {
@@ -314,11 +324,11 @@ mod tests {
314
324
  layer: 2,
315
325
  };
316
326
  let mut hnsw = RAMHnsw::new();
317
- hnsw.entry_point = Some(entry_point);
327
+ hnsw.entry_point = entry_point;
318
328
  hnsw.layers = vec![layer0, layer1, layer2];
319
329
  let mut buf = vec![];
320
330
  DiskHnsw::serialize_into(&mut buf, no_nodes, hnsw).unwrap();
321
- let ep = DiskHnsw::get_entry_point(&buf).unwrap();
331
+ let ep = DiskHnsw::get_entry_point(&buf);
322
332
  assert_eq!(ep, entry_point);
323
333
  let layer0 = buf.as_slice().get_layer(0);
324
334
  layer_check(layer0, no_nodes, &cnx0);
@@ -340,7 +350,7 @@ mod tests {
340
350
  out: cnx0
341
351
  .iter()
342
352
  .enumerate()
343
- .map(|(i, c)| (VectorAddr(i as u32), c.clone()))
353
+ .map(|(i, c)| (VectorAddr(i as u32), RwLock::new(c.clone())))
344
354
  .collect(),
345
355
  };
346
356
  let cnx1 = [vec![(VectorAddr(1), 4.0)], vec![(VectorAddr(2), 5.0)]];
@@ -348,7 +358,7 @@ mod tests {
348
358
  out: cnx1
349
359
  .iter()
350
360
  .enumerate()
351
- .map(|(i, c)| (VectorAddr(i as u32), c.clone()))
361
+ .map(|(i, c)| (VectorAddr(i as u32), RwLock::new(c.clone())))
352
362
  .collect(),
353
363
  };
354
364
  let cnx2 = [vec![(VectorAddr(1), 6.0)]];
@@ -356,7 +366,7 @@ mod tests {
356
366
  out: cnx2
357
367
  .iter()
358
368
  .enumerate()
359
- .map(|(i, c)| (VectorAddr(i as u32), c.clone()))
369
+ .map(|(i, c)| (VectorAddr(i as u32), RwLock::new(c.clone())))
360
370
  .collect(),
361
371
  };
362
372
  let entry_point = EntryPoint {
@@ -364,7 +374,7 @@ mod tests {
364
374
  layer: 2,
365
375
  };
366
376
  let mut hnsw = RAMHnsw::new();
367
- hnsw.entry_point = Some(entry_point);
377
+ hnsw.entry_point = entry_point;
368
378
  hnsw.layers = vec![layer0, layer1, layer2];
369
379
  let mut buf = vec![];
370
380
  DiskHnsw::serialize_into(&mut buf, no_nodes, hnsw).unwrap();
@@ -0,0 +1,178 @@
1
+ // Copyright (C) 2021 Bosutech XXI S.L.
2
+ //
3
+ // nucliadb is offered under the AGPL v3.0 and as commercial software.
4
+ // For commercial licensing, contact us at info@nuclia.com.
5
+ //
6
+ // AGPL:
7
+ // This program is free software: you can redistribute it and/or modify
8
+ // it under the terms of the GNU Affero General Public License as
9
+ // published by the Free Software Foundation, either version 3 of the
10
+ // License, or (at your option) any later version.
11
+ //
12
+ // This program is distributed in the hope that it will be useful,
13
+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ // GNU Affero General Public License for more details.
16
+ //
17
+ // You should have received a copy of the GNU Affero General Public License
18
+ // along with this program. If not, see <http://www.gnu.org/licenses/>.
19
+ //
20
+
21
+ use std::sync::{RwLock, RwLockReadGuard};
22
+
23
+ use rustc_hash::FxHashMap;
24
+ use search::{SearchableHnsw, SearchableLayer};
25
+
26
+ use crate::VectorAddr;
27
+
28
+ use super::*;
29
+
30
+ #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
31
+ pub struct EntryPoint {
32
+ pub node: VectorAddr,
33
+ pub layer: usize,
34
+ }
35
+
36
+ pub type Edge = f32;
37
+
38
+ #[derive(Default)]
39
+ pub struct RAMLayer {
40
+ pub(super) out: FxHashMap<VectorAddr, RwLock<Vec<(VectorAddr, Edge)>>>,
41
+ }
42
+
43
+ impl RAMLayer {
44
+ pub fn new() -> RAMLayer {
45
+ RAMLayer::default()
46
+ }
47
+
48
+ pub fn add_node(&mut self, node: VectorAddr) {
49
+ self.out.entry(node).or_default();
50
+ }
51
+
52
+ pub fn contains(&self, node: &VectorAddr) -> bool {
53
+ self.out.contains_key(node)
54
+ }
55
+
56
+ pub fn num_out_edges(&self, node: &VectorAddr) -> usize {
57
+ // This is called by the serialization code for all nodes and each layer, so we need to handle non-existing nodes
58
+ self.out.get(node).map(|n| n.read().unwrap().len()).unwrap_or(0)
59
+ }
60
+
61
+ /// Remove any links that point to a node which is not in this layer
62
+ /// See RAMHnsw.fix_broken_links for details
63
+ fn fix_broken_links(&self) {
64
+ for edges in self.out.values() {
65
+ let mut edges = edges.write().unwrap();
66
+ edges.retain(|e| self.out.contains_key(&e.0));
67
+ }
68
+ }
69
+ }
70
+
71
+ pub struct RAMHnsw {
72
+ pub entry_point: EntryPoint,
73
+ pub layers: Vec<RAMLayer>,
74
+ }
75
+ impl RAMHnsw {
76
+ pub fn new() -> RAMHnsw {
77
+ Self {
78
+ entry_point: EntryPoint {
79
+ node: VectorAddr(0),
80
+ layer: 0,
81
+ },
82
+ layers: vec![],
83
+ }
84
+ }
85
+
86
+ /// Adds a node to the graph at all layers below the selected top layer
87
+ pub fn add_node(&mut self, node: VectorAddr, top_layer: usize) {
88
+ for _ in self.layers.len()..=top_layer {
89
+ self.layers.push(RAMLayer::new());
90
+ }
91
+
92
+ for layer in 0..=top_layer {
93
+ self.layers[layer].add_node(node)
94
+ }
95
+ }
96
+
97
+ /// Updates the entrypoint to point to the first node of the top layer
98
+ pub fn update_entry_point(&mut self) {
99
+ // Only update if the entrypoint is not already at the top layer
100
+ if self.layers.len() > self.entry_point.layer + 1 {
101
+ self.entry_point = EntryPoint {
102
+ node: *self.layers.last().unwrap().out.keys().next().unwrap(),
103
+ layer: self.layers.len() - 1,
104
+ }
105
+ }
106
+ }
107
+
108
+ pub fn no_layers(&self) -> usize {
109
+ self.layers.len()
110
+ }
111
+
112
+ /// Remove any links that point to a node which is not in this layer
113
+ /// A bug in a previous version of this program could cause a node in layer N
114
+ /// to link to a node in layer N-1. This breaks navigation accross layer N.
115
+ /// This function will delete any such link from the graph.
116
+ pub fn fix_broken_links(&self) {
117
+ for l in &self.layers[1..] {
118
+ l.fix_broken_links();
119
+ }
120
+ }
121
+ }
122
+
123
+ pub struct EdgesIterator<'a>(RwLockReadGuard<'a, Vec<(VectorAddr, Edge)>>, usize);
124
+
125
+ impl<'a> Iterator for EdgesIterator<'a> {
126
+ type Item = (VectorAddr, Edge);
127
+
128
+ fn next(&mut self) -> Option<Self::Item> {
129
+ let it = self.0.get(self.1);
130
+ self.1 += 1;
131
+ it.copied()
132
+ }
133
+ }
134
+
135
+ impl<'a> SearchableLayer for &'a RAMLayer {
136
+ type EdgeIt = EdgesIterator<'a>;
137
+ fn get_out_edges(&self, node: VectorAddr) -> Self::EdgeIt {
138
+ EdgesIterator(self.out[&node].read().unwrap(), 0)
139
+ }
140
+ }
141
+
142
+ impl<'a> SearchableHnsw for &'a RAMHnsw {
143
+ type L = &'a RAMLayer;
144
+ fn get_entry_point(&self) -> EntryPoint {
145
+ self.entry_point
146
+ }
147
+ fn get_layer(&self, i: usize) -> Self::L {
148
+ &self.layers[i]
149
+ }
150
+ }
151
+
152
+ #[cfg(test)]
153
+ mod tests {
154
+ use super::*;
155
+
156
+ #[test]
157
+ fn test_fix_broken_links() {
158
+ // Create a minimal broken graph
159
+ let layer0 = RAMLayer {
160
+ out: [
161
+ (VectorAddr(0), RwLock::new(vec![(VectorAddr(1), 0.5)])),
162
+ (VectorAddr(1), RwLock::new(vec![(VectorAddr(0), 0.5)])),
163
+ ]
164
+ .into_iter()
165
+ .collect(),
166
+ };
167
+ let layer1 = RAMLayer {
168
+ out: [(VectorAddr(0), RwLock::new(vec![(VectorAddr(1), 0.5)]))]
169
+ .into_iter()
170
+ .collect(),
171
+ };
172
+ let mut graph = RAMHnsw::new();
173
+ graph.layers.push(layer0);
174
+ graph.layers.push(layer1);
175
+ graph.fix_broken_links();
176
+ assert!(graph.layers[1].out[&VectorAddr(0)].read().unwrap().is_empty());
177
+ }
178
+ }