开源项目vanna-ai文档翻译:ai-sql-accuracy-2023-08-17.md
文档翻译 https://github.com/vanna-ai/vanna/blob/main/papers/ai-sql-accuracy-2023-08-17.mdAI生成SQL的准确性:通过测试不同大语言模型及上下文策略来最大化SQL生成准确率内容提要打造能够直接回答业务人员纯英文提问的自主AI智能体,这一前景虽然诱人但至今难以实现。许多人尝试让ChatGPT编写SQL查询语句,但成效有限
文章目录

文档翻译 https://github.com/vanna-ai/vanna/blob/main/papers/ai-sql-accuracy-2023-08-17.md
AI生成SQL的准确性:通过测试不同大语言模型及上下文策略来最大化SQL生成准确率
2023-08-17
内容提要
打造能够直接回答业务人员纯英文提问的自主AI智能体,这一前景虽然诱人但至今难以实现。许多人尝试让ChatGPT编写SQL查询语句,但成效有限,主要障碍在于大语言模型对特定查询数据集缺乏认知。
本研究表明,上下文信息至关重要——通过采用恰当的上下文策略,我们成功将准确率从约3%提升至约80%。我们系统检验了三种不同的上下文构建方案,并最终展示出明显胜出的最佳方案:该方案融合了模式定义、文档说明、历史SQL查询记录及相关性搜索技术。
我们还横向对比了多款大语言模型的表现,包括Google Bison、GPT 3.5、GPT 4以及初步测试的Llama 2。虽然GPT 4在SQL生成领域摘得桂冠,但当提供充足上下文时,谷歌Bison模型的表现可与之比肩。
最后,我们演示了如何运用文中的方法为您的数据库生成SQL查询。
以下是我们核心发现的摘要:
Why use AI to generate SQL?
如今,许多组织都已采用数据仓库或数据湖——这些存储库汇集了企业的大量关键数据,可供分析查询。这片数据海洋蕴藏着无数潜在洞察,但企业内部同时掌握以下两项技能的人才却凤毛麟角:
- 扎实的高级SQL功底
- 对企业特有数据结构与模式的全面认知
兼具这两项能力的人才不仅极其稀缺,而且往往并非提出最多业务问题的人群。
企业内部的真实情况是怎样的?产品经理、销售总监、高管等业务人员常常需要数据支撑商业决策与战略规划。他们首先会查看仪表盘,但大多数问题都是临时性的具体问题,无法直接获取答案,于是只能求助具备上述技能的数据分析师或工程师。这些技术人员本身工作繁忙,响应需求需要时间,而当业务人员获得初始答案后,又会衍生出更多追问。
这个过程对业务用户(获取答案周期长)和分析师(打乱主要工作节奏)而言都是痛苦体验,最终导致大量潜在业务洞察被埋没。
生成式AI应运而生! 大语言模型让业务人员有机会直接用英文查询数据库(由大语言模型完成SQL转换),我们已从数十家企业获悉这将为其数据团队乃至整个业务带来颠覆性变革。
核心挑战在于为复杂混乱的数据库生成精准SQL。我们接触的许多人都曾尝试使用ChatGPT编写SQL,但成效有限且过程坎坷。多数人最终放弃并回归手动编写SQL的传统方式。往好了说,ChatGPT充其量只是帮助分析师纠正语法错误的辅助工具。
但希望仍在! 过去几个月我们深入攻克这一难题,尝试了多种模型、技术和方法来提升大语言模型生成SQL的准确率。本文将通过实验数据展示不同大语言模型的表现,并揭示如何通过提供情境化标准SQL范例,使大语言模型实现极高准确率的关键策略。
Setting up architecture of the test 测试架构搭建步骤
首先,我们需要明确测试的整体架构。以下是一个五步流程的概要框架,并附上相应的伪代码说明:
- 问题输入 - 从业务问题开始
question = "德国有多少客户"
- 提示词构建 - 创建发送给大语言模型的提示词
prompt = f"""
请为以下问题编写SQL语句:
{question}
"""
- SQL生成 - 通过API将提示词发送给大语言模型并获取生成的SQL
sql = llm.api(api_key=api_key, prompt=prompt, parameters=parameters)
- 执行SQL - 在数据库中运行生成的SQL语句
df = db.conn.execute(sql)
- 结果验证 - 最终验证结果是否符合预期
由于结果判断存在一定主观性,我们采用了人工评估方式。具体评估结果可在此查看
Setting up the test levers 测试变量设置
完成实验架构搭建后,我们需要确定影响准确性的关键变量及测试集构成。本次测试聚焦两个核心变量(大语言模型选择与训练数据策略),并在由20个问题组成的测试集上进行验证。最终我们共完成:3种大语言模型 × 3种上下文策略 × 20个问题 = 180次独立测试的完整实验矩阵。
数据集选择标准
首先,我们需要选择合适的测试数据集。我们遵循以下几个指导原则:
- 代表性 - 企业级数据集通常具有复杂性,而多数演示/样本数据集无法体现这种复杂性。我们需要包含真实用例和实际数据的复杂数据库。
- 可获取性 - 数据集应公开可用
- 易理解性 - 数据集需便于广大用户理解,过于专业或小众的内容会增加解读难度
- 维护状态 - 优选得到妥善维护和更新的数据集,以反映真实数据库的特征
经过筛选,我们最终选定符合上述标准的Cybersyn SEC申报数据集,该数据集可在Snowflake市场中免费获取:
https://docs.cybersyn.com/our-data-products/economic-and-financial/sec-filings
测试问题选择
接下来需要选定测试问题。以下是部分示例问题(完整列表请参阅此文件):
- 数据集中有多少家公司?
- 'ALPHABET INC.'公司的利润表提供哪些年度指标?
- 特斯拉季度的"汽车销售额"和"汽车租赁收入"分别是多少?
- 目前Chipotle餐厅有多少家门店?
确定数据集和问题后,我们需要设定实验变量。
提示词设计
在提示词方面,本次测试将保持固定提示词模板,后续研究将涉及提示词变体测试。
大语言模型选择
我们将测试以下基础大语言模型:
- Bison(谷歌) - 这是通过GCP API提供的PaLM 2版本
- GPT 3.5 Turbo(OpenAI) - 尽管GPT 4已发布,但由于延迟和成本优势,加上基础任务准确率差异不大,GPT 3.5至今仍是OpenAI的主力模型(我们将通过测试验证这一点)
- GPT 4(OpenAI) - 更先进但性能开销更大的OpenAI模型。GPT 4支持多模态,不过本次测试不会使用该功能
- Llama 2(Meta) - 我们非常希望纳入开源模型,而Meta的Llama 2是当前领先者。但通过Replicate平台的测试环境很快出现故障,未能在发布前及时修复。在早期可运行的测试中,我们发现其表现最多只能算平庸
上下文策略选择
最后,我们将设定三种上下文策略。上下文指的是我们提供给大语言模型的背景信息,旨在帮助模型理解特定数据集的结构特性。
- 仅表结构 - 在上下文窗口中仅提供数据库表结构(使用DDL语句)
- SQL示例 - 在上下文窗口中提供固定的SQL查询示例
- 相关性示例 - 基于向量嵌入的相似性搜索,动态选取最相关的上下文(包括SQL查询/DDL结构/文档说明)注入上下文窗口
使用ChatGPT生成SQL的实践
虽然本节对ChatGPT略显不公,但作为起点具有参考价值。我们直接向ChatGPT提出业务问题并要求生成SQL——
提示词
请编写Snowflake SQL来回答以下问题:
Alphabet公司各业务部门的季度营收是多少?
仅返回SQL语句
生成的回复
SELECT
EXTRACT(QUARTER FROM date_column) AS quarter,
business_segment,
SUM(revenue) AS quarterly_revenue
FROM
revenue_table
WHERE
company_name = 'Alphabet'
GROUP BY
quarter,
business_segment
ORDER BY
quarter,
business_segment;
-- 请将date_column、business_segment、revenue、revenue_table等字段名替换为实际数据库中的字段名,并调整其他标识符以匹配您的具体数据库结构。
果然,当我们尝试运行这段代码时,不可避免地遇到了错误——由于我们没有提供真实的表结构,模型只能凭空编造表名和字段名:
确实,我们目前对大语言模型的要求有失公允——尽管它们表现神奇,但(不幸的是?或者说幸运的是?)它们还无法未卜先知地掌握我们数据库的具体结构。现在,就让我们进入提供更多上下文的测试环节。
仅使用表结构的效果
首先,我们将数据集的表结构置入上下文窗口。这通常是我们在ChatGPT教程中看到的主流做法。
实际提示词示例如下(由于Snowflake数据共享的特殊性,我们实际使用了信息模式表,但以下示例展示了核心原理):
用户提供问题,您需生成SQL。请仅返回SQL代码,不做任何解释。
仅返回SQL代码。不要附带任何解释——只需提供代码。
您可参考以下DDL语句了解可用表结构:
CREATE TABLE 表1...
CREATE TABLE 表2...
CREATE TABLE 表3...
用一句话总结结果:惨不忍睹。在60次尝试(20个问题×3个模型)中,仅有两个问题被正确回答(均由GPT 4完成),准确率低至3%。以下是GPT 4答对的两个问题:
- 按出现频率排序的前10个指标描述是什么?
- 报告属性中有哪些不同的报表类型?

显然,仅依靠表结构远达不到实用AI SQL助手的要求,尽管它或许能作为数据分析师的辅助工具提供有限帮助。
使用SQL示例的效果
如果我们设身处地思考:一个初次接触该数据集的使用者,除了表结构定义外,首先会查阅示例查询来了解如何正确查询数据库。
这些示例查询能提供表结构无法传递的额外信息——例如具体使用哪些字段、表之间的关联方式,以及查询该特定数据集的其他细节技巧。
与Snowflake市场上的其他数据提供商一样,Cybersyn在其文档中提供了少量(本例中为3个)示例查询。现在我们将这些示例纳入上下文窗口。
仅通过提供这3个示例查询,我们就观察到生成的SQL正确率得到显著提升。不过,这种准确度提升在不同底层大语言模型间存在显著差异。GPT-4似乎最擅长从示例查询中举一反三,从而生成最准确的SQL语句。

使用情境关联示例的策略
企业数据仓库通常包含数百(甚至数千)张数据表,而覆盖组织内所有用例的查询数量更是高出数个量级。鉴于现代大语言模型的上下文窗口容量有限,我们不可能将所有历史查询和表结构定义都塞入提示词中。
我们最终的上下文策略采用更精密的机器学习方法:将历史查询(prior queries)和表结构(table schemas)的嵌入向量加载到向量数据库中,仅选择与当前问题最相关的查询/表结构。下图展示了我们的实现流程——请注意绿色框中的情境关联搜索模块:

通过向大语言模型呈现最相关的SQL查询示例,即使性能较弱的大语言模型也能获得显著提升。在本方案中,我们为每个问题提供10个最相关的SQL查询示例(从存储的30个示例中筛选),准确率实现爆发式增长。

通过维护可执行且能正确回答用户实际问题的SQL语句历史记录,我们还能进一步提升模型性能。
结果分析
显然,造成显著差异的关键因素并非大语言模型的类型,而是为模型提供合适上下文的策略(即所使用的"训练数据")。
通过对比不同上下文策略的SQL准确率,可以清晰看出这是决定性能的关键因素。从仅使用表结构时约3%的准确率,到智能运用情境化示例后跃升至约80%的准确率,实现了质的飞跃。

不同大语言模型本身也呈现出有趣的发展趋势。虽然Bison模型在表结构和静态示例策略中表现垫底,但在完整情境化策略下却跃居榜首。综合三种策略的平均表现来看,GPT 4无疑摘得了SQL生成最佳大语言模型的桂冠。
进一步提升准确率的后续计划
我们即将开展更深入的后续研究,进一步探索精准SQL生成的优化路径。下一步计划包括:
- 拓展数据集范围:我们希望在更多真实的企业级数据集上进行测试。当数据表数量达到100张甚至1000张时,模型表现将如何变化?
- 增加训练数据量:当前30条查询示例已取得显著效果,如果将数据量扩大10倍、100倍会产生什么效果?
- 兼容多类型数据库:本次测试基于Snowflake数据库完成,但我们已在BigQuery、Postgres、Redshift和SQL Server等平台上成功实现相同技术
- 扩展基础模型测试:我们即将完成Llama 2的适配,并计划测试更多大语言模型
使用AI为您的数据集生成SQL
虽然SEC数据是个不错的起点,但您可能更关心这项技术如何应用于您的数据。我们正在开发一个Python工具包,不仅能为您的数据集生成SQL,还支持生成图表Plotly代码、智能追问等扩展功能。
以下是该工具的基本使用流程:
import vanna as vn
(笔者注:vanna.ai中所谓的训练,就是喂更多的示例给向量数据库)
- 通过表结构训练
vn.train(ddl="CREATE TABLE ...")
- 通过文档训练
vn.train(documentation="...")
- 通过SQL示例训练
vn.train(sql="SELECT ...")
- SQL生成
开箱即用的最简方式是使用vn.ask(question="查询内容..."),该函数将返回SQL语句、数据表格和可视化图表(如示例笔记所示)。vn.ask是vn.generate_sql、vn.run_sql、vn.generate_plotly_code等功能的集成封装,会自动使用优化后的上下文内容并调用大语言模型生成SQL。
您也可以参考这个笔记使用vn.get_related_training_data(question="查询内容...")获取最相关上下文,用于构建自定义提示词并发送至任意大语言模型。
此训练笔记展示了如何在Cybersyn SEC数据集上使用"静态"上下文策略训练Vanna的完整示例。
更多推荐

所有评论(0)