admin管理员组

文章数量:1607685

本文是Nicholas Carlini撰写的文章“How I Use AI”,主要介绍了作者在使用AI辅助编程和开发过程中的具体方法和技巧。以下是文章的核心内容提炼:

  1. AI在编程中的应用
    • AI助手辅助:描述了一个具体的场景,即用户通过AI助手解决在Ubuntu系统上运行Docker容器时遇到的sudo权限问题。
    • 问题解决流程:AI助手建议将用户添加到Docker组以避免sudo,详细步骤包括使用sudo usermod -aG docker your-username命令并验证。
  2. 安全性与权限管理
    • 安全考量:强调了将用户添加到Docker组的安全隐患,特别是在多用户系统中。
    • 最小化sudo使用:提出了一种替代方案,即将程序拆分为两部分,一部分需要sudo权限处理特权操作,另一部分处理非特权操作。
    • 安全实践:介绍了使用newgrp docker和配置sudo无需密码的具体方法,以提高效率和安全性。
  3. Docker的替代方案
    • Podman介绍:介绍了Podman作为Docker的替代方案,特别是其无需sudo即可运行容器的特性。
    • Rootless Docker:说明了Docker也可以配置为rootless模式,以降低安全风险。
    • Buildah功能:介绍了Buildah用于构建OCI容器镜像的脚本化方法,并可与Podman配合使用。
  4. 工具选择与适用性
    • 工具比较:比较了Podman、Rootless Docker和Buildah在功能、安全性和易用性方面的差异。
    • 推荐依据:根据具体需求(如需要替代Docker、避免sudo或进行镜像构建)推荐最合适的工具。
  5. AI在自动化中的作用
    • 自动化脚本:AI在帮助创建和优化自动化脚本方面的潜力,通过自动化减少人工操作和潜在错误。
    • 效率提升:讨论了AI如何通过分析历史数据和用户习惯来优化开发流程和代码质量。
  6. 持续学习与反馈
    • AI的迭代改进:强调了AI工具需要不断学习和适应用户的新需求和行为模式。
    • 用户反馈机制:介绍了通过用户反馈来改进AI工具的重要性,并讨论了如何有效地收集和利用这些反馈。
  7. 未来展望
    • AI编程的未来:探讨了AI在编程领域的潜在应用和发展方向,如更智能的代码补全、自动化测试等。
    • 人机协作模式:预测了未来开发者与AI工具之间可能形成的新型协作模式。

最后,文章通过具体的实例和详细的步骤展示了AI如何在实际开发中帮助用户解决问题、提高效率和保障安全。这些经验和技巧对于任何希望在开发过程中引入AI辅助的开发者都具有重要的参考价值。
 

原文地址:

How I Use "AI"

我不认为“AI”模型(这里指的是大型语言模型)被过度炒作了。

确实,任何新技术都会吸引骗子。而且,很多公司都喜欢说他们正在“使用AI”,就像他们之前说他们的技术是由“区块链”驱动的一样。(我们已经一次又一次地看到了这种情况。)我们也可能正处于一个泡沫之中。互联网在2000年是一个泡沫,但我们现在拥有的互联网应用以前只是字面意义上的科幻小说里的东西。

但我认为我们最近取得的进步不仅仅是炒作的原因是,在过去的一年里,我每周都至少花几个小时与各种大型语言模型进行交互,并且我一直对它们解决我给出的越来越困难的任务的能力印象深刻。因此,我可以说,由于这些模型,我在编写研究项目和副业项目的代码时,速度至少提高了50%。

我发现,在网上谈论大型语言模型(LLM)效用的人要么极度乐观,声称所有工作都会在三年内自动化,要么极度悲观,说它们没有贡献,也永远不会有贡献。

所以,在这篇文章中,我只是想尝试把对话落到实处。我不会对未来会怎样做任何争论。我只想提供一个列表,列出我与不同的大型语言模型进行的50次对话,这些对话有意义地提高了我进行研究的能力,并帮助我在随机的编码副业项目上工作。其中包括:

使用我从未用过的技术构建整个web应用程序。
教我如何使用各种以前从未使用过的框架。
将数十个程序转换为C或Rust,以提高10-100倍的性能。
修剪大型代码库,以显著简化项目。
为我过去一年写的几乎每一篇研究论文编写初始实验代码。
自动化几乎所有单调的任务或一次性脚本。
几乎完全取代了帮助我设置和配置新软件包或项目的网络搜索。
在帮助我调试错误消息方面,大约50%取代了网络搜索。
如果我要将这些例子分为两大类,它们将是“帮助我学习”和“自动化枯燥的任务”。帮助我学习显然是重要的,因为它意味着我现在可以做我以前会觉得具有挑战性的事情;但自动化枯燥的任务(对我来说)实际上同样重要,因为它让我可以专注于我最擅长的事情,并解决难题。

最重要的是,这些例子是我实际使用LLM来帮助我的真实方式。它们不是为了展示一些令人印象深刻的能力;它们来自于我需要完成实际工作的需求。这意味着这些例子并不华丽,但我每天做的大部分工作都不是,而今天可用的LLM让我可以自动化几乎所有这样的工作。

我在这篇文章中的希望是,通过一个又一个的例子,让你筋疲力尽,了解我在过去一年中如何使用LLM来提高我的生产力。只要知道,在你对我提供的例子感到厌烦之后,我只向你展示了不到2%的我使用LLM来帮助我的情况。

所以,当你感到厌倦时——你一定会的——请随意使用左侧的新导航菜单,这是我(读作:一个LLM)专门为这篇文章写的新菜单,因为它太长了。

微妙之处

如果互联网有一件事做得不好,那就是微妙之处。我不会声称今天的LLM将要接管世界。我不会谈论未来的模型可能或不可能做什么。我只会讨论今天的模型对我来说是否有用。

你可能会想——为什么有人会写一篇整篇文章来证明语言模型是有用的呢?!这不是显而易见的吗?!但似乎有一大群人——在学术文献中,在软件工程领域,以及在媒体领域——他们广泛宣称LLM没有贡献,只是另一个炒作周期,并且在几年后就会消亡,对世界没有影响。我将论证这些人是错误的,因为当前的LLM已经很有用。

但我觉得我需要对我所说的内容进行说明,因为还有另一群同样大声的人宣称相反的观点:今天的模型可以取代所有程序员,人们不应该学习编程,因为他们明年都会失业。我不会明确反驳这些人的说法(这不是这篇文章的重点),但我想明确表示,我并不是在为他们辩护。

我也不会试图论证“只要目的正当,可以不择手段”,并说我们应该训练这些模型,尽管它们有很多有害的影响。

我完全理解这些模型会有负面(可能是非常负面)的后果。我的意思是从虚假信息到滥用、监视、工作替代等一切后果。(或者,如果你相信一些人说的,人类灭绝??)我很快就会写一篇关于我对LLM有害影响的想法的完整文章。链接会放在这里。但这与语言模型是否有用的问题是分开的——这就是我想在这里谈论的内容。

我进一步理解你可能不想使用语言模型的局限性,因为它们倾向于编造、重复事实,并且由于缺乏健壮性而壮观地失败——可能比你更了解这些局限性。这篇文章不会是关于这个的。因为我认为尽管有这些失败,模型仍然可以是有用的。

我进一步、进一步理解训练这些模型的伦理是有问题的。也许你不喜欢它们是在没有得到人们许可的情况下,用人们的数据进行训练的(我可能比你更了解这一点)。或者你可能在考虑那些被明确雇佣来直接训练这些模型的人,他们只得到了微薄的报酬。我同意这些都是问题。但这篇文章也不会是关于这些的。

就像我现在已经说了很多次的一样:我要谈论的只是模型,就它们现在的存在而言,是否有用。

关于我的一些背景

作为一个一般规则,我不是一个轻易相信事情的人。例如:尽管十年前在安全社区经历了加密炒作,但我完全避免了写任何一篇关于区块链的论文。我从来没有拥有过比特币。它们基本上没有目的——除了赌博和欺诈。日复一日,我对所有说法都持怀疑态度。每当有人告诉我“[新技术]将要改变世界”时,我的一般反应都是冷漠。

所以,当我告诉你,我第一次听到有人说这个AI东西将会非常有用,并显著改变我处理日常工作的方式时,我基本上有同样的反应:“我见到的时候才会相信。”

除此之外,我还是一名安全研究人员。近十年来,我的日常工作就是展示AI模型在面对任何它们没有被训练处理的环境时,会以何种方式惨败。我已经证明,稍微扰动机器学习模型的输入,使它们产生极度错误的输出,或者大多数机器学习模型会记住它们训练数据集中的特定示例并在你使用时重复它们,这是很简单的;我完全理解这些系统的局限性。

然而,在这里,我却说,我认为当前的大型语言模型自互联网创建以来,为我的生产力提供了最大的改进。说实话,今天,如果你让我在解决一个随机选择的编程任务时选择使用互联网或使用一个最先进的语言模型,我可能有一半以上的时间会选择语言模型。

我如何使用语言模型

所以,这就是我如何使用LLM来帮助我的。[b]

你可能不喜欢我的用例。你可能认为它们很愚蠢。也可能是这样的情况:这些与你无关,对你没有帮助。我承认这可能是真的。但我只能为自己说话。这些案例中的每一个都是我从过去一年与某个LLM的聊天历史中直接提取出来的。

为我构建完整的应用程序

去年,我做了一个测验,让人们测试他们预测GPT-4解决一系列任务的能力有多好。它最终相当受欢迎——它获得了超过一千万的页面浏览量。你猜怎么着?我让GPT-4为我写了这个应用程序的几乎整个初始版本。我通过一系列问题做到了这一点,从让我询问应用程序的基本结构开始,然后慢慢地构建出各种功能。总的来说,这次对话有30000字长,它真的考验了(当时最先进的)原始GPT-4模型的能力。

如果你浏览这段对话,你会看到各种例子,从我只是用文字描述我想要什么并要求模型提供完整实现的消息,到我要求特定更改的消息(“你能不用说这与平均分的比较,而是用KDE告诉我它是什么百分位数吗?”),到我只是提出一些完全没有明确说明的问题,其中我复制并粘贴了错误消息(例如,“绘图:numpy.linalg.LinAlgError:奇异矩阵”),再到我只是要求简单的一次性回答的情况(“如何用JavaScript将一个iframe添加到页面中,其内容是从字符串中加载的?”)。

一般来说,这种方法之所以有效,是因为语言模型非常擅长解决人们以前已经解决的问题,而这个测验的99%只是任何人都可以编写的带有Python Web服务器后端的基本HTML。这个测验之所以有趣,人们之所以喜欢它,并不是因为它背后的技术,而是因为它的内容。因此,自动化所有枯燥的部分使我制作这个测验变得非常容易。

事实上,我可以自信地说,如果没有语言模型的帮助,我可能根本不会制作这个测验——因为我不想花时间从头开始编写整个Web应用程序。而我还是一个懂得编程的人!我相信,即使是当前的模型也足以让大多数人通过要求解决方案来解决他们以前从未解决过的有意义的任务。

我还有几个这样的例子,我让模型为我编写了整个应用程序,当它们发布时,我会尽量明确它们是在语言模型的帮助下制作的。

作为新技术的导师

曾经有一段时间,我一直紧跟新框架的发展。但是一个人一天中只有那么多的时间,由于我的工作性质,我大部分时间都在关注最新的研究进展,而不是JavaScript框架的最新进展。

这意味着当涉及到在我的特定研究领域之外开始一个新项目时,我一般有两个可能的选择。首先,我可以使用我所知道的东西。这通常是一二十年前的技术,但如果项目很小,通常就足够了。或者,我可以尝试学习新的(通常也是更好的)做事方式。

这就是语言模型发挥作用的地方。因为大多数对我来说是新的框架/工具,比如Docker、Flexbox或React,对其他人来说并不是新的。世界上可能有成千上万的人对这些东西了如指掌。因此,当前的语言模型也能做到。

这意味着我不用阅读一些假设特定读者知道特定事情并想要实现一些特定目标的静态教程,而是可以与语言模型交互学习,以解决我的任务所需的一切。

例如,今年早些时候,我正在构建一个LLM评估框架,并希望能够在受限环境中运行LLM生成的代码,这样它就不会删除我电脑上的随机文件或类似的东西。Docker是这个任务的完美工具,但我以前从未使用过它。

现在,重要的是,这个项目的目标并不是使用Docker。Docker只是我实现目标所需的工具。我只想了解Docker的10%,这样我就能确信自己能以最基本、最安全的方式使用它。

如果我在90年代做这件事,我基本上得买一本关于如何从第一原理使用Docker的书,读前几章,然后试着跳过一些内容来找出如何做我想做的事情。之后情况有所改善;如果我在前一个十年做这件事,我会在网上搜索一些描述如何使用Docker的教程并尝试跟着做,然后搜索我发现的任何错误消息,看看是否有人遇到过同样的问题。

但今天,我只会要求语言模型教我Docker。所以下面就是我这么做的例子。

一旦我设置并运行了Docker,我发现它在Linux上运行时存在一些权限问题。我希望这些问题能够得到解决,于是就请模型帮我解决这个问题。

由此我了解到了Podman,并且让模型帮我把我所有特定于Docker的代码重写为可比的Podman版本。

然后,当我想弄清楚如何在Docker容器中传递主机的GPU时,我也向模型提出了这个请求。

开始新项目

我小时候学的第一门编程语言是Java。(这可能是一个错误。[c])我真的很喜欢编程,但我绝对讨厌的一件事就是面对一个新项目的空白屏幕。尤其是用Java!即使只是编译一个简单的“hello world”程序——这个“public static void main string args”是什么意思?括号放在哪里?哪些字母要大写?为什么这里用大括号,那里用方括号?

所以,我就像任何一个孩子一样——我让我的父亲帮我做。

二十年过去了,我仍然不喜欢用我不太熟悉的框架开始新项目。光是摆脱那些样板代码就要花很多时间,而且我还不知道自己在做什么。

例如,我最近想尝试写一些CUDA代码,以比较在GPU上运行的一些简单的贪婪搜索算法与某人在CPU上实现的高效优化算法的性能。

但我不知道怎么写CUDA程序。我知道怎么写C语言。我了解GPU的工作原理、内核的作用、内存布局等等。但实际上编写代码将任务发送到GPU?我不知道从哪里开始。所以,我就让模型帮我写了CUDA程序的初稿。它完美吗?当然不是!但它是一个开始。而这正是我想要的。

“你会注意到这里的代码有很多错误!但实际上我完全能接受这一点。我并不在寻找一个完美的解决方案,我只是在寻找一个起点,然后我可以从这里开始。如果未来的模型更好,那当然很棒。但我现在所拥有的已经是一个巨大的帮助了。”

“或者,完全与上述内容分开,对于我在家进行的一些其他个人项目,我正在使用Raspberry Pi Pico W。这是我第一次使用它。我希望它能帮我做一些事情,特别是希望它能帮我做一些网络相关的事情。现在,再次说明,我肯定能在网上找到某人提供的良好教程,描述如何做到我想做的事情。但你最近看过互联网吗?前五个结果通常只是一些垃圾内容农场,它们有2008年的错误代码,这些代码只是为了搜索引擎优化而更新,但仍然无法工作。”

“所以,我只是让一个语言模型教我如何做到我想做的事情。我之前曾与微控制器合作过,所以我或多或少了解它们的工作原理。但我之前从未使用过Pico W。我只需要一些东西来帮助我开始处理所有的依赖关系,然后我就可以自己搞定剩下的部分了。”

“对于一个新的微控制器,我总是写的第一个‘hello world’程序是让一个LED灯闪烁。这让我能够测试我是否能够编译并将代码上传到设备上,是否所有引脚都设置正确,以及我是否基本上知道自己在做什么。所以,我们只要请求一个闪烁程序。(再说一遍:这在互联网上存在吗?几乎可以肯定。但然后我就得去寻找它了。)”

“一旦我有了这个代码并运行起来,从这里我就知道该怎么做了。我知道Python是如何工作的(信不信由你!)。所以,我可以直接从那里开始编辑东西,摆脱了特殊的Micro Python的东西。”

“当我遇到另一个需要我特殊处理的问题时,我可以只是让模型帮我解决这个问题。例如,在这里,我继续让模型为我编写一个连接到wifi的脚本。”

“然后当我再次卡住时,这次需要连接到MQTT服务器,我只是让模型帮我解决这个问题。”

“我现在经常这样做。甚至本节顶部的例子也不是假设的——这是我询问如何使用Flexbox的例子,因为上一次我学习了一种新的HTML布局方式,那是使用div而不是表格。”

代码简化

“为了简化代码,作为一名安全研究人员,我经常会遇到这样的情况:我被展示了一个包含数千行他人研究项目的代码的新仓库,并且必须弄清楚它是如何工作的,这样我才能去攻击它。这听起来并不那么难,如果每个人都写干净的代码,那它真的不应该那么难,但这不是我们所生活的世界。研究人员并没有动力去发布干净的代码。所以,人们经常会去发布他们拥有的任何能工作的垃圾代码。(我也这样做。)”

“我没有任何与研究相关的例子可以在这里分享,但我可以分享一个我正在进行的个人项目的例子。有人说我对康威的生命游戏有着不健康的痴迷。最近,我正在尝试找到一种快速的方法来用Python评估一些生命模式。有一个很棒的C++工具叫做golly,它可以做到这一点,但我不想把我的Python代码重写为C++。”

“现在,golly有一个CLI工具可以做到我想要的事情——我只需要一个正确调用它的方法。这的第一步是取支持大约50个不同命令行选项的C++代码,并让它只做我想做的一件事。所以,我只是把全部500行的C++代码丢进了LLM,并要求它给出一个更短的文件,该文件能做同样的事情。”

“你知道吗?它运行得毫无瑕疵。然后,我只要求它给出一个Python包装器来包装C++代码。那也行得通。这是另一种任务,它太烦人了,以至于我可能永远不会自己做。但因为现在我可以只是要求它为我完成,所以我拥有了一些比我的原始Python代码快100倍的东西。”

“我发现自己经常这样做。这里是另一个例子,我在这个例子中做着完全相同的任务,但这次是用Python。”

“再说一次,这些任务都不难。但每次我这样做时,我都节省了大量的时间。这是我认为LLM在今天就很惊人的原因之一:它并不华丽,而且说‘这是一种无聊的方式,我用LLM让我的生活变得更轻松’也不会让你在互联网上获得一堆积分,但它是真实的。”

处理单调任务

“对于单调的任务,有很多事情我必须去做,它们很无聊,不需要任何思考,但需要完成。”

“事实上,我发现自己拖延任务的主要原因之一就是我知道完成它会让人感到厌烦和痛苦。LLM极大地减少了这种痛苦,并让开始某件事情变得如此容易,因为我知道我只需要解决有趣的问题。所以,在这里,我想通过让LLM为我做事来解决一系列完全琐碎的问题。”

“例如,最近,我不得不反编译一些用Python 3.9编写的Python程序。大多数Python反编译器只能在Python 3.7及更早版本上工作,但无法在我正在处理的3.9二进制文件上运行。”

“现在,反编译并不是一个特别困难的任务。它主要只是一项在不犯错误的情况下跟随goto语句来重建控制流的练习。所以,与其花时间手动为几百行代码的几千个操作码执行这种转换,我不如让LLM为我做这件事。它做得很好!比我原本认为的可能要好得多。这里有三段不同的对话,我让模型为我做了这件事。”

“另一个这样的例子是,当我需要将一些非结构化数据格式化为结构化格式时。例如,我正在处理一些项目,并且需要获取带有作者姓名的书籍标题列表。所以我在网上找到了一些非结构化的数据,并让LLM为我格式化它。”

“或者,最近我正在写一篇关于我如何破解某种防御的博客文章,并且想展示我必须更改的代码的完整差异。所以我粘贴了(1)差异,以及(2)之前如何将差异转换为HTML的例子,并让LLM以之前的格式给我这个差异。”

或者,再举一个例子,作为我工作的一部分,我经常需要为我使用的资源生成引用。Google Scholar可以很容易地为论文生成引用,我只需复制粘贴即可。但是引用网页稍微有点麻烦;我最近开始直接让大型语言模型(LLM)为我生成引用。(说清楚一点:我确实会检查这是否正确!)
我可能还能再举至少一百个例子。但我想你已经明白了。

我完全理解这是那种有人会看一眼然后说“就这?”的任务。但我们要记住,五年前,他们几乎无法连贯地写出一个段落,更不用说为你解决整个问题了。

让每个用户都成为“高级用户”

如果你曾经看过一个比你熟练得多的人使用某个工具,那可能会有点痛苦。你会看到他们花费数分钟,有时甚至数小时,来完成一个本可以通过某种宏或巧妙地使用并行应用程序来自动化的任务。

但是学习完成这些任务所需的咒语需要时间,也很有挑战性。

例如,我最近试图编写一个Python程序来处理来自Apple Lisa键盘的键盘输入。我在网上找到了一个人用C语言编写的相关程序,其中包含了很多像#define KEYNAME key_code这样的语句,我想将这些转换成Python字典,将整数代码映射到相应的字符串。

现在我是个emacs用户。我知道如何在emacs中解决这个问题。这其实并不难。以下是我刚刚录制的按键操作,它会产生这个效果:

C-h C-s #def [enter] M-f [delete] C-d M-f
C-[space] M-f C-w C-a C-y : " M-f ", C-g C-] } C-[ {

虽然这对我来说几乎是自然而然的,但我已经花了大半生的时间才在emacs中变得如此熟练。但你知道,即使现在我有了一个接入我编辑器的LLM,我会输入什么?
C-h C-h 将这些#define重写为字典{keycode: string, ...}

然后突然之间,文本就在我眼前被重写了!

我认为,在这种情况下,LLM的潜在效用对于非专家来说甚至比专家更高。这个模型提高了每个人的起点,如果你之前什么都不能做,突然之间你就能做很多事情了。

作为API参考

真正的程序员,当他们想知道某个工具如何工作时,会阅读参考手册。但我是个懒惰的程序员;我只想要现成的答案。所以现在我会问语言模型。

当我向一些人展示这些例子时,他们会有点防备,并说:“LLM做的任何事情,你都可以用你已经拥有的工具来完成!”你知道吗?他们是对的。但是,没有什么是你不能用搜索引擎做到的,而不能用实体书做到的;也没有什么是你不能用实体书做到的,而不能用阅读源代码来完成的。

但是,每一个都比上一个更容易。而当某件事情变得更容易时,你就会更频繁地以不同的方式去做它。

所以我在这里问“什么东西给出了所有剩余的参数”,并得到了答案。(紧接着是另一个“我如何使用这个东西”的问题!)
或者,当我想知道如何在latex中将文本设置为红色时,我不再搜索或阅读文档,而是直接问模型。
当我想知道LLDB中各种GDB命令的等价命令时,我也做同样的事情。
或者当我想知道某个find命令是如何工作的。
或者如何使用lpr。
或者如何重新绑定一些latex命令。
这是我使用LLM最频繁的方式之一。我不能给你链接到一千个更多这样的例子的唯一原因是,我有一个内置于emacs和shell中的查询LLM的工具。所以90%的时间,当我想做这些事情中的任何一件时,我甚至不需要离开我的编辑器。

搜索难以找到的内容

在互联网上搜索内容曾经是一项需要努力学习的技能。你想在查询中包含哪些特定的单词?它们应该是复数形式还是单数形式?过去时态还是现在时态?你想避免在页面上出现哪些单词?你是想要X和Y,还是X或Y?

现在情况不再是这样了。我想不起来我上次在Google查询中使用OR是什么时候了。我也想不起来我上次使用减号(-)来排除一部分结果是什么时候了。在大多数情况下,今天你只需要写下你想找到的内容,搜索引擎就会为你找到它。

但是搜索引擎仍然不是100%的自然语言查询。这仍然有点像是你在玩一场反向Jeopardy游戏,试图使用答案中会出现的关键词,而不是问题中的。我认为这几乎是我们所有人都忘记了我们学过的一项技能。

对于今天的一些简单任务(并且随着时间的推移,越来越多的任务),语言模型只是更好。我可以直接输入“所以我知道+对应__add__,但是~是什么?”它就会告诉我答案是__inv__。
这是很难用标准搜索引擎搜索到的东西。是的,我知道有一种方法可以让我找到答案。也许如果我输入“python documentation metaclass "add"”,然后我可以搜索页面上的~并得到答案。但是你知道还有什么方法有效吗?就是直接把你的问题问LLM。

这样做每次只能节省几十秒,但当你正在解决一些编码任务,并且已经试图同时记住一百万件事情时,能够把你正在尝试解决的问题一股脑地说出来,并得到一个连贯的答案,真是太神奇了。

这并不是说它们今天在这方面已经很完美了。语言模型只知道那些在网上被重复得足够多的事情。而“足够多”意味着什么取决于模型,所以我确实需要花费一些精力去思考我是应该问模型还是问互联网。但是模型只会变得更好。

或者,每当我遇到随机崩溃时,我都会把模型倾倒出来,并询问解释,就像我在这里输入“zsh no matches found "Remote wildcard transfer issue"”时所做的那样。
或者,作为另一个完全独立的例子,我去年写博客文章时,想让第一个单词的首字母变大,并让其余文本环绕它,就像我刚刚在这个句子中所做的那样。这被称为首字下沉。但我不知道。我只知道我想要的效果,所以我就问语言模型:“我想让它看起来像一本花哨的书,文本环绕着O”,它给了我我想要的确切效果:
这项任务也属于“我只是因为LLM才这样做的”类别——我不会认为花很多时间去弄清楚如何做到这一点是值得的。但是因为我可以直接问模型,所以我就做了,它让我的帖子变得更好了一点。

解决一次性任务

有两种程序。首先,你有你想要做得对的程序;它们会存在一段时间,并且整洁性很重要,因为你将不得不维护它们好几年。然后你有那些只存在25秒的程序;它们会帮助你完成一些任务,然后立即被丢弃。

在这些情况下,我一点也不关心代码的质量,并且程序是完全自给自足的,我现在几乎只使用LLM来为我编写它们。

警告:这些情况中的大多数,你再次看到时会说“就这?”。但就像我之前说的那样,我每天只有那么多小时可以用在给定的项目上。如果我能节省下编写一个我再也不会使用的程序的时间和精力,我就会这么做。

最常见的例子可能是帮助我生成一些图表,这些图表可以可视化我作为一些研究实验的结果而生成的数据。我有几十个这样的例子。可能更接近一百个而不是零个。它们看起来都差不多,所以这里只举一个例子:
或者,另一个类似的例子是,当我有一种格式的数据,并想将其转换为另一种格式的数据时。通常这是我只需要做一次的事情,一旦完成,我就会扔掉生成的脚本。
但我可以给你一千个其他的例子。很多时候,当我想写一个足够简单的脚本时,我会直接让LLM为我编写整个脚本。例如,在这里,我让LLM为我编写一个脚本,它会大声读出我的论文,以便我可以确保它们没有愚蠢的语法错误。
在很多情况下,当我不太确定我想要什么时,我也会从让模型提供一些初始代码开始,然后从这里开始迭代。例如,这里有一个一次性任务,我只需要一些数据被快速处理。在2022年,我会花两分钟用python编写这个,然后等几个小时让它运行,因为它只运行一次——优化它的时间会比python程序运行的时间还要长。但现在呢?你当然知道我会花同样的两分钟时间让LLM为我提供用rust编写的数据处理代码。
或者这里还有另一个例子,我让模型为我下载一个数据集,并对它进行一些初步的处理。对我来说容易吗?也许吧。但这不是我想要考虑的任务;我想要考虑的是我将用数据集进行的研究。消除干扰的价值远远超过它节省的几分钟时间。

另一次,我正在编写一个程序,以便我可以使用小立方体3D打印一些像素化的图像。为此,我想将PNG转换为STL文件;但这并不是项目的重点。这只是过程中必须发生的一件事。所以我让大型语言模型(LLM)帮我解决这个问题。

或者,作为另一个例子,我最近想使用Docker Compose来设置一个新项目。我遇到了问题,只想让它运行起来,不管付出什么代价,然后我再去找出问题所在。所以我只能一次次地来回操作,我所做的就是复制一个错误消息接着再复制另一个,直到它最终给了我一个可行的解决方案。

我还会在很多情况下,一开始就要求一个完整的解决方案,然后要求如何修改它的提示。在这次对话中,我开始要求一个解析HTML的程序,然后要求关于API引用或其他改进方式的提示。

或者,另一次我想追踪我的电脑随着时间推移使用了多少内存和CPU。我本可以花几分钟时间找出适当的命令,并将它们组合成一个脚本来完成我想要的操作……或者我可以直接让语言模型为我做这件事。

最近我一直在尝试做一些电子方面的事情,我有一个在Arduino上运行的C程序,但我想让它在MicroPython的Raspberry Pi Pico上运行。这个转换过程中没有什么有趣的内容;它只是需要完成。所以我没有自己做这项工作,而是让语言模型帮我做。

对于另一个项目,我需要使用一些花哨的机器学习模型对一些图像进行分类,并且是在一些交互式的循环中。我本可以自己写,或者我可以直接让模型为我做这件事。

为了向我解释事情

我最近开始涉足电子学。我小时候做过一些电子方面的事情,而且在大学里也上过几门相关的课。但现在我想用它来做一些实际的项目,我发现有一千件小事我不知道,这让做任何事情都变得很难。

现在我可以去读一本关于实用电子学的书。而且我可能会在某个时候这样做,以便我能对这个主题有一个正确的理解。但我真的不想把时间花在学习上。我做电子学的一半原因就是为了从整天阅读和撰写论文中休息一下。

而这就是大型语言模型(LLMs)的伟大之处。它们可能不像世界上最好的人那样知识渊博,但肯定有成千上万,甚至数百万人知道我可能提出的任何电子学问题的答案。这意味着语言模型可能也有答案。它很乐意为我提供所有问题的答案,这样我就可以在不纠结于细节的情况下享受我想要的乐趣。尽管我可能只需要再稍微努力一点,通过搜索互联网就能找到答案,但在花费了一整天研究复杂的科研代码之后,直接让模型为我做这件事真是太放松了。

所以这里有一些例子,我问了一个语言模型关于电子学中事物工作原理的基本问题。这些答案完美吗?谁知道呢。但你知道它们比什么更好吗?比我什么都不知道要好。

为了解决已知解决方案的任务

几乎每件事都已经被别人做过了。你几乎想做的每一件事都不是真正新颖的。而语言模型在给出你以前见过的事物的解决方案方面非常出色。

对于最近的一个项目,我需要提高一些Python代码的性能。所以我(1)让LLM用C语言重写它,然后(2)让它构建接口,这样我就可以从Python调用C代码了。

这两项任务都不“难”。从Python转换到C是我确信自己可以在一两个小时内完成的事情。而且虽然我不知道Python到C的API是如何工作的,但我确信自己可以通过阅读文档来弄清楚。但如果我必须自己做这件事,我永远不会去做。这根本就不是重要路径上的事情,我宁愿等着让电脑解决任务,也不愿花时间去让它运行得更快,因为这些事情我并不需要经常运行。

但是将Python转换为C(在大多数情况下)是一个简单程序的技术过程,而且只有一种标准的Python到C的调用约定。所以我只会让LLM为我做这件事。

从那时起,我就开始期望自己能够做到这一点,基本上每当我需要一些快速的代码片段时,我就会用Python描述我想要的东西,然后请求优化后的C代码。

其他时候我也会做同样的事情,但会要求输出Rust而不是C,因为我认为如果这样做的话,判断Rust输出的正确性会比判断C输出的正确性更容易。

或者,作为另一个例子,使用multiprocessing库将Python函数并行化并不难。你必须编写一些样板代码,然后它基本上就为你完成了。但编写代码有点麻烦,会妨碍你完成实际想做的工作。现在每当我需要做这件事时,我都会让LLM为我做。

或者,在尝试测试一些API时,我通常会先编写一个curl请求来让事情开始运转。一旦我能让它工作了,并且想以编程方式重复这个任务时,我就会把它转换成Python。以前,我通常会做一些非常丑陋的事情,就是调用os.popen()并运行curl命令,但这并不是很好。更好的做法是将它转换为Python的requests库;但这需要时间,所以我不会这样做。但现在我可以让LLM为我做这件事,并得到一个更干净的程序,而且用时更少。

对于一个我即将在这里谈论的项目,我需要知道人们使用什么样的简单无线电发射器。因为我真正想要的是普通人的答案,所以LLM是一个完美的选择!

为了修复常见错误

在2022年之前,当我遇到一些流行工具或库的错误消息时,我会遵循以下步骤:

  1. 复制错误信息。

  2. 将其粘贴到Google搜索。

  3. 点击最顶部的Stack Overflow链接。

  4. 确认问题是否与我遇到的一致;如果不是,返回第2步。

  5. 如果无效,返回第2步,更换搜索词,祈祷等。


因为,说实话,通常出问题的工具与你最终想要解决的任务相隔了五个层级,你根本不在乎如何让它工作,它只需要工作。那么在2024年,这看起来是什么样的呢?

  1. 复制错误信息。

  2. 向LLM询问:“我该如何修复这个错误?(错误)”

  3. 如果无效,反馈“那不起作用”。

现在,我没有任何例子来展示这个。(或者,我找了一个小时也没找到。)但实际上这有一个很好的理由:我已经把它直接融入到我的工作流程中了。

我是一个emacs用户。我已经设置了我的环境,以便每当我运行一个程序并且它以非零状态码退出时(意味着出事了),它会自动调用最新的、最快的LLM,让它解释答案,并同时要求提供一个可以直接应用来修复代码中错误的补丁。

今天的模型在大多数情况下还不足以在这方面打败我,但它们已经接近了。而且时不时地,我会得到一个惊喜,当LLM修复了一个我知道会是一个噩梦般的错误时,因为我在某个地方打了一个错别字。

以及一百万件其他事情

我上面链接的所有对话只占了过去一年我与LLM交互总数的不到2%。[e] 我没有链接到这些其他原因并不是因为它们是我模型失败我的案例(尽管有很多这样的案例),而是因为(1)其中很多重复了我已经链接到的案例的模式,或者(2)它们不容易解释发生了什么,以及为什么它们对我来说做了一些有用的事情。

我完全预料到我的这些模型的使用在未来会继续增长。作为参考,我在2024年通过网页界面进行的LLM查询比2023年多了30%——我甚至无法计算API查询的增加量,但我怀疑那至少是2倍或3倍。

评估LLM能做什么,而不是它们不能做什么

我得到的关于面试求职者的最佳建议之一就是基于他们能做的事情来评估他们,而不是他们不能做的事情。

我怀疑有一些简单的问题我可以问你,会让你看起来很无能。作为一个极端的例子:世界上有十亿人会说普通话;我甚至不会数到十。如果有人给我一份小学普通话考试卷,我会考得很惨。

即使在计算机科学领域,也有一些我完全不了解的领域。我知道如何构造SQL的全部知识就是如何写一个有效的SELECT语句。那就是——字面意义上的——我唯一知道如何写的语句。[f]

所以当我看到人们在网上争论LLM只是炒作,因为“它们甚至不能[X]”时,我真的不明白。这里的[X]可能是:

  • ……数出一个句子中的单词数量!
  • ……写一首每个单词都以字母“a”开头的诗
  • ……将两位数字相乘
  • ……从列表中随机选择一个元素

因为上次你实际上需要做这些事情的时候,并且真诚地认为LLM是合适的工具是什么时候?

就像我不会因为人类不能在我们的头脑中除以64位整数——这是一项对电脑来说完全简单的任务——而认为人类完全没有用一样,我认为因为你可以构造一个LLM不能解决的任务而认为它们没有用是没有意义的。问题显然不在于此——问题在于你能找到它们提供价值的任务吗?

程序员已经很好地理解了这样一个事实:不同的东西可以用于不同的目的。想写一个操作系统吗?也许你应该使用C而不是Python。没有人会说“看看Python多傻,你甚至不能强制一个变量对齐到32字节边界!”这只是抽象层次不同。语言模型完全一样。它们工作在非常高的抽象层次;你不能期望它们解决即使是最简单的程序也能解决的任务。但你可以期望它们解决不同类型的任务。

结论

我写这篇文章的动机有两个。第一个就是我在开头说的:我想论证LLM已经给我提供了很多价值。但还有一个原因是:我看到很多人说“我喜欢使用LLM的想法,但不知道它们怎么能帮助我”。所以希望如果你是这些人中的一员,你可以看到一些我如何使用它们的例子。

因为,至少对我来说,LLM可以做很多事情。它们不能做所有的事情。它们甚至不能做大多数的事情。但当前的模型,就如它们真实地展现在我面前一样,提供了相当大的价值。

在展示这些例子之后,我最常听到的反驳是某种形式的“但这些任务很简单!任何计算机科学本科生都能学会怎么做!”你知道吗?那是对的。一个本科生可以,通过几个小时的搜索,告诉我如何正确地诊断那个CUDA错误

本文标签: 人工智能职业生涯一篇文章万字科学家