大语言模型实战

Text2SQL虽然近年来才流行起来,但实际上它的研究历史还是比较长的。早在20世纪六七十年代,人们就提出了NLIDB(Natural Language Interface to DataBase)概念并做了一些研究。受限于数据量和计算机的算力,当时主要的技术手段是模式匹配、语法树和语义语法等。

在深度学习技术蓬勃发展前,研究者所提出的方法严重依赖于人工设计规则。而近年来深度学习的发展为这一领域注入了新的活力。随着算法的研究深入,基于深度学习的Text2SQL方法不断刷新着记录。当前,基于大模型的方法也在Text2SQL任务上取得了重大效果,接下来,我们将对Text2SQL技术进行研究。

 

1. 基于规则的方法


基于规则的方法通常是将自然语言问句解析成一个树结构的中间表达,不同的模型生成的树不一样。

NaLIR是将输入的依存句法树转化成另一种分析树,通过一个简单的算法来移动任意初始句法树的子树,然后使用一系列节点插入规则,最终实现树结构的变换。

ATHENA是构建一棵解释树(Interpretation Tree),其中节点对应概念或属性,边表示在本体库中概念或属性之间的关系。

SQLizer是将经过预处理的自然语言问句转化成逻辑表达式。

 

2. 基于深度学习的方法


基于深度学习的方法的基本架构都是编码器-解码器结构的。2019年之前的工作,通常都是使用RNN作为编码器对自然语言问句进行编码。但是随着Transformer的特征提取能力逐渐被人们发掘,尤其是以BERT为代表的预训练语言模型技术被提出以后,使用预训练语言模型作为编码器逐渐成为主流。

按照生成SQL语句的方法,已有的深度学习模型可以分成以下3种。

·文本生成式(sequence-to-sequence):输入一个序列,输出一个序列,类似于机器翻译。

·树形生成式(sequence-to-tree):输入一个序列,输出一棵树。

·槽位填充式(slot filling):槽位填充就是把SQL语句看作一系列的槽,通过解码器对槽一个一个地进行填充。比如,我们预先设定一个SQL语句“SELECT FROM WHERE *”,其中“*”就是我们要填充的内容。

下面将详细介绍这3种方法。

(1)文本生成式

在当前深度学习研究背景下,Text-to-SQL任务可被看作一个类似于神经机器翻译的序列到序列的生成任务,主要采用Seq2Seq模型框架。基线Seq2Seq模型加入注意力、复制等机制后,在单领域数据集上可以达到80%以上的准确率,但在多领域数据集上效果很差,准确率均低于25%。首先,SQL由数据库中的元素(如表名、列名、表格元素值)、问题中的词汇和SQL关键字三部分组成,所需要生成的内容较多,导致生成难度较大;其次,为了确保后续训练的模型与数据库之间相互独立,当前数据集在创建时,就需要训练集和测试集的数据与数据库相互独立且无交叉。

然而,这也导致测试集中的大部分元素都属于模型在训练时未见过的内容,存在大量未登录词,从而使得后续结果的可靠性无法得到保证。

 

Seq2SQL(2017)的编码器沿用了BiLSTM(双向长短时记忆)网络,而在解码器中使用了指针网络(Pointer Network),从而很好地解决了这一问题,其输出所用到的词表是随输入而变化的。具体做法是利用注意力机制直接从输入序列中选取单词作为输出,将问题中词汇、SQL关键词、对应数据库的所有元素作为输入序列,利用指针网络从输入序列中复制单词作为最终生成SQL的组成元素。其模型结构如图5-1所示。

 

图5-1 Seq2SQL模型结构

(2)树形生成式

抽象语法树是源代码语法结构的一种抽象表示。它以树状的结构表示编程语言的语法结构,树上的每个节点都表示源代码中的一种结构。

这种方法将SQL结构视作一棵抽象语法树(AST),树中的各个节点是SQL的关键字(SELECT、WHERE、COUNT、AND等)或者table和column的候选值。生成SQL的过程相当于从树的root节点对语法树做一次DST操作。

以开始节点SELECT为例。SELECT节点往下可能包含3个叶子节点:Column、AGG、Distinct,分别代表“选取某一列”“在列前增加聚合操作”“对列进行去重操作”。从SELECT节点向下搜索相当于是一个3分类任务,根据真实路径和搜索路径依次计算各个节点的交叉熵并求和,作为总损失。利用抽象语法树的思想,可以避免设计各种各样的子网络,对于涉及跨表查询、嵌套查询的复杂数据集有很好的效果。Spider排行榜排名靠前的RAT-SQL、IRNet等模型都借鉴了该思想。图5-2为

RAT-SQL在其树解码器中选择列的过程。

(3)槽位填充式

槽位填充方法也可以称为基于模板插值的方法,是SQL生成问题的一种简化形式,仅生成模板中空缺位置所需要的值。同一种SQL语句可能有多种等价的表示形式,例如查询条件中约束的顺序改变往往不影响SQL语句的语义和执行结果。

 

 

这种方法最早在SQLNet(2017)中提出,用于解决WikiSQL数据集中因为SQL语句等价形式所引起的顺序问题。SQLNet引入了序列到集合的结构,用于预测无序的约束集,而不是有序的序列。TypeSQL(2018)中也使用了模板插值,并且在解码过程中将需要插值的内容总结为3个类别并使用3个模型来进行训练,以此针对不同类型的插值进行建模。下面介绍在此类工作中常见的一种模式——“共享编码器+多任务解码”。

对于简单类型的Text2SQL数据集,例如NL2SQL等,“共享编码器+多任务解码器”是一种比较有效、可控的神经网络方法。其中,共享编码器部分一般是使用词向量或语言模型对query、table和column进行联合编码,例如将输入序列拼接为“[CLS] query [SEP] column1 [SEP] column2 [SEP] ....[SEP]”这样的长序列。多任务解码器部分根据SQL语言的组成特点设计不同的子网络来分别解码。

M-SQL是一个经典的案例,它将SQL序列拆分为8个子片段,在解码器中设计了8个神经网络分别解码对应片段的输出,最后通过简单的规则拼接为完整的SQL。其模型结构如图5-3所示。

 

 

多任务架构的优点在于,可以针对不同片段设计有效的损失函数,在训练过程中各个子任务的准确率可以实时监控。再结合一些人工规则,能够生成高质量的SQL,便于在实际中落地。在IEEE上发表的M-SQL各个子任务的准确率都超过了90%,总体准确率超过92%。

 

 

3. 基于预训练语言模型的方法


除了前两种较为成熟的方法,一种训练文本和表格联合编码的预训练语言模型的方法正在逐渐兴起。

将预训练语言模型应用于各种NLP下游任务已经是一种通用的方法,但以往的语言模型如BERT、ERNIE等一般是在通用的文本场景中使用MLM等任务训练得到的,与下游基于表格和文本的Text2SQL任务场景明显不一致。为了获得具有文本和表格联合编码能力的语言模型,耶鲁大学的Yu等人首先提出了一种适用于表格语义解析的语法增强预训练方法。其核心思想是先用语法规则得到一批人工合成的query-SQL语料,然后基于此(主要针对query、column)设计新的训练任务,最终训练得到的语言模型可以捕捉text和table之间的关联信息,获得更好的初始化表示。同时,这种训练方式得到的新模型可以直接替换已有Text2SQL模型中的BERT/Word2Vec编码器。

 

4. 基于大型语言模型的方法


大型语言模型(如GPT-4、GLM等)目前大多采用Transformer架构,通过大量的文本数据训练得来,能够处理长距离的依赖关系,捕捉文本中的复杂模式。在训练过程中,大语言模型会试图预测给定文本序列中的下一个词,这种方式称为自回归模型。通过这种方式,模型逐渐学习到语言的语法规则、词汇关联和语境含义等信息。当模型训练完成后,它就能理解输入的文本,并以人类的方式生成响应。此外,这些模型具有强大的学习能力,可以不断地从新的文本数据中学习和适应,从而在处理各种语言任务时更好地理解和生成语言。

在使用大型语言模型完成SQL生成任务时,主要流程如图5-4所示,根据获取的表字段信息,配置用于生成SQL的提示语,然后调用大型语言模型获取问答结果,判别接口是否合格,若不合格,需要进一步调整提示语,若合格则可以部署上线。

 

大型语言模型完成SQL生成任务时主要包括以下两个步骤。

步骤1:确定表的阶段。模型会先对用户的需求进行语义理解,进一步理解需要查询或者操作的数据所在的表。这个过程可能涉及对用户提出的问题或请求进行深入理解,或者对某个特定业务流程进行理解。例如,如果用户要查询某个设备信息,模型需要理解“设备信息”这个概念对应的是哪个或哪些数据库表。

步骤2:生成SQL语句的阶段。模型会根据第一步确定的表,构造出对应的SQL语句。这个过程需要模型理解并适应SQL语法的规则,同时需要根据具体的查询或操作需求来决定使用哪种类型的SQL语句。在这个阶段,模型还需要处理各种复杂的查询条件,如连接、分组、排序等。


1. ChatGPT

当前ChatGPT在SQL生成任务上已具备一定的效果,但从实际测试结果来看,直接使用可能还存在一定的局限性。我们可以使用OpenAI提供的相关接口来实现SQL生成任务,以下是我们在ChatGPT上测试的SQL生成效果。


(1)单表场景验证

首先针对单表场景进行验证,可以直接调用大型语言模型。例如,现有一张投资顾问表mf_investadvisoroutline,包含id、InvestAdvisorCode、

InvestAdvisorName、InvestAdvisor-AbbrName等字段信息,输入问题“注册资金排行前3的基金管理人是哪些”,正确的SQL语句为“select

investadvisorabbrname from mf_investadvisoroutline order by regcapital desc limit 3”。

调用ChatGPT接口的测试结果如图5-5所示。

 

从ChatGPT输出的结果来看,SELECT语句处有误,但基本正确。


(2)多表场景验证

若针对5张表场景进行验证,例如现有企业信息表lc_mainoperincome、研究人员表lc_intassetsdetail等5张表格,所需验证的问题为“显示基金经理最高学历为博士的总管理规模同类排名情况”,首先需要使用模型进行表格筛选,确定表格,然后调用ChatGPT模型,筛选结果如图5-6所示。

 

ChatGPT所筛选的表格正确,再根据预测的相关表名称结果调用接口生成SQL语句,生成效果如图5-7所示。

 

从图5-7来看,ChatGPT输出的结果不正确。

 

2. SQLCoder

SQLCoder是由DefogAI团队推出的一款基于StarCoder微调的大型语言模型,专注于SQL优化。DefogAI成立于2023年,是一家新兴创业企业,致力于通过大型语言模型这个平台,使用户能够使用自然语言对数据进行提问。SQLCoder的参数规模为150亿,虽然仅为GPT-3的十分之一,但在SQL生成方面的表现优于GPT-3,随后发布的sqlcoder-34b版本甚至超过了GPT-4的效果。对比结果如图5-8所示。

 

官方提供了一个演示地址——https://defog.ai/sqlcoder-demo/,可以测试SQLCoder的实际能力,只需要给出数据库的建表语句,并可用自然语言提问,样例如图5-9所示。

 


3. SQL-LangChain

企业数据通常被存储在SQL数据库中,而大型语言模型的出现使得通过自然语言与SQL数据库进行交互成为现实。

LangChain为此提供了SQL Chains和Agents,用于构建和运行SQL查询,通过自然语言提示进行操作。这些工具兼容SQLAlchemy支持的各种SQL方言,例如MySQL、PostgreSQL、Oracle SQL、Databricks和SQLite。

LangChain提供了与SQL数据库交互的工具,包括根据自然语言用户问题构建SQL查询、使用链进行查询的创建和执行,以及使用代理与SQL数据库进行灵活而强大的查询交互。这一系列工具的整合使LangChain成为一个强大而灵活的工具集,用户能够以直观的方式构建复杂的数据库查询,通过链实现多步骤的查询操作,并通过代理实现智能、定制化的数据库交互体验。LangChain的特点在于简化了用户与SQL数据库之间的交互流程,提高了灵活性和便捷性,有助于满足企业在数据查询和分析方面的需求。

使用LangChain实现Text2SQL任务,整体框架如图5-10所示。

代码样例如下:

 

关于LangChain,我们将在后续章节中进行更为详细的介绍。

 

4. DB-GPT-Hub

DB-GPT-Hub是一个实验项目,采用大型语言模型实现Text-to-SQL解析。该项目主要包括数据集收集、数据预处理、模型选择与构建以及微调权重等关键步骤。通过这一系列的处理,不仅能够提高Text-to-SQL的解析能力,也能够降低模型训练的成本,使更多开发者能够参与到提升Text-to-SQL准确度的工作中。

DB-GPT-Hub的目标是实现基于数据库的自动问答能力,使用户能够通过自然语言描述完成复杂数据库的查询操作等任务。