深入探究 Pinterest 如何构建其 Text-to-SQL 解决方案。

在我们的最新博客文章中,了解 Pinterest 工程团队的 Text-to-SQL 实现如何启发了 WrenAI 的开发。

Howard Chi
Wren AI 联合创始人
更新日期
2024 年 10 月 5 日
2024 年 11 月 25 日
10
分钟阅读
发布日期
2024 年 5 月 10 日

今年四月初,Pinterest 工程团队分享了他们如何在内部实现 Text-to-SQL 解决方案,以使数据用户无需编写 SQL 即可检索数据;他们还分享了该解决方案为用户带来的惊人投资回报率 (ROI),引述如下。

在我们的实际数据中(重要提示:这不控制任务差异),我们发现使用 AI 辅助编写 SQL 查询的任务完成速度提高了 35%。

Wren AI 团队已在 Text-to-SQL 挑战上投入了数月时间,并从这篇博文中获得了许多新的见解和学习;我们想与社区分享我们从这篇博文中学到的以及在开发 Wren AI 过程中获得的经验,以加速将 LLM 的理解能力应用于数据的创新。

在开始之前,如果您还没有了解 Wren AI,请在 GitHub 上查看我们!如果您喜欢我们正在做的事情,别忘了给我们一个 ⭐ 星!

首先,让我们探讨一下 Pinterest Text-to-SQL 和 Wren AI 架构之间的相似性。

Pinterest Text-to-SQL 架构

以下是 Pinterest 在其博文中分享的架构。

Pinterest Text-to-SQL 架构

让我们阶段性地分解这个架构;在进行 Text-to-SQL 实现时,有三个关键阶段: 索引、检索以及增强与生成

将这三个阶段映射到下面的架构中,并深入探讨每个阶段。

映射 RAG 中最重要的 3 个阶段

索引

在该架构中,他们应用了一个离线作业,根据表的摘要和针对它们的历史查询来生成向量存储的索引。目前,他们在向量索引过程中依赖于两种类型的文档嵌入:**表摘要和查询摘要。**

索引阶段通常与 Text-to-SQL 如何在数据库中搜索最相关的表密切相关;您可以为向量存储提供更多上下文,最终结果就会越好。

检索

在检索阶段,如果用户未指定表,其问题将被转换为嵌入向量。应用了几种方法来执行检索阶段,包括 **NLP 表搜索和表重新选择**。表重新选择的结果将返回给用户进行验证,然后再生成为 SQL。

我们通常使用检索后方法来根据附加信息过滤掉低相关上下文,或者对结果应用不同的权重。

增强与生成

在博文中,他们没有详细提及增强和生成阶段的这一部分。

Wren AI 架构

以下是 Wren AI Text-to-SQL 架构的样子。

Wren AI Text-to-SQL 架构

Wren AI 由三个核心服务组成

  • Wren UI: 一个直观的用户界面,用于在 Wren AI 框架内提问、定义数据关系和集成数据源。
  • Wren AI 服务: 使用向量数据库进行上下文检索来处理查询,指导 LLM 生成精确的 SQL 输出。
  • Wren Engine: 作为语义引擎,将业务术语映射到数据源,定义关系,并整合预定义的计算和聚合。

Pinterest Text-to-SQL 和 Wren AI 的设计差异

Wren AI 中的三个 RAG 阶段

让我们看看 **Wren AI 如何在我们的 Text-to-SQL 架构中设计和实现** 这三个阶段,以便您可以与我们刚刚提到的 Pinterest Text-to-SQL 架构进行比较。

索引

Wren AI 中,我们实现了语义引擎架构来为 LLM 提供您的业务上下文;您可以轻松地在数据模式上建立一个逻辑表示层,帮助 LLM 更好地理解您的业务上下文。

Wren AI 中的索引阶段

我们的索引包含哪些内容

  1. 表模式、名称、描述:一旦您连接到数据源,您的表模式将自动同步到向量存储中。您还可以添加其他信息,例如名称、描述等。
  2. 列、名称、类型、描述:在同步表模式时,我们将您的列类型和元数据存储在向量存储中。您还可以添加其他信息,例如名称、描述等。
  3. 关系:关系是 Wren AI 语义建模中一个非常重要的特性,您可以在列之间定义多对一、一对一和多对多关系。这可能与设置主键和外键等约束不同,因为它可能更偏向于业务上下文。设置正确的关系可以极大地提高 LLM 使用正确的列和表生成 JOIN 子句的准确性。
  4. 计算:在业务上下文中,每个业务都有其业务定义和术语,例如当公司提及 收入利润 时,您希望 LLM 理解您的公司如何定义这些术语;这就是 计算 的作用,您可以在语义建模中轻松定义计算,LLM 可以根据您的定义生成正确的 SQL,而不会产生幻觉。
Wren AI 语义建模 UI

相比之下,Pinterest 目前仅依赖表元数据和查询日志,但他们已经实现了**表摘要和查询摘要方法**来改进上下文。

  1. 表摘要:表摘要提示词将包含各种示例查询和表模式。然后将其发送给 LLM 生成摘要并保存到向量存储中。
  2. 查询摘要:除了在表摘要中的作用外,与每个表相关的示例查询也会被单独汇总,包括查询目标和使用的表等具体信息。

经验教训:我们的团队计划在 Wren AI 项目中实现“表摘要”和“查询摘要”。

检索

在 Wren AI 中,在检索阶段,用户问题被转换为嵌入向量,并对向量索引进行相似性搜索,以推断出最适合的前 K 个表,如下所示。

Wren AI 架构中的检索阶段
from typing import Any

from haystack_integrations.components.retrievers.qdrant import QdrantEmbeddingRetriever


def init_retriever(document_store: Any, top_k: int = 10):
    return QdrantEmbeddingRetriever(document_store=document_store, top_k=top_k)

在 Pinterest 的案例中,他们的 Text-to-SQL 实现采用了上述表搜索方法和 **表重新选择。**

表重新选择

从向量索引中检索出前 N 个表后,我们将利用 LLM 通过评估问题和表摘要来选择最相关的 K 个表。

经验教训:从向量存储中选择表后进行表重新选择有助于提高性能。

增强与生成

在 Wren AI 中,我们拥有独特的设计和技术,帮助 LLM 更好地理解业务上下文,以在提示词中增强信息。在**生成**阶段,我们还提供 SQL 验证和自动更正功能。

Wren AI 中的增强与生成阶段

增强

Wren AI 的关键设计之一是语义引擎,即 Wren Engine。该引擎负责通过“分析即代码”的设计方法,定义和映射元数据、模式、术语、数据关系以及计算和聚合背后的逻辑等复杂处理。

借助 Wren Engine,您可以通过“建模定义语言”(MDL)定义语义。此定义封装了计算公式、指标定义和语义关系,减少了重复编码和数据连接处理。

标准 SQL 到不同的 SQL 方言

这里有一个示例;以下是“customers”数据模型的定义。

{
      "name": "customers",
      "refSql": "select * from main.customers",
      "columns": [
        {
          "name": "City",
          "type": "VARCHAR",
          "isCalculated": false,
          "notNull": false,
          "properties": {
            "description": "The Customer City, where the customer company is located. Also called 'customer segment'."
          }
        },
        {
          "name": "Id",
          "type": "VARCHAR",
          "isCalculated": false,
          "notNull": false,
          "properties": {
            "description": "A unique identifier for each customer in the data model."
          }
        },
        {
          "name": "State",
          "type": "VARCHAR",
          "isCalculated": false,
          "notNull": false,
          "properties": {
            "description": "A field indicating the state where the customer is located."
          }
        },
        {
          "name": "orders",
          "type": "orders",
          "relationship": "CustomersOrders",
          "isCalculated": false,
          "notNull": false,
          "properties": {}
        },
        {
          "name": "LatestRecord",
          "type": "DATE",
          "isCalculated": true,
          "expression": "max(orders.PurchaseTimestamp)",
          "notNull": false,
          "properties": {}
        },
        {
            "name": "FirstRecord",
            "type": "DATE",
            "isCalculated": true,
            "expression": "min(orders.PurchaseTimestamp)",
            "notNull": false,
            "properties": {}
        },
        {
            "name": "VIP",
            "type": "BOOLEAN",
            "isCalculated": true,
            "expression": "sum(orders.Size) > 2",
            "notNull": false,
            "properties": {}
        },
        {
            "name": "OrderCount",
            "type": "BIGINT",
            "isCalculated": true,
            "expression": "count(orders.OrderId)",
            "notNull": false,
            "properties": {}
        },
        {
          "name": "Debit",
          "type": "DOUBLE",
          "isCalculated": true,
          "expression": "sum(orders.OrderBalance)",
          "notNull": false,
          "properties": {}
        },
        {
            "name": "ReviewRate",
            "type": "DOUBLE",
            "isCalculated": true,
            "expression": "count(orders.IsReviewed = TRUE) / count(DISTINCT orders.OrderId)",
            "notNull": false,
            "properties": {}
        }
      ],
      "primaryKey": "Id",
      "cached": false,
      "refreshTime": "30.00m",
      "properties": {
        "schema": "main",
        "catalog": "memory",
        "description": "A table of customers who have made purchases, including their city"
      }
    }

在生成提示词时,我们将用文件中定义的语义来增强数据定义语言(DDL),如下所示。

/* {"schema": "main", "catalog": "memory", "description": "A table of customers who have made purchases, including their city"} */
CREATE TABLE customers (
    -- {"description": "The Customer City, where the customer company is located. Also called \'customer segment\'."}
    City VARCHAR,
    -- {"description": "A unique identifier for each customer in the data model."}
    Id VARCHAR PRIMARY KEY,
    -- {"description": "A field indicating the state where the customer is located."}
    State VARCHAR,
    -- This column is a Calculated Field
    -- column expression: max(orders.PurchaseTimestamp)
    LatestRecord DATE,
    -- This column is a Calculated Field
    -- column expression: min(orders.PurchaseTimestamp)
    FirstRecord DATE,
    -- This column is a Calculated Field
    -- column expression: sum(orders.Size) > 2
    VIP BOOLEAN,
    -- This column is a Calculated Field
    -- column expression: count(orders.OrderId)
    OrderCount BIGINT,
    -- This column is a Calculated Field
    -- column expression: sum(orders.OrderBalance)
    Debit DOUBLE,
    -- This column is a Calculated Field
    -- column expression: count(orders.IsReviewed = TRUE) / count(DISTINCT orders.OrderId)
    ReviewRate DOUBLE
)

生成

以下是 Wren AI 如何处理生成阶段,我们将其分为两种不同的场景

启动您的业务问题并进行后续提问
  1. 启动您的业务问题(对话串中的第一个问题):当您在 Wren AI 中开始新的对话并提出第一个问题时,Wren AI 会将您的问题转换为嵌入向量并进行相似性搜索,以获取最相关的表。结合这些表和原始问题,我们将要求 LLM 根据原始问题和检索到的表重新生成**三个最相关的问题**,并要求用户选择最相关的一个来生成结果。
  2. 后续问题:在提出后续问题时,我们会将之前的上下文添加到提示词中,以确保 SQL 生成过程可以基于之前的对话。

在 Pinterest 的案例中,SQL 生成的最后阶段相对简单;他们在博客文章中目前没有详细提及这一部分。

Pinterest 在其 Text-to-SQL 解决方案文章中列出的未来路线图,Wren AI 的情况如何?

在博文中,他们提到了他们在路线图中正在研究和工作的几个领域;其中一些主题已在 Wren AI 中实现,有些正在进行中或计划中。让我们看看下面:

元数据管理(已在 Wren AI 中实现)

在元数据管理方面,我们已在 Wren AI 中实现了名为“建模定义语言”(MDL)的功能,供 LLM 使用,以包含语义关系、领域上下文、标签、描述等;这显著提高了检索阶段的过滤准确性。

索引自动更新(已在 Wren AI 中实现)

在 Wren AI 中,当您通过我们的用户界面进行建模时,索引会自动更新;点击“部署”按钮,系统将自动在向量存储和语义引擎之间同步。

相似性搜索和评分策略修订(计划中)

当前 Wren AI 的评分策略也相当基础;未来,我们计划对其进行微调,以提高检索结果的相关性。

查询验证(已在 Wren AI 中实现)

Wren AI 中的查询验证流程

查询验证过程已在 Wren AI 中实现;我们将在 Wren Engine 中对查询进行空运行(dry run),以确保查询可执行,验证 SQL,并在 SQL 格式无效时请求 LLM 进行修正。

用户反馈(正在进行中)

这是我们在 Wren AI 中设计的最重要的开发领域之一;我们将很快发布包含用户反馈的新版本!发布后我们将分享更多细节,请务必订阅我们的 Medium 以获取最新信息!

评估(正在进行中)

这也是我们在 Wren AI 中设计的最重要的开发领域之一。我们将很快在 Wren AI 中发布端到端评估流程!发布后我们将分享更多细节;请务必订阅我们的 Medium 以获取最新信息!

基本就是这样了!最后,我们感谢 Pinterest 工程团队分享了如此精彩和富有启发性的博文。我们希望更多工程团队能够分享他们在公司内部实现的知识!继续前进!

如果您还没有了解 Wren AI,请查看我们!

👉 GitHub: https://github.com/Canner/WrenAI

👉 X: https://twitter.com/getwrenai

立即使用 AI 提升您的数据能力?!

谢谢!您的提交已收到!
哎呀!提交表格时出错。