当前位置: 首页 > news >正文

如何使用GPT作为SQL查询引擎的自然语言

​生成的AI输出并不总是可靠的,但是下面我会讲述如何改进你的代码和查询的方法,以及防止发送敏感数据的方法。与大多数生成式AI一样,OpenAI的API的结果仍然不完美,这意味着我们不能完全信任它们。幸运的是,现在我们可以编写代码询问GPT如何计算响应,然后如果认可该方法,那我们可以自己运行代码。这意味着我们可以提出自然语言问题,比如“去年按地区的总销售额是多少?”,并且对响应的准确性感到可信。下面是一种快速而简单的技术,用于使用GPT设置自己的数据库的自然语言查询:

  1. 将数据的结构、一些示例行或两者都放入一个文本字符串中。
  2. 使用该信息加上你的自然语言问题来构建一个“提示”给AI。
  3. 将提示发送到OpenAI的GPT-3.5-turbo API,并请求一个SQL查询来回答您的问题。在数据集上运行返回的SQL来计算您的答案。
  4. (可选)创建一个交互式应用程序,以便轻松地使用纯英语查询数据集。

这种方法在处理现实世界的数据时具有几个优点。通过仅发送数据结构和一些示例行(可以包含虚假数据),无需将实际敏感数据发送给OpenAI。如果你的数据超过OpenAI的提示大小限制,也不必担心。通过请求SQL而不是最终答案,检查GPT如何生成答案的能力已经内置到了该过程中。如果真正想要使用生成式AI来开发企业级查询,可以借用一些工具,比如LangChain,它是一个用于处理多个不同的大型语言模型(LLM)的框架,不仅限于OpenAI的GPT。OpenAI最近还宣布了在API请求中包含函数调用的可能性,旨在使查询和类似任务更容易和可靠。但对于快速原型或您自己的使用,这里描述的过程是一个简单的入门方法。我的演示是用R完成的,但这种技术在几乎任何编程语言中都可以使用。

步骤1:将示例数据转换为单个字符字符串

这一步中的示例数据可以包括数据库模式和/或几行数据。将其全部转换为单个字符字符串非常重要,因为它将成为你将发送给GPT 3.5的更大文本字符串查询的一部分。 如果你的数据已经在SQL数据库中,这一步应该很容易。如果不是,我建议将其转换为可查询的SQL格式。为什么?在测试R和SQL代码结果后,我对GPT生成的SQL代码比其R代码更有信心。(我怀疑这是因为LLM在训练时使用了更多的SQL数据而不是R数据。) 在R中,sqldf包允许在R数据框上运行SQL查询,这是我在这个示例中将使用的工具。Python中也有类似的sqldf库。对于性能很重要的大型数据,你还可以查看duckdb项目。以下代码将数据文件导入R,使用sqldf函数查看如果数据框是一个SQL数据库表,SQL模式会是什么样子,使用head函数提取三行示例数据,并将模式和示例数据都转换为字符字符串。补充:ChatGPT编写了将数据转换为单个字符串的基本R部分的代码(通常我会使用paste函数执行这些任务)。

library(rio)
library(dplyr)
library(sqldf)
library(glue)
states <- rio::import("https://raw.githubusercontent.com/smach/SampleData/main/states.csv") |>filter(!is.na(Region))
​
states_schema <- sqldf("PRAGMA table_info(states)")
states_schema_string <- paste(apply(states_schema, 1, paste, collapse = "\t"), collapse = "\n")
​
states_sample <- dplyr::sample_n(states, 3)
states_sample_string <- paste(apply(states_sample, 1, paste, collapse = "\t"), collapse = "\n")

步骤2:为LLM创建提示

格式应该类似于“假设你是一名数据科学家。你有一个名为{table_name}的SQLite表,其模式如下:{schema}。前几行数据如下所示:{rows_sample}。基于这些数据,编写一个SQL查询来回答以下问题:{query}。只返回SQL,不包括解释。”。以下函数创建了这种类型格式的查询,接受数据模式、示例行、用户查询和表名作为参数。

create_prompt <- function(schema, rows_sample, query, table_name) {glue::glue("Act as if you're a data scientist. You have a SQLite table named {table_name} with the following schema:
​```{schema}```
​The first rows look like this: 
​```{rows_sample}```
​Based on this data, write a SQL query to answer the following question: {query}. Return the SQL query ONLY. Do not include any additional explanation."
)
}

步骤3:将数据发送到OpenAI的API

你可以先将数据复制粘贴到OpenAI的Web界面之一中,以在ChatGPT或OpenAI API playground中查看结果。ChatGPT不收费,但无法调整结果。Playground允许设置诸如温度(即回答的“随机性”或创造性程度)和要使用的模型等参数。对于SQL代码,我将温度设置为0。

接下来,我将一个自然语言问题保存到变量question中,使用我的函数创建一个提示,并查看将该提示粘贴到API playground中会发生什么:

> my_query <- "What were the highest and lowest Population changes in 2020 by Division?"
> my_prompt <- get_query(states_schema_string, states_sample_string, my_query, "states")
> cat(my_prompt)
Act as if you're a data scientist. You have a SQLite table named states with the following schema:
​
```
0  State  TEXT  0  NA  0
1  Pop_2000  INTEGER  0  NA  0
2  Pop_2010  INTEGER  0  NA  0
3  Pop_2020  INTEGER  0  NA  0
4  PctChange_2000  REAL  0  NA  0
5  PctChange_2010  REAL  0  NA  0
6  PctChange_2020  REAL  0  NA  0
7  State Code  TEXT  0  NA  0
8  Region  TEXT  0  NA  0
9  Division  TEXT  0  NA  0
```
​
The first rows look like this: 
​
```Delaware   783600   897934   989948  17.6  14.6  10.2  DE  South  South Atlantic
Montana   902195   989415  1084225  12.9   9.7   9.6  MT  West  Mountain
Arizona  5130632  6392017  7151502  40.0  24.6  11.9  AZ  West  Mountain```
​
Based on this data, write a SQL query to answer the following question: What were the highest and lowest Population changes in 2020 by Division?. Return the SQL query ONLY. Do not include any additional explanation.

提示输入OpenAI API playground和生成的SQL代码

以下是我运行建议的SQL时的结果:

sqldf("SELECT Division, MAX(PctChange_2020) AS Highest_PctChange_2020,      MIN(PctChange_2020) AS Lowest_PctChange_2020 FROM states GROUP BY Division;")Division Highest_PctChange_2020 Lowest_PctChange_2020
1 East North Central                    4.7                  -0.1
2 East South Central                    8.9                  -0.2
3    Middle Atlantic                    5.7                   2.4
4           Mountain                   18.4                   2.3
5        New England                    7.4                   0.9
6            Pacific                   14.6                   3.3
7     South Atlantic                   14.6                  -3.2
8 West North Central                   15.8                   2.8
9 West South Central                   15.9                   2.7

步骤4:执行由GPT返回的SQL代码结果

通过编程方式将数据发送到OpenAI并从中返回会比将其复制粘贴到Web界面中更方便。有一些R包可以用于与OpenAI API进行交互。以下代码块使用该包向API发送提示,存储API响应,提取包含所请求SQL代码的文本部分,复制该代码,并在数据上运行SQL。

library(openai)
my_results <- openai::create_chat_completion(model =  "gpt-3.5-turbo", temperature = 0, messages =  list(list(role = "user", content = my_prompt)
)) 
the_answer <- my_results$choices$message.content
​
cat(the_answer)
SELECT Division, MAX(PctChange_2020) AS Highest_Population_Change, MIN(PctChange_2020) AS Lowest_Population_Change
FROM states
GROUP BY Division;
​
sqldf(the_answer)Division Highest_Population_Change Lowest_Population_Change
1 East North Central                       4.7                     -0.1
2 East South Central                       8.9                     -0.2
3    Middle Atlantic                       5.7                      2.4
4           Mountain                      18.4                      2.3
5        New England                       7.4                      0.9
6            Pacific                      14.6                      3.3
7     South Atlantic                      14.6                     -3.2
8 West North Central                      15.8                      2.8
9 West South Central                      15.9                      2.7

如果你想使用OpenAI API,你需要一个OpenAI API密钥。对于这个包,密钥应该存储在系统环境变量中,例如。请注意,这个API不是免费使用的,但在我把它变成我的编辑器之前,我一天运行了这个项目十几次,我的总账户使用量是1美分。

步骤5(可选):创建一个交互式应用程序

现在你已经拥有了在R工作流中运行查询的所有所需代码,可以在脚本或终端中使用它。但是,如果你想创建一个用于以自然语言查询数据的交互式应用程序,我提供了一个基本的Shiny应用程序的代码供你使用。如果你打算发布一个供他人使用的应用程序,而不仅仅是自己使用,你需要加固代码以防止恶意查询,添加更好的错误处理和解释性标签,改进样式,并对企业使用进行扩展。 与此同时,以下代码可以帮助开始创建一个用于使用自然语言查询数据集的交互式应用程序:

library(shiny)
library(openai)
library(dplyr)
library(sqldf)
​
# Load hard-coded dataset
states <- read.csv("states.csv") |>dplyr::filter(!is.na(Region) & Region != "")
​
states_schema <- sqldf::sqldf("PRAGMA table_info(states)")
states_schema_string <- paste(apply(states_schema, 1, paste, collapse = "\t"), collapse = "\n")
​
states_sample <- dplyr::sample_n(states, 3)
states_sample_string <- paste(apply(states_sample, 1, paste, collapse = "\t"), collapse = "\n")
​
# Function to process user input
get_prompt <- function(query, schema = states_schema_string, rows_sample = states_sample_string, table_name = "states") {my_prompt <- glue::glue("Act as if you're a data scientist. You have a SQLite table named {table_name} with the following schema:
​```{schema}```
​The first rows look like this: 
​```{rows_sample}```
​Based on this data, write a SQL query to answer the following question: {query}  Return the SQL query ONLY. Do not include any additional explanation.")print(my_prompt)return(my_prompt)
​
}
​
ui <- fluidPage(titlePanel("Query state database"),sidebarLayout(sidebarPanel(textInput("query", "Enter your query", placeholder = "e.g., What is the total 2020 population by Region?"),actionButton("submit_btn", "Submit")),mainPanel(uiOutput("the_sql"),br(),br(),verbatimTextOutput("results")))
)
​
server <- function(input, output) {
​
# Create the prompt from the user query to send to GPTthe_prompt <- eventReactive(input$submit_btn, {req(input$query, states_schema_string, states_sample_string)my_prompt <- get_prompt(query = input$query)})    
​
# send prompt to GPT, get SQL, run SQL, print results
observeEvent(input$submit_btn, {req(the_prompt()) # text to send to GPT
​# Send results to GPT and get response# withProgress adds a Shiny progress bar. Commas now needed after each statementwithProgress(message = 'Getting results from GPT', value = 0, {  # Add Shiny progress messagemy_results <- openai::create_chat_completion(model =  "gpt-3.5-turbo", temperature = 0, messages =  list(list(role = "user", content = the_prompt()))) the_gpt_sql <- my_results$choices$message.content 
​# print the SQLsql_html <- gsub("\n", "<br />", the_gpt_sql) sql_html <- paste0("<p>", sql_html, "</p>") 
​# Run SQL on data to get resultsgpt_answer <- sqldf(the_gpt_sql) setProgress(value = 1, message = 'GPT results received') # Send msg to user that })# Print SQL and resultsoutput$the_sql <- renderUI(HTML(sql_html)) 
​if (is.vector(gpt_answer) ) {output$results <- renderPrint(gpt_answer) } else {output$results <- renderPrint({ print(gpt_answer) }) } 
})  
}
shinyApp(ui = ui, server = server)

作者: MSharon Machlis

更多技术干货请关注公号“云原生数据库

squids.cn,目前可体验全网zui低价RDS,免费的迁移工具DBMotion、SQL开发工具等

相关文章:

如何使用GPT作为SQL查询引擎的自然语言

​生成的AI输出并不总是可靠的&#xff0c;但是下面我会讲述如何改进你的代码和查询的方法&#xff0c;以及防止发送敏感数据的方法。与大多数生成式AI一样&#xff0c;OpenAI的API的结果仍然不完美&#xff0c;这意味着我们不能完全信任它们。幸运的是&#xff0c;现在我们可以…...

Servlet3.0上传文件

页面&#xff1a; <!DOCTYPE html> <html> <head> <meta charset"UTF-8"> <title>文件上传</title> </head> <body> <form action"fileup" enctype"multipart/form-data" method"…...

【ARM Cache 系列文章 6 番外篇 – MMU, MPU, SMMU, PMU 差异与关系】

文章目录 MMU 与 MPU 之间的关系MMU 与 SMMU 之间的关系MMU 与 PMU 之间的关系 上篇文章&#xff1a;ARM Cache 系列文章 5 – 内存屏障ISB/DSB/DMB MMU 与 MPU 之间的关系 MMU&#xff08;Memory Management Unit&#xff09;和MPU&#xff08;Memory Protection Unit&#…...

NetSuite ERP顾问的进阶之路

目录 1.修养篇 1.1“道”是什么&#xff1f;“器”是什么&#xff1f; 1.2 读书这件事儿 1.3 十年计划的力量 1.3.1 一日三省 1.3.2 顾问损益表 1.3.3 阶段课题 2.行为篇 2.1协作 2.2交流 2.3文档管理 2.4时间管理 3.成长篇 3.1概念能力 3.1.1顾问的知识结构 …...

js 新浏览器打开页面

博主gzh&#xff1a;“程序员野区”&#xff0c;回复“加群”,可进博主web前端微信群 效果如下 setTimeout(()>{var url "https://blog.csdn.net/xuelang532777032?typeblog"; //要打开的网页地址var features "height500, width800, top100, left100, …...

jmeter软件测试实验(附源码以及配置)

jmeter介绍 JMeter是一个开源的性能测试工具&#xff0c;由Apache软件基金会开发和维护。它主要用于对Web应用程序、Web服务、数据库和其他类型的服务进行性能测试。JMeter最初是为测试Web应用程序而设计的&#xff0c;但现在已经扩展到支持更广泛的应用场景。 JMeter 可对服务…...

ZooKeeper原理剖析

1.ZooKeeper简介 ZooKeeper是一个分布式、高可用性的协调服务。在大数据产品中主要提供两个功能&#xff1a; 帮助系统避免单点故障&#xff0c;建立可靠的应用程序。提供分布式协作服务和维护配置信息。 2.ZooKeeper结构 ZooKeeper集群中的节点分为三种角色&#xff1a;Le…...

【算组合数】CF1833 F

少见地秒了这道1700&#xff0c;要是以后都这样就好了.... Problem - F - Codeforces 题意&#xff1a; 给定一个数列&#xff0c;让你在这个数列里找一个大小为M的子集&#xff0c;使得极差不超过M 思路&#xff1a; 子集&#xff0c;不是子序列&#xff0c;说明和顺序无…...

Attention详解(自用)

encoder-decoder 分心模型&#xff1a;没有引入注意力的模型在输入句子比较短的时候问题不大&#xff0c;但是如果输入句子比较长&#xff0c;此时所有语义完全通过一个中间语义向量来表示&#xff0c;单词自身的信息已经消失&#xff0c;可想而知会丢失很多细节信息&#xff0…...

pptx转pdf工具类

引入依赖 <dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>5.0.0</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxm…...

2023华为OD统一考试(B卷)题库清单(持续收录中)以及考点说明

目录 专栏导读2023 B卷 “新加题”&#xff08;100分值&#xff09;2023Q2 100分2023Q2 200分2023Q1 100分2023Q1 200分2022Q4 100分2022Q4 200分牛客练习题 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;A卷B卷&#xff09;》。 刷的越多&…...

论文笔记--Won’t Get Fooled Again: Answering Questions with False Premises

论文笔记--Won’t Get Fooled Again: Answering Questions with False Premises 1. 文章简介2. 文章概括3 文章重点技术3.1 大模型面对FPQs的表现3.2 False QAs数据集3.3 训练和评估 4. 文章亮点5. 原文传送门 1. 文章简介 标题&#xff1a;Won’t Get Fooled Again: Answerin…...

【Django】include app_name和namespace的区别

app_name 区分不同app的url的name&#xff0c;防止不同app之间&#xff0c;url_name的重名&#xff0c;引用时加入app_name:name namespace 区分不同路由 include同一个view module的情况&#xff0c; 让不同路由进入同一个view中&#xff0c;进行reverse时&#xff0c;根据对…...

(黑客)自学笔记

特别声明&#xff1a; 此教程为纯技术分享&#xff01;本教程的目的决不是为那些怀有不良动机的人提供及技术支持&#xff01;也不承担因为技术被滥用所产生的连带责任&#xff01;本教程的目的在于最大限度地唤醒大家对网络安全的重视&#xff0c;并采取相应的安全措施&#x…...

【期末课程设计】学生成绩管理系统

因其独特&#xff0c;因其始终如一 文章目录 一、学生成绩管理系统介绍 二、学生成绩管理系统设计思路 三、源代码 1. test.c 2. Student Management System.c 3.Stu_System.c 4.Teacher.c 5.Student Management System.h 前言&#xff1a; 学生成绩管理系统含教师…...

【论文笔记】KDD2019 | KGAT: Knowledge Graph Attention Network for Recommendation

Abstract 为了更好的推荐&#xff0c;不仅要对user-item交互进行建模&#xff0c;还要将关系信息考虑进来 传统方法因子分解机将每个交互都当作一个独立的实例&#xff0c;但是忽略了item之间的关系&#xff08;eg&#xff1a;一部电影的导演也是另一部电影的演员&#xff09…...

ES6:基础使用,积累

一、理解ES6 ES6是ECMAScript 6.0的简称&#xff0c;也被称为ES2015。它是ECMAScript的第六个版本&#xff0c;是JavaScript标准的下一个重大更新。ES6于2015年6月发布&#xff0c;新增了许多新的语言特性和API&#xff0c;包括箭头函数、let和const关键字、模板字符串、解构赋…...

Android端上传文件到Spring Boot后端

准备 确定好服务器端文件保存的位置确定好请求参数名&#xff08;前后端要保持一致的喔&#xff09;如果手机是通过usb连接到电脑的&#xff0c;需要执行一下&#xff1a; adb reverse tcp:8080 tcp:8080 AndroidManifest.xml的<application/>节点中加上: android:usesC…...

使用GGML和LangChain在CPU上运行量化的llama2

Meta AI 在本周二发布了最新一代开源大模型 Llama 2。对比于今年 2 月发布的 Llama 1&#xff0c;训练所用的 token 翻了一倍&#xff0c;已经达到了 2 万亿&#xff0c;对于使用大模型最重要的上下文长度限制&#xff0c;Llama 2 也翻了一倍。 在本文&#xff0c;我们将紧跟趋…...

微服务基础理论

微服务简介 微服务Microservices之父&#xff0c;马丁.福勒&#xff0c;对微服务大概的概述如下&#xff1a; 就目前而言&#xff0c;对于微服务业界并没有一个统一的、标准的定义&#xff08;While there is no precise definition of this architectural style ) 。但通在其…...

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...

Prompt Tuning、P-Tuning、Prefix Tuning的区别

一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...

Java如何权衡是使用无序的数组还是有序的数组

在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...

[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?

论文网址&#xff1a;pdf 英文是纯手打的&#xff01;论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误&#xff0c;若有发现欢迎评论指正&#xff01;文章偏向于笔记&#xff0c;谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力

引言&#xff1a; 在人工智能快速发展的浪潮中&#xff0c;快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型&#xff08;LLM&#xff09;。该模型代表着该领域的重大突破&#xff0c;通过独特方式融合思考与非思考…...

浅谈不同二分算法的查找情况

二分算法原理比较简单&#xff0c;但是实际的算法模板却有很多&#xff0c;这一切都源于二分查找问题中的复杂情况和二分算法的边界处理&#xff0c;以下是博主对一些二分算法查找的情况分析。 需要说明的是&#xff0c;以下二分算法都是基于有序序列为升序有序的情况&#xf…...

Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析

Java求职者面试指南&#xff1a;Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问&#xff08;基础概念问题&#xff09; 1. 请解释Spring框架的核心容器是什么&#xff1f;它在Spring中起到什么作用&#xff1f; Spring框架的核心容器是IoC容器&#…...

PHP 8.5 即将发布:管道操作符、强力调试

前不久&#xff0c;PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5&#xff01;作为 PHP 语言的又一次重要迭代&#xff0c;PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是&#xff0c;借助强大的本地开发环境 ServBay&am…...

针对药品仓库的效期管理问题,如何利用WMS系统“破局”

案例&#xff1a; 某医药分销企业&#xff0c;主要经营各类药品的批发与零售。由于药品的特殊性&#xff0c;效期管理至关重要&#xff0c;但该企业一直面临效期问题的困扰。在未使用WMS系统之前&#xff0c;其药品入库、存储、出库等环节的效期管理主要依赖人工记录与检查。库…...

echarts使用graphic强行给图增加一个边框(边框根据自己的图形大小设置)- 适用于无法使用dom的样式

pdf-lib https://blog.csdn.net/Shi_haoliu/article/details/148157624?spm1001.2014.3001.5501 为了完成在pdf中导出echarts图&#xff0c;如果边框加在dom上面&#xff0c;pdf-lib导出svg的时候并不会导出边框&#xff0c;所以只能在echarts图上面加边框 grid的边框是在图里…...