Skip to content

NL2SQL如何用自然语言解锁数据库

原文链接:从“写SQL”到“聊数据”:NL2SQL如何用自然语言解锁数据库?

引言

数据驱动决策在各行各业中至关重要,尤其是业务分析师常常面临繁重的数据查询任务。NL2SQL则是通过自然语言生成结构化查询语言的技术。

一个典型的场景:一位业务分析师需要提供上个月销售额最高的前10个商品。如果用传统方法,首先分析师需要知道销售额相关的基础数据表是哪些,接着得确认销售额的具体口径定义,最后需要按照一定方式编写复杂的SQL查询得到结果。这不仅需要对SQL语言有深刻的理解,还要对指标的定义、业务数据来源非常熟悉。

技术背景

问题拆解:

语义理解

要求系统能够准确地捕捉用户查询的意图,并处理自然语言中的模糊和歧义。 这包括理解自然语言中的上下文、处理指代、识别关键实体和关系,以及解析复杂的句子结构。

Schema映射

Schema映射涉及将自然语言查询映射到数据库模式中的具体表和列。数据库的模式通常非常结构化,而自然语言查询可能没那么直接地指明这些结构。 例如,一个查询可能使用同义词或间接提及而不是明示的列名或表名。系统需要具备将自然语言中提到的概念正确映射到数据库结构上的能力。

SQL生成

挑战在于生成的SQL需要处理不同的查询形式和复杂度,包括聚合、嵌套查询、连接等功能。此外,生成的SQL必须满足高性能、合规性和安全性问题。

核心挑战:

语法正确

数据库语法的多元性、表之间的关系复杂性、列名的相似性、以及大数据量的不完整性。

语义正确

要理解复杂的自然语言情况,词义歧义、句法歧义、信息不足和用户错误。 与此同时,当实际应用到业务场景时,不同团队对同一术语的定义也可能不同。

效果稳定

NL2SQL与编程语言不同,因为输入的NL和输出的SQL查询之间通常存在一对多的映射。即使是完全一样的问题,也可能输出各种不同的SQL结果。

关键技术挑战与解决方案

复杂查询理解

Chain of thought (CoT):思维链与大模型相结合,能在复杂推理任务上取得不错结果。

  • Divide and Conquer CoT(分而治之CoT):让模型把查询任务拆解成更细粒度的任务,然后用SQL伪代码写出对这些子任务的查询,最终将结果合成一个完整的SQL。 直接写SQL效果不好是因为模型可能没有见过这样的数据分布,但是它肯定见过简单任务的数据分布,在SQL子语句都写出来了的前提下,SQL的组合就显得没那么复杂了。
  • Query Plan CoT(查询/执行计划CoT):让模型先把SQL的执行计划描述出来,再通过执行计划来生成SQL。 这么做可以让模型换个角度思考问题,将数据分布切换到了另外一个领域,能让模型更多地关注具体要用的表、列,能补足“分而治之”方法对细节把控不足的缺点

提示词工程

将自然语言问题与必要的数据库信息转化为适用于LLM的自然语言序列输入,即问题表示。

可以总结出一套通用且有效的NL2SQL Prompt策略。这一策略由六个关键要素构成,每个要素在提升模型生成SQL的准确性和效率中发挥着重要作用。以下是各个要素的详细说明:

  1. 指令(Instruction):为模型提供清晰而具体的指导方针。例如,"你是一个SQL生成专家。请参考如下的表格结构,直接输出SQL语句,不要提供多余的解释。"

  2. 数据结构(Table Schema):类似于语言翻译中的“词汇表”,这是你需要嵌入到Prompt中的数据库表结构。由于大模型无法直接访问数据库,你需手动提供包括表名、列名、列的类型、列的意义,以及主键和外键信息。

  3. 参考样例(Sample):这是一种启发模型生成SQL的可选技巧。你可以提供一个类似任务的SQL样例作为参考,以帮助模型更好地理解应该如何构建查询。

  4. 其他提示(Tips)/约束条件(Constraint):这些是你认为必要的额外指示。例如,要求生成的SQL中不允许出现某些表达式,或者要求列名必须采用“table.column”的形式。

  5. 领域知识(Knowledge):在某些特定问题中,这是一个可选要素。例如,如果用户的问题涉及“谁是这个月最厉害的销售”,你需要告诉模型,“最厉害”是指“销售单量最多”还是“销售金额最多”。

  6. 用户问题(Question):这是以自然语言形式表达的查询需求,如“统计上个月的平均订单额”。这一部分用于明确用户的意图和需求,以便模型生成正确的SQL语句。

检索增强生成

为了提高NL2SQL生成的SQL质量,需要在提示词中加入业务领域知识、表知识(Scheme)和列知识(Indicator),甚至是一些样例(Examples)问题便于query改写。

而这样往往又会造成token消耗巨大,因此能否通过RAG来及时查询涉及到的部分,解决token过大的问题。

在NL2SQL场景中,以下关键步骤可以借助RAG提高效率:

  • 领域知识查询
    • RAG可以利用预训练模型和检索技术相结合,帮助理解用户的查询所涉及的领域或上下文。通过从相关文档或数据库检索信息,RAG可以为生成更精确的SQL语句提供背景知识。
    • 具体应用包括根据领域特定的术语或概念检索相关信息,从而帮助系统更好地理解和处理复杂或专业的查询。
  • 表查询
    • 在生成SQL查询时,正确选择和理解数据库中的表是至关重要的。
    • RAG可以通过检索数据库的元数据或相关文档,帮助识别合适的表及其结构。
  • 指标查询
    • 对于用户查询中涉及的各种指标,例如计算平均值、总和、最大值等,RAG可以帮助检索相关的计算逻辑或历史数据。
    • RAG能够从过去的查询实例或相关文档中提取信息,帮助提高生成查询的准确性和效率,尤其是在复杂计算的场景中。

semantic语义

除了从数据库和SQL层面思考如何提高NL2SQL的准确性,还可以从增加语义理解层来思考解决方案。因为如何将用户模糊、多变的业务意图如何精准、高效地映射到企业复杂的数据资产中?这一问题本身就是数据工程问题,而非单纯的 AI 问题。

可以通过如果额外引入一层语义层来更好的解决NL2SQL问题。语义层需要有以下特征:

  • 统一的业务语义抽象层,作为Agent和开发人员共同理解的“数据语言”;
  • 强大的元数据管理能力,确保指标定义的唯一性、透明性和可追溯性;

NL2Semantic2SQL 技术路线通过引入语义层作为中间抽象,大幅提升了系统的灵活性和可解释性。指标平台采用"度量"和"维度"两大基础要素,并运用"基础度量"、"业务限定"、"时间限定"和"衍生方式"四大要素,灵活定义和组合具有明确业务含义的指标,打造了一个统一的语义模型。自然语言查询首先被转换为语义表示,然后由系统基于语义模型生成最优SQL查询。

这种语义与表结构的解耦设计,使系统能够理解指标的业务意义,而不仅仅是表结构,确保在不同场景下,同一指标的口径保持一致性。随着业务规则的变化,只需调整语义定义,无需修改所有相关表或查询,显著提高了系统的适应性。

语义层的引入是 NL2Semantic2SQL 相对于传统NL2SQL的核心优势。它不仅提升了查询的准确性,还增强了系统的可解释性,赋予业务人员更强的自助能力。通过构建统一的业务语义模型,指标平台有效地跨越了技术与业务之间的鸿沟,使业务人员可以直接理解和使用数据,而无需深刻掌握SQL语法。

半结构化的数据库表达

scheme LLM专属注释

正如上文所说,在使用基于LLM的NL2SQL技术时,为了使模型能够准确理解数据表的含义和列名的表示,建议为常用的数据表及其列添加注释。

表注释有助于模型更好地理解表的基本信息,从而在生成SQL语句时准确定位相关表。注释应简单明了,概括表的核心内容,如订单、库存等,并建议控制在10字以内,以避免过多解释。

列注释通常由常用名词或短语构成,例如订单编号、日期、店铺名称等,以准确表达列名的意义。此外,可以在列注释中包含列的示例数据或映射关系。例如,对于列名“isValid”,注释可以写成“是否有效。0:否。1:是。”以清楚地表示该列的含义和数值对应关系。

但是传统的数据库表注释和列注释可能已有一定的含义和上下游对接规范,所以目前有些数据库可支持scheme维度LLM专属的注释,用于提供NL2SQL时获取表和列的提供便利。比如阿里的PolarDB,开源的M-Schema项目。

LLM配置表

在解决语义不清的问题时,往往需要我们对原始的问题进行改写符合底层数据的要求。一方面我们可以通过知识库的方式解决,另外一方面也有一些数据库层面提供的解决方案,比如阿里的PolarDB提供了「配置表」功能,通过全局生效的固定表名,存储了诸如「问题文本条件判断」、「问题处理」、「问题补充与具体业务/概念相关的信息」等前置文本转换功能,「模型生成的SQL条件判断」、「处理SQL,用于对业务逻辑中的值映射进行强制处理」等后置文本转换功能信息。