输入“/”快速插入内容

数据可视化Agent-基于Text2SQL的数据分析方案

2024年8月26日修改
作者:王大锤
上篇中,我们探讨了企业应用中基于自然语言的交互式数据分析的业务驱动力和场景,这里主要探讨一下基于Text2SQL的 技术方案 ,也可以理解为NL2SQL,即 自然语言转SQL , SQL作为一种结构化 查询语言 ,是数据库交互的一种标准化语言,几乎存在于所有以数据为中心的企业应用中。
基础实现:
Text2SQL,简单的说,就是把你说的自然语言转化为数据库能够听懂的SQL,然后通过数据库的"语言"与它对话,获得数据查询或统计结果。Text2SQL并不是在大模型之后才出现的话题,早在大模型出世之前已有大量专注于此任务的机器学习项目。在大模型出现以后,凭借其强大的 自然语言理解 和推理能力,让Text2SQL得到了大力的推进。
从上述的图中可以看出,Text2SQL看似一个十分简单的任务,核心是在与如何将自然语言组装成Prompt, 然后交给大模型做推理生成对应的SQL。在OpenAI公司官网上给出了一个标准的ChatGPT做自然语言转SQL的示例:
代码块
System
/*系统指令*/
Given the following SQL tables, your job is to write queries given a user's request.
/*数据库内表结构*/
CREATE TABLE Orders (
OrderID int,
CustomerID int,
OrderData datetime,
OrderTime varchar(8),
PRIMARY KEY (OrderID)
);
...... //省略N张其他表
/*问题*/
Write a SQL query which computes the average total order value for all orders on 2023-04-01.
从上述的任务描述上看,似乎直接利用LLM做推理,就可以直接实现Text2SQL的任务。当然在实际使用中,一般是需要根据你所使用的大模型做适当的调整。但是不管组织的形式如何,端到端的Text2SQL任务的 prompt 基本包括以下几个部分:
指令(Instruction) : 期望大模型去执行的任务说明。比如: "你是一名SQL生成专家,请参考以下的表结构,直接输出对应的SQL语句,不要多余的解释说明。"
数据结构(Table Schema) : 需要使用的数据库结构的描述信息,由于大模型一般不 直接访问 数据库,所以需要将数据的结构组装到Prompt,通村包括表名、列名、列的类型、列的含义、主外键关系等等。
参考样例(Few-Shot) : 一般是个可选项,指导大模型生成本次SQL的参考样例。
用户问题(Question) : 用户输入的自然语言表达的问题,比如:"查看销量大于10000的商品名称。"
其他提示(Tips) : 其他你认为有必要的指示。比如要求生成SQL不允许出现的表达式,或者列名必须用'table.column'等形式。
问题:
实现一个Text2SQL的原型相对比较简单,但是在实际应用时它可能不会那样表现良好,因为它首先有一个关键的问题: 当前AI模型输出的SQL的准确率还远远达不到人类工程师的输出精度。基于深度学习的AI模型预测本身就有 置信度 的问题,无法确保绝对的可靠性,这一点在 大语言模型 的应用层面依然存在。当然,输出的不确定性也是目前限制大模型在企业应用的最大障碍。
除大模型自身的知识能力以外,还有一些客观原因:
自然语言表达本身的歧义性,SQL本身是一种精确的编程语言。在实际的使用过程中,可能会出现无法理解或者错误理解的情况。比如: "价格低于九块九的商品有哪些?", 那么大模型可能无法识别九块九代表的是什么.
通过Prompt输入数据结构信息帮助大模型去理解任务,但仍然可能会由于缺乏外部知识导致错误。比如: "分析去年的整体客户流失率?",那么如果大模型对" 客户流失率 "不理解,自然会出现错误。
对于上述两类问题,可以参考作者前面关于Text2SQL优化的文章来优化。
Text2SQL的技术方案在企业应用中还会面临以下严重的挑战:
执行幻觉 : 完成了对应的动作,但是实际得到的数据结果不符合预期。由于Text2SQL是直接用于数据库访问的语句,从理论上看,只要生成的SQL没有语法错误,便可以执行成功,哪怕转换的SQL在语义上错误的!这里和text2API的区别在与: API由于有很严格的结构化输入输出规范和校验,因此如果模型转换错误,很大概率会导致API调用的异常,使用着能够获得错误的数据反馈。
比如以下两个示例: LLM生成的两个结果都是可以正常执行的,但是第二个对应的SQL明显是错误的,对于不具备专业的SQL知识体系的用户而言,这类问题是很难发现的:
代码块
有多少订单价格不超过1万元?
select count(*) from order where price <= 10000
select count(*) from order where price <> 10000
上述问题的根源,其实是来自于Text2SQL输出正确性的评估困难。这种Text2SQL输出 语义准确性 的衡量复杂性本质上基于这样一个事实:
判断LLM输出的一段代码是否正确,要比判断一个选择题答案是否正确,或者一段字符串的相似度要复杂得多。
如下面这个来自Text2SQL模型的输出评估工具TestSuiteEval中的例子: