前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >告别手敲 SQL ?GPT-3 自动帮你写

告别手敲 SQL ?GPT-3 自动帮你写

作者头像
AI科技大本营
发布2021-02-05 09:44:28
9270
发布2021-02-05 09:44:28
举报
文章被收录于专栏:AI科技大本营的专栏

作者 | Brian Kane @SeekWell

编译 | 伍杏玲

出品 | AI科技大本营(ID:rgznai100)

【导语】手写业务 SQL 很繁琐?GPT-3来帮你!本文作者通过手动输入简单的英文描述秒 Get 到 SQL 了。听说 AI 又来抢开发者饭碗,一起来看看吧:

作为分析师,我花费大量时间编写 SQL 来回复各类业务问题,如简单的客户查询问题“用户X是否有正确的计划”,评估 KPI,增长指标“上个月有多少用户注册,转换为付费用户的百分比是多少”,预估问题“12 个月内我们将获得多少收入”。

为了让我的工作更轻松,我尽量使用自动化来完成。尽管公司研发一些工具来帮助解决,但需要写 SQL 代码的话用当前工具很难自动化,GPT-3 来救驾!

GPT-3 是一种文本完成引擎,它接受输入的文本并返回它认为接下来会出现的文本。现在已经有很多人使用它根据指定说明来生成 HTML、CSS 等代码。

由于我的大部分工作是写 SQL,所以我希望通过简单的英语描述语句,GPT-3 将这些语句转为 SQL 代码。接着执行该 SQL,等待页面返回结果。

对我来说,GPT-3 Instruct(仍处于beta版)比更通用的 GPT-3 引擎更有效果,GPT-3 Instruct(尤其是davinci-instruct)可让你给出 GPT-3 响应的特定指令。下面我将详细为大家展示下一些示例,其中 gif 里输入问题由我生成,为绿色,GPT-3 将其转换为SQL(由GPT-3生成,为蓝色),我对 GPT-3 说明(黄色)和 GPT-3 示例(橙色)。

这是我给的第一条指令,一个问题以及GPT-3的回复:

说明:给定输入问题,请使用语法正确的 PostgreSQL 进行响应。可以有创新,但 SQL 必须正确

输入:how many users signed up in the past month?

GPT-3:

代码语言:javascript
复制
SELECT COUNT(*) FROM users
WHERE signup_time > now() - interval '1 month'

我没给过数据库架构,但假设我有一个名为“ users”的表,有“ signup_time”时间戳字段用于用户注册,这个符合逻辑。它知道在 PostgreSQL 中从今天的日期减去一个月的正确方法(now()-间隔“ 1个月”)。太酷了!

为了给 GPT-3 提供更多的上下文,我将有关数据库模式的信息添加到指令中。我的新指令:

说明:给定输入问题,请使用语法正确的PostgreSQL进行响应。仅使用“用户”和“收费”的表。“用户”表具有以下列:id(整数),signup_dt(时间戳),电子邮件(字符变化)和plan_type(字符变化)。“费用”表中包含列:金额(bigint),user_id(整数)和charge_dt(时间戳)。

我问另一个问题,看看 GPT-3 是否可以根据实际数据库来响应:

输入:how much revenue did we have in the past 7 days?

GPT-3:

代码语言:javascript
复制
SELECT SUM(amount) FROM charges WHERE charge_dt > now() - interval '7 days'

我向它提供了有关数据库中表和列的更多信息,它正确地推断出“ amount” =“ revenue”,并 SUM()来统计 7 天收费后的金额,我们看到,它已知道一些基本的SQL语法,并推断出我的意思。

用示例启动GPT-3

我想需要通过一个简单的示例来明确告知 GPT-3 表中的列,示例是提供 GPT-3上下文并充实一些细节的好方法,这有助于确定哪些列和表可以使用(GPT-3有时喜欢“发明”列)。这是我添加到提示中的示例:

输入:select all available columns from users table.

输出:

代码语言:javascript
复制
SELECT id, signup_dt, email, plan_type FROM users

输入:select all available columns from charges table.

输出:

代码语言:javascript
复制
SELECT amount, user_id, and charge_dt FROM charges

将这些示例提供给 GPT-3,我将再问一个问题:

输入:what was the largest payment amount made in the past 30 days?

GPT-3:

代码语言:javascript
复制
SELECT MAX(amount) FROM charges WHERE charge_dt > NOW() - INTERVAL '30 days'

它知道使用MAX(金额)来获得最大的付款并正确设置日期条件,没看到有关如何从当前日期减去天数的示例。我们再试试其他的:

输入:when did user with email brian@seekwell.io make his last payment?

GPT-3:

代码语言:javascript
复制
SELECT MAX(charge_dt) FROM charges WHERE user_id = 1 AND email = 'brian@seekwell.io'

不太对,“收费”表中没有电子邮件列,因此该查询将失败。我也从来没有说过电子邮件=“ brian@seekwell.io”的用户的user_id = 1-不知道从何而来。要正确回答该问题,必须将“收费”表与“用户”表结合在一起,因为只有“用户”有电子邮件列。

由于知道在users.id = Charges.user_id上联接这些表是一个大的进步,所以我将给 GPT-3 一个“联接”的示例:

输入:when did jane@seekwell.io make her first payment?

输出:

代码语言:javascript
复制
SELECT MIN(charge_dt) as last_payment_dt from charges LEFT JOIN
users ON users.id = charges.user_id
WHERE users.email = 'jane@seekwell.io'

我再试一次:

输入:when did user with email brian@seekwell.io make his last payment?

GPT-3:

代码语言:javascript
复制
SELECT MAX(charge_dt) as last_payment_dt from charges LEFT JOIN users ON users.id = charges.user_id WHERE users.email = 'brian@seekwell.io'

根据示例,它变得太简单了,它正确地更改了MIN()→MAX()并用我要求的电子邮件替换了该电子邮件。我们尝试另一个难度级别,先加更多示例来提供更多背景信息并改善响应。新的例子:

输入:how many users signed up in the past 30 days?

输出:

代码语言:javascript
复制
SELECT COUNT(*) FROM users WHERE signup_dt >= now() - interval '30 days'

输入:when did user with email brian@seekwell.io sign up?

输出:

代码语言:javascript
复制
SELECT signup_dt FROM users WHERE email = 'brian@seekwell.io'

输入: how much revenue did we have in the past 7 days?

输出:

代码语言:javascript
复制
SELECT SUM(amount) from charges WHERE charge_dt >= now() - interval '7 days'

输入:how much revenue did we have from 10-01-20 through 11-15-20?

输出:

代码语言:javascript
复制
SELECT SUM(case when charge_dt>= '10-01-20'::date and charge_dt < '11-15-20'::date then amount else 0 end) as revenue
FROM charges

输入:how much revenue have we had from users that signed up in the last 6 months?

输出:

代码语言:javascript
复制
SELECT SUM(charges.amount) FROM users INNER JOIN
charges ON users.id = charges.user_id
WHERE users.signup_dt>= now() - interval '6 months'

输入:when did user with email brian@seekwell.io make his first payment?

输出:

代码语言:javascript
复制
SELECT MIN(charge_dt) as last_payment_dt from users INNER JOIN
charges ON users.id = charges.user_id
WHERE users.email = 'brian@seekwell.io'

输入:how many new users signed up in each of the last 2 months?

输出:

代码语言:javascript
复制
SELECT sum(case when signup_dt>= now() - interval '1 month' then 1 else 0 end) as signups_this_month,
sum(case when signup_dt>= now() - interval '2 months' and signup_dt < now() - interval '1 month'  then 1 else 0 end) as signups_last_month
FROM users

这些示例为它提供了一些基本查询,因此它更加熟悉我的数据库以及用例的特定术语和概念(例如,“付费用户”表示其plan_type =“ pro”)。我还介绍了汇总两个日期之间的指标(收入)。我们继续加深难度:

输入:how many payments has user with email joe@freshpizza.com made?

GPT-3:

代码语言:javascript
复制
SELECT COUNT(*) FROM users INNER JOIN  charges ON users.id = charges.user_id WHERE users.email = 'joe@freshpizza.com'

GPT-3认为这里的COUNT()是适当的表达式,知道将“用户”与“收费”表结合在一起,并将电子邮件正确设置为我所询问的电子邮件。GPT-3的另一个问题:

输入:how much revenue have we received from users with an email ending in 'seekwell.io' in the last 3 months?

GPT-3:

代码语言:javascript
复制
SELECT SUM(charges.amount) FROM users INNER JOIN charges ON users.id = charges.user_id WHERE users.email LIKE '%seekwell.io%' AND users.signup_dt>= now() - interval '3 months'

太棒了,它知道将“以seekwell.io结尾的电子邮件”在SQL中转换为“ users.email LIKE'%seekwell.io%'”(即使之前从未见过),并对与此匹配的用户收取了所有费用的总和健康)状况。还有一个:

输入:how much revenue did we have between June 1st and August 1st 2020?

GPT-3:

代码语言:javascript
复制
SELECT SUM(case when charge_dt >= '06-01-2020'::date and charge_dt < '08-01-2020'::date then amount else 0 end) as revenue FROM charges

我已经教过它如何从10-01-20到11-15-20来获取收入,所以它要容易一些,它确实知道将6月1日和8月1日转换为SQL中适当的日期格式('06- 01-2020”和“ 08-01-2020”)。如果它只是用“ 6月1日”和“ 8月1日”替换了我示例中的日期,我它不是在获取日期的概念,只是将模式匹配到最接近的示例。有了这个结果,我可以知道GPT-3至少在某种程度上了解了日期的概念。

将 GPT-3 “玩坏了”

刚才我列举的例子都是关于用户、收入和增长指标等基本问题,GPT-3 处理得很好。现在我想知道有多少用户转换为付费用户:

输入:what percent of users who signed up converted to paid?

GPT-3:

代码语言:javascript
复制
SELECT COUNT() as total_users, COUNT() as total_paid_users, 100.0*(COUNT() as total_paid_users) / COUNT() as total_users AS percent_converted FROM users

这不是我想要的,绝对不是正确的SQL。它不理解“百分比”的概,它仅是 COUNT()并乘以100。我使用“百分比”来试验下:

输入:what percent of users have an email ending in 'gmail.com'?

输出:

代码语言:javascript
复制
SELECT SUM(CASE WHEN email like '%gmail.com' then 1 else 0 end)/COUNT(*) as percent_gmail
FROM users

当我尝试相同的问题时,我得到:

输入:what percent of users who signed up converted to paid?

GPT-3:

代码语言:javascript
复制
SELECT SUM(CASE WHEN plan_type = 'pro' THEN 1 else 0 end)/COUNT(*) as percent_paid FROM users

整洁多了,它知道将plan_type ='pro'的用户数除以用户总数即可得到我要求的百分比。我还可以向部分用户(例如最近6个月内注册的用户)询问相同的问题,并获得准确的答复:

输入:what percent of users that signed up in the past 6 months converted to paid?

GPT-3:

代码语言:javascript
复制
SELECT SUM(CASE WHEN plan_type='pro' THEN 1 ELSE 0 END)/COUNT(*) AS percent_paid FROM users WHERE users.signup_dt>= now() - interval '6 months'

调整 GPT-3 的参数

除了给GPT-3提供指导和示例外,还可以调整参数来提高 GPT-3 的有效性。其中关键要素是“Temperature”,它转化为GPT-3在响应中包含多少随机性。如果只需要最高的概率响应(即无随机性),则将 Temperature 设置为0。

以“最近两个月的每个月我们有多少收入?”提示为例,将Temperature 设置为.8的话:

输入: how much revenue did we have in each of the last 2 months?

Temperature为.8时 GPT-3:

代码语言:javascript
复制
SELECT SUM(case when charge_dt>= now() - interval '1 month'  then charges.amount else 0 end) as revenue_this_month, CASE WHEN signup_dt>= now() - interval '2 months' AND signup_dt < now() - interval '1 month' THEN SUM(charges.amount) else 0 end as revenue_last_month FROM charges  LEFT OUTER JOIN users ON users.id = charges.user_id \ WHERE users.signup_dt >= now() - interval '1 month'

将Temperature 设置为较低的.3,可提供一个有效的查询,并回答以下问题:

输入:how much revenue did we have in each of the last 2 months?

Temperature为.3时 GPT-3:

代码语言:javascript
复制
SELECT SUM(case when charge_dt>= now() - interval '1 month' then amount else 0 end) as revenue_this_month, SUM(case when charge_dt>= now() - interval '2 months' and charge_dt < now() - interval '1 month' then amount else 0 end) as revenue_last_month FROM charges

更高的Temperature 让 GPT-3 变得更具“创造力”,但也使它过于复杂并给出了几乎没有意义的响应。Temperature 设置为.3,响应将问题正确转换为SQL。

根据我的经验,如果你问的问题遵循的是示例所建立的模式,则较低的Temperature往往会表现得更好。但是,如果您要问一些需要更多创造力的问题,则更高的Temperature是最佳选择,因为GPT-3更有可能尝试未明确教导的事情。

在下面的案例中,我问:“过去6个月内注册的用户给我们带来了多少收入?” (从我的示例中删除之后)。在较低的Temperature下,GPT-3尝试在“ charges”表中创建一个“ signup_dt”列,因此不必将“ users”表和“ charges”表连接在一起。随着 Temperature 的升高,它确实加入了,这是Temperature设置为.8的响应:

输入:how much revenue have we had from users that signed up in the last 6 months?

Temperature为.8时 GPT-3:

代码语言:javascript
复制
SELECT SUM(charges.amount) FROM users INNER JOIN charges ON users.id = charges.user_id WHERE signup_dt >= DATE_SUB(now(), INTERVAL '6 months')

可以肯定的是,“ DATE_SUB(now(),INTERVAL'6 months')”不是一个有效的Postgres表达式,因此该查询在技术上将失败。但是从结构上讲,它通过加入“ charges”和“ users”而处于正确的道路上,因此可以以“ signup_dt”为条件。同时,使用“ charges”表中实际上不存在的“ signup_dt”列,.Temperature设置为.2时响应完全不正确:

输入:how much revenue have we had from users that signed up in the last 6 months?

Temperature为.2时 GPT-3:

代码语言:javascript
复制
SELECT SUM(CASE WHEN signup_dt >= now() - interval '6 months' THEN amount ELSE 0 END) AS revenue FROM charges

结论

GPT-3 实例会根据简单的英语问题,将其转换为数据库真正有效的SQL。它不总是完美,对“增长率”或“百分比”等复杂的概念仍然需要一些人工帮助,但是它对我的日常工作是有用,对于简单的SQL,GPT-3 能帮忙减轻我的负担,并且对于不熟悉 SQL 语法的初学者很有用。

这个项目的代码传送门:https://github.com/bkane1/gpt3-instruct-sandbox

原文链接:https://blog.seekwell.io/gpt3

本文为AI科技大本营翻译,转载请注明来源出处。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-01-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 AI科技大本营 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 用示例启动GPT-3
  • 将 GPT-3 “玩坏了”
  • 调整 GPT-3 的参数
  • 结论
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档