mcpField
S
sqlite-vec

sqlite-vec

github.com/existential-birds数据与数据库85171 次安装11 周前更新
代码仓库

关于 sqlite-vec

sqlite-vec 是用于在 SQLite 数据库中存储向量嵌入并执行相似度搜索的扩展,面向无需单独向量数据库的开发者。它支持多种向量类型、元数据筛选和分区键。

主要功能

  1. 01在 SQLite 中存储向量
  2. 02KNN 相似度查询
  3. 03支持 float、int8 和 bit 向量
  4. 04元数据筛选与分区键
  5. 05向量运算与量化

适用场景

  1. 01为 SQLite 应用添加相似度搜索
  2. 02按元数据筛选近邻结果
  3. 03按租户划分向量查询
  4. 04执行向量变换和量化

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/existential-birds/beagle --skill sqlite-vec

安装后在 Claude Code 中输入/sqlite-vec确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
tables.md
operations.md
queries.md
setup.md

详细介绍

sqlite-vec

sqlite-vec 是一个轻量级 SQLite 扩展,用于向量相似度搜索。它支持直接在 SQLite 数据库中存储和查询向量嵌入,无需外部向量数据库。

检查关卡

配置存储和 KNN 查询时,请按顺序执行以下步骤;在生产环境中依赖结果或在评审评论中引用结果之前,每一步都必须通过客观检查。

  1. 维度锁定 — float[N]、int8[N] 或 bit[N] 中的 N 必须与嵌入模型的输出长度(以及你应用的任何 Matryoshka 切片)一致。通过标准: CREATE VIRTUAL TABLE DDL 和序列化向量长度(len(vector) 或模型文档中注明的维度)中出现相同的 N。
  2. 序列化匹配 — 列类型必须与 Python(或其他语言)的辅助函数相匹配:float[N] 使用 serialize_float32,int8[N] 使用 serialize_int8,bit[N] 使用二进制规则。通过标准: 至少对一个已知测试向量执行往返插入,并使用相同的序列化器进行 MATCH 查询,且返回预期行(例如,k = 1 返回该行)。
  3. 有文档依据的边界声明 — 只有当距离度量选择、元数据筛选运算符、分区键规则或特定版本行为出现在本技能或 资源 下链接的官方文档中时,才能对其作出断言。通过标准: 在将相关声明视为已确认之前,必须在产物(issue、PR 或备注)中引用相关 URL 或文档章节。

快速参考

加载扩展
import sqlite3
import sqlite_vec
from sqlite_vec import serialize_float32

db = sqlite3.connect(":memory:")
db.enable_load_extension(True)
sqlite_vec.load(db)
db.enable_load_extension(False)
基本 KNN 查询
-- Create table
CREATE VIRTUAL TABLE vec_items USING vec0(
  embedding float[4]
);

-- Insert vectors (use serialize_float32() in Python)
INSERT INTO vec_items(rowid, embedding)
VALUES (1, X'CDCCCC3DCDCC4C3E9A99993E00008040');

-- KNN query
SELECT rowid, distance
FROM vec_items
WHERE embedding MATCH '[0.3, 0.3, 0.3, 0.3]'
  AND k = 10
ORDER BY distance;

核心概念

向量类型

sqlite-vec 支持三种向量元素类型:

  1. float[N] - 32 位浮点数(每个元素 4 字节)

    • 最常用于嵌入(OpenAI、Cohere 等)
    • 示例:文本嵌入 3 小型模型使用 float[1536]
  2. int8[N] - 8 位有符号整数(每个元素 1 字节)

    • 范围:-128 到 127
    • 用于量化嵌入
  3. bit[N] - 二进制向量(每个元素 1 位,打包为字节)

    • 存储最紧凑
    • 用于二进制量化
二进制序列化格式

向量必须以二进制 BLOB 或 JSON 字符串的形式提供。Python 辅助函数:

from sqlite_vec import serialize_float32, serialize_int8
import struct

# Float32 vectors
vector = [0.1, 0.2, 0.3, 0.4]
blob = serialize_float32(vector)
# Equivalent to: struct.pack("%sf" % len(vector), *vector)

# Int8 vectors
int_vector = [1, 2, 3, 4]
blob = serialize_int8(int_vector)
# Equivalent to: struct.pack("%sb" % len(int_vector), *int_vector)

NumPy 数组可以直接传入(必须转换为 float32):

import numpy as np
embedding = np.array([0.1, 0.2, 0.3, 0.4]).astype(np.float32)
db.execute("SELECT vec_length(?)", [embedding])

vec0 虚拟表

vec0 虚拟表是向量搜索的主要数据结构。

创建基本表
CREATE VIRTUAL TABLE vec_documents USING vec0(
  document_id integer primary key,
  contents_embedding float[768]
);
距离度量
CREATE VIRTUAL TABLE vec_items USING vec0(
  embedding float[768] distance_metric=cosine
);

支持的度量:l2(默认)、cosine、hamming(仅限二进制向量)

列类型

vec0 表支持四种列类型:

  1. 向量列 - 存储嵌入(float[N]、int8[N]、bit[N])
  2. 元数据列 - 建立索引,可在 KNN 查询中筛选
  3. 分区键列 - 通过内部分片加快筛选查询
  4. 辅助列 - 未建立索引的存储(以 + 为前缀)

包含所有列类型的示例:

CREATE VIRTUAL TABLE vec_knowledge_base USING vec0(
  document_id integer primary key,

  -- Partition keys (sharding)
  organization_id integer partition key,
  created_month text partition key,

  -- Vector column
  content_embedding float[768] distance_metric=cosine,

  -- Metadata columns (filterable in KNN)
  document_type text,
  language text,
  word_count integer,
  is_public boolean,

  -- Auxiliary columns (not filterable)
  +title text,
  +full_content text,
  +url text
);

KNN 查询

标准查询语法
SELECT rowid, distance
FROM vec_items
WHERE embedding MATCH ?
  AND k = 10
ORDER BY distance;

关键组成部分:

  • WHERE embedding MATCH ? - 触发 KNN 查询
  • AND k = 10 - 限制为 10 个最近邻
  • ORDER BY distance - 按距离由近到远排序结果
元数据筛选
SELECT document_id, distance
FROM vec_movies
WHERE synopsis_embedding MATCH ?
  AND k = 5
  AND genre = 'scifi'
  AND num_reviews BETWEEN 100 AND 500
  AND mean_rating > 3.5
  AND contains_violence = false
ORDER BY distance;

元数据支持的运算符:=、!=、>、>=、<、<=、BETWEEN

不支持:IS NULL、LIKE、GLOB、REGEXP、标量函数

分区键筛选
SELECT document_id, distance
FROM vec_documents
WHERE contents_embedding MATCH ?
  AND k = 20
  AND user_id = 123  -- Partition key pre-filters
ORDER BY distance;

分区键支持多租户或按时间分片。最佳实践:

  • 每个唯一分区值应至少对应 100 个向量
  • 最多使用 1-2 个分区键
  • 避免过度分片(唯一值过多)
与源表联接
WITH knn_matches AS (
  SELECT document_id, distance
  FROM vec_documents
  WHERE contents_embedding MATCH ?
    AND k = 10
)
SELECT
  documents.id,
  documents.title,
  knn_matches.distance
FROM knn_matches
LEFT JOIN documents ON documents.id = knn_matches.document_id
ORDER BY knn_matches.distance;

距离函数

对于手动计算距离(非 vec0 表):

-- L2 distance
SELECT vec_distance_l2('[1, 2]', '[3, 4]');
-- 2.8284...

-- Cosine distance
SELECT vec_distance_cosine('[1, 1]', '[2, 2]');
-- ~0.0

-- Hamming distance (bit vectors)
SELECT vec_distance_hamming(vec_bit(X'F0'), vec_bit(X'0F'));
-- 8

向量操作

构造函数
-- Float32
SELECT vec_f32('[.1, .2, .3, 4]');  -- Subtype 223

-- Int8
SELECT vec_int8('[1, 2, 3, 4]');  -- Subtype 225

-- Bit
SELECT vec_bit(X'F0');  -- Subtype 224
元数据函数
-- Get length
SELECT vec_length('[1, 2, 3]');  -- 3

-- Get type
SELECT vec_type(vec_int8('[1, 2]'));  -- 'int8'

-- Convert to JSON
SELECT vec_to_json(vec_f32('[1, 2]'));  -- '[1.000000,2.000000]'
算术运算
-- Add vectors
SELECT vec_to_json(
  vec_add('[.1, .2, .3]', '[.4, .5, .6]')
);
-- '[0.500000,0.700000,0.900000]'

-- Subtract vectors
SELECT vec_to_json(
  vec_sub('[.1, .2, .3]', '[.4, .5, .6]')
);
-- '[-0.300000,-0.300000,-0.300000]'
转换
-- Normalize (L2 norm)
SELECT vec_to_json(
  vec_normalize('[2, 3, 1, -4]')
);
-- '[0.365148,0.547723,0.182574,-0.730297]'

-- Slice (for Matryoshka embeddings)
SELECT vec_to_json(
  vec_slice('[1, 2, 3, 4]', 0, 2)
);
-- '[1.000000,2.000000]'

-- Matryoshka pattern: slice then normalize
SELECT vec_normalize(vec_slice(embedding, 0, 256))
FROM vec_items;
量化
-- Binary quantization (positive→1, negative→0)
SELECT vec_quantize_binary('[1, 2, 3, 4, -5, -6, -7, -8]');
-- X'0F'

-- Visualize
SELECT vec_to_json(
  vec_quantize_binary('[1, 2, -3, 4, -5, 6, -7, 8]')
);
-- '[0,1,0,0,1,0,1,0]'
迭代
-- Iterate through elements
SELECT rowid, value
FROM vec_each('[1, 2, 3, 4]');
/*
┌───────┬───────┐
│ rowid │ value │
├───────┼───────┤
│ 0     │ 1     │
│ 1     │ 2     │
│ 2     │ 3     │
│ 3     │ 4     │
└───────┴───────┘
*/

Python 集成

完整示例
import sqlite3
import sqlite_vec
from sqlite_vec import serialize_float32

# Setup
db = sqlite3.connect(":memory:")
db.enable_load_extension(True)
sqlite_vec.load(db)
db.enable_load_extension(False)

# Create table
db.execute("""
    CREATE VIRTUAL TABLE vec_items USING vec0(
        embedding float[4]
    )
""")

# Insert vectors
items = [
    (1, [0.1, 0.1, 0.1, 0.1]),
    (2, [0.2, 0.2, 0.2, 0.2]),
    (3, [0.3, 0.3, 0.3, 0.3])
]

with db:
    for rowid, vector in items:
        db.execute(
            "INSERT INTO vec_items(rowid, embedding) VALUES (?, ?)",
            [rowid, serialize_float32(vector)]
        )

# Query
query = [0.25, 0.25, 0.25, 0.25]
results = db.execute(
    """
    SELECT rowid, distance
    FROM vec_items
    WHERE embedding MATCH ?
      AND k = 2
    ORDER BY distance
    """,
    [serialize_float32(query)]
).fetchall()

for rowid, distance in results:
    print(f"rowid={rowid}, distance={distance}")
嵌入 API 集成
from openai import OpenAI
from sqlite_vec import serialize_float32

client = OpenAI()

# Generate embedding
response = client.embeddings.create(
    input="your text here",
    model="text-embedding-3-small"
)
embedding = response.data[0].embedding

# Store in sqlite-vec
db.execute(
    "INSERT INTO vec_documents(id, embedding) VALUES(?, ?)",
    [doc_id, serialize_float32(embedding)]
)

# Query
query_embedding = client.embeddings.create(
    input="search query",
    model="text-embedding-3-small"
).data[0].embedding

results = db.execute(
    """
    SELECT id, distance
    FROM vec_documents
    WHERE embedding MATCH ?
      AND k = 10
    """,
    [serialize_float32(query_embedding)]
).fetchall()

性能提示

  1. 对多租户或按时间筛选的查询,使用分区键
  2. 将 k 控制在合理范围内(大多数用例为 10-100)
  3. 尽可能使用元数据列进行筛选
  4. 为嵌入选择合适的距离度量
  5. 在事务中批量执行操作
  6. 对不需要用于筛选的大型数据,使用辅助列
  7. 确保每个唯一值对应的分区键至少有 100 个向量

常见模式

多租户搜索
CREATE VIRTUAL TABLE vec_docs USING vec0(
  doc_id integer primary key,
  user_id integer partition key,
  embedding float[768]
);

SELECT doc_id, distance
FROM vec_docs
WHERE embedding MATCH ? AND k = 10 AND user_id = 123;
混合搜索
SELECT product_id, distance
FROM vec_products
WHERE embedding MATCH ?
  AND k = 20
  AND category = 'electronics'
  AND price < 1000.0
ORDER BY distance;
Matryoshka 嵌入
-- Adaptive dimensions: slice then normalize
SELECT vec_normalize(vec_slice(embedding, 0, 256))
FROM vec_items;

参考文件

  • setup.md - 安装、扩展加载、Python 绑定、NumPy 集成
  • tables.md - vec0 表创建、列类型、元数据/分区/辅助列
  • queries.md - KNN 查询模式、元数据筛选、分区筛选、优化
  • operations.md - 向量操作、构造函数、转换、量化、批量操作

资源

评论

支持 Markdown