利用ChatGLM3构建Prompt实现Text2SQL

news2024/9/27 7:23:29

之前使用ChatGLM3的自定义工具实现了查询MySQL数据库,但感觉功能还是比较受限。
https://blog.csdn.net/weixin_44455388/article/details/135270879?spm=1001.2014.3001.5501

使用ChatGLM3实现Text2SQL

  • 前言
  • Text2SQL的构建
      • 第一阶段:SQL脚本构建
        • (1)构建数据信息表的 schema,利用 LLM 生成 embedding
        • (2)prompt 提示词构建
      • 第二阶段:查询数据库,提供数据分析
  • 优化
  • 参考

前言

将自然语言文本(Text)转换成结构化查询语言 SQL,帮助用户快速生成想要查询的 SQL 语句;或者是用户输入一段话,然后系统完成一系列自动化查询和报表展示的操作,过自然语言描述完成复杂数据库的查询工作,得到想要的结果。

Text2SQL的构建

我们在 Text2SQL 上面的应用主要包括两个阶段,第一阶段是利用 LLM 理解你的请求,通过请求去生成结构化的 SQL;下一个阶段是在生成的 SQL 上自动化的查询数据库,返回结果,然后利用 LLM 对结果生成总结,提供分析。

第一阶段:SQL脚本构建

利用 LLM大模型理解文本信息,生成 SQL。因为考虑到数据的安全性,我们考虑使用ChatGLM生成SQL语句,从测试结果看,ChatGLM和GPT 对比,还是有比较大的差距,所以无法直接使用。

(1)构建数据信息表的 schema,利用 LLM 生成 embedding

这里我们根据用户描述的 text,让预训练的 chatglm2-6b 生成 embedding,通过 embedding 检索的方式,选出 top1 数据表,这个过程属于先验过滤阶段。
数据表的 schema 设计非常重要,需要描述清楚这个表它的主体信息以及表中重要字段和字段含义。

以下是我们设计的schema:
–tableName表示表名
–info表示该表的描述信息
–fields表示表字段信息,包括英文字段名、中文字段名和字段类型

[
	{
		"tableName":"prompt_history",
		"info":"问答历史会话记录表,包括会话编号id、会用编号id、会话历史记录、会话时间。",
		"fields":{
			"session_id":"会话编号,String",
			"user_id":"用户编号,String",
			"history":"会话历史,String",
			"create_time":"会话时间,datetime"
		}
	},
	{
		"tableName":"common_prompt",
		"info":"常用prompt提示词表,包括提示词id、提示词标题、提示词内容。",
		"fields":{
			"id":"提示词id,int",
			"title":"提示词标题,String",
			"content":"提示词内容,String"
		}
	}
]

开发代码,将以上表信息进行向量化,存储到向量数据库:

public void addTable2Milvus(MultipartFile file) {
    List<String> sqls = new ArrayList<>();
    StringBuilder sb=new StringBuilder();
    try (InputStream inputStream = file.getInputStream()) {
        byte[] buffer = new byte[1024];
        int bytesRead;
        while ((bytesRead = inputStream.read(buffer)) != -1) {
            sb.append(new String(buffer));
        }
        JSONArray jsonArray = JSONArray.parseArray(sb.toString());
        for (int i = 0;i<jsonArray.size();i++){
            String string = jsonArray.getString(i);
            sqls.add(string);
        }
        List<Integer> contentWordCount = new ArrayList<>();
        List<List<Float>> contentVector = new ArrayList<>();
        for(String str : sqls){
            contentWordCount.add(str.length());
        }
        contentVector = embeddingModel.doEmbedding(sqls);

        List<InsertParam.Field> fields = new ArrayList<>();
        fields.add(new InsertParam.Field("content", sqls));
        fields.add(new InsertParam.Field("content_word_count", contentWordCount));
        fields.add(new InsertParam.Field("content_vector", contentVector));

        InsertParam insertParam = InsertParam.newBuilder()
                .withCollectionName("sqls")
                .withFields(fields)
                .build();
        //插入数据
        milvusClient.insert(insertParam);
        log.info(file.getOriginalFilename()+" -> 向量化结束...");
    } catch (IOException e) {
        e.printStackTrace();
    }
}
(2)prompt 提示词构建

我们需要将解析数据表中的信息,加入到 prompt 中,以此来构建完成的 prompt,让 LLM 去理解你的真实意图,生成标准的 SQL。

①开头prompt定义:

你是一个文本转SQL的生成器,你的主要目标是尽可能的协助用户,将输入的文本转化为正确的SQL语句。
上下文开始
表名和表字段来自以下表:

②查询向量数据库

public String buildQuerySql(String prompt) {
    String finalPrompt = null;
    //调用自定义的python服务
    List<Float> vector = embeddingModel.doEmbedding(prompt);
    List<PDFData> searchResult = search(Arrays.asList(vector));
    StringBuilder builder = new StringBuilder();
    for(PDFData data:searchResult){
        builder.append(data.getContent()).append("\n");
    }
    //处理需要请求的信息
    String msg = prefix_prompt+"%s。%s";
    finalPrompt = String.format(msg,builder, prompt);
    return finalPrompt;
}

/**
 * 查询向量数据库
 * @param search_vectors
 * @return
 */
private List<PDFData> search(List<List<Float>> search_vectors){
    milvusClient.loadCollection(
            LoadCollectionParam.newBuilder()
                    .withCollectionName("sqls")
                    .build()
    );
    final Integer SEARCH_K = 4;
    final String SEARCH_PARAM = "{\"nprobe\":10}";
    List<String> ids = Arrays.asList("id");
    List<String> contents = Arrays.asList("content");
    List<String> contentWordCounts = Arrays.asList("content_word_count");
    SearchParam searchParam = SearchParam.newBuilder()
            .withCollectionName("sqls")
            .withConsistencyLevel(ConsistencyLevelEnum.STRONG)
            .withOutFields(ids)
            .withOutFields(contents)
            .withOutFields(contentWordCounts)
            .withTopK(SEARCH_K)
            .withVectors(search_vectors)
            .withVectorFieldName("content_vector")
            .withParams(SEARCH_PARAM)
            .build();
    R<SearchResults> respSearch = milvusClient.search(searchParam);
    List<PDFData> pdfDataList = new ArrayList<>();
    if(respSearch.getStatus() == R.Status.Success.getCode()){
        //respSearch.getData().getStatus() == R.Status.Success
        SearchResults resp = respSearch.getData();
        //判断是否查到结果
        if(!resp.hasResults()){
            return new ArrayList<>();
        }
        for (int i = 0; i < search_vectors.size(); ++i) {
            SearchResultsWrapper wrapperSearch = new SearchResultsWrapper(resp.getResults());
            List<Long> id = (List<Long>) wrapperSearch.getFieldData("id", 0);
            List<String> content = (List<String>) wrapperSearch.getFieldData("content", 0);
            List<Integer> contentWordCount = (List<Integer>) wrapperSearch.getFieldData("content_word_count", 0);
            PDFData pdfData = new PDFData(id.get(0),content.get(0),contentWordCount.get(0));
            pdfDataList.add(pdfData);
        }
    }
    milvusClient.releaseCollection(
            ReleaseCollectionParam.newBuilder()
                    .withCollectionName("sqls")
                    .build());
    return pdfDataList;
}

③得到完成的prompt

你是一个文本转SQL的生成器,你的主要目标是尽可能的协助用户,将输入的文本转化为正确的SQL语句。
上下文开始
表名和表字段来自以下表:{"fields":{"create_time":"会话时间,datetime","user_id":"用户编号,String","session_id":"会话编号,String","history":"会话历史,String"},"tableName":"prompt_history","info":"问答历史会话记录表,包括会话编号id、会用编号id、会话历史记录、会话时间。"}
。查询一下23年12月20日以来的问答历史记录

(3)利用LLM大模型生成SQL语句

JSONObject params = new JSONObject();
params.put("model", "chatglm3-6b");
params.put("max_tokens", maxTokens);
params.put("stream", true);
params.put("temperature", temperature);
params.put("top_p", topP);
params.put("user", user);
JSONObject message = new JSONObject();
message.put("role", "user");
message.put("content", finalPrompt);
params.put("messages", Collections.singleton(message));
log.info("ChatGLM请求参数:"+message.toJSONString());
return webClient.post()
    .uri(chatGlmUrl)
    .header(HttpHeaders.AUTHORIZATION, "Bearer none")
    .bodyValue(params.toJSONString())
    .retrieve()
    .bodyToFlux(String.class)
    .onErrorResume(WebClientResponseException.class, ex -> {
        HttpStatus status = ex.getStatusCode();
        String res = ex.getResponseBodyAsString();
        log.error("ChatGLM error: {} {}", status, res);
        return Mono.error(new RuntimeException(res));
    });

得到最终的SQL语句:

SELECT * FROM prompt_history WHERE create_time > '2023-12-20'

在这里插入图片描述

第二阶段:查询数据库,提供数据分析

可以在代码中连接数据库,运行SQL语句并返回结果。

优化

如果觉得ChatGLM的Text2SQL能力还是比较弱,可以采用微调的方式,强化ChatGLM的Text2SQL能力。

推荐项目:DB-GPT-Hub

参考

https://baijiahao.baidu.com/s?id=1780693355413218644&wfr=spider&for=pc

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

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

相关文章

听GPT 讲Rust源代码--compiler(32)

File: rust/compiler/rustc_middle/src/middle/exported_symbols.rs 在Rust的源代码中&#xff0c;rust/compiler/rustc_middle/src/middle/exported_symbols.rs文件的作用是实现编译器中处理导出符号的功能。 该文件中定义了一些结构体和枚举&#xff0c;用于描述导出符号的信…

MySQL 存储引擎和索引类型介绍

1. 引言 MySQL 是一个流行的关系型数据库管理系统&#xff0c;提供多种存储引擎以满足不同的业务需求。本文将介绍几种常见的 MySQL 存储引擎和索引类型比较&#xff0c;并给出相应的示例。 2. 存储引擎概述 2.1 InnoDB 存储引擎 InnoDB 是 MySQL 的默认存储引擎&#xff0…

向量数据库:usearch的简单使用+实现图片检索应用

usearch的简单使用 usearch是快速开源搜索和聚类引擎&#xff0c;用于C、C、Python、JavaScript、Rust、Java、Objective-C、Swift、C#、GoLang和Wolfram &#x1f50d;中的向量和&#x1f51c;字符串 // https://github.com/unum-cloud/usearch/blob/main/python/README.md …

解决ImportError: Failed to import test module: sys.__init__

解决ImportError: Failed to import test module: sys.init 背景 学习通过文件夹执行测试脚本时&#xff0c;出现了错误&#xff1a;ImportError: Failed to import test module: sys.__init__ 解决过程 根据报错信息&#xff1a;sys is not a package大胆猜测可能是文件名…

【MySQL】数据库之MMM高可用

目录 一、什么是MMM 二、关于MMM架构的说明 三、实操MMM的高可用 步骤一&#xff1a;完成主主复制、主从复制 步骤二&#xff1a;所有节点服务器都安装mysql-mmm,并完成mmm_common.conf文件的配置 步骤三&#xff1a;完成monitor节点服务器的配置文件修改mmm_mon.conf 步…

SpringCloud系列篇:入门讲解Spring Cloud是什么

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于SpringCloud的相关操作吧 目录 &#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 一.Spring Cloud是什么 二.Spring …

家里有必要买NAS吗?

完全没有必要&#xff0c;因为用旧电脑搭建NAS不仅价格实惠&#xff0c;而且非常简单&#xff0c;效果也完全不差买了的&#xff01; 并且......还环保 教程链接&#xff1a; 用旧电脑搭建NAS在您的家庭中&#xff0c;通过将旧 PC 转变为NAS服务器&#xff0c;您可以轻松搭建…

Ubuntu 虚拟机挂接 Windows 目录

Windows 共享目录 首先 Windows 下共享目录 我这里偷懒直接直接 Everyone &#xff0c;也可以指定用户啥的 Ubuntu 挂接 挂接命令&#xff0c;类似如下&#xff1a; sudo mount -o usernamefananchong,passwordxxxx,uid1000,gid1000,file_mode0644,dir_mode0755,dynperm //…

04set注入专题/简单类型/数组/List/Set/Map/空字符串/null/特殊符号

1.1注入外部Bean 在之前使用的案例就是注入外部Bean的方式。 <!-- class属性声明要管理哪个类中的对象 property标签的name是提示set方法名ref标签指明注入的bean的id--><bean id"userServiceBean" class"com.powernode.spring6.service.UserService…

WorkPlus支持平台级定制,助理企业自主掌控业务和生态

在数字化时代&#xff0c;企业越来越需要满足自身特性和需求的定制化解决方案。WorkPlus不同于企业微信、钉钉和飞书&#xff0c;它支持平台级的定制服务&#xff0c;完全掌控自身数字化进程。WorkPlus可根据企业的安全特性、强可控要求和高定制化场景&#xff0c;提供原厂平台…

基于 HTTPS 协议配置 Git 连接 GitHub

文章目录 0.安装 Git1.注册 GitHub 账号2.配置 Git 的用户名和邮箱3.远程连接 GitHub 有两种传输协议4.基于 SSH 协议配置 Git 连接 GitHub5.基于 HTTPS 协议配置 Git 连接 GitHub5.1 创建 GitHub 个人访问令牌5.2 有两种方法将本地仓库和远程仓库关联起来5.2.1 第一种方法&…

位运算--二进制中1的个数(含常见的二进制运算操作)

目录 二进制中1的个数操作 1 查看第k位的数字是否为1操作2 lowbit操作 解题代码&#xff1a; 原题链接: 二进制中1的个数 给定一个长度为 n 的数列&#xff0c;请你求出数列中每个数的二进制表示中 1 的个数。 输入格式 第一行包含整数 n 。 第二行包含 n 个整数&#xff0c…

Turn.js 实现翻书效果

接到了任务&#xff0c;要把孩子画的画放到网页上去&#xff0c;翻页效果还要逼真一点。搜索到了turn.js这个前端翻页组件&#xff0c;效果不错。先上图看效果。 网页实际效果&#xff1a;星月夜诗集 turn.js的官网地址&#xff1a;Turn.js: The page flip effect in HTML5 …

STM32_HAL Freertos按键控制LED

设置GPIO引脚 根据电路图&#xff0c;K0为用户按键&#xff0c;连接在PA0引脚&#xff0c;当K0按下时接地&#xff0c;引脚电平低电平。在CubeMX中设置PA0&#xff0c;将IO设置为输入&#xff0c;上拉&#xff08;上拉外部悬空时&#xff0c;引脚为高电平&#xff09;。 添…

【Linux】Linux基础之权限

目录 一、Linux中的用户1.1 用户之间的身份切换1.2 指令提权 二、权限管理2.1 文件权限2.2 权限操作2.3 chown和chgrp 三、文件类型四、目录文件的权限操作五、权限掩码六、粘滞位 一、Linux中的用户 Linux中主要有两种用户&#xff1a; root&#xff0c;超级用户非root&…

x-cmd pkg | trdsql - 能对 CSV、LTSV、JSON 和 TBLN 执行 SQL 查询的工具

目录 简介首次用户技术特点竞品和相关作品进一步阅读 简介 trdsql 是一个使用 sql 作为 DSL 的强大工具: 采用 SQL 对 CSV、LTSV、JSON 和 TBLN 文件执行查询与 MySQL&#xff0c;Postgresql&#xff0c;Sqlite 的 Driver 协同&#xff0c;可以实现对应数据库的表与文件的 JO…

Python Asyncio网络编程方法全面解析与实战应用!

更多Python学习内容&#xff1a;ipengtao.com Python的asyncio库是一种强大的异步编程工具&#xff0c;它使得编写高效的网络应用程序变得更加容易。在本文中&#xff0c;我们将深入探讨使用asyncio进行网络编程的方法&#xff0c;包括异步IO、协程、事件循环等方面的内容&…

Long类型转换精度丢失问题解决

问题: 启动前端项目 页面传递的ID 和数据库保存的ID不一致 原因&#xff1a;给前端返回的id为long类型&#xff0c;在转换json传递到前端以后精度丢失&#xff0c;所以前端给我们的id也是丢失精度的id,不能查询数据。 因为js数字类型最大长度为16位&#xff0c;而java的long类…

【强力推荐】GitCode AI开源搜索,面向开发者的专业AI搜索

一、GitCode AI开源搜索是什么&#xff1f; GitCode AI开源搜索 是面开发者的 AI 开源搜索工具&#xff0c;目的是为了帮助开发者快速寻找开源项目代码、解决开发问题和快速寻找答案&#xff0c;帮助开发者提升效率的同时利用代码仓托管能力建立自己个人知识库。 二、GitCode…

如何才能成长为一个架构师?

很多技术小伙伴都在问我&#xff0c;架构师是不是很牛逼&#xff0c;那么为什么自己不能成长为一名优秀的架构师呢&#xff1f;而总是作为工程师资源被项目打包带走&#xff0c;并周而复始的完成领导的业务开发需求任务。 架构师的工作职责&#xff1f; 为了方便技术小伙伴理…