共计 4961 个字符,预计需要花费 13 分钟才能阅读完成。
Copilot 是 Github 推出的一款人工智能编程助手,推出仅一年就受到大量开发者的追捧(据官网统计有 120 万用户)。然而,自 2022 年 6 月起,它改为了付费订阅模式(每月 10 美元或每年 100 美元)。
咱们暂且不探讨训练代码可能波及的版权及受权许可问题,能够必定的是,利用机器学习训练出智能编程 AI 模型,这会是将来的大势所趋!
偶合的是,仅在 Copilot 发表免费的几天后,Amazon 就推出了一款竞品 CodeWhisperer!置信在不久的未来,相似的产品会如雨后春笋般涌现,到那时,程序员和编程学习者们就更加有福了!
作者:Brian Tarbox
译者:豌豆花下猫 @Python 猫
英文:https://blog.symops.com/2022/…
转载请保留作者 & 译者 & 起源信息
代码补全最早呈现在 1985 年的一个名为 Alice 的 Pascal 编辑器上。它反对主动缩进、主动补全 BEGIN/END 控制结构,甚至反对语法着色。
争议也随之而来:在 Alice 的晚期,人们放心代码补全使得编写软件过于简略。但它实际上只是一个语法助手。
代码补全能够帮你写出语法正确的、可编译的代码,但它不能帮你写出语义正确的代码,甚至不能写出任何有用的代码。
GitHub 的 CoPilot 和 Amazon 的 CodeWhisperer 扭转了这一点,它们除了提供语法辅助,还能生成语义上正确的代码。它们不仅能提供 if 语句的纲要,还能创立出残缺的代码样例。
但在 2022 年,一个代码辅助工具到底能好到什么水平呢?
本文将重点介绍 CodeWhisperer,尝试答复这个问题。
试用:用 Python 从 S3 读取数据
亚马逊在 2022 年 6 月公布了 CodeWhisperer 预览版,当初它反对 Python、Java 和 JavaScript。
Python 猫注:截至 2022 年 9 月 17 日,这个服务还未全面凋谢。
若要试用,可在官网申请:https://pages.awscloud.com/co…
附官网介绍:https://aws.amazon.com/cn/blo…
在 AWS 博客的一篇文章中,Mark Richman 解释说,CodeWhisperer 的模型是在“包含 Amazon 开源代码在内的各种数据源”上训练的。有了这个语料库(显然的确存在)欠缺 CodeWhisperer 的模型,编写从 S3 读取文件的代码应该是一个很好的测试用例。
在应用 CodeWhisperer(CW)时,你须要写一个正文,形容你心愿函数去做什么。正文的描述性和准确性越高,零碎就越能更好地推断出你想要的逻辑。
Function to open an S3 file
正文以 Function 结尾,让 CW 晓得你想要创立一个函数。也就是说,你须要增加一个正文,作为给 CW 的提醒。
CW 剖析正文并生成一个函数的定义。此时,你能够在生成函数体之前批改函数定义。CW 还可能提供多种函数定义供你抉择。
IntelliJ 集成 CodeWhisperer 的截图
点击“插入代码”,你的函数就在正文的下方创立好了。留神 CodeWhisperer 不仅插入了代码,还创立了一个文档字符串。
# Function to open an S3 file
def open_s3_file(filename):
"""
:param filename:
:return:
"""s3 = boto3.resource('s3')
return s3.Object(bucket, filename).get()['Body'].read()
看起来不错!这段代码实现了你的正文所冀望的性能,并且是在几秒钟内就生成了。节俭了查找 boto3
API 的工夫,你只须要查看代码,确保语义正确。
接着看看提出更多要求时,会产生什么。
这有一个很有用的例子:写一个函数从 S3 的文件中返回前“n”行。
# Function to get first n lines from a file in S3
def get_first_n_lines_from_s3(filename, n):
"""
Get the first n lines of a file in S3
:param filename:
:param n:
:return:
"""
lines = []
for line in open_s3_file(filename):
lines.append(line)
if len(lines) >= n:
break
return lines
真厉害!CodeWhisperer 应用了之前创立的辅助办法 open_s3_file,并生成了正确的函数。
在 CW 生成函数体之前,你能够批改参数名,进步代码的可读性。例如,如果咱们输出:
# Function to find common elements in lists
CW 会提醒:
def find_common_elements(list1, list2)
在生成函数体之前,咱们能够批改函数定义,使其更具描述性:
def find_common_elements(first, second)
如果咱们承受它的函数定义,CodeWhisperer 将应用函数签名和正文来构建函数体。失去的函数将应用改良后的参数名。
# Function to find common elements in lists
def find_common_elements(first, second):
return list(set(first) & set(second))
CodeWhisperer 不仅仅能够创立整个函数;它还能够在函数中插入代码片段,并在过程中推断相干变量。
# reverse the list order
lines.reverse()
CodeWhisperer 是一个重要的生产力助推器
应用 CodeWhisperer,我可能更快地编写代码。到目前为止,最大的价值是 S3 示例所演示的性能。
如果我本人写代码,大部分工夫将会用来查找 boto API 文档,以确保写出正确的调用。应用 CodeWhisperer,则只需三秒钟。
这让我想到了一段曾花了很多工夫的烦人代码:给 CloudWatch 发送数据。让咱们看看 CodeWhisperer 是否有所帮忙,试试提供正文:“Function to emit a CloudWatch metric”。
# Function to emit a cloudwatch metric
def put_metric_data(metric_name, metric_data):
"""
Put a metric data into cloudwatch
:param metric_name:
:param metric_data:
:return:
"""cloudwatch = boto3.client('cloudwatch')
cloudwatch.put_metric_data(
Namespace='my_namespace',
MetricData=[
{
'MetricName': metric_name,
'Dimensions': [
{
'Name': 'string',
'Value': 'string'
},
],
'Unit': 'Seconds',
'Value': metric_data
},
]
)
十分有用!CW 为我节俭了许多打字和查阅 API 文档的工夫。
我有可能须要重构这段代码,但即便我从零开始编写它,第一步也要写出相似这样的原始逻辑。现在只花三秒钟,我节俭了编写大量样板代码的工夫,有了一个很好的自定义或重构的终点。
那么 CodeWhisperer 是一个比我更好的程序员吗?
只管有一丝题目党,但 CW 的代码是否比我的好,这并不重要。重要的是,它能够为我节俭大量的工夫和精力,让我可能专一于改良、重构和测试。
它通过承当一些同质化的沉重工作,让我有机会成为一个更好的程序员。
下面的例子是 Amazon 工具(通过 Amazon 开源代码训练)可能表现出色的例子。当然,在大多数开发人员须要破费很多工夫的中央,比方编写畛域相干的逻辑时,CW 兴许不会十分有用。让咱们看看 CW 会出什么问题。
咱们能够从 Python 文档中的数据类示例开始。
@dataclass
class InventoryItem:
"""Class for keeping track of an item in inventory."""
name: str
unit_price: float
quantity_on_hand: int = 0
def total_cost(self) -> float:
return self.unit_price * self.quantity_on_hand
我想晓得 CodeWhisperer 是否能够向这个类增加一个办法。让咱们看看如果增加正文:” Function that return this item costs more than $10″,会产生什么?
@dataclass
class InventoryItem:
"""Class for keeping track of an item in inventory."""
name: str
unit_price: float
quantity_on_hand: int = 0
def total_cost(self) -> float:
return self.unit_price * self.quantity_on_hand
# Function that returns whether this item costs more than $10
def expensive(self) -> bool:
return self.unit_price > 10
十分酷。值得注意的是,CW 给函数起了一个直观的名字,并蕴含了对 self 的援用。
接着,让咱们尝试用 CW 来做测试,看是否会涉及它的极限。
# Function to test InventoryItem class
def test_inventory_item():
"""
Test InventoryItem class
:return:
"""item = InventoryItem("Widget", 10, 5)
assert item.name == "Widget"
assert item.unit_price == 10
assert item.quantity_on_hand == 5
assert item.total_cost() == 50
assert not item.expensive()
🤯哇!在下面的代码中,我输出了正文,CW 主动实现了剩下的工作。
测试仿佛是一个极好的证实 CW 能够节省时间的例子。我不须要浪费时间去想测试的值,也不必输出所有的成员变量和办法。
CodeWhisperer 的局限性
它当初还处于初级阶段,还有很多问题。
钻研人员发现,GitHub CoPilot 生成的代码有 40% 存在安全漏洞。
CodeWhisperer 还没有这类的统计数据,但 AWS 仿佛强调了对安全性的关注。
据我测试,在一些例子中,CW 生成的函数有 bug,或者后果没有合乎我的用意。
下方的例子应该返回两个文件中最长的公共行,但它只返回了第一个匹配的行:
# Function to find the longest common line in two files
def find_longest_common_line(file1, file2):
"""
Find the longest common line in two files
:param file1:
:param file2:
:return:
"""with open(file1,'r') as f1:
with open(file2, 'r') as f2:
for line in f1:
if line in f2:
return line
CW 还呈现了其它问题,起因是它没有足够的上下文来了解我的用意。通过反思,我感觉如果四周的代码构造很好的话,也是能够实现的。
如果你在设计代码时用了精确示意畛域的名词,那么,在给出了良好正文的前提下,很容易设想 CW 可能创立出特定于畛域的逻辑。至于 bug,未来必定会失去改善的。
写在最初
如果你尝试应用 CW,它可能会让你设想:可能有一天,有人会写出历史上最初一行由人类编写的代码。
在那之前,CW 能够帮忙你成为一个更好的程序员,这样即便世界上最初一个程序员是你,人类的最初一行代码也不会有 bug。
本文首发于 Python 猫 ,未经许可,请勿转载
知乎:Python 猫
博客园:豌豆花下猫
掘金:豌豆花下猫
CSDN:Python 猫