LLM实现text2SQL实战总结

news2025/4/16 8:08:02

        LLM在组织内部应用的一类重要场景就是利用LLM的NL2SQL能力,简化用户对数据库的访问。本文主要介绍如何使用LLM生成SQL语句,不涉及到如何训练提升LLM的SQL生成能力。

        开启正文之前,我们先明确一下这类功能在组织内服务的目标群体。我们将服务目标定位为没有太多IT技术背景的业务及运营人员。这些人访问数据库的需求,伴随着业务的发展,会超过特定服务软件提供的功能边界。服务软件的开发周期很难适配应用需求的迫切性。另外,熟练的使用服务软件获取使用者期望的信息也需要一定的学习成本。为此,利用LLM的SQL生成能力实时获取期望的数据库信息就成为了此类需求非常好的解决方案。这里,我们还要排除掉一部分IT运维用户的需求。因为这些用户可能会有需求让LLM帮忙生成出非常复杂的SQL语句以方便运维。但是为了让LLM能够生成对应的SQL语句,需要输入的文本描述会非常复杂,且需要对数据表的结构及关系有一些了解。这对于一般用户来说都太有难度,所以我们先排除掉这类需求。

        很多时候,用户会问我们LLM生成SQL语句的准确率问题。这个问题比较难回答。因为如果我用训练集训练一个LLM,并用测试集测试,比较好回答此类问题。但今天我们讲的是一个利用LLM进行工程落地的场景,不涉及训练优化问题。所以,这个基础的NL2SQL的准确率问题是由选中的LLM模型保障的,而我们会通过一些设计原则优化LLM提示来提升这种SQL生成的准确率问题,从而确保用户的使用体验。当然,当我们在最后评价这个NL2SQL应用的效果时,可以用一个预先准备好的测试集对系统进行测试,确认系统的准确率是否满足使用要求。

        在网络上我们能够看到很多用来训练模型NL2SQL能力的训练数据,这些数据给出的数据结构描述往往都比较简单。这可能会误导一些希望利用LLM生成SQL的使用者的工程方案。想让LLM通过数据库表的字段名或简单的注释就能了解该如何生成正确的SQL语句。其实,这是远远不够的。在这种场景下,笔者觉得使用者应该把LLM当成一个拥有丰富数据库经验的DBA来看待。如果希望他能正确的帮到你,你应该尽量的描述数据表结构的细节。毕竟,你希望DBA在没看到数据表的数据之前就能正确生成SQL语句。你不描述清楚点,DBA肯定是做不到的。同理,LLM也是做不到的。尽量不要期待LLM在此有一种与你心意相通的能力,它总能猜到你想要的。 当然这种问题在我们人类世界里也经常会遇到。在人与人沟通时,我们经常会潜意识的认为对方是知道一些“显而易见”的信息的。因为,这些显而易见的信息是行业或组织内都清楚的信息,属于任何沟通场景下的“背景信息”。这经常会被沟通者无意识的忽略,从而会导致沟通不畅或引起误会。有经验的沟通者,通常会在沟通前对齐一些“背景信息”以确保沟通的顺畅。但这显然是会浪费一些时间的,这也就导致在中国的商业环境里,甲方通常是愿意与有行业经验的乙方合作,因为无需对齐“背景信息”,可以大大提高沟通效率。当然,这也是新入行者比较难于获得甲方青睐的原因之一。

        对于LLM来说,由于它没有什么行业经验,所以我们需要尽可能的给予它恰当的“背景信息”,才能使它更好的工作。所谓恰当,不是越多越好,因为太多的信息会消耗掉LLM的可接受上下文大小,同时也可能会造成LLM信息理解混乱。因此,笔者从实践中总结了以下几条数据库“背景信息”整理原则,用于提高LLM生成SQL语句的正确率:

尽量全面的描述表的功能
  • 以业务视角描述表的功能含义,表的描述文字尽量与常用的业务数据契合。比如:这是一张学生信息表。

  • 包含表中拥有的核心字段信息。如:包括,学生的学号,姓名,年龄,性别,班级ID...。这些信息可以有效帮助LLM判断回答问题时,是否要检索这张表。

  • 描述表的关联性,如果当前表与其它表有关联性,需要描述表的关联性。比如:本表通过班级ID与班级表相关,班级表的ID字段是班级ID的外键。这种描述方便LLM了解表之间的结构。

尽量全面的描述字段的功能
  • 以业务视角描述字段的功能含义,字段的描述文字也应尽量与常用的业务数据契合。比如:学生的名字。

  • 数值类型的字段,如有计量单位,应写出计量单位。比如:千米/小时,万辆等。

  • 枚举类型的字段,即当前字段的取值是有限的。需要视LLM的能力来判断是需要列出全部值还是只列出部分值。比如:字段是一个“表示行政区县的字段”,但这种描述不太容易让LLM准确理解字段的含义,可以继续加入下面的描述“其值包括:海淀区,昌平区,东城区等”;如果字段业务性特别强,LLM难于确认提取出的问题要素与那个人字段相关,那么LLM就无法正常转换为SQL。此时,需要将全部可能的取值都列出来,帮助LLM判断如何选取字段。此时,那些针对行业应用的LLM会拥有一定的优势。就是它可以了解字段的业务含义,知道可能的取值,因此不必列出所有的取值情况。

  • 时间字段,一定要描述时间在表中的存储格式。对于SQL检索来说,时间字段的格式转换是最频繁的,也是最容易出错的。因此告诉LLM时间字段的格式,可以帮助LLM提高生成SQL语句的正确率。

  • 如果可以,尽量描述出数据值的格式,增强LLM对字段含义的理解。如:学生的住址信息,格式:XXX省XXX市XXX(区/县)XXX(街道/村)XXX小区等。

  • 如果字段是外键字段,需要描述与其它表的关系。

适当放弃意义等价的字段

        有时数据表设计时会留存意义等价的字段。比如:在学生表中有个存放学生所在行政区县的字段area,同时也有一个区县对应行政编号的字段area_code。二者在业务意义上是等价的,如果在性能上没有特别的检索要求。那么,可以忽略掉area_code字段。因为很少有人会使用行政编码查找区域内的学生。

放弃业务上无用的字段

                对于有些数据表,数据字段做了一些冗余性的设计。这些字段对业务没有太多的帮助。检索时,也基本不会用到。在提供表的背景信息时,可以考虑删除掉这些字段,不进行描述。如:设计中留了经纬度字段,但实际应用中,并没有相关数据,可以忽略掉这些信息。

以上是一些基于工作实践总结出的数据库“背景信息”整理原则。主打一个该详细,详细;该简略,简略。核心一个原则,“让LLM能够清晰理解数据库的样子”。细心的读者应该已经发现,上述原则中我们对表描述时,会涉及到部分字段的描述。在字段的描述中,我们又进一步详细的进行了描述。这样的描述方式会增大对LLM上下文的占用,感觉有些冗余。其实不然,这里我们给出的原则有一个配套的用法,用于面对拥有几十上百张表的应用场景。很显然,一次丢这么多张表及其结构描述给LLM让其根据问题生成SQL语句,极有可能超出其上下文限制。那么在碰到此类场景时,我们可以将这个目标拆解为两步。第一步,我们只为LLM提供表的描述信息,让LLM根据表的“背景信息”选出回答问题需要用到哪几张表,并输出表名字;第二步,将对应表名的表连同其结构描述一起交给LLM,由其根据输入的信息生成对应的SQL语句。通过这样的两步操作,可以有效的解决占用LLM上下文过大的问题。

        以上的原则只是给出了一些思想方法,具体描述相关信息以及生成SQL时,还会受到LLM的型号,版本等的限制。需要做一些适当的修改。希望能够给与笔者一样,在LLM应用路上的朋友一点帮助和启发。

以下是交给LLM的数据库“背景信息”的格式:

{
	"tables": [
		{
			"name": "表名称",
			"note": "表描述",
			"columns": [
				{
					"name": "列名称",
					"type": "字段类型",
					"note": "列描述"
				},
				{...col-n...}
			]
		},
		{...tab-n...}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2335809.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

字节跳动开源 LangManus:不止是 Manus 平替,更是下一代 AI 自动化引擎

当 “AI 自动化” 成为科技领域最炙手可热的关键词,我们仿佛置身于一场激动人心的变革前夜。各行各业都在翘首以盼,期待 AI 技术能够真正解放生产力,将人类从繁琐重复的工作中解脱出来。在这个充满无限可能的时代,字节跳动悄然发布…

21.C++11

1.列表初始化 1.1C11中的{} •C11以后想统⼀初始化⽅式,试图实现⼀切对象皆可⽤{}初始化,{}初始化也叫做列表初始化。 • 内置类型⽀持,⾃定义类型也⽀持,⾃定义类型本质是类型转换,中间会产⽣临时对象,最…

STM32 HAL库之WDG示例代码

独立看门狗(IWDG) 初始化独立看门狗,在main.c中的 MX_IWDG_Init();,也就是iwdg.c中的初始化代码 void MX_IWDG_Init(void) {/* USER CODE BEGIN IWDG_Init 0 *//* USER CODE END IWDG_Init 0 *//* USER CODE BEGIN IWDG_Init 1 …

Spring AI 发布了它的 1.0.0 版本的第七个里程碑(M7)

Spring AI 发布了它的 1.0.0 版本的第七个里程碑(M7),下个月就是 RC1,紧接着就是 GA!,对于我们 Java 开发者来说,这绝对是个值得关注的好消息! 但是对于 Java 学习者来说&#xff0c…

jdk 安装

oracle官网 : Java Archive | Oracle 中国 export JAVA_HOME/Users/xxxxx/app/services/x86jdk/jdk1.8.0_431.jdk/Contents/Home export PATH$JAVA_HOME/bin:$PATH 华为镜像网站:Index of java-local/jdk

3.2.2.2 Spring Boot配置视图控制器

在Spring Boot中配置视图控制器可以简化页面跳转跳逻辑。通过实现WebMvcConfigurer接口的addViewControllers方法,可以直接将URL映射到特定的视图,而无需编写控制器类。例如,将根路径"/"映射到welcome.html视图,当访问应…

华为OD机试真题——找出两个整数数组中同时出现的整数(2025A卷:100分)Java/python/JavaScript/C++/C语言/GO六种最佳实现

2025 A卷 100分 题型 本文涵盖详细的问题分析、解题思路、代码实现、代码详解、测试用例以及综合分析; 并提供Java、python、JavaScript、C++、C语言、GO六种语言的最佳实现方式! 华为OD机试真题《找出两个整数数组中同时出现的整数》: 目录 题目名称:找出两个整数数组中同…

烽火ai场控接入deepseek自动回复话术软件

要将烽火AI场控软件与DeepSeek自动回复话术软件进行对接,实现直播间自动互动功能,需通过API接口或脚本工具完成数据互通。以下是具体操作步骤及注意事项: 确认兼容性与准备工作 软件支持检查 确认烽火AI场控是否开放API接口(一般需…

【Linux系统】进程地址空间

命令行参数 int main (int argc, char* argv[]) 命令行参数列表 argc&#xff1a;参数的个数argv&#xff1a;参数的清单 int main (int argc, char* argv[]) {printf("argc: %d\n",argc);for(int i 0; i < argc; i){printf("argv[%d] : %s \n", i…

记录学习的第二十六天

还是每日一题。 今天这道题有点难度&#xff0c;我看着题解抄的。 之后做了两道双指针问题。 这道题本来是想用纯暴力做的&#xff0c;结果出错了。&#x1f613;

python成功解决AttributeError: can‘t set attribute ‘lines‘

文章目录 报错信息与原因分析解决方法示例代码代码解释总结 报错信息与原因分析 在使用 matplotlib绘图时&#xff0c;若尝试使用 ax.lines []来清除图表中的线条&#xff0c;会遇到AttributeError: can’t set attribute错误。这是因为 ax.lines是一个只读属性&#xff0c;不…

如何建立可复用的项目管理模板

建立可复用的项目管理模板能够显著提高项目执行效率、减少重复劳动、确保项目管理标准化。在企业中&#xff0c;项目管理往往涉及多个步骤和多个团队&#xff0c;然而每次开始一个新项目时&#xff0c;如果都从头开始设计流程和文档&#xff0c;势必浪费大量的时间和精力。通过…

如何使用通义灵码玩转Docker - AI助手提升开发效率

一、引言 Docker 作为一种流行的虚拟化技术&#xff0c;能够帮助开发者快速搭建所需的运行环境。然而&#xff0c;对于初学者来说&#xff0c;掌握 Docker 的基本概念和使用方法可能会遇到一些挑战。本文将介绍如何利用通义灵码这一智能编码助手&#xff0c;帮助你更高效地学习…

GGML源码逐行调试(下)

目录 前言1. 简述2. 预分配计算图内存2.1 创建图内存分配器2.2 构建最坏情况的计算图2.3 预留计算图内存 3. 分词4. 模型推理与生成4.1 模型推理4.2 采样 结语下载链接参考 前言 学习 UP 主 比飞鸟贵重的多_HKL 的 GGML源码逐行调试 视频&#xff0c;记录下个人学习笔记&#x…

「2025AIGC终极形态」AI系统源码:文本→图像→音乐→视频生成

—从技术痛点到企业级部署&#xff0c;手把手实现全流程AI内容工厂 行业核心痛点&#xff1a;为什么需要多模态AIGC系统&#xff1f; 1. 工具割裂&#xff0c;效率低下 传统流程&#xff1a; 文案&#xff08;ChatGPT&#xff09;→ 配图&#xff08;Midjourney&#xff09;→…

使用CS Roofline Toolkit测量带宽

使用CS Roofline Toolkit测量带宽 工程下载&#xff1a;使用CS Roofline Toolkit测量带宽-案例工程文件&#xff0c;也可以按照下面的说明使用git clone下载 目录 使用CS Roofline Toolkit测量带宽0、Roofline模型理解1、CS Roofline Toolkit下载1.1、设置代理1.2、git clone下…

L1-4 拯救外星人

题目 你的外星人朋友不认得地球上的加减乘除符号&#xff0c;但是会算阶乘 —— 正整数 N 的阶乘记为 “N!”&#xff0c;是从 1 到 N 的连乘积。所以当他不知道“57”等于多少时&#xff0c;如果你告诉他等于“12!”&#xff0c;他就写出了“479001600”这个答案。 本题就请你…

现代c++获取linux系统名称

现代c获取linux系统名称 前言一、使用命令获取操作系统名称二、使用c代码获取操作系统名称三、验证四、总结 前言 本文介绍一种使用c获取当前操作系统名称的方法 一、使用命令获取操作系统名称 在linux系统中可以使用uname或者uname -s命令来获取当前操作系统名称&#xff0c…

力扣刷题HOT100——53.最大子数组和

给你一个整数数组 nums &#xff0c;请你找出一个具有最大和的连续子数组&#xff08;子数组最少包含一个元素&#xff09;&#xff0c;返回其最大和。 子数组是数组中的一个连续部分。 示例 1&#xff1a; 输入&#xff1a;nums [-2,1,-3,4,-1,2,1,-5,4] 输出&#xff1a;6…

ES和MySQL概念对比

基本概念 ES和MySQL都属于数据库&#xff0c;不过各有各的特性&#xff0c;大致使用方法与MySQL类似并无区别。 MySQL&#xff1a;擅长事务持有ACID的特性&#xff0c;确保数据的一致性和安全。 ES&#xff1a;持有倒排索引&#xff0c;适合海量数据搜索和分析。 ES和MySQL如何…