我正在使用今年的Advent of Code来学习 Rust——在GitHub Copilot和 OpenAI 的新ChatGPT的帮助下。
我认为大型语言模型最令人兴奋的应用之一是支持自学。如果使用得当,像 GPT-3 这样的语言模型可以充当一种超级聪明和超级愚蠢的助教:你可以问它问题和后续问题,如果你答对了问题它可以真正帮助您为手头的主题建立良好的心理模型。
它也可能产生幻觉,并以一种非常有说服力的方式教给你一些完全脱离现实的东西!
我开始认为他们是某些话题的优秀老师,同时也是其他话题的阴谋论者:你可以与他们进行愉快的交谈,但你需要对他们所说的一切持保留态度。
几个月来,我一直在研究这个想法,主要是通过 GPT-3 Playground 。 ChatGPT 为此提供了一个更好的界面,我准备在一个更大、更结构化的项目中试用它。
学习生锈
几年来,我一直在寻找探索Rust的借口。作为一个主要的 Python 程序员,我的工具箱中缺少的最大工具是更底层的东西——我希望能够自信地切换到更多的系统语言来执行性能关键型任务,同时仍然能够在我的 Python 项目。
Rust 感觉是最好的选择。它有一个非常好的 Python 集成支持,已经在 Python 生态系统中广泛使用(例如,通过密码学包),我尊敬的很多人都使用过它,但后来没有大声表达他们对它的厌恶!
问题是找到合适的项目。我通过构建东西来学习,但是如果我在学习基础知识的同时构建了糟糕的版本,那么我可以想象用 Rust 构建的项目(例如高性能 Web 代理)对我没有用。
Advent of Code证明是完美的选择。
每天你都会得到一个新的练习,旨在在短时间内解决(至少到目前为止)。练习会使用您独有的输入文件自动评分,因此您不能通过复制其他人的答案作弊(尽管您可以通过复制和运行他们的代码来作弊)。
练习设计的太好了! Eric Wastl 已经运行了七年,到目前为止,我对它的工作方式或练习质量印象深刻(我刚刚完成第 5 天)。
对于我学习一门新的编程语言的目标来说,它绝对是完美的。
人工智能辅助学习工具
今年我看到很多人试图通过将问题提供给 AI 模型来解决 Advent of Code。这是一个有趣的练习,但我在这里做的有点不同。
我的目标是对基本的 Rust 足够熟悉,这样我就可以尝试一个更大的项目,而不会觉得我在浪费时间编写无用的糟糕代码。
我还想看看 AI 辅助学习是否真的像我认为的那样有效。
我在这里使用两种工具来帮助我:
- GitHub Copilot在我的 VS 代码编辑器中运行。在过去的几个月里,我主要将它用作打字助手(以及用于编写重复测试之类的东西)。对于这个项目,我将更加依赖它——我正在利用评论驱动的提示,您可以在其中添加代码评论,Copilot 将建议与评论相匹配的代码。
- 聊天GPT 。我将其用作教授/助教/学习伙伴。我问它关于如何使用 Rust 做事的问题,它回答了答案(通常还有一个代码示例)。我也一直在使用它来帮助理解错误消息,事实证明它在这方面非常有效。
和丰富的笔记
我在 GitHub 上的 simonw/advent-of-code-2022-in-rust存储库中公开进行所有这方面的工作。每天都会遇到一个问题,我会在详细的问题评论中记录我从 AI 工具获得的帮助。
到目前为止,这是我的问题线程:
如果您想了解这一切的进展情况,我建议您完整查看每个问题。
来自 ChatGPT 的一些示例
以下是迄今为止我与 ChatGPT 互动的一些亮点:
- 使用“添加解释每一行的注释”使其输出带有极其冗长注释的替换代码示例。
- 粘贴代码和由此产生的 Rust 编译器错误– ChatGPT 清楚地向我解释了错误,并吐出包含修复程序的代码版本!
- 另一个来回对话的例子——我从“在 Rust 中给定两个字符串,识别出现在两个字符串中的字符”开始,然后说“你能在没有 HashSet 的情况下做到这一点吗?”,然后最后要求它“根本没有任何模块”。然后我说“把它变成一个我可以调用的函数”,它也为我写了那个代码。
- 我从我使用的 VS Code 扩展中得到一个错误:“rust-analyzer 未能发现工作区”——所以我将其粘贴到 ChatGPT 中,它为我提供了修复该问题的分步说明。
- 我粘贴了 Copilot 生成的一些粗糙的嵌套代码,ChatGPT提出了一项改进,删除了嵌套,我什至没有问它如何改进这些代码。虽然有趣的是它使用了已弃用的 Rust 语法,但我花了很长时间才弄明白。
- Amos发表了一系列关于今年的 Advent of Code 的文章,他用这些文章来说明 Rust 的高级功能。我偶尔会将他的代码粘贴到 ChatGPT 中,并要求它解释每个概念——在这种特殊情况下,我使用 Copilot 生成问题列表,然后将它们粘贴到 ChatGPT 中以获取答案。
在 Rust 中处理 CLI 参数
我将完整地包括我最近的亮点:
我想向我的 Rust 程序添加命令行参数,所以我询问了 ChatGPT :
我如何编写一个接受命令行选项的 Rust 程序 – 一个必需的位置参数和一个可选的 –multistack 标志?
它回答说:
要编写接受命令行选项的 Rust 程序,您可以使用
clapcrate。首先,将clap添加到您的Cargo.toml文件中,如下所示:[依赖关系] 拍手= “ 2.33.0 ”接下来,导入 crate 并使用它的宏来定义程序接受的命令行参数。例如:
使用clap :: { App , Arg } ; fn主( ) { let matches = App :: new ( "我的程序" ) .参数( Arg :: with_name ( “位置” ) .帮助( “位置参数” ) .必填(真) .索引( 1 ) , ) .参数( Arg :: with_name ( “多堆栈” ) . help ( "启用多个堆栈的标志" ) .长( “多堆栈” ) .短( “米” ) , ) . get_matches ( ) ; // 获取位置参数的值 让位置=匹配。 value_of ( “位置” ) 。展开( ) ; // 检查是否传递了多堆栈标志 让multistack = 匹配。 is_present ( "多堆栈" ) ; }在此示例中,
position参数是必需的,并且必须指定为程序的第一个参数。multistack标志是可选的,可以使用--multistack或-m标志指定。
事情是这样的:我仍在研究 Rust 基础知识,所以我并不是特别想直接跳到为此使用外部依赖项。所以我问了一个后续问题:
有没有办法完全不使用任何外部箱子来做到这一点?
它回答说:
是的,您可以在不使用 Rust 中的任何外部 crate 的情况下解析命令行参数。为此,您可以使用
std::env::args函数,该函数返回传递给程序的参数的迭代器。例如,您可以像这样解析所需的
position参数和可选的multistack标志:使用std :: env ; fn主( ) { // 获取参数作为迭代器 让args : Vec < String > = env :: args ( ) 。收集( ) ; // 确保至少传递了一个参数 如果参数。长度( ) < 2 { 打印! ( “错误:缺少必需的参数‘位置’” ) ; 返回; } // 获取位置参数的值 让position = & args [ 1 ] ; // 检查是否传递了多堆栈标志 让multistack = args 。迭代器( ) 。任意( |arg| arg == "--multistack" || arg == "-m" ) ; }在此示例中,
position参数是必需的,并且必须指定为程序的第一个参数。multistack标志是可选的,可以使用--multistack或-m标志指定。然后,您可以在程序中使用这些参数的值,如图所示。请注意,这种方法没有提供像
clap这样的专用 crate 那样多的功能或便利性,但在某些情况下它可能很有用。
我真的很喜欢这个例子。
我特意设计了我的原始问题,以包含我想做的事情的详细信息——不仅仅是添加 CLI 选项,而是添加一个特定的位置参数和一个特定的标志。
这生成了我需要的确切代码,加上一个非常高质量的散文解释。
然后我用一个后续问题得到了一个完全不同的方法,更符合我的个人品味。自发地,它甚至在最后包含了关于该方法缺点的注释!
副驾驶也是
我没有详细记录我的 Copilot 交互,因为这些在我的编辑器中采用自动完成的形式,很难写下来。
不过,我确实捕获了一些说明性的屏幕截图。一些例子:

我根本不喜欢这个建议——太复杂了。所以我改变了我的评论提示并得到了更好的东西:

事实证明,这种以评论为导向的提示 Copilot 的方法非常有效。我正在学习 Rust 而无需花任何时间查找 – 我正在使用 Copilot 向我展示示例,然后如果我不理解它们,我将它们粘贴到 ChatGPT 中并要求详细解释。
哪里出错了
这个练习的一个有趣的部分是发现哪里出了问题。
Rust不是一门容易学习的语言。有一些概念,比如借用检查器,我什至还没有开始接触,而且我仍然掌握了一些基本概念,比如选项和结果。
大多数情况下,Copilot 和 ChatGPT 能够充当自信的向导——但我时不时地遇到他们假装自信的尖锐边缘,以及他们实际上只是语言模型,并没有真正理解他们的意思是做。
我有一个例子,我因为一个整数溢出错误而越来越沮丧地反复思考了大约一个小时——在使用 ChatGPT 调试失败后,我最终不得不认真思考这个问题!
我还遇到过一个事件,我使用cargo add itertools安装了一个包,然后决定删除它。我就此询问了 ChatGPT ,它自信地向我提供了有关使用cargo remove itertools的说明……结果证明这是一个不存在的命令!它幻觉了那个,然后幻觉了更多的选择,直到我放弃并自己想出来。
那么它在工作吗?
到目前为止,我认为这非常有效。
我觉得我开始对 Rust 的工作原理有了一个很好的心理模型,很多基本语法开始融入我的肌肉记忆中。
真正的考验是我是否能先熬到第 25 天(之前没有 Advent of Code 经验,我不知道增加的难度水平会对我的学习造成多大的干扰),然后我是否真的能写出有用的之后的 Rust 程序无需这些 AI 模型的任何帮助。
老实说,这里的另一大好处是非常有趣。我发现以这种方式与 AI 互动——作为一种实际练习,而不仅仅是尝试它们——是非常令人满意和智力刺激的。
这是道德的吗?
围绕生成 AI 的伦理问题——包括 GPT-3 等大型语言模型和Stable Diffusion 等图像生成模型,仍然是我职业生涯中迄今为止遇到的最复杂的问题。
我相信一件符合道德的事情是尽可能多地学习这些工具,并帮助其他人也理解它们。
将它们用于像这样的个人学习练习对我来说是最好的方法之一。
我喜欢这是一个我可以编写不会包含在产品中或用来赚钱的代码的空间。对于在未经创建者许可的情况下收集的大量数据集上进行训练的模型,我对引导我的 Rust 教育并不感到难过。
(Advent of Code 确实有一个竞争排行榜,看看谁能最快地完成练习。我对在这方面竞争一点兴趣都没有,而且我避免在练习一发布就尝试跳上去。)
我目前对这些模型的道德立场最好概括为承认该技术现在已经存在,并且不能将其放回瓶中。
我们的工作是想办法最大限度地提高其对社会的利益,同时最大限度地减少其造成的危害。
原文: http://simonwillison.net/2022/Dec/5/rust-chatgpt-copilot/#atom-everything