作为天天跟数据打交道的程序员,咱都知道 NL2SQL(自然语言转 SQL)是个好东西 —— 不用死记硬背 SQL 语法,对着数据库唠两句就能出结果,简直是业务同学的救星。但说实话,现在市面上的 NL2SQL 模型到底靠不靠谱,咱心里都没底。比如你换个说法问同一个问题,模型可能就懵了,这就是所谓的 “linguistic variation(语言变体)” 问题,可偏偏现有 benchmark(比如 Spider、BIRD)没把这事儿当重点,导致模型在测试集上分数挺高,一到真实业务场景就拉胯。

最近 Oracle AI 的团队搞了个新活:用 SQL2NL(SQL 转自然语言)反过来构建评测框架,专门测 NL2SQL 模型对语言变体的鲁棒性。简单说就是先从测试集中扒出 “标准答案 SQL” 和对应的数据库 schema,再用 SQL2NL 模型生成一堆语义相同但表达方式不同的自然语言问句,最后看 NL2SQL 模型在这些 “换皮问句” 上的正确率掉多少。这招妙就妙在能把 “schema 对齐”(也就是模型能不能把问句里的词和数据库的表 / 列对应上)这个变量控制住,单独拎出 “语言变体” 对模型的影响 —— 之前的研究要么混着测歧义,要么改 schema,从来没这么精准过。

先给大家看看这个评测流程的全貌,下图把每一步都画得很清楚:从基准测试集里提取黄金 SQL 和 schema,用 SQL2NL 生成 K 个 paraphrase(同义改写)问句,接着让 NL2SQL 模型去处理这些改写问句,计算它的执行准确率(EM),最后还要人工打分(CS,语义相似度)来修正准确率,避免因为改写本身出问题冤枉模型。这里要提一嘴,团队用的是同一个大模型同时做 SQL2NL 和 NL2SQL,省得不同模型的差异干扰结果。

图片

图 1:我们首先从基准 NL2SQL(自然语言转 SQL)测试集中提取黄金 SQL 查询(标准答案 SQL 查询)及其关联的数据库模式(schema)。随后,使用一个 SQL2NL(SQL 转自然语言)模型生成 k 个同义改写的自然语言查询。为确保语义不变,每个改写查询都会与原始查询进行语义验证。经过验证的改写查询随后会输入到 NL2SQL 模型中,以生成预测的 SQL 查询。模型的鲁棒性通过改写查询集上的执行匹配准确率(execution-match accuracy)来衡量 —— 即比较预测 SQL 与黄金 SQL 在数据库中执行结果的一致性。原则上,SQL2NL 和 NL2SQL 可视为两个独立的建模任务,但在本研究中,我们采用了一个统一的模型来处理这两个方向的转换。

那他们生成的改写问句质量怎么样?总不能为了变而变,把语义改歪了吧?团队用 SentenceBERT 算语义相似度,Spider 数据集的改写问句平均相似度 0.81,中位数 0.83,大部分都在 0.77-0.86 之间,说明语义没跑偏;BIRD 数据集稍低一点,平均 0.8,但方差更大,这也能理解,毕竟 BIRD 的 schema 更复杂,改写空间本来就大。给大家看几个实际例子,比如原句是 “Find the name of the makers that produced some cars in the year of 1970?”,改写后能变成 “What car manufacturers produced models in 1970?” 或者 “Which makers are associated with car models from 1970, according to the database records?”,相似度都在 0.84 左右,既换了说法,又没改意思;还有个原句问 “最早生产汽车的厂商和年份”,改写后相似度 0.53,虽然低了点,但仔细看还是围绕同一个问题,只是侧重点稍微变了点,这种情况在真实场景里也很常见。

除了语义,语法结构也得看看。团队用 SpaCy 生成依存句法树,算两个指标:树结构相似度(看子树重叠度)和 POS 标签相似度(看词性重叠度),最后平均一下得到语法相似度。结果挺有意思,Spider 和 BIRD 的改写问句都呈现 “双峰分布”—— 一部分和原句语法很像(高相似度峰),另一部分则改得比较彻底(低相似度峰)。比如原句是 “How many countries does each continent have? List the continent id, continent name, and the number of countries.”,改写后变成 “What is the distribution of countries across different continents?”,原句是两个分句,还明确提了要返回的列,改写后变成单句,更简洁,但语法相似度就低了。不过这正是团队想要的效果:既要保留一部分 “轻度改写”,也要有 “重度改写” 来测试模型的极限。

再看句子长度、句法深度和词汇多样性这三个指标(下图是 Spider 数据集的分布)。改写后的句子平均 15.02 个词,比原句的 12.4 个词长;句法深度(词到句法中心词的最大距离)也稍高,12.53 vs 10.8;但词汇多样性几乎没变化,都是 0.94(独特词数 / 总词数)。这说明改写没有牺牲词汇丰富度,反而通过更长的句子和更复杂的结构,更贴近真实场景里用户的 “啰嗦提问”—— 毕竟不是所有人都能像写 SQL 一样精准提问,多加点修饰词、换种句式太正常了。

图片

图 2:原始查询与同义改写查询在句子长度、句法深度和词汇多样性三个维度上的分布情况。同义改写查询的句子长度更长,句法深度也略高;而在词汇多样性方面,改写查询与原始查询均保持较高水平,且二者数值相近(无显著差异)。

接下来就是重头戏:模型在这些改写问句上表现到底怎么样?团队选了几个主流大模型,在 Spider 开发集里随机挑了 1000 个黄金 SQL,每个生成 10 个改写问句,总共 1 万条测试数据。先看整体成绩,GPT-4o-mini 在原句上准确率 77.4%,改写后掉到 65.2%,降了 12.2 个百分点;Llama3.3-70B 原句 77.1%,改写后 66.9%,降了 10.23 个百分点,算是比较稳的;最惨的是 Llama3.1-8B,原句 62.9%,改写后直接掉到 42.5%,足足降了 20 个百分点!这说明模型规模还是很关键,小模型处理语言变体的能力明显不行 —— 毕竟真实业务里,用户不会只按一种方式提问,小模型要是这么脆,根本没法用。

再深入看看,模型性能和 SQL 里的 JOIN 数量有没有关系?毕竟 JOIN 越多,查询越复杂,模型越容易懵。下图是 Llama3.3-70B 在 Spider 数据集上的表现:0 个 JOIN 时,原句准确率 84.04%,改写后 77.83%,降了 6.21 个百分点,就算最简单的查询,换个说法也会掉分;1 个 JOIN 时最惨,原句 65.44%,改写后 49%,降了 16.44 个百分点,这说明 JOIN 一出现,模型对 schema 的对齐能力就容易受语言变体影响 —— 比如原句说 “join 表 A 和表 B”,改写后说 “把表 A 里的 xx 和表 B 里的 yy 对应起来”,模型可能就找不到对应的表了;2 个 JOIN 时降了 6.72 个百分点,反而比 1 个 JOIN 时好点,团队推测是因为 2 个 JOIN 的原句本身就复杂,模型在原句上的准确率就不算高(64.29%),改写带来的额外影响反而小了。

图片

图 3:在 Spider 开发集(Spider dev set)中,LlaMa3.3-70B 模型在不同 JOIN 类别下的准确率表现,误差棒基于自助法(bootstrap)计算得出。结果分别展示了模型在同义改写自然语言查询(paraphrased NL queries)和原始自然语言查询(original NL queries)上的性能,均以执行匹配准确率(execution match accuracy)为衡量标准。其中,误差棒代表 95% 置信区间,该区间已考虑到每个 JOIN 类别下数据集规模差异所带来的变异性。

BIRD 和 FIBEN 数据集的情况又不一样。BIRD 里 0 个 JOIN 时,改写后准确率甚至比原句高一点(59.68% vs 59.51%),2 个 JOIN 时也高 1.8 个百分点(45.23% vs 43.4%),这可能是因为 BIRD 的原句本身对 schema 的描述不够清晰,而改写句是基于 SQL 和 schema 生成的,反而帮模型理清了表和列的关系;FIBEN 更极端,不管多少个 JOIN,原句和改写句的准确率都差不多,误差范围内基本持平,团队分析是因为 FIBEN 的查询以复杂嵌套为主,语言变体对模型的影响被嵌套结构的难度盖过了 —— 模型连嵌套逻辑都快理不清了,哪还顾得上句式变没变。

除了 JOIN,SQL 里的 clauses(子句)对模型性能也有影响。在 Spider 里,带 ORDER BY 的查询改写后准确率降了 27.93%,是所有子句里最惨的 —— 比如原句说 “按销量从高到低排”,改写后说 “把销量降序排列”,模型可能就没反应过来 “降序” 对应 ORDER BY DESC;带 GROUP BY 的降了 14.64%,带嵌套的降了 12.69%;反而带 HAVING 的只降了 4.8%,算是比较稳的。而 BIRD 里,带 ORDER BY 的改写后准确率甚至涨了 1.75%,带 HAVING 的只降 1%,整体比 Spider 稳得多,这进一步说明不同数据集的特性会直接影响模型对语言变体的敏感度 —— 不能只看一个数据集的结果就下结论。

还有个很重要的点:schema 对齐错误有没有减少?团队分析了四种错误:漏列、多列、漏表、多表,用 SQLGlot 解析 SQL 后,把错误率归一化(避免不同查询复杂度带来的偏差)。结果如下图所示,改写句的归一化错误率在所有类别里都比原句低,平均 9.9 vs 13.7。比如 “漏表” 错误,原句 17.33%,改写句 11.36%;“漏列” 原句 12.67%,改写句 8.67%。这说明用 SQL2NL 生成改写句时,因为是基于 schema 的,所以会更明确地提到表和列的信息,帮模型减少了 schema 对齐的错误 —— 这也印证了团队一开始的设计思路:把 schema 对齐这个变量控制住,才能更精准地测语言变体的影响。

图片

图 4:原始查询与同义改写查询的归一化模式(schema)错误率对比。为确保比较的公平性,假例(False cases,即模型预测错误的情况)中的错误率已基于正例(True cases,即模型预测正确的情况)基准进行了缩放处理。结果显示,在所有错误类别中,同义改写查询的归一化错误率均更低,这表明其模式对齐(schema alignment,即自然语言查询与数据库表 / 列等模式元素的匹配)效果得到了改善。

最后,团队还测了 Pass@K 指标 —— 简单说就是生成 K 个结果,只要有一个对就算对,这个指标能减少大模型生成的随机性。结果挺反常识的:当 K=5 或 10 时,SQL2NL 的 Pass@K 反而比 NL2SQL 高。比如 K=10 时,SQL2NL 是 84.6%,NL2SQL 是 81.3%。这说明如果给模型多几次机会,基于 SQL 生成自然语言再转 SQL,反而比直接用自然语言转 SQL 更靠谱 —— 这对实际应用很有启发,比如做 NL2SQL 工具时,可以让模型多生成几个 SQL,再执行验证,正确率能提不少。

不过这篇研究也有局限性,比如没测模糊问句、不可回答的问句,也没测多轮对话场景 —— 这些在真实业务里太常见了,比如用户问 “上个月卖得最好的产品”,没说哪个地区、哪个品类,模型怎么处理?多轮对话里用户前面提过 “北京地区”,后面没说,模型能不能记住?这些都是下一步要解决的问题。另外,研究假设 schema 是已知的,但真实场景里还得先从一堆表中找出相关的 schema,这步本身就很麻烦,要是把 schema 检索加进来,模型的鲁棒性可能还要再打个折扣。

总的来说,这篇研究的价值在于给 NL2SQL 模型的评测提供了一个新角度 —— 别光看 “能不能转对”,更要看 “换个说法还能不能转对”。对咱们程序员来说,以后选 NL2SQL 模型或者自己调参时,除了看 Spider、BIRD 的分数,最好也用这种改写问句测测鲁棒性,不然上线后用户换个说法就报错,那可就麻烦了。而且用 SQL2NL 生成训练数据来微调模型,也是个不错的思路 —— 毕竟真实的多样化问句不好收集,用 SQL 反向生成,既保证语义正确,又能覆盖各种语言变体,性价比很高。

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐