Type something to search...
掌握检索增强生成:简化 Sqlite 初学者的 Rag 实现

掌握检索增强生成:简化 Sqlite 初学者的 Rag 实现

我们真的可以用单文件架构实现 RAG 吗?

这是关于使用 SQLite 进行机器学习的两部分系列中的第二部分。在我上一篇文章中,我深入探讨了 SQLite 如何迅速成为 Web 应用程序的生产就绪数据库。在本文中,我将讨论如何使用 SQLite 执行检索增强生成(RAG)。

本文中提到的代码可以在这里找到。

当我第一次学习如何作为一个新兴的数据科学家执行检索增强生成(RAG)时,我遵循了_传统路径_。这通常看起来像:

  • 谷歌检索增强生成并寻找教程
  • 找到最流行的框架,通常是 LangChain 或 LlamaIndex
  • 找到最流行的云向量数据库,通常是 Pinecone 或 Weaviate
  • 阅读大量文档,将所有部分组合在一起,然后成功!

事实上,我确实写了一篇关于我在 LangChain 中使用 Pinecone 构建 RAG 系统的经验的文章(链接)。

使用带有云向量数据库的 RAG 框架并没有什么特别错误。然而,我认为对于初学者来说,这使情况变得过于复杂。我们真的需要一个完整的框架来学习如何做 RAG 吗?进行 API 调用到云向量数据库是必要的吗?这些数据库充当黑箱,这对学习者(或者说对任何人)来说都不是好事。

在本文中,我将向您展示如何在最简单的栈上执行 RAG。实际上,这个“栈”只是带有 sqlite-vec 扩展和 OpenAI API 的 SQLite,以使用它们的 embedding 和聊天模型。我建议您阅读第一部分以深入了解 SQLite 以及它如何迅速为 Web 应用程序做好生产准备。就我们在这里的目的而言,了解 SQLite 是最简单的数据库类型就足够了:您仓库中的一个单文件。

所以放弃您的云向量数据库和臃肿的框架,让我们来做一些 RAG。

SQLite-Vec

SQLite数据库的一个强大功能是使用扩展。对于熟悉Python的人来说,扩展就像库一样。它们是用C语言编写的模块化代码,旨在扩展SQLite的功能,使曾经不可能的事情变为可能。一个流行的SQLite扩展示例是Full-Text Search (FTS)扩展。这个扩展允许SQLite在大量文本数据中执行高效搜索。由于该扩展纯粹用C编写,我们可以在任何可以运行SQLite数据库的地方运行它,包括树莓派和浏览器。

在本文中,我将介绍被称为sqlite-vec的扩展。它赋予SQLite执行vector search的能力。vector search类似于full-text search,因为它允许在文本数据中进行高效搜索。然而,vector search并不是搜索文本中的确切单词或短语,而是具有语义理解。换句话说,搜索“horses”将找到“equestrian”、“pony”、“Clydesdale”等的匹配。full-text search无法做到这一点。

sqlite-vec利用virtual tables,就像大多数SQLite扩展一样。虚拟表类似于常规表,但具有额外的功能:

  • 自定义数据源: SQLite中标准表的数据存储在一个单一的db文件中。对于虚拟表,数据可以存储在外部源中,例如CSV文件或API调用。
  • 灵活的功能: 虚拟表可以添加专门的索引或查询能力,并支持复杂的数据类型,如JSON或XML。
  • 与SQLite Query Engine的集成: 虚拟表与SQLite的标准查询语法无缝集成,例如SELECTINSERTUPDATEDELETE选项。最终,由扩展的编写者来支持这些操作。
  • 模块的使用: 虚拟表的后端逻辑由一个module(用C或其他语言编写)实现。

创建虚拟表的典型语法如下所示:

CREATE VIRTUAL TABLE my_table USING my_extension_module();

该语句的重要部分是my_extension_module()。这指定了将为my_table虚拟表提供后端支持的模块。在sqlite-vec中,我们将使用vec0模块。

代码讲解

本文的代码可以在 这里 找到。它是一个简单的目录,绝大多数文件为 .txt 文件,我们将使用这些文件作为我们的虚拟数据。由于我是一个物理爱好者,绝大多数文件与物理相关,只有少数文件与其他随机领域相关。在本次讲解中,我不会展示完整的代码,而是会突出重要的部分。下面是该仓库的树状视图。请注意,my_docs.db 是 SQLite 用于管理我们所有数据的单文件数据库。

.
├── data
│   ├── cooking.txt
│   ├── gardening.txt
│   ├── general_relativity.txt
│   ├── newton.txt
│   ├── personal_finance.txt
│   ├── quantum.txt
│   ├── thermodynamics.txt
│   └── travel.txt
├── my_docs.db
├── requirements.txt
└── sqlite_rag_tutorial.py

第一步是安装必要的库。下面是我们的 requirements.txt 文件。如你所见,它只有三个库。我建议创建一个最新版本的 Python 虚拟环境(本文使用的是 3.13.1),然后运行 pip install -r requirements.txt 来安装这些库。

sqlite-vec==0.1.6
openai==1.63.0
python-dotenv==1.0.1

第二步是创建一个 OpenAI API 密钥,如果你还没有的话。我们将使用 OpenAI 为文本文件生成 embeddings,以便进行 vector search。

import sqlite3
from sqlite_vec import serialize_float32
import sqlite_vec
import os
from openai import OpenAI
from dotenv import load_dotenv

client = OpenAI(api_key=os.getenv('OPENAI_API_KEY'))

第三步是将 sqlite-vec 扩展加载到 SQLite 中。我们将在本文的示例中使用 Python 和 SQL。加载扩展后立即禁用加载扩展的能力是一种良好的安全实践。

db_path = 'my_docs.db'

db = sqlite3.connect(db_path)
db.enable_load_extension(True)
sqlite_vec.load(db)
db.enable_load_extension(False)

接下来,我们将创建我们的虚拟表:

db.execute('''
    CREATE VIRTUAL TABLE documents USING vec0(
        embedding float[1536],
        +file_name TEXT,
        +content TEXT
    )
''')

documents 是一个包含三列的虚拟表:

  • sample_embedding: 1536维的 float,用于存储我们样本文档的 embeddings。
  • file_name: 存储我们在数据库中存储的每个文件名称的文本。请注意,这一列和下一列前面都有一个 + 符号。这表明它们是 辅助字段。 之前在 sqlite-vec 中只能在虚拟表中存储 embedding 数据。然而,最近 推出了一项更新,允许我们在表中添加我们不想嵌入的字段。在这种情况下,我们在与我们的 embeddings 相同的表中添加了内容和文件名称。这将使我们能够轻松查看哪些 embeddings 对应于哪些内容,同时避免了额外的表和 JOIN 语句的需要。
  • content: 存储每个文件内容的文本。

现在我们在 SQLite 数据库中设置了虚拟表,我们可以开始将文本文件转换为 embeddings 并将其存储在我们的表中:

def get_openai_embedding(text):
    response = client.embeddings.create(
        model="text-embedding-3-small",
        input=text
    )
    return response.data[0].embedding

for file_name in os.listdir("data"):
    file_path = os.path.join("data", file_name)
    with open(file_path, 'r', encoding='utf-8') as file:
        content = file.read()

    embedding = get_openai_embedding(content)
    if embedding:
        db.execute(
            'INSERT INTO documents (embedding, file_name, content) VALUES (?, ?, ?)',
            (serialize_float32(embedding), file_name, content)
        )

db.commit()

我们基本上遍历每个 .txt 文件,嵌入每个文件的内容,然后使用 INSERT INTO 语句将 embeddingfile_namecontent 插入到 documents 虚拟表中。最后的提交语句确保更改被持久化。请注意,我们在这里使用的是来自 sqlite-vec 库的 serialize_float32。SQLite 本身没有内置的向量类型,因此它将向量存储为二进制大对象 (BLOBs),以节省空间并允许快速操作。在内部,它使用 Python 的 struct.pack() 函数,该函数将 Python 数据转换为 C 风格的二进制表示。

最后,要执行 RAG,你可以使用以下代码进行 K-Nearest-Neighbors (KNN 风格) 操作。这是 vector search 的核心。

query_text = "What is general relativity?"
query_embedding = get_openai_embedding(query_text)
if query_embedding:
    rows = db.execute(
        """
        SELECT
            file_name,
            content,
            distance
        FROM documents
        WHERE embedding MATCH ?
        ORDER BY distance
        LIMIT 3
        """,
        [serialize_float32(query_embedding)]
    ).fetchall()

print("Top 3 most similar documents:")
top_contexts = []
for row in rows:
    print(row)
    top_contexts.append(row[1])

我们首先从用户那里获取查询,在这种情况下是 “What is general relativity?”,并使用与之前相同的 embedding 模型对该查询进行嵌入。然后我们执行 SQL 操作。让我们分解一下:

  • SELECT 语句意味着检索到的数据将有三列:file_namecontentdistance。前两列我们已经提到过。distance 将在 SQL 操作期间计算,稍后会详细介绍。
  • FROM 语句确保你从 documents 表中提取数据。
  • WHERE embedding MATCH ? 语句在数据库中所有向量与查询向量之间执行相似性搜索。返回的数据将包括一个 distance 列。这个距离只是一个浮点数,测量查询与数据库向量之间的相似性。数字越高,向量越接近。sqlite-vec 提供了几种计算这种相似性的方法。
  • ORDER BY distance 确保以相似性递减的顺序(高 -> 低)对检索到的向量进行排序。
  • LIMIT 3 确保我们只获取与查询嵌入向量最近的前三个文档。你可以调整这个数字,看看获取更多或更少向量如何影响结果。

给定我们的查询“What is general relativity?”,以下文档被提取。效果相当不错!

Top 3 most similar documents:
('general_relativity.txt', 'Einstein’s theory of general relativity redefined our understanding of gravity. Instead of viewing gravity as a force acting at a distance, it interprets it as the curvature of spacetime around massive objects. Light passing near a massive star bends slightly, galaxies deflect beams traveling millions of light-years, and clocks tick at different rates depending on their gravitational potential. This groundbreaking theory led to predictions like gravitational lensing and black holes, phenomena later confirmed by observational evidence, and it continues to guide our understanding of the cosmos.', 0.8316285610198975)
('newton.txt', 'In classical mechanics, Newton’s laws of motion form the foundation of how we understand the movement of objects. Newton’s first law, often called the law of inertia, states that an object at rest remains at rest and an object in motion continues in motion unless acted upon by an external force. This concept extends into more complex physics problems, where analyzing net forces on objects allows us to predict their future trajectories and behaviors. Over time, applying Newton’s laws has enabled engineers and scientists to design safer vehicles, more efficient machines, and even guide spacecraft through intricate gravitational fields.', 1.2036118507385254)
('quantum.txt', 'Quantum mechanics revolutionized our understanding of the microscopic world. Unlike classical particles, quantum entities such as electrons can exhibit both wave-like and particle-like behaviors. Phenomena like quantum superposition suggest that particles can exist in multiple states at once, and the act of measurement often “collapses” these states into one observed outcome. This strange and counterintuitive theory underpins modern technologies like semiconductors and lasers, and it provides a conceptual framework for emerging fields like quantum computing and cryptography.', 1.251380205154419)

然后,我们可以将模型的上下文填充这三份文档,并让它尝试回答我们的提

这忠实于我们提供给模型的文档。干得好 4o-mini!

结论

sqlite-vec 是一个由 Mozilla Builders Accelerator 项目赞助的项目,因此它背后有一些重要的支持。非常感谢 Alex Garciasqlite-vec 的创作者,帮助推动 SQLite 生态系统,并使得使用这个简单的数据库实现机器学习成为可能。这是一个维护良好的库,定期有更新。截至 11 月 20 日,他们甚至 添加了元数据过滤!也许我应该用 SQLite 重新做我之前提到的 RAG 文章 🤔。

该扩展还为几种流行的编程语言提供了绑定,包括 Ruby、Go、Rust 等等。

能够将我们的 RAG 流程简化到基本要素是非常了不起的。回顾一下,不需要像 Postgres、MySQL 等数据库服务的启动和关闭。也不需要对云供应商进行 API 调用。如果您通过 Digital Ocean 或 Hetzner 直接部署到服务器,您甚至可以避免与 AWS、Azure 或 Vercel 等托管云服务相关的 昂贵且不必要的复杂性

我相信这种简单的架构可以用于各种应用。它更便宜,更易于维护,并且迭代速度更快。一旦您达到一定规模,迁移到更强大的数据库,例如具有 RAG 功能的 pgvector 扩展的 Postgres,可能会更有意义。对于更高级的功能,例如分块和文档清理,框架可能是正确的选择。但对于初创公司和小型企业来说,SQLite 是通往成功的道路。

祝您玩得开心,亲自尝试 sqlite-vec

简单的 RAG 架构。作者创作。

Related Posts

结合chatgpt-o3-mini与perplexity Deep Research的3步提示:提升论文写作质量的终极指南

结合chatgpt-o3-mini与perplexity Deep Research的3步提示:提升论文写作质量的终极指南

AI 研究报告和论文写作 合并两个系统指令以获得两个模型的最佳效果 Perplexity AI 的 Deep Research 工具提供专家级的研究报告,而 OpenAI 的 ChatGPT-o3-mini-high 擅长推理。我发现你可以将它们结合起来生成令人难以置信的论文,这些论文比任何一个模型单独撰写的都要好。你只需要将这个一次性提示复制到 **

阅读更多
让 Excel 过时的 10 种 Ai 工具:实现数据分析自动化,节省手工作业时间

让 Excel 过时的 10 种 Ai 工具:实现数据分析自动化,节省手工作业时间

Non members click here作为一名软件开发人员,多年来的一个发现总是让我感到惊讶,那就是人们还在 Excel

阅读更多
使用 ChatGPT 搜索网络功能的 10 种创意方法

使用 ChatGPT 搜索网络功能的 10 种创意方法

例如,提示和输出 你知道可以使用 ChatGPT 的“搜索网络”功能来完成许多任务,而不仅仅是基本的网络搜索吗? 对于那些不知道的人,ChatGPT 新的“搜索网络”功能提供实时信息。 截至撰写此帖时,该功能仅对使用 ChatGPT 4o 和 4o-mini 的付费会员开放。 ![](https://images.weserv.nl/?url=https://cdn-im

阅读更多
掌握Ai代理:解密Google革命性白皮书的10个关键问题解答

掌握Ai代理:解密Google革命性白皮书的10个关键问题解答

10 个常见问题解答 本文是我推出的一个名为“10 个常见问题解答”的新系列的一部分。在本系列中,我旨在通过回答关于该主题的十个最常见问题来分解复杂的概念。我的目标是使用简单的语言和相关的类比,使这些想法易于理解。 图片来自 [Solen Feyissa](https://unsplash.com/@solenfeyissa?utm_source=medium&utm_medi

阅读更多
在人工智能和技术领域保持领先地位的 10 项必学技能 📚

在人工智能和技术领域保持领先地位的 10 项必学技能 📚

在人工智能和科技这样一个动态的行业中,保持领先意味着不断提升你的技能。无论你是希望深入了解人工智能模型性能、掌握数据分析,还是希望通过人工智能转变传统领域如法律,这些课程都是你成功的捷径。以下是一个精心策划的高价值课程列表,可以助力你的职业发展,并让你始终处于创新的前沿。 1. 生成性人工智能简介课程: [生成性人工智能简介](https://genai.works

阅读更多
揭开真相!深度探悉DeepSeek AI的十大误区,您被误导了吗?

揭开真相!深度探悉DeepSeek AI的十大误区,您被误导了吗?

在AI军备竞赛中分辨事实与虚构 DeepSeek AI真的是它所宣传的游戏规则改变者,还是仅仅聪明的营销和战略炒作?👀 虽然一些人将其视为AI效率的革命性飞跃,但另一些人则认为它的成功建立在借用(甚至窃取的)创新和可疑的做法之上。传言称,DeepSeek的首席执行官在疫情期间像囤积卫生纸一样囤积Nvidia芯片——这只是冰山一角。 从其声称的550万美元培训预算到使用Open

阅读更多
Type something to search...