四时宝库

程序员的知识宝库

如何在 SQLite 中实现矢量搜索?

如何在 SQLite 中实现矢量搜索?

在现代应用中,尤其是在自然语言处理(NLP)和机器学习(ML)领域,矢量搜索变得越来越重要。

SQLite 是一种轻量级数据库,虽然没有内置的矢量搜索功能,但通过扩展和一些额外的步骤,可以轻松实现矢量搜索。

什么是sqlite-vec?

sqlite-vec是一个SQLite数据库的向量搜索扩展,添加了向量搜索功能。

该扩展完全用C语言编写,无依赖性,具有极好的可移植性,可以在大多数操作系统和环境中运行,且具有MIT/Apache-2.0双重许可证。

sqlite-vec 是一个极小且“足够快”的 SQLite 扩展,允许在 SQLite 中存储和查询浮点、整数和二进制矢量。

它是 sqlite-vss 的继任者,旨在提供跨平台的矢量搜索能力,能够在各种环境下运行,包括 Linux、MacOS、Windows,甚至浏览器(使用 WASM)和树莓派等设备。

什么时候使用sqlite-vec,适用于哪些场景?

大多数现实世界的AI应用并不涉及数十亿个向量,而是处理数千或数百个向量。

最近邻(ANN)算法用于索引,但这会降低搜索效率。

sqlite-vec使用快速的暴力搜索,因此适合小型应用(或数据库)使用。

sqlite-vec有哪些优势?

sqlite-vec的几个优势包括:

  1. 无其他依赖
  2. 使用虚拟表
  3. 在阴影表中存储向量块
  4. 避免一次性加载所有内容到内存中
  5. 支持在 vec0 虚拟表中存储和查询浮点、int8 和二进制矢量。
  6. 使用纯 C 编写,无任何依赖项,能够在任何支持 SQLite 的环境中运行。
  7. 可通过 rowid IN (...) 子查询预筛选矢量。

安装

要在您的项目中使用 sqlite-vec,您可以根据您的开发环境选择相应的安装方式:

语言

安装命令

更多信息

Python

pip install sqlite-vec

PyPI

Node.js

npm install sqlite-vec

npm

Ruby

gem install sqlite-vec

Gem

Go

go get -u github.com/asg017/sqlite-vec/bindings/go

Go Reference

Rust

cargo add sqlite-vec

Crates.io

Datasette

datasette install datasette-sqlite-vec

Datasette

rqlite

rqlited -extensions-path=sqlite-vec.tar.gz

rqlite

sqlite-utils

sqlite-utils install sqlite-utils-sqlite-vec

sqlite-utils

入门示例

以下是如何使用 sqlite-vec 的简单示例:

以下是如何使用 sqlite-vec 的简单示例:

1、加载扩展

.load ./vec0

2、创建虚拟表

CREATE VIRTUAL TABLE vec_examples USING vec0(
  sample_embedding FLOAT[8]  -- 创建一个包含8维浮点向量的虚拟表
);

3、插入矢量

您可以通过 JSON 格式或紧凑的二进制格式提供向量。以下是将几个矢量插入表的示例:

INSERT INTO vec_examples(rowid, sample_embedding)
VALUES
  (1, '[-0.200, 0.250, 0.341, -0.211, 0.645, 0.935, -0.316, -0.924]'),
  (2, '[0.443, -0.501, 0.355, -0.771, 0.707, -0.708, -0.185, 0.362]'),
  (3, '[0.716, -0.927, 0.134, 0.052, -0.669, 0.793, -0.634, -0.162]'),
  (4, '[-0.710, 0.330, 0.656, 0.041, -0.990, 0.726, 0.385, -0.958]');

4、执行 KNN 查询

您可以执行 KNN 查询来查找与给定向量最接近的向量:

SELECT
  rowid,
  distance
FROM vec_examples
WHERE sample_embedding MATCH '[0.890, 0.544, 0.825, 0.961, 0.358, 0.0196, 0.521, 0.175]'
ORDER BY distance
LIMIT 2;

这将返回最接近的两个结果,查询结果类似于:

一个完整示例

假设我们想要创建一个在线书籍推荐系统。每本书都有一些特征,比如主题、风格和情感色彩等。我们将用这些特征来为用户推荐相似的书籍。

import sqlite3
import sqlite_vec

from typing import List
import struct

def serialize_f32(vector: List[float]) -> bytes:
    """将浮点数列表序列化为紧凑的原始字节格式"""
    return struct.pack("%sf" % len(vector), *vector)

# 连接到内存数据库
db = sqlite3.connect(":memory:")
db.enable_load_extension(True)
sqlite_vec.load(db)
db.enable_load_extension(False)

# 查询SQLite和vec版本
sqlite_version, vec_version = db.execute(
    "select sqlite_version(), vec_version()"
).fetchone()
print(f"sqlite_version={sqlite_version}, vec_version={vec_version}")

# 准备书籍数据,每本书有一个嵌入向量表示其特征
books = [
    (1, [0.9, 0.8, 0.1, 0.2]),  # 书籍 1 特征向量
    (2, [0.7, 0.6, 0.2, 0.4]),  # 书籍 2 特征向量
    (3, [0.1, 0.1, 0.9, 0.8]),  # 书籍 3 特征向量
    (4, [0.3, 0.5, 0.7, 0.9]),  # 书籍 4 特征向量
    (5, [0.2, 0.4, 0.6, 0.5]),  # 书籍 5 特征向量
]
# 用户喜欢的书籍特征向量
query = [0.1, 0.1, 0.9, 0.8]  # 用户输入的书籍特征向量

# 创建虚拟表用于存储书籍信息
db.execute("CREATE VIRTUAL TABLE vec_books USING vec0(embedding float[4])")

# 插入书籍数据
with db:
    for book in books:
        db.execute(
            "INSERT INTO vec_books(rowid, embedding) VALUES (?, ?)",
            [book[0], serialize_f32(book[1])],
        )

# 查询与用户喜欢的书籍相似的书籍
rows = db.execute(
    """
      SELECT
        rowid,
        distance
      FROM vec_books
      WHERE embedding MATCH ?
      ORDER BY distance
      LIMIT 3
    """,
    [serialize_f32(query)],
).fetchall()

# 输出推荐的书籍
print("推荐的书籍 ID 和与用户输入书籍的距离:")
for row in rows:
    print(row)

代码解读

1、数据准备

每本书用一个浮点数列表表示其特征向量,向量的不同维度可以代表书籍的主题、风格和情感等。例如:

书籍 1:特征向量 [0.9, 0.8, 0.1, 0.2] 可能表示一本浪漫小说。

书籍 2:特征向量 [0.7, 0.6, 0.2, 0.4] 可能表示一本悬疑小说。

书籍 3:特征向量 [0.1, 0.1, 0.9, 0.8] 可能表示一本科幻小说。

2、查询相似书籍

用户输入的书籍特征向量为 [0.1, 0.1, 0.9, 0.8],代表他们喜欢的书籍。

使用 sqlite_vec 扩展的 MATCH 功能查询与用户输入书籍相似的书籍,结果按照距离升序排列,并限制返回 3 条记录。

3、输出推荐结果

最后打印推荐的书籍的 ID 和与用户输入书籍的距离。

输出:

这个代码实现了一个简单的书籍推荐系统,通过输入用户喜欢书籍的特征,查询与之相似的书籍,并推荐给用户。

这样的实现方式可以用在各种基于特征的推荐系统中,比如电影推荐、音乐推荐等。

知识拓展

Q: 什么是向量量化?它为什么重要?向量量化如何工作?

A: 向量量化是一种向量压缩技术。我们通过以下例子来理解:

每个浮点向量占用4字节的空间。如果我们需要存储100万个向量,每个向量有1500维,那么所需的存储空间为:

sqlite-vec支持位向量和浮点向量换句话说,在sqlite-vec中,一个向量可以用1位表示。因此,大小减少了32倍。


Q: 向量量化的后果是什么?

A: 向量量化或任何其他向量压缩技术会导致质量损失。根据嵌入模型的不同,准确率将降低约5-10%,但查询速度将提高约10倍。

结论

sqlite-vec 提供了一种简单、跨平台的方式来实现 SQLite 中的矢量搜索。

通过加载扩展、创建虚拟表、插入矢量并执行 KNN 查询,您可以在自己的应用程序中轻松集成这一强大功能。

这种能力能够显著提升数据检索的灵活性和准确性,特别是在处理自然语言处理和机器学习相关任务时。

https://alexgarcia.xyz/blog/2024/sqlite-vec-stable-release/index.html

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言
    友情链接