背景
让非技术人员可以从数据库中提问,这是学术界和工业界多年来感兴趣的问题。最近,大型语言模型(LLM)技术(如GPT-4)的进展提高了所提出解决方案的准确性。然而,由于最先进的LLM尚未开放进行微调,因此最近在这一领域的研究集中在创建能够在不修改基础LLM的情况下实现复杂的自然语言到SQL(NL-to-SQL)场景的检索增强生成(RAG)算法。
上周,OpenAI开放了GPT-3.5-turbo供微调使用。在本文中,我们将微调自己的NL-to-SQL模型,并将其性能与最先进的RAG方法进行比较。我们将使用耶鲁大学的Spider数据集作为测试基准。
以下是来自Spider数据集的两个示例:样例。通过简单的处理,我们可以从这个数据集获得以下训练数据:
[
{
"query": "SELECT count(*) FROM singer",
"question": "有多少歌手?"
},
{
"query": "SELECT count(*) FROM singer",
"question": "歌手的总人数是多少?"
}
]
准备训练数据集
对于微调GPT-3.5-Turbo,首先要做的是创建和上传训练数据集。由于GPT-3.5-Turbo是一个ChatModel,因此此数据集必须使用以下格式,并被上传为JSON文件。
{"messages": [{"role": "system", "content": "system_prompt"}, {"role": "user", "content": "user_prompt"}, {"role": "assistant", "content": "assistant_prompt"}]}
{"messages": [{"role": "system", "content": "system_prompt"}, {"role": "user", "content": "user_prompt"}, {"role": "assistant", "content": "assistant_prompt"}]}
{"messages": [{"role": "system", "content": "system_prompt"}, {"role": "user", "content": "user_prompt"}, {"role": "assistant", "content": "assistant_prompt"}]}
创建训练数据集
一个NL-to-SQL任务的定义如下:给定一个问题和数据库,确定一个SQL查询,当对数据库执行该查询时,返回一个结果集,可以回答这个问题。对于如何更好地提示LLMs执行此任务,研究人员探索了各种方法,并普遍认为提示需要包括指令组件、Data Schema的详细信息、关于数据内容、一组任务特定的演示以及实际的问题。
给定ChatModel训练数据的格式,上述元素必须在以下三个提示中呈现:
-
system_prompt – 包含指令、Data Schema和数据库内容
-
user_prompt – 包含自然语言问题
-
assistant_prompt – 包含SQL查询和推理步骤
让我们看看如何为我们的NL-to-SQL训练数据集创建每个提示。
准备 system_prompt
创建system_prompt是这个任务中最复杂的部分。至少,system_prompt需要包括:
-
系统指令
-
Data Schema
-
数据内容
此外,对于任何实际的用例,如果有大量的表,则训练集中的样本还应该训练模型选择正确的表格用于SQL查询(即执行模式链接)。
准备 系统指令
对于指令,我们使用了以下标准提示:
You are an assistant that is an expert in generating Sqlite SQL queries.
Having the access to database content, generate a correct Sqlite SQL query for the given question.
### Database content ###
Data Schema
对于Data Schema,文献中有许多提出的格式,但没有明确的共识,哪种格式表现最佳。我们发现以下是Data Schema的最佳表示方式:
CREATE TABLE concert (
"concert_ID" INTEGER NOT NULL,
"concert_Name" TEXT NOT NULL,
"Theme" TEXT,
"Stadium_ID" TEXT NOT NULL,
"Year" TEXT,
PRIMARY KEY ("concert_ID"),
FOREIGN KEY("Stadium_ID")
REFERENCES stadium ("Stadium_ID")
)
CREATE TABLE singer (
"Singer_ID" INTEGER NOT NULL,
"Name" TEXT,
"Country" TEXT NOT NULL,
"Song_Name" TEXT NOT NULL,
"Song_release_year" TEXT,
"Age" INTEGER,
"Is_male" BOOLEAN NOT NULL,
PRIMARY KEY ("Singer_ID")
)
数据内容
经过多次实验,我们发现以下模板在最佳的训练模型数据内容方面表现最好:
/*
Columns in concert and 3 examples in each column for the high cardinality columns :
concert_ID: 1025 , 1101 , 1247
concert_Name : "Fire", "Dance", "Sky"
Stadium_ID : 9, 10, 11
*/
/*
Columns in concert and all categories for the low cardinality columns :
Theme : " ROCK ", " POP ", " HIP-HOP "
Year : 2022, 2021, 2023, 2020
*/
/*
Columns in singer and 3 examples in each column for the high cardinality columns :
Singer_ID : 10235 , 110231 , 1242447
Name : "Jordan", "Gabriel", "Tiffany"
Country : "Iran", "India", "Canada"
Song_Name : "dance in the fire", "rain", "sky"
Age : 19, 20, 21
*/
/*
Columns in singer and all categories for the low cardinality columns :
Is_male : "MALE", "FEMALE",
Song_release_year : 2022, 2021, 2023, 2020
*/
数据库内容中的一个重要元素是如何识别分类(低基数)列。区分低基数和高基数列的阈值取决于要微调的大型语言模型(LLM)的上下文窗口大