NL2SQL(自然语言到SQL)解决方案面临的一个普遍问题是数据查询的准确性不高。尽管使用自然语言查询数据库可以简化数据分析流程,避免复杂的报告开发过程,但查询结果的准确性严重限制了这项技术在实际企业应用中的效果。在某些情况下,数据不准确可能会导致严重后果,例如向客户提供错误信息或影响关键的公司报告。
本文将探讨几种提高人工智能生成SQL准确性的方法。
方法一:项目实施中的正确姿势
首先,确保大语言模型具备必要的背景知识,以生成正确的SQL语句。缺乏背景知识(如数据库表信息)会导致SQL生成不准确。因此,大模型至少需要以下背景知识:
-
自然语言生成SQL场景的特有提示词模板
-
数据库表及其说明,包括表的结构定义和详细说明
-
数据库表之间的关系说明,特别是在进行复杂的多表关联查询时
(注意:以下最佳实践由SQLCoder推荐)
### Instructions: Your task is to convert a question into a SQL query, given a Postgres database schema. Adhere to these rules: - **Deliberately go through the question and database schema word by word** to appropriately answer the question - **Use Table Aliases** to prevent ambiguity. For example, `SELECT table1.col1, table2.col1 FROM table1 JOIN table2 ON table1.id = table2.id`.- When creating a ratio, always cast the numerator as float ### Input:Generate a SQL query that answers the question `{question}`.This query will run on a database whose schema is represented in this string:
CREATE TABLE products (
product_id INTEGER PRIMARY KEY, -- Unique ID for each product
name VARCHAR(50), -- Name of the product
price DECIMAL(10,2), -- Price of each unit of the product
quantity INTEGER -- Current quantity in stock
);
CREATE TABLE customers (
customer_id INTEGER PRIMARY KEY, -- Unique ID for each customer
name VARCHAR(50), -- Name of the customer
address VARCHAR(100) -- Mailing address of the customer
);
CREATE TABLE salespeople (
salesperson_id INTEGER PRIMARY KEY, -- Unique ID for each salesperson
name VARCHAR(50), -- Name of the salesperson
region VARCHAR(50) -- Geographic sales region
);
CREATE TABLE sales (
sale_id INTEGER PRIMARY KEY, -- Unique ID for each sale
product_id INTEGER, -- ID of product sold
customer_id INTEGER, -- ID of customer who made purchase
salesperson_id INTEGER, -- ID of salesperson who made the sale
sale_date DATE, -- Date the sale occurred
quantity INTEGER -- Quantity of product sold
);
CREATE TABLE product_suppliers (
supplier_id INTEGER PRIMARY KEY, -- Unique ID for each supplier
product_id INTEGER, -- Product ID supplied
supply_price DECIMAL(10,2) -- Unit price charged by supplier
);
-- sales.product_id can be joined with products.product_id
-- sales.customer_id can be joined with customers.customer_id
-- sales.salesperson_id can be joined with salespeople.salesperson_id
-- product_suppliers.product_id can be joined with products.product_id
### Response:
Based on your instructions, here is the SQL query I have generated to answer the question `{question}`:
第二种方法:少样本提示(Few-Shot Prompt)
少样本提示在NL2SQL领域尤为重要。模型需要将自然语言问题映射到SQL查询,这通常需要大量训练数据。通过以下示例,可以提高NL2SQL的准确性:
问题:查询分数大于60的学生姓名。
SQL 答案:“SELECT Name FROM Students WHERE Score > 60;”
问题:查询18岁以下学生姓名。
SQL 答案:“SELECT Name FROM Students WHERE Age < 18;”
第三种:RAG
企业的特定业务知识对大型模型来说是未知的,每个公司对关键指标的定义各不相同。数据库表、字段数据和关系等信息(尤其是在处理复杂业务和大型数据库时)可能存在很大差异。我们知道,添加这些背景信息可以提高大型模型的输出准确性,但静态提示无法处理如此大量的文本信息。
其次,少量提示也会面临同样的问题。当我们拥有大量自然语言问题及其对应的SQL查询示例时,将它们全部作为提示输入到大型模型中既不必要也不现实。相反,我们只需为每次对话选择最相关的示例。
通过预先组织业务知识、数据库模式信息、自然语言问题和SQL查询示例,我们可以利用检索增强生成(RAG)技术来优化提示,从而在令牌限制内提升模型性能。
简而言之,在自然语言生成SQL的过程中,我们从自然语言输入中提取关键词,并使用向量库匹配相应的数据库、表格和字段信息,然后将这些信息提供给大模型生成SQL查询。这显著提高了SQL输出的准确性。
第四种:微调
在企业应用中,除了人工标注的自然语言问题和SQL查询示例外,我们还可以通过用户反馈获取大量准确的示例。这些数据可以作为数据集来微调大型模型。尽管微调的成本高于使用检索增强生成(RAG),但对特定任务数据集进行微调可以帮助大型模型更好地适应特定任务。
简而言之,就是使用一组标准的自然语言问题和SQL语句来对大型模型进行微调。使用微调后的模型来生成SQL。
第五种:使用SQL数据库专用有的大语言模型
使用专门优化的专有大型模型为企业提供了一种有效的替代方案。在实际应用中,虽然大型模型生成SQL不会导致数据泄露,但使用提示、RAG等技术仍需将数据库和业务信息输入模型,这对某些敏感用户来说可能不可接受。在这种情况下,基于开源基础模型并可私有部署的专有大型模型是理想选择。
OLLAMA官网上找到两个开源SQL数据库专用大语言模型(huggingface.co上的选择会更多一些):
-
SQLCoder-15B:基于StarCoder基础模型微调的开源模
-
DuckDB-NSQL-7B:专为SQL生成任务设计,基于Meta的原始Llama-2 7B模型微调
根据个人测试,与 ChatGPT-4、Llama 3-32B 以上版本和通义千问 32B 以上版本相比,当前模型还存在一定差距。主要限制因素有两个:一是受限于所使用的小规模模型,二是这些模型主要基于英文训练。