Rust高效向量搜索库usearch的使用,usearch提供快速相似性搜索和近似最近邻算法实现
Rust高效向量搜索库usearch的使用
USearch是一个小型且快速的单文件相似性搜索和聚类引擎,用于向量和文本数据。它提供了以下主要特性:
- 比FAISS快10倍的HNSW实现
- 简单且可扩展的C++11单头文件库
- 支持用户自定义度量标准
- 硬件无关的f16和i8支持(半精度和四分之一精度)
- 可以从磁盘查看大型索引而无需加载到RAM
- 支持异构查找、重命名/重新标记和即时删除
基本用法示例
以下是Rust中使用USearch进行向量搜索的基本示例:
use usearch::ffi::IndexOptions;
use usearch::ffi::MetricKind;
use usearch::Index;
fn main() {
// 创建索引
let options = IndexOptions {
dimensions: 3,
metric: MetricKind::L2sq,
quantization: usearch::ffi::ScalarKind::F32,
connectivity: 0,
expansion_add: 0,
expansion_search: 0,
multi: false,
};
let mut index = Index::new(options).unwrap();
// 添加向量
let key: u64 = 42;
let vector = vec![0.2, 0.6, 0.4];
index.add(key, &vector).unwrap();
// 搜索相似向量
let results = index.search(&vector, 10).unwrap();
assert_eq!(results.keys[0], key);
assert!(results.distances[0] <= 0.001);
}
过滤搜索示例
USearch支持在搜索过程中应用过滤谓词:
let is_odd = |key: u64| key % 2 == 1;
let query = vec![0.2, 0.1, 0.2, 0.1, 0.3];
let results = index.filtered_search(&query, 10, is_odd).unwrap();
assert!(
results.keys.iter().all(|&key| key % 2 == 1),
"All keys must be odd"
);
完整示例代码
以下是一个更完整的Rust示例,展示USearch的更多功能:
use usearch::ffi::{IndexOptions, MetricKind, ScalarKind};
use usearch::Index;
use rand::Rng;
fn main() {
// 配置索引参数
let options = IndexOptions {
dimensions: 128,
metric: MetricKind::Cos,
quantization: ScalarKind::F16,
connectivity: 16,
expansion_add: 128,
expansion_search: 64,
multi: false,
};
// 创建索引
let mut index = Index::new(options).unwrap();
// 生成1000个随机向量并添加到索引
let mut rng = rand::thread_rng();
for i in 0..1000 {
let vector: Vec<f32> = (0..128).map(|_| rng.gen()).collect();
index.add(i, &vector).unwrap();
}
// 生成查询向量
let query: Vec<f32> = (0..128).map(|_| rng.gen()).collect();
// 执行搜索并获取前10个最相似结果
let results = index.search(&query, 10).unwrap();
println!("最相似的10个向量:");
for i in 0..results.count {
println!("ID: {}, 距离: {}", results.keys[i], results.distances[i]);
}
// 保存索引到文件
index.save("data.usearch").unwrap();
// 从文件加载索引
let loaded_index = Index::load("data.usearch").unwrap();
// 使用加载的索引进行搜索
let new_results = loaded_index.search(&query, 5).unwrap();
println!("从加载索引中获取的5个结果:");
for i in 0..new_results.count {
println!("ID: {}, 距离: {}", new_results.keys[i], new_results.distances[i]);
}
// 使用过滤搜索
let is_even = |key: u64| key % 2 == 0;
let filtered_results = loaded_index.filtered_search(&query, 5, is_even).unwrap();
println!("偶数ID的结果:");
for i in 0..filtered_results.count {
println!("ID: {}, 距离: {}", filtered_results.keys[i], filtered_results.distances[i]);
}
}
性能优化建议
- 对于大型数据集,考虑使用
ScalarKind::BF16
或ScalarKind::F16
来减少内存使用 - 调整
connectivity
参数可以影响索引构建时间和搜索质量 expansion_add
和expansion_search
参数可以控制召回率和搜索速度的平衡
USearch支持的距离度量包括:
- 欧几里得距离(L2sq)
- 内积(IP)
- 余弦相似度(Cos)
- 哈弗辛距离(Haversine)
- 自定义距离函数
这个库非常适合需要高效向量搜索的应用场景,如:
- 推荐系统
- 图像检索
- 文本相似性搜索
- 语义搜索
- 聚类分析
1 回复
以下是基于您提供的usearch库使用指南的完整示例代码,演示了从创建索引到搜索相似向量的完整流程:
use usearch::Index;
fn main() {
// 1. 创建索引
let dimensions = 128; // 向量维度
let mut index = Index::options()
.dimensions(dimensions)
.metric("cos") // 使用余弦相似度
.quantization("f32") // 使用f32量化
.connectivity(16) // 连接性参数
.build()
.unwrap();
println!("索引创建成功");
// 2. 添加一些示例向量
let vectors = vec![
vec![0.1; dimensions], // 向量1
vec![0.2; dimensions], // 向量2
vec![0.3; dimensions], // 向量3
];
let keys = vec![1, 2, 3]; // 向量对应的唯一ID
// 批量添加向量
index.extend(&keys, &vectors).unwrap();
println!("成功添加了{}个向量", keys.len());
// 3. 搜索相似向量
let query_vector = vec![0.15; dimensions]; // 查询向量
let k = 2; // 返回2个最相似的结果
let results = index.search(&query_vector, k).unwrap();
println!("最相似的{}个结果:", k);
for result in results {
println!("ID: {}, 距离: {:.4}", result.key, result.distance);
}
// 4. 保存和加载索引
let save_path = "example_index.usearch";
index.save(save_path).unwrap();
println!("索引已保存到: {}", save_path);
// 从文件加载索引
let loaded_index = Index::load(save_path).unwrap();
println!("索引加载成功");
// 5. 使用加载的索引进行搜索
let new_results = loaded_index.search(&query_vector, k).unwrap();
println!("使用加载的索引搜索的结果:");
for result in new_results {
println!("ID: {}, 距离: {:.4}", result.key, result.distance);
}
}
这个完整示例演示了:
- 使用
Index::options()
创建可配置的索引 - 使用
extend()
方法批量添加多个向量 - 使用
search()
方法查询相似向量 - 使用
save()
和load()
方法持久化索引 - 展示了完整的搜索工作流程
代码中的注释详细解释了每个步骤的作用,您可以直接运行这个示例来体验usearch的基本功能。根据实际需求,您可以调整维度数、距离度量类型等参数来优化性能。