
Research
Two Malicious Rust Crates Impersonate Popular Logger to Steal Wallet Keys
Socket uncovers malicious Rust crates impersonating fast_log to steal Solana and Ethereum wallet keys from source code.
@leolee9086/hnsw
Advanced tools
JavaScript HNSW (Hierarchical Navigable Small World) 向量索引库,支持动态操作和泛型搜索
JavaScript HNSW (Hierarchical Navigable Small World) 向量索引库,用于快速相似性搜索。纯 JavaScript 实现,支持动态操作和泛型搜索。
npm install @leolee9086/hnsw
# 或使用 pnpm
pnpm add @leolee9086/hnsw
# 或使用 yarn
yarn add @leolee9086/hnsw
import { hnsw } from '@leolee9086/hnsw';
// 创建HNSW索引
const index = hnsw.createIndex({
M: 16, // 每个节点的最大连接数
efConstruction: 200, // 构建时的搜索参数
metricType: 'cosine' // 距离度量类型: 'cosine' | 'l2'
});
// 插入向量
const vectors = [
[1, 2, 3, 4],
[2, 3, 4, 5],
[3, 4, 5, 6],
// ... 更多向量
];
vectors.forEach(vector => {
index.insertNode(vector);
});
// 搜索最近邻
const queryVector = [1.5, 2.5, 3.5, 4.5];
const results = index.search(queryVector, 5); // 返回5个最近邻
console.log(results);
// [
// { idx: 0, distance: 0.1 },
// { idx: 1, distance: 0.2 },
// ...
// ]
// 使用L2距离
const l2Index = hnsw.createIndex({
M: 32,
efConstruction: 400,
metricType: 'l2'
});
// 自定义搜索参数
const results = index.search(queryVector, 10, 300); // 使用efSearch=300
// 删除节点
index.deleteNode(0); // 删除索引为0的节点
// 获取统计信息
const stats = index.getStats();
console.log(stats);
// {
// nodeCount: 100,
// activeNodeCount: 99,
// deletedNodeCount: 1,
// entryPoint: { idx: 5, level: 3 }
// }
本库提供了泛型化版本,支持任意数据类型和自定义距离函数:
import { hnsw } from '@leolee9086/hnsw';
// 1. 向量相似性搜索(使用自定义距离函数)
const cosineDistance = (a: number[], b: number[]): number => {
let dotProduct = 0;
let normA = 0;
let normB = 0;
for (let i = 0; i < a.length; i++) {
dotProduct += a[i]! * b[i]!;
normA += a[i]! * a[i]!;
normB += b[i]! * b[i]!;
}
normA = Math.sqrt(normA);
normB = Math.sqrt(normB);
if (normA === 0 || normB === 0) return 1.0;
return 1.0 - dotProduct / (normA * normB);
};
const vectorIndex = hnsw.createIndexGeneric({
M: 16,
efConstruction: 200,
distanceFunction: cosineDistance
});
// 2. 字符串相似性搜索(使用编辑距离)
const editDistance = (a: string, b: string): number => {
const matrix: number[][] = [];
for (let i = 0; i <= a.length; i++) {
matrix[i] = [];
matrix[i]![0] = i;
}
for (let j = 0; j <= b.length; j++) {
matrix[0]![j] = j;
}
for (let i = 1; i <= a.length; i++) {
for (let j = 1; j <= b.length; j++) {
if (a[i - 1] === b[j - 1]) {
matrix[i]![j] = matrix[i - 1]![j - 1]!;
} else {
matrix[i]![j] = Math.min(
matrix[i - 1]![j]! + 1, // 删除
matrix[i]![j - 1]! + 1, // 插入
matrix[i - 1]![j - 1]! + 1 // 替换
);
}
}
}
return matrix[a.length]![b.length]!;
};
const stringIndex = hnsw.createIndexGeneric({
M: 16,
efConstruction: 200,
distanceFunction: editDistance
});
// 插入字符串
const strings = ['hello', 'world', 'help', 'hell', 'hero'];
strings.forEach(str => stringIndex.insertNode(str));
// 搜索相似字符串
const results = stringIndex.search('help', 3);
console.log(results); // 找到编辑距离最小的字符串
// 3. 自定义对象相似性搜索
interface Point {
x: number;
y: number;
label: string;
}
const euclideanDistance = (a: Point, b: Point): number => {
const dx = a.x - b.x;
const dy = a.y - b.y;
return Math.sqrt(dx * dx + dy * dy);
};
const pointIndex = hnsw.createIndexGeneric({
M: 16,
efConstruction: 200,
distanceFunction: euclideanDistance
});
// 插入点对象
const points: Point[] = [
{ x: 0, y: 0, label: 'origin' },
{ x: 1, y: 0, label: 'right' },
{ x: 0, y: 1, label: 'up' },
{ x: 1, y: 1, label: 'diagonal' }
];
points.forEach(point => pointIndex.insertNode(point));
// 搜索最近的点
const queryPoint: Point = { x: 0.1, y: 0.1, label: 'near_origin' };
const nearestPoints = pointIndex.search(queryPoint, 2);
// 4. 优化距离函数(支持预计算)
const optimizedCosineDistance = (a: number[], b: number[]): number => {
let dotProduct = 0;
let i = 0;
// 循环展开优化
for (; i < a.length - 3; i += 4) {
dotProduct +=
a[i]! * b[i]! +
a[i + 1]! * b[i + 1]! +
a[i + 2]! * b[i + 2]! +
a[i + 3]! * b[i + 3]!;
}
// 处理剩余部分
for (; i < a.length; i++) {
dotProduct += a[i]! * b[i]!;
}
// 假设向量已归一化,简化计算
return 1.0 - dotProduct;
};
const optimizedIndex = hnsw.createIndexGeneric({
M: 16,
efConstruction: 200,
distanceFunction: optimizedCosineDistance
});
hnsw.createIndex(config)
创建HNSW索引实例(标准版,仅支持向量)。
参数:
config.M
(number): 每个节点的最大连接数,影响图的连接密度
config.efConstruction
(number): 构建时的搜索参数,影响构建质量
config.metricType
('cosine' | 'l2'): 距离度量类型
'cosine'
: 余弦距离,适用于归一化向量'l2'
: 欧几里得距离的平方返回: HNSWIndex实例
hnsw.createIndexGeneric<T>(config)
创建泛型HNSW索引实例,支持任意数据类型。
参数:
config.M
(number): 每个节点的最大连接数config.efConstruction
(number): 构建时的搜索参数config.distanceFunction
(a: T, b: T) => number: 必需,自定义距离函数config.distanceToQuery?
(query: T, target: T) => number: 可选,查询专用距离函数返回: HNSWIndex实例
距离函数要求:
示例距离函数:
// 余弦距离
const cosineDistance = (a: number[], b: number[]): number => {
// 实现余弦距离计算
return 1.0 - dotProduct / (normA * normB);
};
// 编辑距离
const editDistance = (a: string, b: string): number => {
// 实现编辑距离计算
return matrix[a.length]![b.length]!;
};
// 欧几里得距离
const euclideanDistance = (a: Point, b: Point): number => {
const dx = a.x - b.x;
const dy = a.y - b.y;
return Math.sqrt(dx * dx + dy * dy);
};
index.insertNode(item)
向索引中插入新项目。
标准版参数:
item
(number[]): 要插入的向量
泛型版参数:
item
(T): 要插入的项目
注意: 插入操作是O(log n)复杂度,适合实时插入
index.search(queryItem, k, efSearch?)
搜索最近邻。
标准版参数:
queryItem
(number[]): 查询向量
泛型版参数:
queryItem
(T): 查询项目
通用参数:
k
(number): 返回的最近邻数量
efSearch
(number, 可选): 搜索时的参数
返回: Neighbor[] - 包含idx和distance的对象数组,按距离升序排列
index.deleteNode(nodeIdx)
删除指定节点。
参数:
nodeIdx
(number): 要删除的节点索引返回: boolean - 删除是否成功
注意:
index.getStats()
获取索引统计信息。
返回:
{
nodeCount: number, // 节点总数(包括已删除的)
activeNodeCount: number, // 活跃节点数(未删除的)
deletedNodeCount: number, // 已删除节点数
entryPoint: { // 入口点信息
idx: number, // 入口点索引
level: number // 入口点层级
}
}
参数 | 推荐值 | 说明 |
---|---|---|
M | 16-64 | 连接数,影响搜索精度和速度 |
efConstruction | 100-400 | 构建质量,影响索引质量 |
efSearch | k的2-4倍 | 搜索精度,影响召回率 |
getStats()
监控索引状态距离函数优化:
类型安全:
性能考虑:
应用场景:
pnpm install
# 运行所有测试
pnpm test
# 运行测试并监听变化
pnpm test:watch
# 运行基准测试
pnpm bench
# 生成覆盖率报告
pnpm test:coverage
# 构建项目
pnpm build
# 开发模式构建
pnpm dev
项目包含完整的基准测试套件,对比HNSWLib等主流实现:
# 运行性能基准测试
pnpm bench
基准测试包括:
欢迎提交Issue和Pull Request!
MIT License - 详见 LICENSE 文件。
FAQs
JavaScript HNSW (Hierarchical Navigable Small World) 向量索引库,支持动态操作和泛型搜索
We found that @leolee9086/hnsw demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Socket uncovers malicious Rust crates impersonating fast_log to steal Solana and Ethereum wallet keys from source code.
Research
A malicious package uses a QR code as steganography in an innovative technique.
Research
/Security News
Socket identified 80 fake candidates targeting engineering roles, including suspected North Korean operators, exposing the new reality of hiring as a security function.