大语言模型应用Text2SQL本地部署实践初探
自从两年前OpenAI公司发布ChatGPT后,大模型(Large Language Model,简称LLM)相关技术在国内外可谓百家争鸣,遍地开花,在传统数据挖掘、机器学习和深度学习的基础上,正式宣告进入快速发展的人工智能(Artificial Intelligence,简称AI)2.0时代。
人工智能的本质上是基于海量数据(包括结构化数据,文本数据,图片数据,音频数据,视频数据等)不断学习和推理,去模仿人类思考、认知、决策和行动。
我在项目实施工作中,跟数据打交道很多,主要是传统的数据建模和分析,基本都是基于商业产品,比如SAP,Qlik,帆软,永洪等;或者是基于公司的自研产品,大体功能类似但二次开发比较容易。由于这种壁垒,对机器学习和大模型了解甚少,基本停留在了解一些基本概念和关注一些技术新闻方面。最近几年的项目上重复遇到过一些困扰我好久的问题,项目范围内的数据模型搭完后,对数据比较依赖的部门比如财务,审计等会不断涌现出新的数据需求,如何让业务部门的用户快速获取和分析数据为日常工作提供决策支持是一个痛点,以往的大宽表模型和自助式BI分析解决方案不太理想,而学习数据建模由于太过技术性往往让用户望而却步。
最近通过在B站学习了一些优秀up主的大模型讲解视频,以及阅读了一些技术大拿的博文,受益匪浅。通过了解Text2SQL,帮我开拓了思路,似乎让我找到了解决以上痛点问题的契机。
Text2SQL也叫NL2SQL(Natural Language To SQL),是一种自然语言生成技术(文字->代码->结果),通过将人类用自然语言提出的数据问题(Text),转化为结构化查询语言(Structured Query Language,简称SQL)代码,然后自动执行生成的代码实现人类和数据的直接对话,持续提升数据分析效率。
Text2SQL实现的技术路线有很多,本篇主要讲述了基于阿里巴巴开源大模型Qwen,开源框架Vanna,以及Ollama,Mysql,Python3等技术栈的组合来部署实践。由于考虑到企业级数据的安全性,所有组件都是本地化部署,内网可以直接使用。虽然还没延伸考虑数据权限、SQL准确性、复杂场景实现等面临的挑战,但先迈出第一步等于成功了一半,不断学习不断进步,像LLM一样:)
以下是部署实践的步骤:
1. 准备一个linux虚拟机作为服务器。
我电脑是win11+vmware+centos7.6+Xshell,这里的安装略过,可自行网上搜索教程,安装后的效果:

如果装完的OS是图形化启动,可以通过如下命令设置为命令行启动,节省硬件资源:
systemctl set-default multi-user.target
再通过ifconfig查看ip:

获取到ip后就可以通过Xshell远程连系统了:

2. 安装Python3.11环境。
开源框架Vanna是基于Python的,我们通过Miniconda来安装Python3.11。
下载conda安装脚本:
wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh

安装:bash Miniconda3-latest-Linux-x86_64.sh

这里输入yes:


使环境变量生效后查看conda版本验证是否安装OK:
source ~/.bashrc
conda --version

安装python3.11
conda create -n py311 python=3.11


激活Python3环境,并查看版本:
conda activate py311
python -V

3. 安装Ollama。
Ollama是开源大模型的管理运行工具,支持很多国内外开源的大模型,包括我们这次要用的qwen2.5.


安装命令:
curl -fsSL https://ollama.com/install.sh | sh

4. 安装大模型。
安装好后通过ollama -v看下版本,考虑到笔记本性能,选择本地安装qwen2.5:3b版本的开源大模型,3b表示3billon也即30亿个模型参数。
qwen2.5:3b

ollama run qwen2.5:3b

安装完后,就可以直接run模型,和模型对话:

5. 安装mysql并模拟准备企业数据。
Mysql的安装此处略过,可以网上搜索教程。我安装的是mysql8.0+客户端工具Dbeaver:

创建一个vanna的数据库并准备三张表:

DDL和写数脚本如下:
CREATE DATABASE `vanna` /*!40100 DEFAULT CHARACTER SET utf16 */ /*!80016 DEFAULT ENCRYPTION='N' */;
-- vanna.DEPT definition
CREATE TABLE `DEPT` (
`DEPTNO` int NOT NULL COMMENT '部门编号',
`DNAME` varchar(14) DEFAULT NULL COMMENT '部门名称',
`LOC` varchar(13) DEFAULT NULL COMMENT '部门地址',
PRIMARY KEY (`DEPTNO`)
) ENGINE=InnoDB DEFAULT CHARSET=utf16 COMMENT='部门';
-- vanna.SALGRADE definition
CREATE TABLE `SALGRADE` (
`GRADE` int DEFAULT NULL COMMENT '工资等级',
`LOSAL` double DEFAULT NULL COMMENT '最低工资',
`HISAL` double DEFAULT NULL COMMENT '最高工资'
) ENGINE=InnoDB DEFAULT CHARSET=utf16 COMMENT='工资等级';
-- vanna.EMP definition
CREATE TABLE `EMP` (
`EMPNO` int NOT NULL COMMENT '员工编号',
`ENAME` varchar(10) DEFAULT NULL COMMENT '员工名称',
`JOB` varchar(9) DEFAULT NULL COMMENT '工作',
`MGR` double DEFAULT NULL COMMENT '直属领导编号',
`HIREDATE` date DEFAULT NULL COMMENT '入职时间',
`SAL` double DEFAULT NULL COMMENT '工资',
`COMM` double DEFAULT NULL COMMENT '奖金',
`DEPTNO` int DEFAULT NULL COMMENT '部门编号',
PRIMARY KEY (`EMPNO`),
KEY `DEPTNO` (`DEPTNO`),
CONSTRAINT `EMP_ibfk_1` FOREIGN KEY (`DEPTNO`) REFERENCES `DEPT` (`DEPTNO`)
) ENGINE=InnoDB DEFAULT CHARSET=utf16 COMMENT='员工';
INSERT INTO vanna.EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) VALUES
(7369,'SMITH','CLERK',7902.0,'1980-12-17',800.0,NULL,20),
(7499,'ALLEN','SALESMAN',7698.0,'1981-02-20',1600.0,300.0,30),
(7521,'WARD','SALESMAN',7698.0,'1981-02-22',1250.0,500.0,30),
(7566,'JONES','MANAGER',7839.0,'1981-04-02',2975.0,NULL,20),
(7654,'MARTIN','SALESMAN',7698.0,'1981-09-28',1250.0,1400.0,30),
(7698,'BLAKE','MANAGER',7839.0,'1981-05-01',2850.0,NULL,30),
(7782,'CLARK','MANAGER',7839.0,'1981-06-09',2450.0,NULL,10),
(7788,'SCOTT','ANALYST',7566.0,'1987-07-13',3000.0,NULL,20),
(7839,'KING','PRESIDENT',NULL,'1981-11-17',5000.0,NULL,10),
(7844,'TURNER','SALESMAN',7698.0,'1981-09-08',1500.0,0.0,30),
(7876,'ADAMS','CLERK',7788.0,'1987-07-13',1100.0,NULL,20),
(7900,'JAMES','CLERK',7698.0,'1981-12-03',950.0,NULL,30),
(7902,'FORD','ANALYST',7566.0,'1981-12-03',3000.0,NULL,20),
(7934,'MILLER','CLERK',7782.0,'1982-01-23',1300.0,NULL,10);
INSERT INTO vanna.SALGRADE (GRADE,LOSAL,HISAL) VALUES
(1,700.0,1200.0),
(2,1201.0,1400.0),
(3,1401.0,2000.0),
(4,2001.0,3000.0),
(5,3001.0,9999.0);
INSERT INTO vanna.DEPT (DEPTNO,DNAME,LOC) VALUES
(10,'ACCOUNTING','NEW YORK'),
(20,'RESEARCH','DALLAS'),
(30,'SALES','CHICAGO'),
(40,'OPERATIONS','BOSTON');
6. 安装Vanna。
参照Vanna的github指导:
https://github.com/vanna-ai/vanna
pip install vanna
![]()
安装完成后,根据官网介绍,如果使用在线大模型、向量数据库和数据库,几行代码就可以run起来,前提是需要vanna.ai网站申请api key.
https://vanna.ai/docs/app/

7. 安装开源向量数据库Chromadb。我们把向量数据库安装到本地,pip install即可,但是安装过程中会有一些问题,建议可以根据报错在在网上搜索答案。

8. 装PyCharm,远程连接虚拟机的Python环境。具体安装细节网上自行搜索,我电脑安装后的效果如下:

9. Python代码开发,连接qwen大模型,连接mysql,训练数据,启动vanna。
完整代码如下:
from vanna.ollama import Ollama
from vanna.chromadb import ChromaDB_VectorStore
import pandas as pd
import mysql.connector
from vanna.flask import VannaFlaskApp
class MyVanna(ChromaDB_VectorStore, Ollama):
def __init__(self, config=None):
ChromaDB_VectorStore.__init__(self, config=config)
Ollama.__init__(self, config=config)
#vn = MyVanna(config={'model': 'llama3.2:latest','ollama_host':'http://192.168.112.164:11434'})
vn = MyVanna(config={'model': 'qwen2.5:3b','ollama_host':'http://192.168.112.164:11434'})
def run_sql(sql: str) -> pd.DataFrame:
cnx = mysql.connector.connect(user='root', password='888888', host='192.168.112.164', database='vanna')
cursor = cnx.cursor()
cursor.execute(sql)
result = cursor.fetchall()
columns = cursor.column_names
#print('columns:',columns)
df = pd.DataFrame(result, columns=columns)
return df
vn.run_sql = run_sql
vn.run_sql_is_set = True
#给模型训练ddl语句
df_count = vn.run_sql("show tables")
for i in range(0,len(df_count)):
str = "show create table " + df_count['Tables_in_vanna'].loc[i]
df = vn.run_sql(str)
#print(df['Create Table'].loc[df.index[0]])
vn.train(ddl=df['Create Table'].loc[df.index[0]])
#执行web应用
VannaFlaskApp(vn,allow_llm_to_see_data=True).run()

10. 运行Vanna,测试Text2SQL功能:

可以看到控制台给出了运行的地址,这里的localhost换成虚拟机的ip即可访问:

在Training Data页签可以看到我们代码里添加的DDL训练数据加到向量数据库了。然后通过New Question来向数据库提问题:
由于笔记本性能问题,可能要运行一会才出答案,不得不说大模型也是很烧硬件的。


至此,Text2SQL的本地化部署和实践已完成。下一步有待继续探索真实案例和复杂场景的尝试。
相关文章:
大语言模型应用Text2SQL本地部署实践初探
自从两年前OpenAI公司发布ChatGPT后,大模型(Large Language Model,简称LLM)相关技术在国内外可谓百家争鸣,遍地开花,在传统数据挖掘、机器学习和深度学习的基础上,正式宣告进入快速发展的人工智能(Artificial Intellig…...
每日十题八股-2024年12月7日
1.说说hashmap的负载因子 2.Hashmap和Hashtable有什么不一样的?Hashmap一般怎么用? 3.ConcurrentHashMap怎么实现的? 4.分段锁怎么加锁的? 5.分段锁是可重入的吗? 6.已经用了synchronized,为什么还要用CAS呢…...
VTK编程指南<三>:基于VTK入门程序解析来理解VTK基础知识
1、VTK入门程序 下面是一个完整的Vtk入门程序,我们基于这个程序来对VTK的基本知识进行一个初步了解。 #include <iostream>#include <vtkAutoInit.h> VTK_MODULE_INIT(vtkRenderingOpenGL2);// VTK was built with vtkRenderingOpenGL2 VTK_MODULE_INI…...
PyQt5快速开发与实战
PyQt5快速开发与实战相关资源 PyQt5快速开发与实战配套代码资源获取 PyQt5快速开发与实战 第一个要跟大家分享的就是的《PyQt5快速开发与实战》。该书既涵盖了 PyQt5 的基础知识,又包含了实战应用技巧,对 PyQt5 的基本概念和技术细节进行了详细阐述&…...
SpringBoot 开源停车场管理收费系统
一、下载项目文件 下载源码项目文件口令: 【前端小程序地址】(3.0):伏脂火器白泽知洞座/~6f8d356LNL~:/【后台管理地址】(3.0):伏脂火器仇恨篆洞座/~0f4a356Ks2~:/【岗亭端地址】(3.0):动作火器智汇堂多好/~dd69356K6r~:/复制口令…...
cmake: error while loading shared libraries: libssl.so.1.1
在ubuntu22.04中编译c文件时出现如下错误: cmake: error while loading shared libraries: libssl.so.1.1: cannot open shared object file: No such file or directory 解决办法:1.进网站下载对应的.deb文件,链接为:https://sec…...
部署loki,grafana 以及springcloud用法举例
文章目录 场景docker 部署grafanadocker-compose部署loki维护配置文件 local-config.yaml维护docker-compose.yml配置启动 grafana 添加loki数据源springcloud用法举例查看loki的explore,查看日志 场景 小公司缺少运维岗位,需要研发自己部署日志系统,elk…...
后端-编辑按钮的实现
编辑一共要实现两步: 1.点击编辑蹦出来一个弹窗,此时需要回显,根据id查出来这条数据 2.修改某些值之后点击保存的时候调用修改的接口 根据id查询的时候正常操作 修改值的时候要注意一些问题 mapper层的Employee和impl层的接收实体不一样...
uniapp中的@tap与@click:点击事件的微妙差异
在uniapp的开发过程中,我们经常会遇到两种点击事件:tap和click。虽然它们都是点击事件,但在实际使用中却存在一些微妙的差异。本文将详细解析这两种事件的区别,帮助开发者更好地理解和应用。 首先,让我们来看看它们的…...
Uniapp的vue、nvue、uvue后缀名区别
在 UniApp 中,.vue、.nvue 和 .uvue 是不同的文件后缀名,每个文件格式的使用场景和兼容性略有不同。下面是每个文件后缀的详细解释以及它们的兼容性: 1. .vue 文件 定义:.vue 是标准的 Vue 单文件组件格式,主要用于基…...
完美解决Qt Qml窗口全屏软键盘遮挡不显示
1、前提 说明:我使用的是第三方软键盘 QVirtualKeyboard QVirtualKeyboard: Qt5虚拟键盘支持中英文,仿qt官方的virtualkeyboard模块,但使用QWidget实现。 - Gitee.com 由于参考了几篇文章尝试但没有效果,链接如下: 文章一:可能…...
寄存器、缓存、内存三者关系
寄存器、缓存、内存三者关系: 按与CPU远近来分,离得最近的是寄存器,然后缓存(CPU缓存),最后内存。CPU计算时,先预先把要用的数据从硬盘读到内存,然后再把即将要用的数据读到寄存器。于是 CPU<--->…...
九、RNN的变体
RNN的变体 前言一、长短期记忆网络(LSTM)1.1 LSTM结构分析1.1.1 遗忘门1.1.1.1 遗忘门结构图与计算公式1.1.1.2 结构分析1.1.1.3 遗忘门的由来1.1.1.4 遗忘门的内部演示 1.1.2 输入门1.1.2.1 输入门结构图与计算公式1.1.2.2 结构分析1.1.2.3 输入门的内部…...
高级java每日一道面试题-2024年12月07日-JVM篇-如何选择垃圾收集器?
如果有遗漏,评论区告诉我进行补充 面试官: 如何选择垃圾收集器? 我回答: 在Java高级面试中,选择垃圾收集器(Garbage Collector,GC)是一个重要且常见的议题。选择合适的垃圾收集器对于优化应用程序的性能至关重要。以下是对如何…...
棋牌游戏项目ctrl + c无法退出进程问题
棋牌游戏项目ctrl c无法退出进程问题 运行的服务为 user , 启动命令为 cd user && go run main.go启动之前先加入调试语句 在 go func() { metric.Serve(...) } 打日志在 app.Run(...) 打日志 user/main.go var configFile flag.String("config", "…...
论文概览 |《Urban Analytics and City Science》2023.03 Vol.50 Issue.3
本次给大家整理的是《Environment and Planning B: Urban Analytics and City Science》杂志2023年3月第50卷第3期的论文的题目和摘要,一共包括18篇SCI论文! 论文1 A new kind of search 一种新型的搜索 【摘要】 ChatGPT (2022) was first launched o…...
前端知识1html
VScode一些快捷键 Ctrl/——注释 !——生成html框架元素 *n——生成n个标签 直接书写html的名字回车生成对应的标签 常见标签 span: <span style"color: red;">hello</span> <span>demo</span> span实现: 标题…...
Vue03
目录 一、今日目标 1.生命周期 2.综合案例-小黑记账清单 3.工程化开发入门 4.综合案例-小兔仙首页 二、Vue生命周期 三、Vue生命周期钩子 四、生命周期钩子小案例 1.在created中发送数据 六、工程化开发模式和脚手架 1.开发Vue的两种方式 2.Vue CLI脚手架 基本介绍…...
深入浅出:Gin框架路由与HTTP请求处理
深入浅出:Gin框架路由与HTTP请求处理 引言 在Web开发中,路由和HTTP请求处理是构建API的核心部分。Gin框架作为Go语言中最受欢迎的Web框架之一,提供了简洁而强大的工具来处理这些任务。本文将深入浅出地介绍如何使用Gin框架进行路由定义、处…...
C++初阶——模板初阶
目录 1、如何实现一个通用的交换函数 2、函数模板 2.1 函数模板的概念 2.2 函数模板的格式 2.3 函数模板的原理 2.4 函数模板的实例化 2.5 模板参数的匹配原则 3、类模板 3.1 类模板的格式 3.2 类模板的实例化 1、如何实现一个通用的交换函数 void Swap(int& lef…...
【Java学习笔记】Arrays类
Arrays 类 1. 导入包:import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序(自然排序和定制排序)Arrays.binarySearch()通过二分搜索法进行查找(前提:数组是…...
如何在看板中有效管理突发紧急任务
在看板中有效管理突发紧急任务需要:设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP(Work-in-Progress)弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中,设立专门的紧急任务通道尤为重要,这能…...
使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装
以下是基于 vant-ui(适配 Vue2 版本 )实现截图中照片上传预览、删除功能,并封装成可复用组件的完整代码,包含样式和逻辑实现,可直接在 Vue2 项目中使用: 1. 封装的图片上传组件 ImageUploader.vue <te…...
06 Deep learning神经网络编程基础 激活函数 --吴恩达
深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...
什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南
文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果,支持8kHz~96kHz采样率,集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器,适用于高保真音频采集场景。 2. 核心特性 高精度:24位分辨率,…...
C# 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...
AI病理诊断七剑下天山,医疗未来触手可及
一、病理诊断困局:刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断",医生需通过显微镜观察组织切片,在细胞迷宫中捕捉癌变信号。某省病理质控报告显示,基层医院误诊率达12%-15%,专家会诊…...
【Go语言基础【13】】函数、闭包、方法
文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数(函数作为参数、返回值) 三、匿名函数与闭包1. 匿名函数(Lambda函…...
