大模型LLM在 Text2SQL 上的应用实践
一、前言
目前,大模型的一个热门应用方向Text2SQL,它可以帮助用户快速生成想要查询的SQL语句,再结合可视化技术可以降低使用数据的门槛,更便捷的支持决策。本文将从以下四个方面介绍LLM在Text2SQL应用上的基础实践。
· Text2SQL概述
· LangChain基础知识
· 基于SQLDatabaseChain的Text2SQL实践
· 后续计划
二、Text2SQL概述
Text-to-SQL(或者Text2SQL),顾名思义就是把文本转化为SQL语言,更学术一点的定义是:把数据库领域下的自然语言(Natural Language,NL)问题,转化为在关系型数据库中可以执行的结构化查询语言(Structured Query Language,SQL),因此Text-to-SQL也可以被简写为NL2SQL。

· 输入:自然语言问题,比如“查询表t_user的相关信息,结果按id降序排序,只保留前10个数据 ”
· 输出:SQL,比如 “SELECT * FROM t_user ORDER BY id DESC LIMIT 10”
Text2SQL应用主要是帮助用户减少开发时间,降低开发成本。“打破人与结构化数据之间的壁垒”,即普通用户可以通过自然语言描述完成复杂数据库的查询工作,得到想要的结果。

基于LLM的应用开发基本架构如上图,本文介绍以LangChain + OpenAI + RDB的方式来实现Text2SQL的实践方案。
三、LangChain基础知识
LangChain是一个面向大语言模型的应用开发框架,如果将大语言模型比作人的大脑,那么可以将LangChain可以比作人的五官和四肢,它可以将外部数据源、工具和大语言模型连接在一起,既可以补充大语言模型的输入,也可以承接大语言模型的输出。
LangChain提供各种不同的组件帮助使用LLM,如下图所示,核心组件有Models、Indexes、Chains、Memory、Prompt以及Agent。

3.1 Models
LangChain本身不提供LLM,提供通用的接口访问LLM,可以很方便的更换底层的LLM以及自定义自己的LLM。主要有2大类的Models:
1)LLM:将文本字符串作为输入并返回文本字符串的模型,类似OpenAI的text-davinci-003
2)Chat Models:由语言模型支持将聊天消息列表作为输入并返回聊天消息的模型。一般使用的ChatGPT以及Claude为Chat Models。
与模型交互可以通过给予Prompt的方式,LangChain通过PromptTemplate的方式方便我们构建以及复用Prompt。
代码示例如下:
from langchain import PromptTemplate# 定义提示模板
prompt = PromptTemplate(input_variables=["question"], template="""简洁和专业的来回答用户的问题。如果无法从中得到答案,请说 “根据已知信息无法回答该问题” 或 “没有提供足够的相关信息”,不允许在答案中添加编造成分,答案请使用中文。 
问题是:{question}""",)print(prompt.format_prompt(question="如何进行数据治理"))
 
3.2 Indexes
索引和外部数据进行集成,用于从外部数据获取答案。如下图所示,主要的步骤:
· 通过Document Loaders加载各种不同类型的数据源
· 通过Text Splitters进行文本语义分割
· 通过Vectorstore进行非结构化数据的向量存储
· 通过Retriever进行文档数据检索

3.3 Chains
LangChain通过chain将各个组件进行链接,以及chain之间进行链接,用于简化复杂应用程序的实现。其中主要有LLMChain、SQLDatabase Chain以及Sequential Chain。
3.3.1 LLMChain
最基本的链为LLMChain,由PromptTemplate、LLM和OutputParser组成。LLM的输出一般为文本,OutputParser用于让LLM结构化输出并进行结果解析,方便后续的调用。

其实现原理如图所示,包含三步:
· 输入问题
· 拼接提示,根据提示模板将问题转化为提示
· 模型推理,输出答案
代码如下所示:
from langchain.prompts import PromptTemplate
from langchain.chains import LLMChain
from langchain import OpenAI
import osos.environ["OPENAI_API_KEY"] = "Your openai key"
# 定义模型
llm = OpenAI(temperature=0)# 定义提示模板
prompt = PromptTemplate(input_variables=["question"], template="""简洁和专业的来回答用户的问题。如果无法从中得到答案,请说 “根据已知信息无法回答该问题” 或 “没有提供足够的相关信息”,不允许在答案中添加编造成分,答案请使用中文。问题是:{question}""",)
# 定义chain
chain = LLMChain(llm=llm, prompt=prompt, verbose=True)
# 执行chain
print(chain.run("如何开展数据治理"))
 
3.3.2 SQLDatabaseChain
SQLDatabaseChain能够通过模型自动生成SQL并执行,其实现原理如图所示,包含如下过程:

· 输入问题;
· 获取数据库Schema,Schema包含数据库所有表的建表语句和数据示例,LangChain支持多种关系型数据库,包括MariaDB、MySQL、SQLite、ClickHouse、PrestoDB等;
· 拼接提示,根据提示模板将问题、数据库Schema转化为提示,并且提示中包含指示,要求模型在理解问题和数据库Schema的基础上,能够按一定的格式输出查询SQL、查询结果和问题答案等;
· 模型推理,这一步预期模型根据问题、数据库Schema推理、输出的答案中包含查询SQL,并从中提取出查询SQL;
· 执行查询SQL,从数据库中获取查询结果;
· 拼接提示,和上一次拼接的提示基本一致,只是其中的提示中包含了前两步已获取的查询SQL、查询结果;
· 模型推理,这一步预期模型根据问题、数据库Schema、查询SQL和查询结果推理出最终的问题答案。
3.3.3 SequentialChain
SequentialChains是按预定义顺序执行的链。SimpleSequentialChain为顺序链的最简单形式,其中每个步骤都有一个单一的输入/输出,一个步骤的输出是下一个步骤的输入。SequentialChain为顺序链更通用的形式,允许多个输入/输出。
3.4 Memory
正常情况下Chain无状态的,每次交互都是独立的,无法知道之前历史交互的信息。LangChain使用Memory组件保存和管理历史消息,这样可以跨多轮进行对话,在当前会话中保留历史会话的上下文。Memory组件支持多种存储介质,可以与Mongo、Redis、SQLite等进行集成,以及简单直接形式就是Buffer Memory。
3.5 Agent
Agent字面含义就是代理,如果说LLM是大脑,Agent就是代理大脑使用工具Tools。目前的大模型一般都存在知识过时、逻辑计算能力低等问题,通过Agent访问工具,可以去解决这些问题。目前这个领域特别活跃,诞生了类似AutoGPT、BabyAGI、AgentGPT等一堆优秀的项目。传统使用LLM,需要给定Prompt一步一步地达成目标,通过Agent是给定目标,其会自动规划并达到目标。
四、基于SQLDatabaseChain的Text2SQL实践
4.1 简介
LangChain提供基于LLM的SQLDatabaseChain,可以利用LLM的能力将自然语言的query转化为SQL,连接DB进行查询,并利用LLM来组装润色结果,返回最终answer。
在后台,LangChain 使用SQLAlchemy连接到 SQL 数据库。因此,SQLDatabaseChain可以与 SQLAlchemy 支持的任何 SQL 方言一起使用,例如 MS SQL、MySQL、MariaDB、PostgreSQL、Oracle和 SQLite。
4**.**2 数据准备
本案例使用SQLite 和示例Chinook 数据库,用户可按照https://database.guide/2-sample-databases-sqlite/ 上的说明进行设置。Chinook表示一个数字多媒体商店,包含了顾客(Customer)、雇员(Employee)、歌曲(Track)、订单(Invoice)及其相关的表和数据,数据模型如下图所示。

4.3实践过程
需求: 测试中文提问“总共有多少员工?”,即英文提问“How many employees are there?”
期望: 模型先给出查询Employee表记录数的SQL,再根据查询结果给出最终的答案。
(1)测试中文提问,代码如下所示:
from langchain.llms import OpenAI
from langchain.utilities import SQLDatabase
from langchain_experimental.sql import SQLDatabaseChain
import osos.environ["OPENAI_API_KEY"] = "Your openai key"db = SQLDatabase.from_uri("sqlite:///..../Chinook.db")
llm = OpenAI(temperature=0, verbose=True)
db_chain = SQLDatabaseChain.from_llm(llm, db, verbose=True)
db_chain.run("总共有多少员工?")
 
输出结果如下:

这里我们使用商业化的OpenAI,并将其temperature设为0,因为查询DB不太需要创造性和多样性。从返回的过程来看,自然语言被翻译成了SQL,得到查询结果后,解析包装结果,最终返回我们可以理解的答案。这里LLM成功将“总共”转成select count(*),并准确地识别出表名,且最终组装出正确的结果。
注意: 对于数据敏感项目,可以在 SQLDatabaseChain 初始化中指定 return_direct=True,以直接返回 SQL 查询的输出,而无需任何其他格式设置。这样可以防止 LLM 看到数据库中的任何内容。但请注意,默认情况下,LLM 仍然可以访问数据库方案(即所用方言、表名和列名)。
(2)测试英文提问,也可以得到我们想要的结果:

通过上例,我们可以借助LangChain提供的SQLDatabaseChain,轻松地连接LLM与Database,自然语言的方式输入,自然语言的方式输出,借助LLM的强大能力来理解问题、生成SQL查询数据并输出结果。
五、后续计划
随着大模型的发展,LangChain是目前最火的LLM开发框架之一,能和外部数据源交互、能集成各种常用的组件等等,大大降低了LLM应用开发的门槛。基于SQLDatabaseChain实现的Text2SQL只是最基础的实践方式,但对于逻辑复杂的查询在稳定性、可靠性、安全性方面可能无法达到预期,比如输出幻觉问题、数据安全问题。如何解决或减少该类问题的出现,可改进的措施和方案在后续专题中继续讨论,大家一起群策群力。总之,实现高稳定、高可靠的基于LLM的应用,是一个持续改进的过程,是一个多种技术相结合的过程。
参考文献:
https://docs.langchain.com/docs/
https://platform.openai.com/
https://database.guide/2-sample-databases-sqlite/
https://www.langchain.asia/modules/chains/examples/sqlite
https://mp.weixin.qq.com/s/pgRC71IkSXrOjZg3W9V72g
https://zhuanlan.zhihu.com/p/640580808
相关文章:
大模型LLM在 Text2SQL 上的应用实践
一、前言 目前,大模型的一个热门应用方向Text2SQL,它可以帮助用户快速生成想要查询的SQL语句,再结合可视化技术可以降低使用数据的门槛,更便捷的支持决策。本文将从以下四个方面介绍LLM在Text2SQL应用上的基础实践。 Text2SQL概…...
数据库:园林题库软件(《城市绿地设计规范》答题卷一 )
《城市绿地设计规范》答题卷一 填空题 1、城市绿地设计应贯彻人与自然和谐共存、可持续发展、经济合理等基本原则,创造良好生态和景观效果,促进人的身心健康。 2、城市绿地 urban green space 以植物为主要存在形态,用于改善城市生态&am…...
MySQL之视图外连接、内连接和子查询的使用
目录 一. 视图 1.1 含义 1.2 视图的基本语法 1.3 视图的实操 二. 外连接、内连接和子查询的使用 2.1 SQL脚本 2.2 使用外连接、内连接和子查询进行解答 三. 思维导图 一. 视图 1.1 含义 视图(view)是一种虚拟存在的表,是一个逻辑表&#x…...
MoE模型性能还能更上一层楼?一次QLoRA微调实践
Fine-Tuning Mixtral 8x7B with QLoRA:Enhancing Model Performance 🚀 编者按:最近,混合专家(Mixture of Experts,MoE)这种模型设计策略展现出了卓越的语言理解能力,如何在此基础上进一步提升 MoE 模型的性能成为业界…...
Java线程学习笔记
1、判断线程存活 1. 当线程run()或者call()方法执行结束,线程进入终止状态 2. 当线程内发生异常,并且异常没有被捕获,线程进入终止状态 3. 线程调用stop()方法后,线程进入终止状态(不推荐使用) 当主线程结束时,其他线程…...
平面光波导_三层均匀平面光波导_射线分析法
平面光波导_三层均匀平面光波导_射线分析法 三层均匀平面光波导: 折射率沿 x x x 方向有变化,沿 y y y、 z z z 方向没有变化三层:芯区( n 1 n_1 n1) > > > 衬底( n 2 n_2 n2) ≥ \geq ≥ 包层( n 3 n_3 n3)包层通常为空…...
IPV6学习记录
IPV6的意义 从广义上来看IPV6协议包含的内容很多: IPV6地址的生成与分配 IPV6的报头的功能内容 IPV4网络兼容IPV6的方案 ICMPv6的功能(融合了arp和IGMP功能) IPV6的路由方式 ipv6的诞生除了由于ipv4的地址枯竭外,很大程度上也是因为ipv4多年的发展产生了很多…...
使用proteus进行主从JK触发器仿真失败原因的分析
在进行JK触发器的原理分析的时候,我首先在proteus根据主从JK触发器的原理进行了实验根据原理图,如下图: 我进行仿真,在仿真的过程中,我向电路图中添加了外部的置0/1端口,由此在proteus中得到下面的电路图 …...
Golang基础入门及Gin入门教程(2024完整版)
Golang是Google公司2009年11月正式对外公开的一门编程语言,它不仅拥有静态编译语言的安全和高性能,而 且又达到了动态语言开发速度和易维护性。有人形容Go语言:Go C Python , 说明Go语言既有C语言程序的运行速度,又能达到Python…...
202312 青少年软件编程(C/C++)等级考试试卷(四级)电子学会真题
2023年12月 青少年软件编程(C/C)等级考试试卷(四级)电子学会真题 1.移动路线 题目描述 桌子上有一个m行n列的方格矩阵,将每个方格用坐标表示,行坐标从下到上依次递增,列坐标从左至右依次递增…...
leetcode-合并两个有序数组
88. 合并两个有序数组 题解: 这是一个经典的双指针问题,我们可以使用两个指针分别指向nums1和nums2的最后一个元素,然后比较两个指针所指向的元素大小,将较大的元素放入nums1的末尾,并将对应的指针向前移动一位。重复…...
网站怎么做google搜索引擎优化?
网站想做google搜索引擎优化,作为大前提,您必须确保网站本身符合google规范,我们不少客户实际上就连这点都无法做到 有不少客户公司自己本身有技术,就自己弄一个网站出来,做网站本身不是难事,但前提是您需要…...
TDengine 签约西电电力
近年来,随着云计算和物联网技术的迅猛发展,传统电力行业正朝着数字化、信息化和智能化的大趋势迈进。在传统业务基础上,电力行业构建了信息网络、通信网络和能源网络,致力于实现发电、输电、变电、配电和用电的实时智能联动。在这…...
赛门铁克OV代码签名证书一年多少钱?
在当前,软件和应用程序的安全性变得尤为重要。为了保护软件的完整性和安全性,越来越多的开发者和厂商开始采用代码签名的方式来确保软件的真实性和完整性。赛门铁克OV代码签名证书成为了其中一个备受信任的选择。那么,赛门铁克OV代码签名证书…...
Dockerfile详解
文章目录 一、Dockerfile介绍二、常用指令三、Dockerfile示例四、最佳实践 一、Dockerfile介绍 Dockerfile是一个包含创建镜像所有命令的文本文件,通过docker build命令可以根据Dockerfile的内容构建镜像。 一般的,Dockerfile分为四部分:基础…...
零基础小白如何自学sql?
学习SQL对于数据分析和处理来说非常重要。SQL是一种强大的工具,可以帮助你与数据库沟通,提取,整理和理解数据。 以下是一些学习SQL的建议: 01 前期:SQL数据库学习 了解SQL的基本概念:首先,你…...
【刷题笔记2】
刷题笔记2 最小公倍数、最大公约数 两个数的最大公约数两数乘积/最小公倍数 #<include> cmath; int a,b; int mgcd(a,b);//求最大公约数复制字符串substr()函数 s.substr(pos, len) :pos的默认值是0,len的默认值是s.size() - pos string a1;in…...
Kafka之集群搭建
1. 为什么要使用kafka集群 单机服务下,Kafka已经具备了非常高的性能。TPS能够达到百万级别。但是,在实际工作中使用时,单机搭建的Kafka会有很大的局限性。  消息太多,需要分开保存。Kafka是面向海量消息设计的,一个T…...
Linux备忘手册
常⽤命令 作⽤ shutdown -h now 即刻关机 shutdown -h 10 10分钟后关机 shutdown -h 11:00 11:00关机 shutdown -h 10 预定时间关机(10分钟后) shutdown -c 取消指定时间关机 shutdown -r now 重启 shutdown -r 10 10分钟之后重启 shutdown -…...
Qt中QGraphicsView总体架构学习
前沿 前段时间学习了下如何在QGraphicsView架构中绘制刻度尺,主要是与OnPainter中进行比较的,那么今天就来详细讲解下我对QGraphicsView框架的认知吧~ 最近一段时间想学习下,如果我有不正确的,欢迎留言探讨哟~ QGraphicsView架…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)
HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...
2024年赣州旅游投资集团社会招聘笔试真
2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...
JDK 17 新特性
#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持,不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的ÿ…...
JVM虚拟机:内存结构、垃圾回收、性能优化
1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...
人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式
今天是关于AI如何在教学中增强学生的学习体验,我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育,这并非炒作,而是已经发生的巨大变革。教育机构和教育者不能忽视它,试图简单地禁止学生使…...
莫兰迪高级灰总结计划简约商务通用PPT模版
莫兰迪高级灰总结计划简约商务通用PPT模版,莫兰迪调色板清新简约工作汇报PPT模版,莫兰迪时尚风极简设计PPT模版,大学生毕业论文答辩PPT模版,莫兰迪配色总结计划简约商务通用PPT模版,莫兰迪商务汇报PPT模版,…...
SQL Server 触发器调用存储过程实现发送 HTTP 请求
文章目录 需求分析解决第 1 步:前置条件,启用 OLE 自动化方式 1:使用 SQL 实现启用 OLE 自动化方式 2:Sql Server 2005启动OLE自动化方式 3:Sql Server 2008启动OLE自动化第 2 步:创建存储过程第 3 步:创建触发器扩展 - 如何调试?第 1 步:登录 SQL Server 2008第 2 步…...
ubuntu22.04有线网络无法连接,图标也没了
今天突然无法有线网络无法连接任何设备,并且图标都没了 错误案例 往上一顿搜索,试了很多博客都不行,比如 Ubuntu22.04右上角网络图标消失 最后解决的办法 下载网卡驱动,重新安装 操作步骤 查看自己网卡的型号 lspci | gre…...
绕过 Xcode?使用 Appuploader和主流工具实现 iOS 上架自动化
iOS 应用的发布流程一直是开发链路中最“苹果味”的环节:强依赖 Xcode、必须使用 macOS、各种证书和描述文件配置……对很多跨平台开发者来说,这一套流程并不友好。 特别是当你的项目主要在 Windows 或 Linux 下开发(例如 Flutter、React Na…...
Vue3中的computer和watch
computed的写法 在页面中 <div>{{ calcNumber }}</div>script中 写法1 常用 import { computed, ref } from vue; let price ref(100);const priceAdd () > { //函数方法 price 1price.value ; }//计算属性 let calcNumber computed(() > {return ${p…...
