这是用C ++编写的HNSWLIB索引库的WebAssembly(WASM)版本。此WASM端口是由@shravansunder使用EMCC WASM编译器创建的,请参见此处的存储库。
受HNSWLIB节点库的启发。 @Yoshoku为Hnswlib节点提供了一些精彩的文档。谢谢, @yoshoku!
注意:这个图书馆仍处于初期!它是为需要在浏览器中运行HNSWLIB的用例而构建的。
hnswlib-wasm为HNSWLIB提供了WASM绑定,该结合基于层次可导航的小世界图实现了近似最近的邻居搜索。它在浏览器中起作用,并与Emscripten编辑。
$ yarn add hnswlib-wasm请参阅此处的NPM软件包。
indexedDB (在浏览器中),并使用emscripten的FS通过虚拟文件系统和IDBF来保存和加载索引。hnswlib-node的ChangElog。首先,创建库的运行时实例:
import { loadHnswlib } from 'hnswlib-wasm' ;
const lib = await loadHnswlib ( ) ;这是一个完整的示例,即如果存在索引或创建新索引(如果不存在):
const filename = 'ghost.dat' ;
const { loadHnswlib } = await import ( 'hnswlib-wasm' ) ;
this . hnswlib = await loadHnswlib ( ) ;
this . hnswlib . EmscriptenFileSystemManager . setDebugLogs ( true ) ;
this . vectorHnswIndex = new this . hnswlib . HierarchicalNSW ( 'cosine' , 1536 ) ;
await syncFileSystem ( 'read' ) ;
const exists = this . hnswlib . EmscriptenFileSystemManager . checkFileExists ( filename ) ;
if ( ! exists ) {
this . vectorHnswIndex . initIndex ( 100000 , 48 , 128 , 100 ) ;
this . vectorHnswIndex . setEfSearch ( 32 ) ;
this . vectorHnswIndex . writeIndex ( 'ghost.dat' ) ;
} else {
this . vectorHnswIndex . readIndex ( filename , 100000 , true ) ;
this . vectorHnswIndex . setEfSearch ( 32 ) ;
}您可以创建索引并这样使用。
// Here you're creating a new index with the L2 distance metric and 1000 as the max number of elements
const hnswIndex = lib . HierarchicalNSW ( 'l2' , 100 ) ;
// Initialize the index with the dimensions (1536), m, efConstruction. See the section below on parameters for more details. These cannot be changed after the index is created.
index . initIndex ( 1536 , 36 , 16 , 200 ) ;
// Set efSearch parameters. This can be changed after the index is created.
index . setEfSearch ( efSearch ) ;
// Now you can add items to the index, labels are returned as an array for the vectors. It will reuse deleted labels if possible based on the second parameter.
const labels = index . addItems ( vectors , true ) ;
// Now you can search the index
const result1 = index . searchKnn ( vectors [ 10 ] , 10 , undefined ) ;
// You can also search the index with a label filter
const labelFilter = ( label : number ) => {
return label >= 10 && label < 20 ;
}
const result2 = index . searchKnn ( testVectorData . vectors [ 10 ] , 10 , labelFilter ) ;更多用法示例要添加。
现在,请参见测试文件夹中的
HierarchicalNSW.test.ts文件,并参考HNSWLIB节点API文档。
hnswlib-wasm库提供了对索引DB(IDBF)的扩展支持,以存储和管理浏览器中的搜索索引。这使您可以轻松地在Web环境中保存和加载搜索索引,也不必将数据从EMCC文件系统移动到JavaScript内存。它使用Emscripten的FS通过虚拟文件系统保存和加载索引。虚拟文件系统与IDBF同步。
要保存搜索索引,请使用writeIndex方法:
await index . writeIndex ( 'savedIndex' ) ;要加载先前保存的搜索索引,请使用readIndex方法:
await index . readIndex ( 'savedIndex' , false ) ; syncFs方法用于将Emscripten文件系统与持久存储IDBF同步。您可以使用此方法从文件系统的持久源保存或读取数据。
await lib . EmscriptenFileSystemManager . syncFS ( true , emscripten :: val :: undefined ( ) ) ; // Read data from the persistent source
await lib . EmscriptenFileSystemManager . syncFS ( false , emscripten :: val :: undefined ( ) ) ; // Save data to the persistent source 本节将概述HNSW算法参数及其对使用HNSWLIB-WASM库时对性能的影响。 HNSW(层次可导航的小世界)是一种基于图的索引结构,用于在高维空间中有效相似性搜索。
来自Pinecone.io的图像
它具有几个可以调整的参数,以控制搜索质量和索引大小或施工时间之间的权衡。这是一些关键参数。
EFSearch是搜索过程中最近使用的邻居的动态列表的大小。较高的efsearch值会导致更准确但较慢的搜索。 EFSearch不能设置低于查询最近的邻居K的数量,并且可以是K和数据集大小之间的任何值。
M是在索引构建过程中为每个新元素创建的双向链接的数量。 M的合理范围是2-100。较高的M值在具有较高固有维度和/或高召回率的数据集上效果更好,而较低的M值对于固有维度低和/或低召回率的数据集效果更好。该参数还确定了算法内存消耗,该算法大致是每个存储元素的M * 8-10字节。
EFConstruction控制索引构建时间和准确性。较大的EFConstruction值会导致更长的施工时间,但指数质量更好。在某个时候,增加的EFConstruction并不能提高指数的质量。要检查所选的efconstruction值是否合适,请在efsearch = efconstruction时测量M最近的邻居搜索的回忆。如果召回低于0.9,则有改进的余地。
当使用HNSWLIB-WASM时,必须根据数据集大小和维度选择M,EFSearch和EFConstruction的适当值。由于HNSWLIB-WASM在浏览器中运行,因此您应该考虑可用的内存和性能限制。以下是一些建议:
选择一个在12-48范围内的值,因为它在大多数用例中都很好。您可能需要进行试验以找到特定数据集的最佳值。
从接近M的值开始,然后根据您所需的搜索速度和准确性之间的权衡进行调整。较低的值将更快,但准确较少,而较高的值将更准确但较慢。
考虑预期查询量的设置此值。如果您预计较低的查询量,则可以为EFConstruction设置更高的值,以改善召回量,对搜索时间的影响最小,尤其是在使用较低的M值时。
请记住,较高的M值将增加索引的内存使用量,因此在选择HNSWLIB-WASM参数时,您应该平衡性能和内存约束。
通过Pinecone学习HNSW
Pinecone的向量索引
来自Pinecone.io的图像
根据Apache-2.0许可条款,可以作为开源的HNSWLIB-WASM提供。
建造
yarn install
make rebuild
yarn build
测试
yarn test
首先联系@shravansunder!