文本到 SQL 的架构模式:利用 LLM 增强 BigQuery 交互
TLDR:本文深入探讨了文本到 SQL 领域,展示了这项复杂任务对大型语言模型 (LLM) 的日益依赖。它强调了 LLM 和 Google 的 BigQuery 之间的协同关系,展示了这种合作关系如何改善各种应用程序中的 SQL 查询生成。本文解释了 LLM 如何充当认知处理引擎,准确解释用户请求并与 BigQuery 交互以生成精确的 SQL 命令。这种组合简化了用户的数据采集,并为数据库交互提供了一个可扩展的框架,可在不同部门采用。本文探讨了旅游休闲行业的一个案例研究,展示了这项技术在管理旅行预订中的整合。本文研究了文本到 SQL 的五种不同架构模式**,讨论了它们的优缺点,并概述了它们的最佳用例场景。它还提供了使用笔记本的实际演示,其中包含数据集和可执行代码来展示每种模式。
图片来源:Unsplash
介绍
文本转 SQL 是自然语言处理 (NLP) 中的一项任务,旨在从自然语言文本自动生成结构化查询语言 (SQL) 查询。此任务涉及将文本输入转换为结构化表示,并使用它来生成可在数据库上执行的语义正确的 SQL 查询。这项任务带来了许多挑战。从本质上讲,困难源于人类语言(流动、模糊且依赖于上下文)与 SQL(精确且结构化的语言)之间的固有差异。
从历史上看,这个问题被视为查询重构任务,采用序列到序列模型并采用深度神经架构。这些模型经过战略性训练,利用自然语言与 SQL 表达式之间的复杂映射,将自然语言转化为相应的 SQL 表达式。
尽管如此,这些架构也带来了一系列挑战。首先,需要生成和管理包含人类语言查询对及其相应的 SQL 语句的数据集,以进行预训练或微调。此外,输入(自然语言查询)和输出(SQL 查询)通常都需要规范化。这需要预处理和后处理阶段,从而增加了流程的复杂性。这也意味着大量的训练数据是必不可少的。自定义领域知识(例如表名、模式和列描述)的整合也带来了巨大的挑战。
在引入文本转 SQL 的 LLM 之前,必须对用户查询进行预处理以匹配特定模板。然后使用此模板重新表述用户查询。但是,这些模板通常是针对特定用例的,因此很难进行扩展。因此,需要大量的数据准备和手动工作才能实现必要的格式和模板。
随着 LLM 的出现,文本到 SQL 领域发生了重大转变。LLM 表现出色,能够从自然语言描述生成准确的 SQL 查询,这一壮举得益于其庞大的知识库和上下文理解能力。其复杂的架构,加上用于预训练的全面数据,使它们能够解读单词之间的复杂关系,从而克服了以前方法中存在的许多挑战。随着 LLM 的发展,它们在这一领域的熟练程度预计将进一步提高,预示着自然语言与数据库接口的新时代的到来。LLM 的主要优势之一是无需从自然语言到查询整理和细化训练数据集。LLM 的一个主要优势是不需要从自然语言到查询来管理和细化训练数据集。
图片来源:Unsplash
在我们即将进行的演示中,我们将利用 Google 的PaLM 2模型的功能,这是 LLM 系列的最新成员,重点是文本到 SQL。我们的重点是航班预订系统,这是一个具有错综复杂关系和数据结构的复杂领域。在这个系统中,我们将探索各种表格,包括航班详情、乘客信息、预订历史等,所有这些都托管在 BigQuery 数据集中。利用 PaLM 2 的 LLM 驱动架构模式,我们旨在展示将自然语言查询无缝转换为精确的 SQL 查询。这不仅会突出该模型在理解和处理人类语言方面的有效性,还会突出它在导航关系数据库和生成准确、可操作的 SQL 输出方面的熟练程度。通过这些示例,我们将亲身体验文本到 SQL 功能的演变以及 LLM 在实际应用中的潜力。
BigQuery是 Google 的全托管数据仓库服务,BigQuery 为大规模数据分析提供了强大的平台。它支持快速 SQL 查询,因其性能、可扩展性和易于数据集成而备受推崇,是数据驱动型企业的必备工具。
在航班预订系统中进行查询会带来无数挑战,这主要是因为所涉及数据的多面性。航班系统包含大量相互关联的表格和数据集,从客户详细信息和票务信息到航班时刻表和定价指标。利用 BigQuery 进行分析进一步加剧了复杂性,因为分析师旨在利用其功能深入挖掘数据、趋势预测和实时洞察。特别令人担忧的是数据工程师、科学家和其他专家在编写必要的 SQL 查询时需要投入大量时间和精力。
创建这些查询并不是一项简单的线性任务。相反,它通常涉及一系列级联的 SQL 命令,每个命令都建立在另一个命令之上,以各种方式聚合、分组、过滤和剖析数据,以提取有意义的见解。数据的切分和分解,尤其是在像航班预订这样复杂的系统中,需要对细节一丝不苟,并深入了解数据的结构和业务需求。因此,专业人士经常会花费数小时甚至数天的时间来完善他们的查询并建立高效的数据管道,以确保信息的顺畅流动和处理。
深入研究一个实际示例,让我们考虑在包含四个表的系统中查询的复杂性,以便于理解:、、reservations
和。每个表虽然本身很有价值,但与其他表互连时会变得更加重要。例如,旨在识别最常飞行的查询可能需要将客户表与预订和航班连接起来,将乘客详细信息与航班预订进行交叉引用。当试图辨别这些常旅客中哪一个在上个季度进行了最多交易时,情况会变得更加复杂,因此需要与交易表合并。customers``transactions``flights
上述每个查询场景都涉及多个连接、聚合、过滤器以及可能的子查询。编写这些查询不仅需要 SQL 专业知识,还需要对底层数据关系和业务目标有深刻的理解。从这四个表中可以得出的潜在组合和见解非常多,每个查询都可能成为一项复杂的任务,这凸显了此类系统固有的挑战。
文本到 SQL:架构要求
将自然语言转换为 SQL 对于高效的数据管理和检索至关重要。结构良好的架构可提高这些转换的准确性和速度,从而增强 LLM 处理复杂用户查询的能力。
了解此架构中特定模式的优缺点非常重要。它们的有效性取决于上下文,知道在何处应用它们可以优化文本到 SQL 的转换。调整这些模式以适应独特的场景可以产生更好的 SQL 生成。
Google Cloud Platform (GCP) - GenAI 词汇表
图片来源:Unsplash
Vertex AI是 Google Cloud 的套件,旨在简化和集成团队的 ML 工作流程,旨在加速 AI 模型的开发和部署。它以在安全且可扩展的基础架构上自动化和优化 ML 任务的能力而脱颖而出。
PaLM 2
是 Google 开发的最先进的语言模型,具有改进的多语言、推理和编码能力。该模型针对 100 多种语言的多语言文本进行训练,显著提高了其理解、生成和翻译多种语言中细微文本的能力。
我们将在本文中使用的基础模型是 Google 生成式 AI 工具套件的一部分。这些模型针对各种任务进行了优化,并且基于 PaLM 2。每个模型都是 AI 生态系统中的战略构建块,旨在提高各种应用的生产力和创新能力。
Text Bison
:经过微调以遵循自然语言指令的模型,适用于各种语言任务。
Chat Bison
:针对多轮对话用例进行微调的模型。它旨在以类似聊天的形式提供整合、建议和问题帮助。
Code Bison
:根据所需代码的自然语言描述进行微调以生成代码的模型。
Code Chat Bison
:针对聊天机器人对话进行微调的模型,可帮助解决与代码相关的问题。它是支持专门针对代码的多轮对话的基础模型。
Code Bison
和之间的主要区别Code Chat Bison
在于它们的预期用途。Code Bison
专为需要单次交互的代码生成任务而设计,而Code Chat Bison
针对连续对话格式的来回交互进行了优化。Code Chat Bison
更适合通过多次交互完成的代码任务,例如代码调试或解决问题。
除了以PaLM 2
API 形式提供的基于 的基础模型外,Vertex AI 还提供一系列生成式 AI 工具。这些工具包括 Vertex AI Search and Conversation、Generative AI Studio 和 Model Garden。每种工具都有其独特的功能:
Vertex AI Search and Conversation
:此工具使开发人员能够构建生成式 AI 搜索和聊天体验。它提供现成的功能,可快速构建和部署聊天机器人和搜索应用。开发人员还可以通过 API 集成或控制台将多种功能整合到他们的工作流程中。Generative AI Studio
:此 Google Cloud 控制台允许快速原型设计和测试生成式 AI 模型。开发人员可以使用它通过提示样本测试模型、设计和保存提示、调整基础模型以及通过丰富的 UI 在语音和文本之间进行转换。Model Garden
:Model Garden 拥有 100 多个尖端的 LLM 和特定任务模型。其中包括上面讨论的 Google 自己的第一方模型,以及开源模型,如Llama 2
、TIIFalcon
、Stable Diffusion
等Mistral
。它通过 API 和控制台简化了开发人员查找、部署和维护基础模型的过程。
在本文中,我们将重点介绍 Google Cloud 的第一方基础模型 —Code Bison
以及Code Chat Bison
。
架构模式
基于 LLM 的应用程序在数据库管理和查询制定方面的发展为数据交互开辟了新途径。通过将 LLM 集成到从自然语言生成 SQL 查询的过程中,我们可以简化和增强数据检索过程。在这里,我们概述了在 SQL 查询生成中实现 LLM 的五种不同模式。
模式一:使用文本到 SQL 进行意图检测和实体识别
在传统的自然语言理解 (NLU) 系统中,将文本转换为 SQL 查询的过程始于意图检测。此步骤至关重要,因为它可以从用户的查询或话语中辨别出用户的目的,这在聊天机器人等应用中尤为重要。意图检测通常被视为多类分类问题,需要一个监督学习模型,该模型在平衡所有可能意图的数据集上进行训练。
使用文本到 SQL 进行意图检测和实体识别
然而,LLM 的引入改变了这一格局。这些模型可以以零样本或少样本的方式执行意图检测等任务,从而无需大量训练数据。
传统文本到 SQL 系统的另一个关键组件是命名实体识别 (NER),它涉及从用户输入中识别和提取实体。识别这些实体至关重要,因为它们通常对应于数据库元素(如表名或列值),而这些元素对于制定 SQL 查询至关重要。
LLM 擅长 NER 和上下文理解,这使得他们能够有效地识别文本中的实体。此功能允许将这些实体无缝集成到 SQL 查询模板中。
现在,让我们探索第一个模式,看看它是如何工作的,如上所示。此模式建立在通常涉及意图和 NER 组件的传统系统之上,但在这里,它使用的是 LLM。
- 意图检测:用户的查询或话语被输入到 LLM 中,LLM 会确定用户的意图。例如,在预订航班的背景下,查询背后的意图。下面显示了用于 LLM 意图分类的少数样本提示的示例提示完成对。传统上,这将由监督微调分类器或规则引擎执行。
需要 2023 年 10 月 10 日至 15 日的所有预订。,RETRIEVE_RESERVATIONS
谁在上周三进行了预订?,IDENTIFY_RECENT_CUSTOMERS
2023 年 10 月我们从已确认的预订中获得了多少收入?,CALCULATE_REVENUE
“2023 年,哪个月的出发人数最多?”,FIND_PEAK_DEPARTURE_MONTHS 有
多少客户属于五个不同的年龄类别?,GROUP_AND_COUNT_CUSTOMERS_BY_AGE
2.实体识别:LLM 同时或顺序分析相同的用户输入,以执行 NER(从文本中提取相关实体)。下面,我们展示了用于提示的示例对。
“您能向我显示 2023 年 10 月 10 日至 2023 年 10 月 15 日的所有预订吗?”,“开始日期:2023 年 10 月 10 日|结束日期:2023 年 10 月 15 日” “
从 2023 年 10 月 10 日到 2023 年 10 月 15 日我们有哪些预订?”,“开始日期:2023 年 10 月 10 日|结束日期:2023 年 10 月 15 日”
“显示 2023 年 10 月第二周之间发生的预订。”,“开始日期:2023 年 10 月 8 日|结束日期:2023 年 10 月 15 日”
“列出 2023 年 10 月 10 日至 15 日发生的所有预订。”,“开始日期:2023 年 10 月 10 日|结束日期:2023 年 10 月 15 日”
“从2023 年 10 月的第二周。”,“开始日期:2023 年 10 月 8 日|结束日期:2023 年 10 月 15 日”
3.将意图映射到数据库表:检测到的意图用于确定要查询哪些数据库表。虽然 LLM 可以协助完成此步骤,但它也可以以编程方式视为键值映射检索。示例映射如下所示。
RETRIEVE_RESERVATIONS,预订|航班
IDENTIFY_RECENT_CUSTOMERS,预订|客户
CALCULATE_REVENUE,预订|交易
FIND_PEAK_DEPARTURE_MONTHS,航班
GROUP_AND_COUNT_CUSTOMERS_BY_AGE,客户
4.模式过滤:识别后,检索相关表的模式,为 SQL 生成做好准备。
- SQL 语句构建:收集的信息(包括用户查询、检测到的意图和提取的实体)与映射表和过滤的架构信息(例如表和列描述)集成在一起。这些综合数据信息被编译成 LLM 的结构化提示,如下所示。这有助于 LLM 生成准确的 SQL 语句以响应用户的查询。
请使用下面提供的信息构建一个 SQL 查询:
输入参数:
-----------------
意图:{intent}
提取的实体:{entities}
映射的表:{tables}
用户查询:
-----------
{user _query}
表模式:
--------------
{filtered_ table _schemas_ text}
注意:
-请在表名前加上“flight_reservations”作为前缀。
以下是用户查询的示例以及 LLM 生成的相应 SQL 语句:
提供 2023 年 10 月 10 日至 10 月 15 日所有航班预订清单
选择 *
从flight_reservations.reservations
中查找reservation_datetime ,其中 '2023-10-10' 和 '2023-10-15'
- SQL执行:生成的SQL语句在数据库中执行,完成文本到SQL的转换过程。
7.人性化输出:可选地,SQL 查询的输出可以返回到 LLM,重新格式化为更人性化的格式,从而改善用户体验。如果您想在聊天应用程序或任何对话界面中提供响应,这尤其有用。
此步骤的示例查询如下:
用户的问题:
----------------
{user _query}
BigQuery 结果:
----------------
{bq_ response}
任务:
-----
请将上述查询结果转换为人类可读的格式。
重要说明:
----------------
-答复应礼貌且人性化。
-如果答案不需要表格结构,请避免使用它。
简而言之,模式 I 简化了文本到 SQL 系统中通常遇到的复杂性。这不仅使解决方案更高效,而且更易于设计。要查看此模式在实践中的应用,可以参考包含相关代码的示例笔记本。它可在此 GitHub位置访问。存储库还包含所有必要的支持文件,例如用于小样本提示的提示完成对、模板和其他资源,位于数据目录中。
请注意,在继续执行模式 I 的笔记本之前,设置所需的 BigQuery 数据集和表非常重要。这可以通过运行“00-Setup”目录中的设置笔记本来完成,具体来说00-create-tables.ipynb
。这一准备步骤对于成功实施本文中介绍的所有模式至关重要。
优点:
- 适用于表和列数量有限的小型 BigQuery 数据集。
- 非常适合用基于 LLM 的解决方案取代现有的意图检测和 NER 系统。
- 通过消除多模型训练和重新训练管道的需要来简化管道。
- 适用于面向客户端的应用程序或场景范围有限的系统。
- 旨在提高 SQL 查询生成的准确性并提供可解释性。
- 有助于更轻松地调试和检查单个模块或组件。
限制:
- 扩展到包括新的场景需要手动更新用于小样本提示的数据。
- 缺乏无需人工干预即可自动处理新查询场景的灵活性。
模式 II:带有检索增强生成(RAG)的 LLM 流程
如果我们在 BigQuery 中处理数百甚至数千个表,或者表包含数千个列,则前一种模式就不适用了。将检测到的意图映射到相应的表几乎是不可能的。当我们面对新的场景或查询类型时,也会出现同样的问题,第一种模式无法可靠地将意图映射到正确的表,或者在处理大规模数据时过滤架构描述和列。因此,我们需要一种更有效的方法,这就是模式 II 的用武之地。
本质上,模式 II 利用了 RAG。我们将表描述和模式描述(列)转换为嵌入,然后为搜索编制索引。使用语义搜索,我们将用户的查询编码为嵌入,并将其与索引的嵌入进行比较以查找匹配的表和列。此策略缩小了搜索空间,使我们能够挑选出前 K 个结果。结果是一个可以大规模运行的系统,可以自动近似我们生成 SQL 所需的候选。让我们一步一步地分解它。
带检索增强生成 (RAG) 的 LLM 流程
- **嵌入和索引描述:**首先使用文本嵌入模型将表和列描述编码为嵌入。例如,您可以使用 Vertex AI 的文本嵌入模型。对描述进行编码后,创建两个索引 — 一个用于表描述,另一个用于列描述。考虑到这只是一个演示,这里可以使用
textembedding-gecko
独立的向量索引。FAISS
独立向量索引极大地增强了向量嵌入的搜索和检索,但它们缺少向量引擎或数据库中的一些功能。向量引擎是允许高效相似性搜索和密集向量聚类的工具。它们旨在搜索任意大小的向量集,即使是那些不适合 RAM 的向量集,因此非常适合具有数十亿个向量的大规模应用程序。这些引擎围绕向量嵌入的概念展开,向量嵌入是携带关键语义信息的向量数据表示,可供 AI 在执行复杂任务时理解和维持长期记忆。
Google Cloud 提供Vertex AI Vector Search
,原名Vertex AI Matching Engine
,它是一种高规模、低延迟的向量数据库。它旨在以低延迟处理大量数据,使其适用于需要高效向量相似性匹配或近似最近邻 (ANN) 服务的应用程序。Vertex AI Vector Search
可用于多种用途,例如实现推荐引擎、搜索引擎、聊天机器人和文本分类。它支持从数十亿个语义相似或相关的项目中进行搜索,并且嵌入的使用不仅限于单词或文本,还可以应用于图像、音频、视频和用户偏好。
2.查询向量化和表匹配:在流程的第二阶段,使用指定的编码模型将用户的查询转换为向量表示。然后,将此编码查询与预先索引的表描述存储库进行比较,以识别与用户意图一致的相关表。结果匹配按相关性排序,重点关注前五个匹配,通过将参数 K 设置为 5 来确定。
3.**列发现和元数据集成:**进入第三步,应用类似的程序,但这次查询的向量与列描述索引进行匹配。此匹配过程会产生一组相关列,每个列都附有元数据和相应的表信息。在此阶段,参数 K 设置为 20,以扩大搜索范围并提供更广泛的潜在匹配选择。
通过整合第二步和第三步的结果,特别是在涉及多个 BigQuery 数据集的情况下,此架构模式采用了多层搜索策略。这种三层方法(包括对数据集、表和列的单独搜索)允许进行全面而精细的匹配过程,从而确定最适合查询构建的候选对象。
- **SQL 查询综合:**在下一步中,重点是 SQL 生成,系统将所有已识别的组件综合成一个有凝聚力的 SQL 查询。此查询的制定由 LLM 指导,它将用户的初始请求转换为准确的 SQL 语句。下面提供了此类查询的示例模板,说明了系统查询组装的过程。
给定以下输入:
USER _QUERY:
--
{query}
--
MATCHED_ SCHEMA:
--
{matched _schema}
--请使用
上面提供的
MATCHED_ SCHEMA 和 USER _QUERY 构建 SQL 查询。目标是根据提供的信息确定酒店的空房情况。重要提示:仅使用 MATCHED _SCHEMA 中提到的列名(column_ name)。请勿使用除此之外的任何其他列名。
重要提示:仅将MATCHED _SCHEMA 中提到的column_ name 关联到MATCHED _SCHEMA 下指定的table_ name 。
注意:使用 SQL“AS”语句在需要时为表列甚至表临时分配新名称。
- SQL执行:生成的SQL语句在数据库中执行,完成文本到SQL的转换过程。
6.人性化输出:可选地,SQL 查询的输出可以传回 LLM,以重新表述为更人性化可读的格式,从而增强用户体验。
优点:
- 适用于处理 BigQuery 中的大型数据集和宽表。
- 通过将意图检测、NER 和手动映射到语义搜索中来简化工作流程。
- 由于提示更短、更有效,从而降低了推理成本。
- 修剪不必要的数据,重点关注相关的表和列的描述。
- 增强数据处理任务的可扩展性。
限制:
- 由于需要语义搜索,增加了管道的复杂性。
- 需要仔细考虑嵌入策略和参数才能实现有效搜索。
- 一个问题是,该工具经常检索不相关的表和列。这会导致复杂的查询和不必要的连接,从而增加计算时间并导致冗长的、不必要的响应。
- 鉴于该方法的初始阶段本质上是搜索,它存在常见的信息检索问题,例如召回率和准确率较差。它可能需要重新排序等缓解策略来突出显示最相关的结果。
可以在此处找到演示 Text2SQL 的 RAG 模式的示例笔记本。
模式三:使用 SQL 代理
代理是先进的 AI 系统,它扩展了 LLM 的功能,使其能够执行超越基本文本生成的广泛任务。这些代理的核心是用于交互式通信、推理和任务执行。它们通过详细的提示进行操作,这些提示定义角色、提供指令、授予权限并提供上下文。这些提示塑造了代理的响应并指导他们的行动。
从本质上讲,代理利用 LLM 的复杂语言能力,以自主或半自主的方式运行,响应人类的提示。它们配备了一系列工具,包括计算器、代码解释器、API 和搜索引擎,使它们能够获取信息并执行操作以完成指定任务,从而使自己比简单的语言处理器更具活力。基于 LLM 的自主代理系统的关键组件是:1/ 其规划能力,2/ 将任务分解为子目标,3/ 选择适当的 API 进行调用,以及 4/ 根据这些 API 提供的结果制定响应。
此外,这些代理能够通过将自然语言查询转换为 SQL 命令来分析 SQL 数据库。BigQueryLangChain
的 SQL 代理体现了这种能力,使用户能够使用自然语言与 BigQuery 数据库进行交互。LangChain
它本身是一个开源框架,利用 LLM 处理自然语言并执行各种任务,展示了这些智能系统的多方面效用。
使用 SQL 代理
以下是有关如何使用 LLM 代理与 SQL 数据交互的分步指南,如上图所示:
- 建立数据库连接:首先与 Simba Google BigQuery 连接器建立 ODBC 连接。确保您拥有适当的凭据和权限,这些凭据和权限可能因语言模型代理和相关数据库而异。确保这些要求得到满足后,您可以继续将用户的问题或话语直接传递给代理进行处理。
- 模式推断和配置:配置目录和数据集名称等基本参数,并使用驱动程序和服务帐户密钥凭据通过 OAuth 进行身份验证。此配置对于 LLM 代理理解数据库模式至关重要。
- 自然语言查询处理:启动代理后,用户可以输入自然语言查询。代理会解释这些查询以生成相应的 SQL 命令。
- 查询执行:LLM 代理执行 SQL 命令,自主访问表和列以构建和检索查询结果。
- 回溯和自我纠正:如果 LLM 生成的查询在语法上不正确,就会发生回溯。代理具备使用此反馈进行自我纠正的能力,确保查询执行过程顺畅而高效。
- 人性化的输出格式:为了增强用户体验,LLM 代理将 SQL 查询的输出重新表述为更人性化、更易读的格式,从而提供清晰、简洁的数据呈现。
以下是展示中间状态的示例输出 — 让您一窥代理的思维过程和行动。该场景涉及查找和列出特定日期范围内的所有航班预订。
提供 2023 年 10 月 10 日至 10 月 15 日所有航班预订清单
> 进入新的 AgentExecutor 链...
动作:sql _db_ list _tables
动作输入:
观察:客户、航班、预订、交易
想法: 动作:sql_ db _schema
动作输入:航班
观察:
创建表 `flights` (
`flight_ id` INT64 NOT NULL,
`origin` STRING NOT NULL,
`destination` STRING NOT NULL,
`departure_datetime` DATETIME NOT NULL,
`arrival_datetime` DATETIME NOT NULL,
`carrier` STRING NOT NULL,
`price` FLOAT64 NOT NULL
)
/ *
来自航班表的 3 行:
flight_id 出发地 目的地 出发日期时间 到达日期时间 承运人 价格
1 JFK LAX 2023-11-05 09:00:00 2023-11-05 12:30:00 达美航空 450.0
2 LAX JFK 2023-11-10 15:00:00 2023-11-10 23:30:00 达美航空 450.0
3 JFK ATL 2023-11-15 07:00:00 2023-11-15 09:30:00 西南航空 300.0
* /
想法:行动:sql _db_ schema
行动输入:reservations
观察:
CREATE TABLE `reservations` (
`reservation_id` INT64 NOT NULL,
`customer_id` INT64 NOT NULL,
`flight_id` INT64 NOT NULL,
`reservation_datetime` DATETIME NOT NULL,
`status` STRING NOT NULL
)
/ *
来自 reservations 表的 3 行:
reservation_id customer_id flight_id reservation_datetime status
1 1 1 2023-10-01 10:30:00 已确认
2 2 2 2023-10-02 11:00:00 已确认
3 3 3 2023-10-03 12:15:00 已确认
* /
想法: 操作:sql _db_查询
操作输入:SELECT * FROM reservations WHERE reservation_datetime BETWEEN '2023-10-10' AND '2023-10-15'
观察:[(6, 6, 6, datetime.datetime(2023, 10, 10, 0), '已确认'), (7, 6, 7, datetime.datetime(2023, 10, 12, 11, 30), '已确认')]
想法: 最终答案:10 月至 2023 年 10 月期间预订了 2 个航班2023 年 10 月 10 日和 10 月 15 日。
> 完成链条。
以下是代理制定行动方案的场景。最初,代理生成 SQL 查询。但是,执行失败。然后代理使用回溯进行自我纠正。
找出过去 7 天内预订过航班的所有客户。
> 进入新的 AgentExecutor 链...
动作:sql _db_ list _tables
动作输入:
观察:客户、航班、预订、交易
想法: 动作:sql_ db _schema
动作输入:客户
观察:
CREATE TABLE `customers` (
`customer_id` INT64 NOT NULL,
`first_name` STRING NOT NULL,
`last_name` STRING NOT NULL,
`email` STRING NOT NULL,
`date_of_birth` DATE NOT NULL,
`created_at` DATETIME NOT NULL
)
/ *
来自客户表的 3 行:
customer_id first_name last_name email date_of_birth created_at
1 John Doe john.doe@example.com 1985-02-15 2021-01-01 08:30:00
2 Jane Doe jane.doe@example.com 1987-05-23 2021-01-15 12:45:00
3 爱丽丝·约翰逊 alice.j@example.com 1990-08-10 2021-03-20 09:00:00
* /
想法: 行动:sql _db_ schema
行动输入:flights
观察:
CREATE TABLE `flights` (
`flight_id` INT64 NOT NULL,
`origin` STRING NOT NULL,
`destination` STRING NOT NULL,
`departure_datetime` DATETIME NOT NULL,
`arrival_datetime` DATETIME NOT NULL,
`carrier` STRING NOT NULL,
`price` FLOAT64 NOT NULL
)
/ *
来自 flights 表的 3 行:
flight_id 出发地 目的地 出发日期时间 到达日期时间 承运人 价格
1 JFK LAX 2023-11-05 09:00:00 2023-11-05 12:30:00 达美航空 450.0
2 洛杉矶国际机场 JFK 2023-11-10 15:00:00 2023-11-10 23:30:00 达美航空 450.0
3 肯尼迪国际机场 ATL 2023-11-15 07:00:00 2023-11-15 09:30:00 西南航空 300.0
* /
想法:操作:sql _db_ schema
操作输入:reservations
观察:
CREATE TABLE`reservations` ( `
reservation_id` INT64 NOT NULL,
`customer_id` INT64 NOT NULL,
`flight_id` INT64 NOT NULL,
`reservation_datetime` DATETIME NOT NULL,
`status` STRING NOT NULL
)
/ *
3 行来自预订表:
reservation_id customer_id flight_id reservation_datetime 状态
1 1 1 2023-10-01 10:30:00 已确认
2 2 2 2023-10-02 11:00:00 已确认
3 3 3 2023-10-03 12:15:00 已确认
* /
想法: 行动:sql _db_查询
行动输入:SELECT customer _id, first_ name, last _name, email, reservation_ datetime
FROM customers c
JOIN reservations r ON c.customer _id = r.customer_ id
WHERE r.reservation _datetime >= DATE_ SUB(CURRENT _DATE(), INTERVAL 7 DAY)
ORDER BY r.reservation_ datetime DESC
LIMIT 1000;
观察:错误:(google.cloud.bigquery.dbapi.exceptions.DatabaseError)400 列名 customer _id 在 [1:8] 处不明确
位置:美国
工作 ID:adb6b286-65d2-47cc-934e-941f3ddc229d
[SQL:SELECT customer_ id、first _name、last_ name、email、reservation _datetime
FROM customers c
JOIN reservations r ON c.customer_ id = r.customer _id
WHERE r.reservation_ datetime >= DATE _SUB(CURRENT_ DATE(), INTERVAL 7 DAY)
ORDER BY r.reservation _datetime DESC
LIMIT 1000;]
(此错误的背景信息:https://sqlalche.me/e/14/4xp6)
想法:行动:sql_ db _query_ checker
行动输入: SELECT customer _id, first_ name, last _name, email, reservation_ datetime
FROM customers c
JOIN reservations r ON c.customer _id = r.customer_ id
WHERE r.reservation _datetime >= DATE_ SUB(CURRENT _DATE(), INTERVAL 7 DAY)
ORDER BY r.reservation_ datetime DESC
LIMIT 1000;
观察: ```sql
SELECT customer_id, first_name, last_name, email, reservation_datetime
FROM customers c
JOIN reservations r ON c.customer_id = r.customer_id
WHERE r.reservation_datetime >= DATE_SUB(CURRENT_DATE(), INTERVAL 7 DAY)
ORDER BY r.reservation_datetime DESC
LIMIT 1000;
```
想法: 行动: sql _db_查询
行动输入: SELECT c.customer _id, c.first_ name, c.last _name, c.email, r.reservation_ datetime
FROM customers c
JOIN reservations r ON c.customer _id = r.customer_ id
WHERE r.reservation _datetime >= DATE_ SUB(CURRENT _DATE(), INTERVAL 7 DAY)
ORDER BY r.reservation_ datetime DESC
LIMIT 1000;
观察:[(20, 'Ryan', 'Reynolds', 'ryan.r@example.com', datetime.datetime(2023, 11, 22, 9, 10)), (19, 'Queen', 'Elizabeth', 'queen.e@example.com', datetime.datetime(2023, 11, 20, 16, 30)), (18, 'Peter', 'Parker', 'peter.p@example.com', datetime.datetime(2023, 11, 15, 12, 50)), (17, 'Olivia', 'Newton', 'olivia.n@example.com', datetime.datetime(2023, 11, 11, 10, 15)), (16, 'Nick', 'Fury', 'nick.f@example.com', datetime.datetime(2023, 11, 8, 15, 30)), (15, 'Mary', 'Jane', 'mary.j@example.com', datetime.datetime(2023, 11, 4, 10, 45)), (13, 'Kate', 'Winslet', 'kate.w@example.com', datetime.datetime(2023, 11, 2, 8, 20)), (13, 'Kate', 'Winslet', 'kate.w@example.com', datetime.datetime(2023, 10, 30, 14, 50)), (11, 'Ian', 'Somerhalder', 'ian.s@example.com', datetime.datetime(2023, 10, 28, 17, 10))]
想法: 最终答案: 以下是过去 7 天内预订过航班的客户:
| customer _id | first_ name | last _name | email | reservation_ datetime |
| ----------- | ---------- | -------- | ----- | ---------------------- |
| 20 | Ryan | Reynolds | ryan.r@example.com | 2023-11-22 09:10:00 |
| 19 | Queen | Elizabeth | queen.e@example.com | 2023-11-20 16:30:00 |
| 18 | Peter | Parker | peter.p@example.com | 2023-11-15 12:50:00 |
| 17 | Olivia | Newton | olivia.n@example.com | 2023-11-11 10:15:00 |
| 16 | 尼克 | 弗瑞 | nick.f@example.com | 2023-11-08 15:30:00 |
对于上述场景,在初始查询尝试中,存在列名customer_id
不明确的问题,因为它同时存在于customers
和reservations
表中,并且查询未指定从哪个表使用它。 这导致出现错误消息,指示由于列引用不明确而无法处理 SQL 查询。
识别出错误后,修改了查询,通过在列名前加上适当的表别名(c
forcustomers
和r
for reservations
)来完全限定列名。这是 SQL 中的一种常见做法,用于在处理具有相同名称的列的多个表时避免歧义。更正后的查询指定customer_id
应该来自customers
表,这解决了问题并允许成功执行查询,检索最近预订航班的客户列表。
优点:
- 大大简化了用户任务。
- 可以快速实施,解决各种场景。
- 系统从挫折中学习并提高其性能。
- 对于具有统一模式和可识别查询操作的数据库特别有效。
限制:
- 对于标准代理来说,驾驭复杂的数据库架构可能有点困难。
- 该系统适应性不够强,定制化程度可以更好。
- LLM 有一个上下文窗口,限制了它能处理的文本量。这可能会给大型数据库带来问题。
- 可能需要微调 LLM 代理的提示和参数以满足您的特定数据库和查询需求,这会增加其不透明性和有限的适应性。
- 代理在处理 SQL 数据库时经常会遇到一些问题,例如弥补数据库中不存在的表和字段。
此笔记本中包含一个示例 Jupyter 笔记本,演示了如何设置 BigQuery SQL 代理以及如何在六种不同的航班预订场景中测试其文本到 SQL 功能。
模式 IV:直接图式推理并自我纠正
受到我们先前模式的启发,其中代理自主推断数据库模式,纠正错误,并最终制定有效的 SQL 策略,模式 IV 重新审视了该方法的核心机制,同时增强了可定制性和可解释性。
这种方法从模式的直接推断开始,利用“种子提示”指示 LLM 构建与用户查询相对应的 SQL 查询。此初始提示的执行会不断迭代,直到成功。失败被视为 LLM 的关键学习机会,使其能够仔细检查回溯并利用错误消息来改进和发展种子提示,使其成为改进的查询迭代。然后测试这个自我修正的查询;如果成功,则该过程完成;如果不成功,则持续迭代改进和测试,直到获得成功的结果。
该模式的独特之处在于它对初始种子提示模板、自我修正提示演化机制以及允许重试次数等重要过程参数提供了精细控制,所有这些都可以进行微调以提高效率。
直接模式推理与自我纠正
让我们按照上面的架构图分解这些步骤:
- 我们从用户查询(问题)和种子模板开始,如下所示:
请为 BigQuery 编写一个 SQL 查询,以解决下面提供的以下问题。
确保您引用下面 SCHEMA 中提供的相应 BigQuery 表和列名。
连接表时,使用类型强制来保证连接列的数据类型一致性。
此外,输出列名应在适用的情况下指定单位。\n
问题:
{}\n
SCHEMA:
{}\n
重要提示:
仅使用 DATETIME 并且不要使用 TIMESTAMP。——
确保
您的 SQL 查询准确定义了 DATETIME 范围的开始和结束。
2.模式推断:LLM 获取用户输入的表名并推断数据库模式。此步骤对于理解数据的关系和结构至关重要。与自动执行此步骤的 SQL 代理模式不同,此步骤涉及手动方面,用户选择要关注的表。BigQuery 客户端用于直接从所选表中推断模式。
3.查询生成:使用推断出的模式,LLM 生成初始 SQL 查询。它涉及用必要的元素填充种子模板中的空白。此过程在后台进行,LLM 根据提供的模板构建 SQL 语句。
4.**错误处理和自我纠正:**如果初始查询执行失败,LLM 将捕获错误消息并使用它们来修改查询。错误反馈和不正确的 SQL 语句将指导 LLM 改进查询。LLM 继续迭代种子提示,不断完善它,直到查询成功执行。
5.执行和退出:当演化查询执行无错误时,该过程成功结束。此时,系统停止进一步迭代并退出查询生成循环。
这是一个进化提示的例子,它随着每次迭代而扩展原始种子提示。
{prompt}
遇到错误:{msg}。
要解决此问题,请生成替代 SQL 查询响应以避免此特定错误。
按照上述说明修复错误。
修改以下 SQL 查询以解决问题:
{generated_sql_query}_sql_查询}
确保修改后的 SQL 查询与初始问题中概述的要求完全一致。
优点:
- 该实现非常简单,因为它依赖于直接模式推理,从而使系统设置起来非常直观。
- 表和列的可选描述意味着系统可以使用最少的元数据运行,从而提供灵活性。
- 高可解释性是一个关键优势;人们可以跟踪提示的演变和错误代码来了解 LLM 的响应并解决问题。
- 与以前的模型相比,可定制性得到了增强,允许调整提示、进化标准和重试次数以满足特定需求。
限制:
- 该过程可能涉及多次迭代,这可能会引入执行开销,从而影响性能。
- 手动选择表进行模式推断可能会耗费大量劳动力,而且效率低于自动化流程,尤其是在尝试处理新的和未见过的情况时。
- 使用种子提示需要整合完整的架构,由于语言模型的上下文窗口限制,这个过程可能非常耗费资源。当添加表和列描述以及样本数据时,这个问题会变得更加明显——尤其是对于分类和字符串数据类型。此外,随着提示通过添加错误消息和之前的错误尝试而演变,超出上下文窗口容量的风险也会增加,从而对模型在每次重试操作中有效管理和处理越来越大的输入的能力构成潜在挑战。
这是说明模式 IV 的示例笔记本。它展示了我们之前使用代理测试的六种场景(模式 III)的自我纠正。此示例使用Code Bison
此设置的认知功能。
模式推理模式的变体:
当前模式的缺点是每次迭代时种子提示都会扩展,包含错误消息和之前生成的错误 SQL 查询。由于输入大小不断增加,这种扩展可能会导致后续调用 LLM 的成本增加。
为了缓解这个问题,一个战略性的调整是用Code Bison
对话代码模型(例如)取代标准代码生成模型()Code Chat Bison
。这种方法将迭代过程重新定义为对话,其中错误消息和不正确的 SQL 语句与简单的指令一起以对话的方式传递给代码模型。这有效地规避了提示扩大的问题,从而保留了上下文窗口容量并降低了在评估过程中上下文耗尽的风险,这在多次重试的情况下尤其有益。
在下面的进化提示中,我们没有在原始提示前加上前一个状态。我们并没有像之前那样扩展种子提示,而是在聊天会话中只传递错误消息和生成的 SQL 查询。
prompt = f"""遇到错误:{msg}。
要解决此问题,请生成替代 SQL 查询响应以避免此特定错误。
按照上述说明修复错误。
修改以下 SQL 查询以解决问题:
{generated_sql_query}_sql_查询}
确保修改后的 SQL 查询与初始问题中概述的要求完全一致。"""
经过优化后,改进的进化提示可为 LLM 保持简洁而集中的输入流。我们在此处Code Chat Bison
共享的 GitHub 存储库中提供的示例笔记本展示了利用自我纠正机制的有效性。
自我纠正检查
让我们深入研究共享笔记本中的一个具体示例,即场景 6,以说明这种方法如何巧妙地自我纠正,最终为所述问题生成准确的 BigQuery SQL。
识别并按年龄对所有 18 岁以上且本月有“已确认”预订的客户进行排名。确保在结果中显示他们的年龄。本月的“已确认”预订,按预订时间排序。请确保在结果中显示预订时间。
尝试:11
--------------------------------------------------
使用current_month作为(
选择DATE_TRUNC(CURRENT_DATE(),MONTH)作为start_of_month,
DATE_ADD(DATE_TRUNC(CURRENT_DATE(),MONTH),间隔 1 MONTH)作为end_of_month
)
选择c.customer_id,
c.first_name,
c.last_name,
DATEDIFF(current_month.end_of_month,c.date_of_birth)/ 365 作为年龄,
r.reservation_id,
r.status
从current_month
交叉 连接flight_reservations.customers c
连接flight_reservations.reservations r
ON c.customer_id = r.customer_id
WHERE r.status = 'Confirmed'
AND r.reservation_datetime BETWEEN current_month.start_of_month AND current_month.end_of_month
AND DATEDIFF(current_month.end_of_month, c.date_of_birth) / 365 >= 18按年龄
排序 --------------------------------------------------失败= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
= = = = =
尝试:2
--------------------------------------------------
选择DATE_TRUNC(CURRENT_DATE(),MONTH)作为start_of_month,
DATE_ADD(DATE_TRUNC(CURRENT_DATE(),MONTH),间隔 1 MONTH)作为end_of_month
)
选择c.customer_id、
c.first_name、
c.last_name、
DATE_DIFF(current_month.end_of_month、c.date_of_birth、YEAR)作为年龄、
r.reservation_id、
r.status
从current_month
交叉 连接flight_reservations.customers c
连接flight_reservations.reservations r
ON c.customer_id = r.customer_id
其中r.status = 'Confirmed'
并且r.reservation_datetime介于current_month.start_of_month和current_month.end_of_month
AND DATE_DIFF(current_month.end_of_month, c.date_of_birth, YEAR ) >= 18
--------------------------------------------------
失败
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = == = = =
尝试:3
--------------------------------------------------
使用current_month作为(
选择DATE_TRUNC(CURRENT_DATE(),MONTH)作为start_of_month,
DATE_ADD(DATE_TRUNC(CURRENT_DATE(),MONTH),间隔 1 MONTH)作为end_of_month
)
选择c.customer_id、
c.first_name、
c.last_name、
DATE_DIFF(current_month.end_of_month、c.date_of_birth、YEAR)作为年龄、
r.reservation_id、
r.status
从current_month
交叉 连接flight_reservations.customers c
连接flight_reservations.reservations r
ON c.customer_id = r.customer_id
其中r.status = 'Confirmed'
并且r.reservation_datetime在current_month.start_of_month之间并且current_month.end_of_month
AND DATE_DIFF(current_month.end_of_month, c.date_of_birth, YEAR ) >= 18按年龄
排序 ;--------------------------------------------------成功CPU 时间:用户86.8毫秒,系统:21.3毫秒,总计:108毫秒挂钟时间:16秒
让我们分解一下这些尝试,以了解系统如何自我纠正其 SQL 查询:
尝试 1
目标:
该查询的目的是选择本月已确认航班预订且年满 18 岁的客户。
问题:
- 年龄计算不正确。它使用
DATEDIFF
计算客户出生日期与当月月底之间的天数差,然后除以 365。这种方法对于计算年龄来说不够精确。 - 定义通用表表达式 (CTE) 的语法
current_month
是正确的,但是查询失败,可能是由于年龄计算方法造成的。
第二次尝试
调整:
- 年龄计算:将年龄计算方法替换为
DATE_DIFF(current_month.end_of_month, c.date_of_birth, YEAR)
。这直接计算年龄(以岁为单位),更为准确。
问题:
- 查询以
SELECT
CTE 之外的语句开头,并且没有WITH
关键字,导致语法错误。
第三次尝试
最后修正:
- 语法更正
WITH
:通过在查询开头添加关键字来更正语法,以正确定义current_month
CTE。 - 成功执行:此查询成功检索到所需数据:当前月份已确认预订且年龄至少 18 岁的客户,按年龄排序。
因此,可以观察到系统通过首先增强年龄计算方法,然后纠正语法错误进行了自我纠正。在最终成功的尝试中,它有效地将准确的年龄计算与正确的 SQL 结构结合起来,从而获得了预期的查询结果。
模式五:直接模式推理、自我纠正和优化
让我们来看看我们想要介绍的最后一个模式。这个模式建立在前一个模式的基础上,但有一个关键区别:我们不会在成功执行后停止,而是不断优化流程。我们要求系统优化查询的延迟,并仅在达到一定数量的迭代后停止。本质上,这种模式涉及持续的自我修正和优化。
直接模式推理、自我纠正和优化
这些步骤与模式 4 中的步骤类似,但增加了优化措施。其中包括查询优化循环,即使在成功执行后也会不断优化查询以提高性能。此外,还注重通过减少查询执行时间来改善延迟。
**注意:**在我们修改后的方法中,我们与之前的模式有显著的不同。我们将温度参数从 0 调整为 1,这一变化对模型的运行产生了重大影响。在过去(模式 IV),温度设置为 0,这会导致确定性的模型输出,即相同的输入始终导致相同的输出,几乎没有变化或创造的空间。我们通过动态地改进提示,包括错误代码和生成的查询,增强了这一点。现在温度为 1,模型的行为发生了显著改变。它现在允许更具创造性和即兴的反应。该模型不再严格地与最有可能的反应挂钩,而是探索了更广泛的可能性。这为模型的行为增加了不可预测性或“随机性”的元素,这有利于生成更多样化和创新的反应。这种方法旨在优化反馈回路,而无需在错误代码后加后缀。
优点:
- 提高查询效率和速度,优化动态改进。
- 适用于查询执行时间优先的高性能设置。
限制:
- 由于多次执行涉及多次调用 LLM,因此产生了更高的成本,增加了每次调用的费用。
- 进程较慢,因为它需要等待所有候选者的执行和排序,而由于需要先前的状态信息,因此无法并行化。
- 无法保证最快的查询会产生准确的结果,因此需要对结果进行评估。
涵盖此模式的演示笔记本可在此处文章附带的共享存储库中找到。
自我纠正和优化模式的变化:
与我们在模式 IV 中观察到的类似,我们将 替换Code Bison
为Code Chat Bison
将提示扩展策略更改为对话策略,我们可以在这里做同样的事情。Code Chat Bison
可以在此处找到涵盖模式 V 的示例笔记本。
自我修正和自我优化的检验
让我们深入研究一个涉及航班预订的场景(来自上面共享笔记本的场景 1),利用 LLM 进行自我纠正以及查询优化。LLM 会经历几次 SQL 查询迭代,每次迭代都旨在提高性能和纠正错误。此过程的特点是进行一系列试验,每次后续尝试都会根据前几次的结果优化查询。以下是对每次试验的详细分析,以帮助您了解这一渐进过程。
提供 2023 年 10 月 10 日至 10 月 15 日所有航班预订清单
试验:11
--------------------------------------------------
SELECT
r.reservation_id、
r.customer_id、
r.flight_id、
r.reservation_datetime、
r.status、
f.origin、
f.destination、
f.departure_datetime、
f.arrival_datetime、
f.carrier、
f.price
FROM arun - genai - bb.flight_reservations.reservations r
JOIN arun - genai - bb.flight_reservations.flights f
ON CAST (r.flight_id AS STRING) = CAST (f.flight_id AS STRING )
WHERE r.reservation_datetime BETWEEN '2023-10-10 00:00:00' AND '2023-10-15 23:59:59'
--------------------------------------------------
成功
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =试验:2 --------------------------------------------------选择 r.reservation_id、r.customer_id 、 r.flight_id、r.reservation_datetime 、 r.status、 f.origin、 f.destination、 f.departure_datetime、 f.arrival_datetime、 f.carrier、 f.price从 arun -
genai - bb.flight_reservations.reservations AS r
JOIN
arun-genai-bb.flight_reservations.flights AS f ON r.flight_id = f.flight_id WHERE r.reservation_datetime BETWEEN ' 2023-10-10 00:00:00' AND ' 2023-10-15 23:59:59' ORDER BY r.reservation_datetime ;--------------------------------------------------成功= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =试验: 3 -------------------------------------------------- SELECT r.reservation_id , r.customer_id, r.flight_id, r.reservation_datetime, r.status, f.origin, f.destination, f.departure_datetime, f.arrival_datetime, f.carrier, f.price FROM arun - genai - bb.flight_reservations.reservations AS r JOIN arun - genai - bb.flight_reservations.flights AS f ON r.flight_id = f.flight_id WHERE r.reservation_datetime BETWEEN
'2023-10-10 00:00:00' 和 '2023-10-15 23:59:59'按 r.reservation_datetime限制100
排序 ;--------------------------------------------------成功= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =试验: 4 -------------------------------------------------- SELECT r.reservation_id , r.customer_id, r.flight_id, r.reservation_datetime, r.status, f.origin, f.destination, f.departure_datetime, f.arrival_datetime, f.carrier, f.price FROM arun - genai - bb.flight_reservations.reservations AS r JOIN arun - genai - bb.flight_reservations.flights AS f ON r.flight_id = f.flight_id WHERE r.reservation_datetime BETWEEN '2023-10-10 00:00:00' AND '2023-10-15 23:59:59' ORDER BY r.reservation_datetime LIMIT 100 USE INDEX (reservation_datetime); --------------------------------------------------失败= = = = = =
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =试验:5 --------------------------------------------------选择/*+USE_NL(r)USE_NL(f)*/r.reservation_id,r.customer_id,r.flight_id,r.reservation_datetime,r.status,f.origin,f.destination,f.departure_datetime,f.arrival_datetime,f.carrier,f.price 来自arun - genai - bb.flight_reservations.reservations AS r JOIN arun - genai - bb.flight_reservations.flights AS f ON r.flight_id = f.flight_id WHERE r.reservation_datetime BETWEEN '2023-10-10 00:00:00' AND '2023-10-15 23:59:59' ORDER BY r.reservation_datetime LIMIT 100 ; --------------------------------------------------成功= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = CPU时间:用户332毫秒,系统:65毫秒,总计:397毫秒挂钟时间:45.5秒
试验 1
- 方法:基本 JOIN 和 WHERE 子句。
- 结果:成功。
- 分析:LLM 以一个简单的查询开始,该查询使用 WHERE 子句连接两个表。此处的成功表明基本查询结构是正确的。
试验 2
- 改进:添加表别名和ORDER BY子句。
- 结果:成功。
- 分析:在成功的基础查询的基础上,LLM 引入了别名以提高可读性,并引入了 ORDER BY 子句来对结果进行排序,这表明试图增强查询的可用性和数据呈现。
试验 3
- 改进:在查询中引入 LIMIT。
- 结果:成功。
- 分析:LLM 添加了 LIMIT 子句,通过限制返回的行数来优化查询性能。这是数据库查询中提高响应时间的常见做法,尤其是在处理大型数据集时。
试验 4
- 改进:尝试使用索引。
- 结果:失败。
- 分析:本次试验引入了索引提示(USE INDEX)来进一步优化查询。但是,它失败了,可能是由于语法问题或指定的索引不存在。这显示了 LLM 尝试在更高级的层面上优化查询性能,尽管并非所有此类尝试都成功。
试验 5
- 改进:使用优化器提示进行连接操作。
- 结果:成功。
- 分析:LLM 通过使用优化器提示 (USE_NL) 来改变策略,具体指示数据库如何执行连接。这表明对数据库优化技术的深入了解,旨在使查询执行更加高效。
LLM 从失败和成功中学习。第 4 次试验中的失败可能为第 5 次试验中的方法提供了参考,即从使用特定索引提示转向更广泛的优化器提示。在建立成功的基础查询后,后续试验将重点关注优化 — 对结果进行排序、限制输出和指导查询执行计划。
这种迭代方法证明了 LLM 根据结果调整和改进其策略的能力,展示了 SQL 查询中基础理解和高级优化技术的融合。
下面,我们展示成功执行的生成的查询,按延迟排序。
+ --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| |查询|延迟| |
| | -------|---------| |
| | 选择 /*+USE_NL(r)USE_NL(f)*/r.reservation_id、r.customer_id、r.flight_id、r.reservation_datetime、r.status、f.origin、f.destination、f.departure_datetime、f.arrival_datetime、f.carrier、f.price来自arun - genai - bb.flight_reservations.reservations AS r JOIN arun-genai-bb.flight_reservations.flights AS f ON r.flight_id = f.flight_id其中r.reservation_datetime介于' 2023-10-10 00:00:00 '和' 2023-10-15 23:59:59'之间按r.reservation_datetime排序LIMIT 100;| 7.883168 | | | |从arun - genai - bb.flight_reservations.reservations r 中选择 r.reservation_id、r.customer_id、r.flight_id、r.reservation_datetime、r.status、f.origin、f.destination、f.departure_datetime、f.arrival_datetime、f.carrier、f.price,并加入arun-genai-bb.flight_reservations.flights f,并将它们合并到CAST (r.flight_id AS STRING ) = CAST ( f.flight_id AS STRING),其中r.reservation_datetime介于' 2023-10-10 00:00:00'和'2023-10-15 23:59:59'之间;|
8.936372 | |
| | 从arun - genai - bb.flight_reservations.reservations AS r 中选择 r.reservation_id、r.customer_id、r.flight_id、r.reservation_datetime、r.status、f.origin、f.destination、f.departure_datetime、f.arrival_datetime、f.carrier、f.price,并加入 arun-genai-bb.flight_reservations.flights AS f ,在r.flight_id = f.flight_id之间,其中r.reservation_datetime介于' 2023-10-10 00:00:00 '和' 2023-10-15 23:59:59 '之间,按r.reservation_datetime 限制100排序;| 11.076487 | | | |从arun - genai - bb.flight_reservations.reservations AS r中选择r.reservation_id、r.customer_id、r.flight_id、r.reservation_datetime、r.status、f.origin、f.destination、f.departure_datetime、f.arrival_datetime、f.carrier、f.price,并加入arun - genai - bb.flight_reservations.flights AS f ,然后r.flight_id = f.flight_id ,其中r.reservation_datetime介于'2023-10-10 00:00:00'和'2023-10-15 23:59:59'之间,按r.reservation_datetime排序;| 12.221815 | | + ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
以下是执行优化查询后的最终结果。
+----------------+-------------+-----------+----------------------+---------------------+-----------+-------------+--------------------+---------------------+---------------------+-----------+---------------------+---------------------+-----------+
| reservation_id | customer_id | flight_id | reservation_datetime | 状态 | 出发地 | 目的地 | 出发日期时间 |到达 日期时间 | 承运人 | 价格 | |
+----------------+-------------+-----------+----------------------+------------------------+-----------+---------------------+---------------------+-----------+---------------------+-----------+
| 0 | 6 | 6 | 6 | 2023-10-10 10:00:00 | 已确认 | SEA | JFK | 2023-11-25 06:00:00 | 2023-11-25 14:30:00 | 联合航空 | 550.0 |
| 1 | 7 | 6 | 7 | 2023-10-12 11:30:00 | 已确认 | JFK | MIA | 2023-11-27 20:00:00 | 2023-11-27 23:30:00 | 美国 | 380.0 |
| 2 | 8 | 8 | 8 | 2023-10-15 13:20:00 | 已确认 | MIA | JFK | 2023-11-30 10:00:00 | 2023-11-30 13:30:00 | 美国 | 380.0 |
+----------------+-------------+-----------+-------------------------+-----------+-------------+--------------------+---------------------+-----------+-----------+
结论
我们上面探讨的五种模式提供了一系列策略,从简单的意图检测和实体识别到更复杂的自我纠正和优化技术。每种方法都有其优缺点,强调需要根据应用程序的独特需求和数据集的复杂性选择正确的方法。
展望未来,我们可以预期 LLM 将继续发展,可能带来更无缝的集成和更智能的数据库交互界面。这一发展将带来更直观、更高效、更用户友好的数据管理系统,以满足不同行业和用例的需求。
10:00:00 | 已确认 | SEA | JFK | 2023-11-25 06:00:00 | 2023-11-25 14:30:00 | 联合航空 | 550.0 |
| 1 | 7 | 6 | 7 | 2023-10-12 11:30:00 | 已确认 | JFK | MIA | 2023-11-27 20:00:00 | 2023-11-27 23:30:00 | 美国 | 380.0 |
| 2 | 8 | 8 | 8 | 2023-10-15 13:20:00 | 已确认 | MIA | JFK | 2023-11-30 10:00:00 | 2023-11-30 13:30:00 | 美国 | 380.0 |
+----------------+-------------+-----------+-------------------------+-----------+-------------+--------------------+---------------------+-----------+-----------+
结论
我们上面探讨的五种模式提供了一系列策略,从简单的意图检测和实体识别到更复杂的自我纠正和优化技术。每种方法都有其优缺点,强调需要根据应用程序的独特需求和数据集的复杂性选择正确的方法。
展望未来,我们可以预期 LLM 将继续发展,可能带来更无缝的集成和更智能的数据库交互界面。这一发展将带来更直观、更高效、更用户友好的数据管理系统,以满足不同行业和用例的需求。
本次讨论中穿插的实际示例和演示不仅展示了这些模型的当前功能。它们还为该领域的未来突破奠定了基础。通过掌握这些模式,开发人员和组织可以充分利用文本到 SQL 技术,简化数据工作流程,并从数据库中发现新见解。
博客原文:专业人工智能社区