作为分析师,我花费大量时间编写SQL(或其他代码)来回答有关我们业务的问题。这些问题的范围从简单的客户支持查询(用户X是否有正确的计划?)到评估KPI和增长指标(最近有多少用户注册)月份,转换为已付费的百分比是多少?)改为开放式(12个月后我们将获得多少收入?)。
为了使我的工作更轻松,我尝试使所有这些问题尽可能自动化。我的公司SeekWell构建了出色的工具来帮助解决此问题,例如统一的团队SQL存储库以及对查询,报告和警报的无缝调度。但是,许多事情(如实际编写SQL代码)很难自动化,或者至少已经自动化了。
Openai的GPT-3开始打破传统的观念,即可以自动执行哪些任务。从最基本的角度来看,GPT-3是一种文本完成引擎,在大量互联网上进行了培训。它接受输入的文本并返回它认为接下来会出现的文本。许多人已经使用它根据特定的设计说明生成HTML和CSS代码。其他人则在一些由GPT-3生成的流行趋势博客帖子中排名第一,并带有一些创意提示。
就我而言,由于我的大部分工作是写SQL,所以我希望能够用简单的英语描述一个问题,并让GPT-3将其转换为SQL代码,如果在我的Postgres数据库上执行该代码,它将回答该问题。
为此,我发现使用GPT-3 Instruct(仍处于beta版)比更通用的GPT-3引擎取得了更大的成功。 GPT-3 Instruct(尤其是davinci-instruct)可让您给出具体说明,例如“仅以正确的SQL语法进行响应”,以指导GPT-3的响应。如果您想尝试一下,可以在此处注册GPT-3 API的候补名单。
下面,我将详细介绍我在API方面的经验。在每个示例中,我都会向GPT-3提问。 gif下方是输入问题(由我生成,为绿色)和GPT-3的响应,将其转换为SQL(由GPT-3生成,为蓝色)。我还将包括我对GPT-3的说明(黄色)和示例我为GPT-3提供的示例(橙色)。
说明:给定输入问题,请使用语法正确的PostgreSQL进行响应。有创造力,但SQL必须正确。
哇。我从未提供过数据库架构,但假设我有一个名为" users"的表。 (这是准确的),并且有一个名为" signup_time"的时间戳字段。用户何时注册。很合逻辑。它也知道在PostgreSQL中从今天的日期减去一个月的正确方法(now()-间隔1个月),而没有看到示例。太酷了!
为了给GPT-3提供更多的上下文,我将在指令中添加有关我的数据库模式的信息。我的新指令:
说明:给定输入问题,请使用语法正确的PostgreSQL进行响应。有创造力,但SQL必须正确。仅使用称为" users"的表和" charges ##。用户"该表具有以下列:ID(整数),signup_dt(时间戳),电子邮件(字符变化)和plan_type(字符变化)。费用"该表具有以下列:数量(bigint),用户ID(整数)和费用_dt(时间戳)。
现在,我将尝试问另一个问题,并查看GPT-3是否可以根据我的实际数据库进行响应:
真好我向它提供了有关数据库中表和列的更多信息,它正确地推断出" amount" ="收入"并向SUM()知道过去7天的收费金额以回答问题。显然,它已经知道一些基本的SQL语法,并且可以推断出我的意思。
我将尝试另一个问题,但首先可能需要通过一个简单的示例将GPT-3明确地告知表中的列。示例是提供GPT-3上下文并充实一些细微之处的好方法,这些细微之处在一条指令中可能并不明显。我发现这确实有助于真正确定哪些列和表可以使用(GPT-3有时喜欢“发明”列以使回答问题更加容易)。这是我添加到提示中的示例:
输入:从用户表中选择所有可用列。输出:SELECT ID,signup_dt,电子邮件,plan_type来自用户
输入:从费用表中选择所有可用列。输出:SELECT费用,user_id和charge_dt FROM费用
它知道使用MAX(金额)来获得最大的付款并正确设置日期条件,而没有看到有关如何从当前日期减去天数的示例。效果不错,但现在使用相同的说明和示例尝试一些棘手的事情:
好吧,不太正确。费用"表没有用于电子邮件的列,因此此查询将失败。我也从未说过电子邮件=" [email protected]"的用户。的user_id = 1-不知道它是从哪里得到的。要正确回答问题,您必须加入" charges"与用户的表因为只有" users"有一个电子邮件列。
由于知道如何在users.id = charges.user_id上联接这些表是一个巨大的飞跃(即使对于人工分析人员来说似乎很合乎逻辑),因此我将为GPT-3提供一个示例34; join"所以它有一些不足之处:
输入:简@ seekwell.io何时付款?输出:从LEFT JOINusers个用户上的费用中,作为last_payment_dt的SELECT MIN(charge_dt)SELECT MIN(charge_dt)用户。
GPT-3响应:从LEFT JOIN用户上的用户中,向用户收取费用中的last_payment_dt选择MAX(charge_dt)MAX.charge = user.id where where users.email =' [email protected]'
因此,根据示例来看,这可能会使它变得太简单了,但是它正确地更改了MIN()→MAX()并用我要求的电子邮件替换了该电子邮件,因此这不是一个总的给我。让我们尝试另一个难度级别,但首先,我将添加更多示例以提供更多背景信息并改善响应。新的例子:
输入:过去30天内有多少用户注册?输出:在用户signup_dt> = now()-间隔' 30天'中从用户中选择COUNT(*)个
输入:使用电子邮件[email protected]的用户何时注册?输出:从用户所在的地方SELECT signup_dt电子邮件=' [email protected]'
输入:过去7天我们有多少收入?输出:从charge_dt> = now()-间隔' 7天'中的费用中选择SELECT SUM(金额)
输入:从10-01-20到11-15-20,我们有多少收入?输出:SELECT SUM(在charge_dt> =' 10-01-20' :: date和charge_dt<' 11-15-20':date然后金额为0结束的情况下)作为收入从收费
输入:过去6个月内注册的用户给我们带来了多少收入?输出:来自用户的SELECT SUM(charges.amount)INNER JOIN对users收费。id= charges.user_idWHERE users.signup_dt> = now()-间隔' 6个月'
输入:使用电子邮件[email protected]的用户什么时候付款?输出:SELECT MIN(charge_dt)作为用户的last_payment_dt INNER JOIN向用户收费。id= charges.user_idWHERE users.email =' [email protected]'
输入:最近2个月中,每年有多少新用户注册?输出:SELECT sum(case signup_dt> = now()-间隔' 1个月'然后1 else 0结束)作为signupsthis_month,sum(case case signup_dt> = now()-间隔' 2 months'和signup_dt< now()-间隔' 1个月'然后1其他0结束)作为signups_last_monthFROM用户
这些示例提供了一些基本查询,因此更加熟悉我的数据库以及用例的特定术语和概念(例如,“付费用户”表示他们的plan_type =" pro& #34;)。我还介绍了一些更高级的概念,例如汇总两个日期之间的指标(收入)。现在,我将更加努力:
GPT-3响应:从用户SELECT COUNT(*)通过INNER JOIN向用户收费。id= charges.user_id,其中users.email =' [email protected]'
凉! GPT-3认为COUNT()是此处的适当表达式,知道要加入" users"与"表格,然后将电子邮件正确设置为我询问的电子邮件。 GPT-3的另一个问题:
输入:我们收到了多少以电子邮件结尾的用户收入? seekwell.io'最近3个月内?
GPT-3响应:从用户中选择SELECT SUM(charges.amount),INNER JOIN对users.id = Charges.user_id,在哪里收取费用。向LIKE'%seekwell.io%'发送电子邮件AND users.signup_dt> = now()-间隔' 3个月'
完善!它知道"电子邮件以seekwell.io结尾。用SQL转换为" users。给LIKE'%seekwell.io%'发送电子邮件" (即使以前没有看到过),并为满足该条件的用户收取了所有费用的总和。还有一个:
GPT-3响应:SELECT SUM(在charge_dt> =' 06-01-2020' :: date和charge_dt<' 08-01-2020':date然后金额否则0结束)作为收费收入
这有点容易,因为我已经教过它如何从10-01-20到11-15-20来获取收入,但是它确实知道将6月1日和8月1日转换为SQL中适当的日期格式(&#39 ; 06-01-2020'和' 08-01-2020')。如果它只是将我示例中的日期替换为" June 1st"和" 8月1日"然后我知道它没有得到日期的概念,而只是将模式匹配到最接近的示例。有了这个结果,我可以知道GPT-3至少在某种程度上了解了日期的概念。
到目前为止,我一直在询问有关用户,收入和增长指标的基本问题,而GPT-3一直很好地处理了这些问题。因此,让它更具挑战性。我想知道有多少用户转换为付费用户。 GPT-3,您可以:
GPT-3响应:SELECT COUNT()作为total_users,COUNT()作为total_paid_users,100.0 *(COUNT()作为total_paid_users)/ COUNT()作为total_users AS percent_converted from users
好的,不是我想要的,绝对不是正确的SQL。我不认为它真正理解" percent"的概念,只是它涉及COUNT()并乘以100。我将添加一个实现该概念的示例,看看是否有GPT -3可以赶上。我的新示例使用" percent&#34 ;:
输入:有百分之几的用户拥有以'结尾的电子邮件gmail.com&#39 ;?输出:SELECT SUM(以%_gmailFROM用户身份使用COUNT&*(*电子邮件),例如'%gmail.com'然后1个其他0结束的邮件)
GPT-3响应:SELECT SUM(在plan_type =' pro' THEN 1 else 0 end的情况下)/ COUNT(*)作为percent_paid FROM用户
干净得多。它知道使用plan_type =' pro'划分用户数量。通过用户总数来获得我要求的百分比。我还可以向部分用户(例如最近6个月内注册的用户)询问相同的问题,并获得准确的答复:
输入:过去6个月内注册的用户中有多少转换为付费用户?
GPT-3响应:SELECT SUM(在plan_type =' pro' THEN 1 ELSE 0 END的情况下)/ COUNT(*)从用户WHERE users.signup_dt> = now()-间隔' 6个月
除了给GPT-3提供指导和一些示例外,还可以调整一些参数来提高GPT-3的有效性。重要的是"温度"这实质上就是GPT-3在响应中包含了多少随机性。如果您只想获得最高的概率响应(即无随机性),则可以将温度设置为0。
例如,(有些棘手)提示,"最近两个月的每个月我们有多少收入?"。将温度设置为.8会给您完全荒谬的东西:
.8温度响应GPT-3响应:SELECT SUM(在charge_dt> = now()-间隔' 1个月'然后charge.amount否则为0结束的情况下)作为Revenue_this_month,当case sign_dt> = now()时-间隔' 2个月' AND signup_dt< now()-间隔' 1个月' THEN SUM(charges.amount)否则为0,作为Revenue_last_month FROM在用户上向LEFT OUTER JOIN个用户收取费用。id= charges.user_id \ WHERE users.signup_dt> = now()-间隔' 1个月'
同时,将温度设置为较低的.3可以为您提供一个有效的查询,可以回答以下问题:
.3温度GPT-3响应:SELECT SUM(在charge_dt> = now()的情况下-间隔' 1个月'然后数量0结束的情况)作为Revenue_this_month,SUM(在charge_dt> = now(now的情况下)-间隔' 2个月'和charge_dt< now()-间隔' 1个月'然后金额不为0的结束时间)作为Revenue_last_month FROM费用
使用以前未曾见过的表达式和技术,更高温度的GPT-3更具创造力,但也使它过于复杂并给出了几乎没有意义的响应。另一方面,.3温度响应将问题正确转换为SQL。
以我的经验,如果您要问一个遵循示例已建立的模式的问题,则凉爽的温度往往会表现得更好。但是,如果您要问一些需要更多创造力的问题,则更高的温度是最佳选择,因为GPT-3更有可能尝试未明确教导的事情。
在下面的情况下,我问"在过去6个月内,我们从注册用户中获得了多少收入? (从我的示例中删除之后)。在较低的温度下,GPT-3尝试发明了一种" signup_dt" “费用”列中的“表格,因此不必加入用户。和" charges ##;表在一起。随着温度的升高,它确实加入了它们,这对于正确回答这个问题是必要的。这是.8温度响应:
输入:过去6个月内注册的用户给我们带来了多少收入?
.8温度GPT-3响应:来自用户的SELECT SUM(charges.amount)INNER JOIN对用户收费。id= charges.user_id WHERE signup_dt> = DATE_SUB(now(),INTERVAL' 6个月')
可以肯定的是," DATE_SUB(now(),INTERVAL' 6个月')"不是有效的Postgres表达式(温度较高的缺点之一是它会尝试无法正常工作的东西),因此该查询在技术上会失败。但是从结构上讲,通过加入Charges#34;可以走上正确的道路和" users"因此它可以以" signup_dt"为条件。同时,在使用" signup_dt"时,.2温度响应完全不准确。 “费用”中实际上不存在的列表:
输入:过去6个月内注册的用户给我们带来了多少收入?
.2温度GPT-3响应:SELECT SUM(当signup_dt> = now()-间隔' 6个月,然后数量0结束的情况下)作为收费收入
现在,我有了一个GPT-3实例,该实例可以回答一个简单的英语问题,并将其转换为对我的数据库真正有效的SQL。它并不总是完美的,对于诸如“增长率”之类的更复杂的概念仍然需要一些帮助。或"%"但这绝对有用。现在,当我有一个关于数据库的简单问题需要解决时,我可以节省一些时间,而又不想自己编写SQL。
甚至只是GPT-3知道SQL概念(例如从日期中增加或减去日期间隔)的事实(而没有首先看到它的示例),也意味着它对于不熟悉SQL语法的初学者很有用。只是问一下GPT-3,您如何从SQL中的今天起减去30天?似乎比谷歌搜索或阅读文档容易。
至于根据GPT-3获得的答案实际采取的行动,就目前而言,这仍然是一项艰巨的工作。
快速插接:我们目前正在为SeekWell客户测试一项功能,该功能使用GPT-3自动根据您的数据库架构定制的简单英语生成SQL。如果您有兴趣尝试此操作,请通过[email protected]与我们联系。