关于 how-to-do-offline-recommendations-with-sqlite-and-gemini
本指南介绍如何用 SQLite 向量搜索和 Gemini 生成的描述与嵌入,构建离线相关内容推荐,适合为 CMS 内容添加推荐功能的开发者。
主要功能
- 01使用 Gemini 生成描述
- 02创建文本嵌入
- 03用 sqlite-vec 存储向量
- 04通过 kNN 搜索相关帖子
- 05内容变更时更新向量
适用场景
- 01展示相关博客文章
- 02无需每次访问发起网络请求即可提供推荐
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ rodydavis/ skills --skill how-to-do-offline-recommendations-with-sqlite-and-gemini安装后在 Claude Code 中输入/how-to-do-offline-recommendations-with-sqlite-and-gemini确认已加载。
详细介绍
如何使用 SQLite 和 Gemini 实现离线推荐
使用 CMS(如 PocketBase)时,通常会为相关内容添加某种推荐功能。例如,你可以列出博客文章,并通过随机选择或最近浏览的内容来展示相关文章。
我最初是从 Aaron Francis 的 YouTube 频道上了解到这项技术的:
文本嵌入
文本嵌入是一种将一段文本转换为数字数组的方法。有了这种数学表示形式,我们就可以轻松地将其存储在数据库中,并运行常见函数来计算已存储向量之间的距离。
你需要一个 AI Studio API 密钥来生成描述和嵌入。
为了创建嵌入,我们需要先生成足够小、能够适配嵌入窗口大小的文本块。例如,我们可以使用 Gemini 等大模型生成博客文章的描述,然后将描述向量化并存储在数据库中。
只有在内容发生变化时,我们才需要生成新的嵌入和描述,因此计费成本取决于内容变化的频率。
存储向量
要将文本嵌入存储为向量,我们可以使用名为 sqlite-vec 的运行时可加载扩展,将其保存到 SQLite 数据库中。下面是 README 中关于如何直接在 SQLite 中查询向量的示例:
.load ./vec0
create virtual table vec_examples using vec0(
sample_embedding float[8]
);
-- vectors can be provided as JSON or in a compact binary format
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]');
-- KNN style query
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;
/*
┌───────┬──────────────────┐
│ rowid │ distance │
├───────┼──────────────────┤
│ 2 │ 2.38687372207642 │
│ 1 │ 2.38978505134583 │
└───────┴──────────────────┘
*/
现在,我们只需将之前创建的向量存储在一个表中,该表会随着内容变化而更新。
CREATE TABLE posts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
content TEXT NOT NULL,
description TEXT.
embeddings TEXT
);
CREATE VIRTUAL TABLE vec_posts USING vec0(
id INTEGER PRIMARY KEY,
embedding float[768]
);
-- Sync vectors
INSERT INTO vec_posts(id, embedding) SELECT id, embeddings FROM posts;
我们也可以设置触发器来保持数据最新,但在 PocketBase 中,我使用事件钩子来更新虚拟表。
生成推荐结果
要离线生成推荐结果,我们只需使用一篇博客文章作为输入查询,然后通过 k 近邻搜索(kNN)获取 N 篇相关文章。
SELECT
vec_posts.id as id,
vec_posts.embedding as embedding,
posts.title as title,
posts.description as description,
posts.slug as slug
FROM vec_posts
INNER JOIN vec_posts.id = posts.id
WHERE embedding match ?
AND k = 6
ORDER BY distance;
我们只需将当前选中的博客文章的向量作为 ? 参数传入,然后从列表中过滤掉当前博客文章,就能得到向量数据库中与之最相关的 N 篇博客文章。
总结
这样,无论一篇博客文章被访问多少次,推荐功能都不会产生网络调用,因此能够很好地扩展。
你可以在我的网站上浏览各种博客文章,查看每篇文章末尾生成的描述和相关文章,亲自体验这一功能。