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

news2024/11/24 18:48:29

​生成的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 GPT
  the_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 statement
  withProgress(message = 'Getting results from GPT', value = 0, {  # Add Shiny progress message
  my_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 SQL
  sql_html <- gsub("\n", "<br />", the_gpt_sql) 
  sql_html <- paste0("<p>", sql_html, "</p>") 
​
  # Run SQL on data to get results
  gpt_answer <- sqldf(the_gpt_sql) 
  setProgress(value = 1, message = 'GPT results received') # Send msg to user that 
  })
  # Print SQL and results
  output$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开发工具等

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

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

相关文章

Packet Tracer – 配置动态 NAT

Packet Tracer – 配置动态 NAT 拓扑图 目标 第 1 部分&#xff1a;配置动态 NAT 第 2 部分&#xff1a;验证 NAT 实施 第 1 部分&#xff1a; 配置动态 NAT 步骤 1&#xff1a; 配置允许的流量。 在 R2 上&#xff0c;为 ACL 1 配置一个语句以允许属于 172.16.0.…

【JVM】浅看JVM的运行流程和垃圾回收

1.JVM是什么 JVM&#xff08; Java Virtual Machine&#xff09;就是Java虚拟机。 Java的程序都运行在JVM中。 2.JVM的运行流程 JVM的执行流程&#xff1a; 程序在执行之前先要把java代码转换成字节码&#xff08;class文件&#xff09;&#xff0c;JVM 首先需要把字节码通过…

Visio/PPT/Matlab输出300dpi以上图片【满足标准投稿要求】

1. visio 遵照如下输出选项&#xff0c;另存为tif格式文件时&#xff0c;选择正确输出便是300dpi以上 2. matlab 文件选项选中导出设置&#xff0c;在渲染中选择dpi为600&#xff0c;导出图片即可&#xff0c;科研建议选择tif格式文件 3.ppt 打开注册表&#xff0c;winr键…

【报错】在python3.9环境下安装sqlmap报错

问题描述 报错内容&#xff1a; missing one or more core extensions (‘ssl’, ‘sqlite3’) most likely because current version of Python has been built without appropriate dev packages 原因分析&#xff1a; 缺少一个或多个核心扩展&#xff08;‘ssl’、‘sqlit…

常见的栈溢出StackOverFlow 与 内存溢出OutOfMemory的区别

0、前言&#xff1a;内存模型 对于多线程运行情况下的jvm内存&#xff0c;我们应当知道&#xff1a; 每创建一个线程&#xff0c;jvm就会为其分配一块线程私有的工作内存&#xff0c;其中包括程序计数器、栈&#xff0c;等等。 对于每一个线程私有的栈&#xff0c;当线…

怎么限制文件打开次数、打开时间?

一些公司出于业务需求&#xff0c;可能会给客户或者合作伙伴发一些涉密图纸、文档、文件等重要文件&#xff0c;但是又不想文件被外发泄露随意传播&#xff0c;今天就教大家一个方法限制文件外发后别人打开这个文件的打开次数、打开时间、另存为等操作。 设置方法 本篇文章测试…

page _refcount和_mapcount字段

linux page有两个非常重要的引用计数字段_refcount和_mapcount&#xff0c;都是atomic_t类型&#xff0c;其中&#xff0c;_refcount表示内核中应用该page的次数。当_refcount 0时&#xff0c;表示该page为空闲或者将要被释放。当_refcount > 0&#xff0c;表示该page页面已…

APP-脱壳+反编译

APP反编译加固-自动查壳脱壳 为什么要脱壳&#xff1f; 因为不脱壳无法进行反编译 查壳工具&#xff1a;https://pan.baidu.com/s/1rDfsEvqQwhUmep1UBLUwSQ 密码: wefd 脱壳工具&#xff1a;https://github.com/CodingGay/BlackDex 查壳演示&#xff1a; 使用Java运行jar包&a…

浙江大学软件学院2022保研经历分享

首先&#xff0c;我想强调一点&#xff0c;如果我们只是一个普通的非211&#xff0c;985的本科生&#xff0c;一定要参加浙江大学每年7月份组织的夏令营&#xff0c;因为浙大的夏令营是一个海王营&#xff0c;基本上不会对入营的学生做筛选&#xff0c;但是要想获得优秀营员&am…

pandas笔记:groupby整理

0 数据集 # Visual Python: Data Analysis > File vp_df pd.read_csv(https://raw.githubusercontent.com/visualpython/visualpython/main/visualpython/data/sample_csv/fish.csv) vp_df 1 单列聚合 vp_df.groupby(Type)[Kg].mean()Type mackerel 1.417456 salmon…

【C语言项目】三子棋

文章目录 项目思路一、分文件进行创建二、进入游戏前的目录2.1 目录的功能&#xff1a;2.2 目录界面&#xff1a;2.3 选择进入或退出游戏2.4 多次重玩功能 三、画出棋盘3.1 写出棋子3.2 初始化棋盘3.2 画出棋盘的框架3.3 代码实现 四、玩家落子4.1 落子逻辑4.2具体情况分类讨论…

初识C++(下)——“C++”

各位CSDN的uu们你们好呀&#xff0c;今天终于是小雅兰的初识C的下的文章啦&#xff0c;下面&#xff0c;让我们进入C的世界吧&#xff01;&#xff01;&#xff01; 内联函数 我们首先得知道&#xff1a;C中的内联函数是用来解决C语言中宏的坑的&#xff01;&#xff01;&…

jenkins中配置了发送邮件,构建后却没有发邮件Not sent to the following valid addresse

【问题描述】&#xff1a;jekins中配置了发送邮件&#xff0c;构建后却没有发邮件的问题&#xff0c;构建报错&#xff1a;Not sent to the following valid addresse 【报错显示】&#xff1a; 【问题定位】&#xff1a;Extended E-mail Notification中&#xff0c;没有配置…

【Docker】Docker的使用案例以及未来发展、Docker Hub 服务、环境安全的详细讲解

前言 Docker 是一个开源的应用容器引擎&#xff0c;让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux或Windows操作系统的机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。 &#x1f4d5;作者简介&#xff1a;热…

LabVIEW - 串口通信

1. 题目 使用并行程序设计技术&#xff0c;实现串口通信/TCP通信/UDP通信&#xff08;任选3者一种&#xff0c;其中TCP为客户端&#xff09;数据发送和数据接收功能在各自的线程中实现&#xff0c;即一个线程只管处理数据发送功能的实现&#xff0c;另一个线程只管数据接收和数…

P2698 [USACO12MAR] Flowerpot S

P2698 [USACO12MAR] Flowerpot S 文章目录 P2698 [USACO12MAR] Flowerpot S题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 提示思路分析code [P2698 USACO12MAR] Flowerpot S - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题目描述 Farmer John has been having …

【漏洞复现】厦门才茂通信网关formping远程命令执行漏洞

文章目录 前言声明一、漏洞描述二、漏洞复现 前言 厦门才茂通信网关formping存在远程命令执行漏洞&#xff0c;攻击者可通过特定payload对目标服务器发起攻击&#xff0c;造成不可估量的影响。 声明 请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提…

文心一言 VS 讯飞星火 VS chatgpt (65)-- 算法导论6.5 4题

四、在 MAX-HEAP-INSERT 的第 2行&#xff0c;为什么我们要先把关键字设为 -∞ &#xff0c;然后又将其增加到所需的值呢? 文心一言&#xff1a; 在 MAX-HEAP-INSERT 算法的第二行将关键字设为 -∞&#xff0c;是为了保持堆的性质。堆是一种二叉树结构&#xff0c;其中每个节…

python调用文心千帆大模型

一、登录智能云控制台 https://console.bce.baidu.com/ 二、创建AI应用 已登录状态下&#xff0c;进入控制台创建应用 https://console.bce.baidu.com/ai/#/ai/easydlLiteNlp/app/list 应用创建后获取AppID、API Key、Secret Key 三、API调用 import requests import jso…

uniapp项目集成本地插件

在项目根目录下创建nativeplugins文件夹 拷贝插件到目录nativeplugins 在manifest.json -> App原生插件配置 -> 本地插件里勾选插件 删除本地基座和手机app从新自定义基座运行