发布时间:2024 年 09 月 04 日
Tool-Assisted Agent on SQL Inspection and Refinement in Real-World Scenarios
近期,Text-to-SQL 技术通过整合数据库系统的反馈,有效利用了大型语言模型(LLMs)。尽管这些技术能有效纠正 SQL 查询的执行错误,但在处理数据库不匹配问题上仍显不足,这类问题不会引发执行异常。为此,我们设计了一个辅助工具框架,包括检索器和检测器,专门用于诊断并修正 SQL 查询中的不匹配问题,从而提升 LLM 在实际应用中的查询处理能力。同时,我们推出了 Spider-Mismatch 数据集,专门针对现实场景中的条件不匹配问题。实验显示,我们的方法在少样本环境下,不仅在 Spider 系列数据集上表现卓越,更在 Spider-Mismatch 这一更具现实挑战的数据集上大幅超越了传统方法。
https://arxiv.org/abs/2408.16991
1. Text2SQL现状
Text-to-SQL 任务是将自然语言问题自动转化为结构化查询语言(SQL),从而让非专业用户能够更便捷地从数据库获取数据。
Text-to-SQL 任务研究着重于运用各种框架和策略来训练模型,需要大量的标注数据。近期的研究探索了用大型语言模型(LLMs)的方案,并将上下文学习(ICL)应用于该任务。仅需提供几个示例,就能在众多任务中的表现媲美微调模型。
提高Text2SQL的准确性,目前有两个主流优化方案:自我纠正和基于执行反馈的优化。
-
• 自我纠正方:引导 LLMs 依据预定义的纠正准则生成修订后的 SQL 查询,但仅能处理有限范围的错误。
-
• 执行反馈:通过利用在数据库管理系统(DBMS)上执行这些查询所得到的反馈来优化 SQL 查询,确保可激发性并改进结果。这方法对于那些未触发执行异常的问题却无能为力。
作者文章中主要关注于执行反馈策略中一种特定错误类型:数据库不匹配。这种错误类型涵盖了两个常见的问题:
1.1 条件不匹配(Mismatch of Conditions)
SQL 查询中条件子句的不匹配可能导致空结果或错误结果。
在真实场景中,用户问题的多样性和不规则性导致 LLMs 难以将问题与数据库精准对齐并生成正确的 SQL 条件子句。
上图展示了在真实场景中将自然语言查询转换为 SQL 的难题,凸显了用户问题中常见的模糊性。
因为问题表述不够清晰,使得 LLMs 难以确切判定用户所指的是“Written_by”还是“Directed_by”等特定列。
此外,即便确定了正确的列,用户问题中提及的值与数据库中的实际数据存在不一致时,也可能导致空结果(例如,“todd casey”与“Todd Casey”)。
尽管现有方法试图通过为每个列提供示例值来协助 LLMs,但在真实场景中仍然不够。
1.2 更严格约束的不匹配(Mismatch of Stricter Constraints)
在真实场景中,SQL 查询通常需要遵循更严格的约束,这可能源于 SQL 的固有特性或用户自定义的规则。
例如,前者可能涉及与外键关系或列数据类型相关的限制,后者可能包含诸如“NULL”值或特定数据格式等强制流程。
这些更严格约束的不匹配在执行时未被体现,但不满足这些约束的 SQL 查询可能无法产生预期结果。
这使得 LLMs 难以在单个流程中生成准确的 SQL 查询,需要多步优化才能完成 SQL 生成。
2 Tool-SQL
为了解决以上不足,作者提出了Tool-SQL:一个工具辅助的智能体框架,检查并纠正 SQL 查询中的错误。运用多种工具来诊断 SQL 查询中的问题,并利用基于 LLM 的智能体根据这些工具提供的反馈有针对性地优化这些查询。
Tool-SQL设计了两个特定工具来解决上述问题:
-
• (1)数据库检索器,当 SQL 条件子句与数据库中的任何条目均不匹配时,通过检索相似的数据库单元作为反馈来协助基于 LLM 的代理。
-
• (2)错误检测器,诊断更广泛的错误,包括执行错误以及由 SQL 规则或领域专家定义的更严格约束的不匹配。
如上图,将一组 Python 函数定义为智能体的动作空间。这些函数对应不同的 SQL 子句。因此,输出是代表 SQL 查询的一系列动作,而非 SQL 查询本身。
通过 Python 解释器执行动作序列,工具集中的每个工具都会依据问题和数据库进行调用,以检查函数调用中的不同错误。若检测到错误,每个工具都会向智能体提供特定反馈,帮助智能体优化特定的 SQL 子句,而非盲目修改 SQL 查询。
检查和优化过程是迭代式的。智能体生成一系列动作后,会调用所有工具来检查潜在问题。若所有工具都认可动作序列,它将用于组装最终的 SQL 查询。反之,若有任何工具检测到问题,代理将依据原始序列和工具的反馈生成新的动作序列。
此过程可能会重复多次,直至所有工具都认可序列或达到最大尝试次数。
2.1 函数调用设计
上图展示了Tool-SQL的函数设计。基于 SQL 的主要子句定义了八个 Python 函数,这些函数在优化后可用于组装 SQL 查询。
每个 SQL 子句都有相应的函数动作,比如“WHERE”子句由“add_where”函数表示。
为减少智能体的动作空间,将 SQL 查询连接运算符(如“UNION”“INTERSECT”“EXCEPT”)合并到一个“add_merge”函数中。
“WHERE”或“HAVING”子句中的连接运算符(如“AND”和“OR”)隐藏在函数设计中,并在最后由大型语言模型处理,简化了动作生成过程。由于每个 SQL 子句具有不同的结构特征,每个子句的内容作为参数传递给相应的函数。例如,“WHERE”子句“A = B”表示为“add_where(A, =, B)”。
这种参数化方式使得我们框架中的工具能更有效地诊断 SQL 子句中的错误,并降低字符串解析的复杂性。
还引入“QA()”函数以更好地处理子问题,增强智能体的推理能力。当执行此函数时,智能体会为子问题生成单独的动作。
这九个函数构成了基于大型语言模型代理的动作空间。
对于推理阶段的新问题,由于上下文为智能体提供了一个完整且不会立即改变的数据库模式,智能体会一次性生成动作序列,而非像其他工作那样逐步进行。这种方式避免了智能体与环境之间过多且不必要的交互。对于上下文中未涵盖的大多数数据库表单元格,Tool-SQL的数据库检索工具会检查条件子句并向智能体提供反馈。
2.2 检查工具(Inspection Tools)
Tool-SQL 定义了两个工具——数据库检索器和错误检测器,用于检查 SQL 查询中的问题,并协助智能体优化 SQL 查询。
2.2.1 数据库检索器(Database Retriever)
数据库检索器的主要作用是协助智能体验证 SQL 条件子句的正确性。
检索器检查条件动作(如“add_where”和“add_having”)中的参数是否与数据库中的任何条目匹配,若未找到匹配项,则为智能体提供类似单元格的参考。
通过使用检索器,智能体能够将 SQL 查询中的值与数据库中的相应单元格对齐,或者决定从条件子句中排除列,这对于现实世界中的文本到 SQL 任务至关重要。
用户问题通常包含与数据库中的标准化值不同的不规则值,在执行查询前需要进行验证。此外,用户问题的模糊性可能使即便是高级代理也难以在条件子句中找到正确的列名。
使用 SimCSE 作为检索模型,因为它能有效捕获约束值和数据库单元格之间的语义信息,对于处理具有显著变化(如缩写)的情况特别有用。
基于检索器返回的单元格,智能体评估条件子句的正确性。
若条件被认定为正确,智能体选择真实的单元格来替换值的提及;否则,智能体生成新的条件动作。每次智能体执行新动作时,都会从上下文中的数据库模式中移除先前使用的条件列,以避免重复动作。这个过程会重复多次,直至生成正确的约束,或者达到最大尝试次数。若达到最大尝试次数仍未成功,将使用初始条件动作作为最终答案,因为它可能是最准确的。
2.2.2 错误检测器(Error Detector)
错误检测器的作用是通过间接访问数据库来检查更严格的约束的不匹配情况,并检测 SQL 中的执行错误。
由大型语言模型生成的 SQL 可能因不熟悉特定领域的 SQL 或产生幻觉等因素而包含错误,所以错误检测至关重要。
解析 Python 函数的参数并设计验证程序,在数据库的协助下进行检测。
与 MAC-SQL 不同,Tool-SQL不在 DBMS 中直接执行 SQL 查询来收集反馈,因为这种方法的错误检测能力有限,通常只能捕获语法错误和数据库模式错误等执行异常。
此外,尽管权限控制策略能够防止潜在有害的 SQL 损坏数据库中的重要数据,但执行未经检查的 SQL 查询仍存在风险,因为它可能导致大型数据库中的响应时间变慢。
在检查过程中,首先提取数据库的模式信息,包括所有表名、列名和类型、外键关系等。
然后,设计验证程序来检查函数的参数是否满足 SQL 操作和数据库模式。对于更严格的约束,诊断过程重点检测基于 SQL 特性的以下错误:
-
• 1)外键关系不匹配
-
• 2)“JOIN”操作的冗余或缺失
-
• 3)条件子句中列类型不匹配
-
• 4)“GROUP BY”子句的缺失或不当使用
工具具有可扩展性,并且能够通过分析函数调用中的参数轻松适应在现实世界场景中检测用户定义的约束。例如,真实世界场景中,对列数据处理有特定要求时,工具可以扩展以检测是否排除了“NULL”值或是否正确处理了具有特定格式的列。
2.3 SQL 生成
使用校正后的动作序列生成 SQL 查询。使用 Python 解释器执行这些函数调用并提取 SQL 查询的主要组件。对于动作序列中未包含的“WHERE”或“HAVING”子句中缺失的逻辑运算符“AND”和“OR”,依靠大型语言模型来预测。
3. 效果评估
3.1 评估指标
执行准确率(EX)和精确匹配准确率(EM)这两项在Text-to-SQL任务中常用的评估指标来评估Tool-SQL的表现。
执行准确率(EX)评估预测的SQL查询的执行结果是否与相应的标准查询相同。
精确匹配准确率(EM)要求预测的SQL查询的每个组件都与标准查询完全匹配,不过它会忽略SQL查询中的值的差异。
然而,由于对于给定的问题可能存在多个正确的SQL查询,EM指标可能会将部分正确的SQL查询判定为不正确。所以,将执行准确率用作主要评估指标。
3.2 测试基准
对于Spider和Spider-Realistic,主要选取少样本的SOTA方法作为基线以确保比较的公平性。少样本方法在LLM的情境中仅使用几个静态示例,这与从整个训练集中选取示例的示范选择方法有所不同。
对于Spider-Mismatch,与以下少样本方法进行对比:
-
• ACT-SQL:一种引入思维链范式进行SQL生成的单阶段方法,与使用ChatGPT的其他方法相比,在Spider-Realistic数据集上取得了出色的成果。
-
• DIN-SQL:一种运用自我校正方式来优化SQL查询的多阶段方法,将文本到 SQL 任务分解为模式链接、问题分类、SQL 生成和自相关,以降低整体难度。
-
• MAC-SQL:一种基于DBMS反馈来优化SQL的多智能体协作方法。
3.3 测评结果
3.3.1 在Spider和Spider-Realistic上的结果
如上表,Tool-SQL在Spider开发集上达成了最高的执行准确率,以及在Spider开发集和测试集上的平均结果。
在Spider-Realistic上,相较于基线,取得了更大的性能差距。
如上表所示,Tool-SQL + GPT-4的表现比在Spider上表现出色的其他方法至少高出4.8%,这表明Tool-SQL在处理Spider-Realistic中的列干扰方面更具成效。Tool-SQL在Spider和Spider-Realistic上的稳定性能显示出其在应对不同场景挑战时的稳健性。
在Spider-Mismatch上的结果
上表展示了在Spider-Mismatch上的结果。在少样本设定下,以ChatGPT和GPT-4作为代理,Tool-SQL分别超出基线9.6%和7.1%。Spider-Mismatch针对现实场景中的用户问题,聚焦于条件的不匹配。
现有方法难以从表中提取足够的价值信息,致使它们难以生成准确的条件子句。Tool-SQL在Spider-Mismatch上保持了出色的性能,表明Tool-SQL显著增强了基于LLM的代理处理现实世界问题的能力。
3.4 消融分析
为评估Tool-SQL中每个验证工具的有效性,在Spider-Mismatch上针对每个工具展开了消融研究,其中的问题更能反映现实世界的场景。
如上图所示,排除每个工具都会逐步降低LLM代理的性能。
当移除数据库检索器时,ChatGPT和GPT-4的执行准确率分别下降了4.1%和3.2%,表明用户问题的模糊性使得LLM难以生成正确的SQL条件子句。此问题在真实场景中可能更为显著,因为数据库中众多相似的单元格会使通过条件后处理方法选取正确的单元格变得复杂。
此外,盲目应用条件后处理方法可能导致不准确的执行结果,特别是对于数据库无法回答的用户问题,凸显了探索数据库内单元格的必要性。
当错误检测工具也被去除时,观察到LLM性能的进一步下滑,ChatGPT的下降幅度更大。表明在没有错误检测器的协助下,较弱的LLM更容易出错。
将错误检测器替换为数据库验证(对应于上图中的“w/ DBMS”)。与错误检测器相比,当从数据库获取反馈时,ChatGPT和GPT-4的执行准确率分别下降了1.6%和1.0%。表明错误检测器在检查SQL查询的更严格约束以及诊断SQL查询的执行错误方面的有效性。
3.5 其他分析
上图展示了在以ChatGPT和GPT-4作为代理的情况下,最大迭代次数对Spider-Mismatch的影响。
结果表明,SQL查询中的大多数错误通过一次纠正即可解决,主要处理执行错误和更严格的约束不匹配。
仍有许多错误需要多次迭代来细化,其中多数是条件子句的细化。意味着智能体在面对现实世界场景中具有挑战性的用户问题时,可能需要多次尝试才能找到正确的条件。
根据Spider-Mismatch的结果,使用Tool-SQL + ChatGPT 所需的平均迭代次数为0.74,而对于Tool-SQL + GPT-4,平均为0.44。
还探究了删除条件后处理模块对结果的影响。如上表所示,删除后处理模块后,所有基线方法的性能都显著降低,凸显了LLM预测的值与数据库中的真实单元格之间的差异。