這是用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!