向量搜索
LanBuffer 的 Table API 基于 Lance 格式提供高性能向量搜索能力,兼容 LanceDB 协议。
基本向量搜索
向量搜索通过查询端点 POST /v1/table/{id}/query/ 实现。当请求体中包含非空的 vector 字段时,自动执行向量搜索。
SDK 示例:
import * as lancedb from "@lancedb/lancedb";
const db = await lancedb.connect("lanbuff://127.0.0.1:7001");
// 创建包含向量数据的表
const tbl = await db.createTable("products", [
{ vector: [0.1, 0.2, 0.3, 0.4], name: "产品A", price: 29.9 },
{ vector: [0.5, 0.1, 0.8, 0.2], name: "产品B", price: 49.9 },
{ vector: [0.9, 0.7, 0.1, 0.6], name: "产品C", price: 19.9 },
{ vector: [0.3, 0.4, 0.5, 0.1], name: "产品D", price: 99.9 },
]);
// 搜索最相似的 3 条记录
const results = await tbl.search([0.1, 0.2, 0.3, 0.4]).limit(3).toArray();
console.log(results);
HTTP 请求:
curl -X POST http://127.0.0.1:7001/v1/table/products/query/ \
-H "Content-Type: application/json" \
-d '{
"vector": [0.1, 0.2, 0.3, 0.4],
"k": 3
}'
距离度量
通过 distance_type 参数指定距离计算方式:
| 度量 | 说明 | 适用场景 |
|---|---|---|
L2 | 欧氏距离(默认) | 通用场景 |
cosine | 余弦相似度 | 文本嵌入、归一化向量 |
dot | 内积 | 推荐系统、最大内积搜索 |
hamming | 汉明距离 | 二进制向量 |
// 使用余弦相似度
const results = await tbl
.search([0.1, 0.2, 0.3, 0.4])
.distanceType("cosine")
.limit(5)
.toArray();
带过滤的向量搜索
结合 SQL 过滤表达式缩小搜索范围:
// 先过滤再搜索(prefilter,默认行为)
const results = await tbl
.search([0.1, 0.2, 0.3, 0.4])
.where("price < 50")
.limit(10)
.toArray();
预过滤 vs 后过滤:
- 预过滤(
prefilter: true,默认)— 先根据条件过滤数据,再在过滤后的子集上执行向量搜索。结果数量精确等于k(如果有足够的匹配数据)。 - 后过滤(
prefilter: false)— 先执行向量搜索找到k个最近邻,再用条件过滤。结果数量可能少于k。
// 后过滤模式
const results = await tbl
.search([0.1, 0.2, 0.3, 0.4])
.where("price < 50")
.prefilter(false)
.limit(10)
.toArray();
选择返回列
只返回需要的列以减少数据传输:
const results = await tbl
.search([0.1, 0.2, 0.3, 0.4])
.select(["name", "price"])
.limit(5)
.toArray();
向量索引
对于大规模数据集,创建向量索引可以显著提升搜索性能:
// 创建 IVF_PQ 索引
await tbl.createIndex("vector", {
config: lancedb.Index.ivfPq({
numPartitions: 256,
numSubVectors: 16,
}),
});
索引类型选择:
| 索引类型 | 特点 | 建议场景 |
|---|---|---|
IVF_FLAT | 无量化,精度最高 | 数据量 < 100 万,对精度要求极高 |
IVF_PQ | 乘积量化,内存占用小 | 通用大规模场景(默认推荐) |
IVF_SQ | 标量量化,精度与速度平衡 | 中等规模,需要较好精度 |
IVF_HNSW_SQ | HNSW 图 + 标量量化 | 对延迟要求极高的场景 |
索引参数调优
搜索时可通过参数调整召回率与速度的平衡:
// nprobes: 探测的分区数,越大召回率越高但越慢
// refine_factor: 精炼因子,从候选集中重新排序
const results = await tbl
.search([0.1, 0.2, 0.3, 0.4])
.nprobes(20)
.refineFactor(10)
.limit(5)
.toArray();
| 参数 | 说明 | 默认值 |
|---|---|---|
nprobes | 探测的 IVF 分区数,增大可提高召回率 | 由索引决定 |
refine_factor | 精炼因子,先取 k * refine_factor 个候选再精排 | 无 |
暴力搜索
跳过索引直接暴力搜索(适合小数据集或调试):
curl -X POST http://127.0.0.1:7001/v1/table/products/query/ \
-H "Content-Type: application/json" \
-d '{
"vector": [0.1, 0.2, 0.3, 0.4],
"k": 5,
"bypass_vector_index": true
}'