项目介绍:client-vector-search
client-vector-search是一个强调在客户端进行矢量搜索的库,能够实现文档嵌入、搜索及缓存功能。该库不仅可以在浏览器中使用,也支持在服务器端操作。此外,其性能超过了OpenAI提供的text-embedding-ada-002,并且在速度上远胜于Pinecone及其他矢量数据库。
这个库的创始人也是searchbase.app平台的创建者,为满足产品及客户需求开发了此工具,并将在产品中正式使用。用户可以放心,client-vector-search将持续获得维护与更新。
项目特点
- 文档嵌入:默认使用transformers(例如gte-small,约30MB)进行嵌入。
- 余弦相似度:计算嵌入向量之间的余弦相似度。
- 客户端索引创建及搜索:支持在客户端直接创建索引及执行搜索操作。
- 缓存支持:支持使用浏览器缓存来存储向量。
项目持续在进步,并有许多值得期待的改进计划。
项目路线图
我们的目标是构建一个超级简单且快速的矢量搜索工具,支持处理数百到数千个矢量,对99%的使用场景做出覆盖(每个用户大约1千个矢量)。我们计划将响应时间保持在100毫秒以下,并进一步简化复杂性。
计划任务
- 引入在Node和浏览器环境均可运行的HNSW索引,不依赖于HNSW绑定库。
- 为库增加完善的测试套件及持续集成/持续交付(CI/CD)。
- 包括简单的健康测试。
- 使用Jest模拟@xenova/transformers。
- 进行性能测试,监控召回率、内存使用量、CPU使用等指标。
快速开始
client-vector-search库提供了一种即插即用的方案,用户能够轻松进行文档嵌入与矢量搜索。下面是一个快速启动的指导:
import { getEmbedding, EmbeddingIndex } from 'client-vector-search';
// getEmbedding是一个异步函数,需要使用'await'或'.then()'以获取结果
const embedding = await getEmbedding("Apple"); // 返回嵌入向量以number[]的形式
// 每个对象需有一个类型为number[]的'embedding'属性
const initialObjects = [
{ id: 1, name: "Apple", embedding: embedding },
{ id: 2, name: "Banana", embedding: await getEmbedding("Banana") },
{ id: 3, name: "Cheddar", embedding: await getEmbedding("Cheddar") },
{ id: 4, name: "Space", embedding: await getEmbedding("Space") },
{ id: 5, name: "database", embedding: await getEmbedding("database") },
];
const index = new EmbeddingIndex(initialObjects); // 创建索引
// 查询应是一个类型为number[]的嵌入向量
const queryEmbedding = await getEmbedding('Fruit'); // 查询嵌入
const results = await index.search(queryEmbedding, { topK: 5 }); // 返回相似度最高的对象
// 指定存储类型
await index.saveIndex('indexedDB');
const results = await index.search([1, 2, 3], {
topK: 5,
useStorage: 'indexedDB',
// storageOptions: { // 仅在重写默认值时使用
// indexedDBName: 'clientVectorDB',
// indexedDBObjectStoreName: 'ClientEmbeddingStore',
// },
});
console.log(results);
await index.deleteIndexedDB(); // 如果重写默认值,请指定数据库名称
故障排除
NextJS 整合
在NextJS项目中使用此库时,需要更新next.config.js
文件,以包含以下内容:
module.exports = {
// 重写默认的webpack配置
webpack: (config) => {
// 请参阅 https://webpack.js.org/configuration/resolve/#resolvealias
config.resolve.alias = {
...config.resolve.alias,
sharp$: false,
"onnxruntime-node$": false,
};
return config;
},
};
页面加载后模型加载
在生成嵌入前初始化模型,以保证模型加载完成后再使用它,有助于提升用户体验。
import { initializeModel } from "client-vector-search"
...
useEffect(() => {
try {
initializeModel();
} catch (e) {
console.log(e);
}
}, []);
使用指南
本指南提供了关于库主要功能的逐步操作说明,涵盖从字符串生成嵌入到在索引中执行添加、更新及删除操作。还包括如何将索引保存至数据库及在其中执行搜索操作的说明。在完整的参考文档完成之前,用户可以在本指南中找到全部方法及其用法。每一步均附有代码示例以表明方法的具体使用,用户可自行尝试以获得更深入的了解。
步骤1:生成字符串嵌入
使用getEmbedding
方法生成给定字符串的嵌入。
const embedding = await getEmbedding("Apple"); // 以number[]形式返回嵌入
注意:
getEmbedding
是异步的,请确保使用await
。
步骤2:计算余弦相似度
计算两个嵌入之间的余弦相似度。
const similarity = cosineSimilarity(embedding1, embedding2, 6);
注意:两个嵌入的长度应一致。
步骤3:创建索引
用初始对象数组创建索引,每个对象必须包含一个'嵌入'属性。
const initialObjects = [...];
const index = new EmbeddingIndex(initialObjects);
步骤4:添加到索引
向索引中添加一个对象。
const objectToAdd = { id: 6, name: 'Cat', embedding: await getEmbedding('Cat') };
index.add(objectToAdd);
步骤5:更新索引
更新索引中的已有对象。
const vectorToUpdate = { id: 6, name: 'Dog', embedding: await getEmbedding('Dog') };
index.update({ id: 6 }, vectorToUpdate);
步骤6:从索引中移除
从索引中移除一个对象。
index.remove({ id: 6 });
步骤7:从索引中检索
检索索引中的对象。
const vector = index.get({ id: 1 });
步骤8:搜索索引
使用查询嵌入在索引中进行搜索。
const queryEmbedding = await getEmbedding('Fruit');
const results = await index.search(queryEmbedding, { topK: 5 });
步骤9:打印索引
在控制台打印整个索引。
index.printIndex();
步骤10:保存索引至IndexedDB(浏览器)
将索引保存至持久性IndexedDB数据库。
await index.saveIndex("indexedDB", { DBName: "clientVectorDB", objectStoreName:"ClientEmbeddingStore"})
重要:在IndexedDB中搜索
在IndexedDB中执行搜索操作。
const results = await index.search(queryEmbedding, {
topK: 5,
useStorage: "indexedDB",
storageOptions: { // 仅在希望重写默认选项时使用,默认值如下
indexedDBName: 'clientVectorDB',
indexedDBObjectStoreName: 'ClientEmbeddingStore'
}
});
删除数据库
删除整个数据库。
await IndexedDbManager.deleteIndexedDB("clientVectorDB");
删除对象存储
从数据库中删除对象存储。
await IndexedDbManager.deleteIndexedDBObjectStore("clientVectorDB", "ClientEmbeddingStore");
检索全部对象
从特定对象存储中检索全部对象。
const allObjects = await IndexedDbManager.getAllObjectsFromIndexedDB("clientVectorDB", "ClientEmbeddingStore");
以上就是client-vector-search项目的详细介绍,它旨在为用户提供一个高效且易用的客户端矢量搜索工具。通过本指南,相信用户可更好地理解和使用该库。