扫码阅读
手机扫码阅读

资深程序员撰文:LLM将从根本上改变软件工程(下)

362 2023-07-13
【本篇接续:资深程序员撰文:LLM将从根本上改变软件工程(上)
方法论转变#4:建立更多的工具
我们都知道,工具是很重要的,有效的工具在创建时是具有挑战性的,而且管理层并不关心或理解对工具的需求。LLM让我们能够以所谓的 "嘴的速度 "建立工具。我知道,我现在可以花30到45分钟与ChatGPT交谈,并完成一个相当坚实的工具。这在以前可能需要我花4到5个小时编程,这意味着必须分2-3个工作日完成(考虑到会议、代码审查、午休、中断)。这通常意味着,这个工具不会被建立。
在过去的3个月里,我建立了一个工具列表(前面5个工具的代码已经上传到GitHub上)
  • sqleton - 一个将SQL查询作为命令行程序运行的工具
  • escuse-me - 同样是用于Elasticsearch的工具
  • geppetto - 与GPT的API相同
  • biberon - 与bibtex相同(非常简陋,它能完成一项工作)。
  • majuscule - twitter hashtag segmentation原型,但有动态HTML调试UI
  • 一个在我离开电脑时停止OBS记录的脚本
许多工作上的实用工具:
  • 将任意的文档转换为代码(见上面Google Tag Manager的例子)。
  • 解析和分析搜索日志。
  • 一个用于上述搜索日志的SQL构建器。
  • 一个全功能的GTM服务器端实现。
  • 用于管理横幅及其资产的工具。
  • 一个通过OCR运行发票的应用程序,用GPT进行清理,搜索ElasticSearch的SKU,并渲染出与我们的库存相匹配的经过清理的发票。
  • 报告生成器,用于我必须做的每一个数据链调试。
  • 用于谷歌标签管理器JSON导出的文档生成器
我无法表达现在编程的感觉有多大的不同,因为我每天可以为我想抓的每一个痒点建立两个高质量的工具。
旁白#2:基础知识可能同样重要
我相信,抽象主要是通过看到和玩过足够多的具体用例来学习的,从而形成更高层次的结构。抽象是一把双刃剑,因为不适当的抽象会导致后续不断的摩擦。虽然LLM允许我们在 "模糊的抽象 "层面上工作,以及快速探索具体的实现方式,但 "控制"LLM最好是通过对心中的问题有一个坚实的理解。
我在对话式LLM中体验到的一个非常真实的缺点是,人们会不断地聊天,不断地试探各种问题,希望模型能在某个时候 "理解 "它。当我们没有正确掌握待解决的问题时,这种情况就更严重了,我们的注意力会从有成效的对话转移到跌跌撞撞的幻觉上,这些幻觉把我们引向疯狂的追赶。在这些情况下,我认为应该马上断开互联网连接。相反,我坚持使用离线文档和一本书,直到我对所处理的问题有了更好的认识。
有了 "真正的 "知识在手,向LLM提出正确的问题,会使这类对话更有成效。任何嘲笑 "提示工程 "是一门可笑的学科的人,都没有花足够的时间去尝试写有效的提示。
旁白#3:避免无益的聊天会话
我希望未来的对话代理能够在这些低效的对话发生时进行标记。目前,ChatGPT只是不停地和我们对话,但我希望看到它在某些时候能停下来、指向适当的教程和资源,或停下来、要求我们提供更多的细节。ChatGPT4似乎已经取得了进步,这是相当令人印象深刻的。这个领域教会我的一点是:不要对下一代LLM的能力做出假设。它可能有与当前模型相同的基本问题,但它可能只是变得 "足够好",以至于就所有意图和目的而言,那些问题已无关紧要。
方法论转变#5:持续代码审查
我认为,LLM另一个焦点将是 "持续代码审查"一个模型可以观察所构建的软件,推断我们的意图和思维结构,并对其中的方法提供反馈编者:这就是我最近经常说的:有不同的LLM或机器人,扮演不同角色)。它可以标记出错别字、安全错误和对API不恰当的使用。让我印象深刻的是,ChatGPT4纠正了我的代码,并且自己把问题分解成了一些相当有效的接口和函数事实上,ChatGPT4是一个比我好得多的程序员。它知道更多的习惯用语,不会忘记安全问题,而且它能以token采样的速度吐出单元测试。
有些人会认为:这些模型会导致充满安全错误的底层堆栈流代码的泛滥,但他们忽视了这些模型在他们的工作中又是如何迅速变得更好的,这是因为他们很容易忘记现有网络上可以找到多少好的代码。优秀的代码必然会在其训练语料库中得到更广泛的传播,而这些语料库肯定会被严格审查和调整。从ChatGPT3.5到ChatGPT4在软件架构 "修辞 "方面的跳跃式提升,充分证实了这一点。
我使用了一系列的提示,要求模型就安全问题、所遗漏的特殊用例、不清楚的文档等给出反馈。到目前为止,我必须手动复制和粘贴这些内容到chatGPT中,提供缺失的背景并完善它的答案。但这只是一个工程问题,容易解决LLM模型本身已经实现了令人印象深刻的评审能力,这比我职业生涯中获得的大多数代码评审能力要好得多,而且是实时的,同时还给出具体的实例来重现发现的问题和修复建议。
现在更容易编写复杂的、模糊的提示器,可以检查特定领域、特定代码库的模式,因为这种提示由几个(见多识广的)人类语言提示组成。指示LLM-linter "只在处理客户数据时才对单例(singletons)进行检查"可能比在editorconfig中正确配置大括号行为要快。它不会抓住每一个用例,但它会抓住足够多的用例,值得一试。
方法论转变#6:使用LLM的认知影响
这可能是最微妙的转变,但我相信这也是使用LLMs给我带来的最深刻的变化。在专注于做好 "繁琐的事情"(使用正确的API、检查正确的错误、正确调用API X、为Y实现单元测试和模拟、为Z编写API封装等)的一天之后,我的大脑会完全消失,被细枝末节和不出错的强度所吞噬。
自从广泛使用Copilot和ChatGPT后,这种认知上的疲惫感就基本消失了。下午6点一到,我感觉我是花了一天时间和一个哥们儿聊天,然而5个PR已经合并,单元测试已经写好,两个工具已经改进,代码已经发布。
这使我能够在我的开源项目上取得重大进展。我知道我能够在晚餐前完成一件非重要的事情,也许在晚餐后还能完成一两件事。以前我会在周六花3个小时试图让AWS的lambda运行,想知道 "为什么我的周六要这样度过",现在我会很高兴地关闭一两个问题单(tickets),然后用剩下的时间和家人一起做家务。
做更多的 "高级 "思考
我是一个坚定的信仰者,让事情停下来,做 "淋浴思维驱动"的软件工程(短语"Shower-thought-driven"通常用来形容一个人在洗澡时,处于放松的状态,没有干扰和压力,思维变得清晰,灵感迸发,从而产生了新的想法或解决问题的方法)。我相信,有必要对某件事进行深入思考,尝试建立几个原型,然后让它沉淀下来。真正的洞察力(和问题解决)发生在散步的时候,当我的大脑得到充分休息的时候,在运动后或在传说中的淋浴中。以前我每天能有30分钟到1小时的 "自由 "时间,如果有的话,我可以把过去需要4小时的繁琐工作缩减为1~2小时(这是平均数,但现在写一个API封装器之类的程序只要花10分钟而不是2天),现在我每天有3~4个小时的 "自由 "思考时间。
这意味着我可以考虑什么需要做,什么不需要做;也意味着,我可以花一些时间尝试其他方法(建立更多的原型,如上文详述的)。我可以花更多时间与干系人交谈,弄清楚他们到底需要什么。我可以考虑团队本身需要的工具,可以在培训材料上下功夫,也可以让报告变得漂亮。并不是说这些事情以前不能做,而是它们已经变得如此之便宜,以至于没有理由不做。
结论
我希望有更多的资深研发人员花时间正确地评估这些技术,以开放的心态,而不是以膝跳的方式做出防御反应。这些技术是可怕的,因为它们清楚地表明,程序员将成为第一个被机器取代的排头兵。
以上列出的所有 "改进 "都将被我们的行业系统化之后再利用(在某种程度上,企业已经是AI了),以便为极少数人的利益压榨出更多令人崩溃的生产力。我们现在有一个机会来考虑如何处理这些新兴力量。我正在努力找出未来发展的方向,除了呈现出有价值的工程洞察力:把这些技术从硅谷公司的护城河中拿出来;利用LLM来建立更好的开源;利用这些技术来为人们而不是为商业目的构建工具。
此外,虽然我可能会把LLM人格化,但我这样做的方式是“编译器会思考”就我而言,LLM是在大量数据上训练的、相对简单的代码片段,ChatGPT并不比/bin/ls和在线日志S3 Bucket更生动、更理性或更有感觉。它不知道、它不记得、它没有意图,它没有与世界的互动。我想让我们谈谈LLM的本质:语言的概率模型,在经过训练后,根据给定的上下文预测下一个标记。这个公式导致了ChatGPT这样的事情,这让我很震惊,但我对讨论无可辩驳的猜测不感兴趣。我只是想写代码,老兄!
关于编程与软件工程的关系,我从来没有完全理解过。当然,软件工程是关于构建良好的软件,而编程也是,构建良好的软件。当我画图的时候,我就是在编程。当我写文件时,我就是在编程。当我和同事在白板前交谈时,我们就是在编程。当我阅读和编写大量的软件时,我做了大量的软件工程,因为我希望软件在今天、明天和十年后都能工作(这意味着测量、测试、基准测试、破坏、压力测试和记录都正常)。我希望即使在30个人在最后期限的压力下开发出来的软件也能正常工作(这意味着设计、重构、测试、建立开发工作流程、编写文档、沟通、了解团队结构和商业目标、遗留问题和个人认知风格等都没问题)。我称其为编程,因为唯一能让我们真正达成共识的有形结果是所产生的人工制品(源代码和文档)。我喜欢研究和阅读遗留的代码库,可以在源代码本身中读到大部分 "更抽象 "的东西(从更简单的方面来看:团队功能失调、目标不一致、沟通不足;困难的一面:良好的入职培训,个人贡献者的成长、出色的业务一致性)。这就是为什么我总是提起编程。你可以漂亮地谈论各种概念,但真正重要的是所产生的代码。对我来说,好的代码就是好的工程(好的代码可以是:解决业务问题的代码,通常没有代码是最好的代码;优雅的代码,有些程序员喜欢编写优雅的东西,大多数程序员喜欢使用优雅的东西;有趣的代码等)
如果这话说得很夸张,那么在发现自己患有自闭症后的去年,我学到的一件事就是不要太在意自己的表现我认为我是一个比较糟糕的、粗心的程序员;我喜欢分享我所知道的一切:我希望每个人都能找到我使用电脑时的那种热爱我感到失望的是,我永远不会成为一个万能的人,因为计算机世界有太多很酷的东西。我将把“精通”留给那些更专注、更有好奇心的人。 
这似乎是另一个人们为定义而争论不休的术语。我把“嵌入式、一些web、分布式、操作系统和一些数据库”的开发归入系统编程的范畴。这似乎是一个非常广泛的保护伞,但从编程的角度来看,它是对“队列、资源所有权、资源初始化和拆除、并发、锁定”的编程;对“协议、数据序列化、存储、带宽、吞吐量、延迟”的编程;对“状态机、循环程序、调度程序、线程、驱动程序和API”的编程。当我们从编程的角度来定义 "系统编程 "时,我们会发现许多相似之处是 "生成性的",即它们通过使用代码来产生洞察力和想法这与将 "系统编程 "定义为操作系统的编程形成鲜明的对比,因为失去了洞察力。它导致一代又一代的web开发人员在每次想要管理本地资源而不是使用资源池时都要重新发明轮子。它导致一代又一代的嵌入式开发者拒绝更好的工具、有效的测试和部署实践。它导致了一个设计不良的嵌入式UI和缓慢的Web应用的大杂烩,以及令人不快的并发性抽象和认为一切是整数的操作系统。
你可能想知道为什么我把 Common Lisp 和 PHP 放在一起。Common Lisp作为一种语言的特殊之处在于:不管需要什么,它允许我们在需要的时候构建自己的语言,我们可以交互地完善它。如果我们的目标是用清晰的结构和明确的上下文来写代码,那么Common Lisp就是一个很好的工具。你不用把通信塞进一个现成的、僵硬的框架里,而是建立一个适合自已的通信框架。正如我们所看到的,这就是让LLM做得好的原因。另外,看看Common Lisp规范,告诉我它不是......笨重的,而且是剥落的油漆。
我认为,担心初级程序员被淘汰的人,更应该担心初级程序员取代高级程序员。我们很容易相信,随着年龄的增长,你的思想依旧保持年轻。然而,和那些充满激情的15岁的孩子们混在一起,很快就会让我看到自己已经变得多么的钙化。我可能认为我对前端框架和基于组件的CSS的优雅处理,我理想的git工作流程和可观察性实践是工艺的体现。同时,孩子们认为我也可以写COBOL,同时合并他们今天的第30个pull request。这将使全自动的CI/CD能够部署新创建的工件。每一个在Tiktok上被分享的随机仓库都会在几天内得到300(3000 或30000?)颗星。在1998年,我写开源代码意味着也许能得到一个补丁的合并,因为我在IRC上认识了一个关心我的人,而今天,这意味着我们能非常快速地成长并迅速成为敏捷的技术领导者。
作为一个需要对某人喋喋不休以澄清自己的想法的人,这是真正的魔法。一个缺点是,这个工具的 "个性 "随着时间的推移而改变。它抓住了新奇的概念,并大量改编或淡化了更多的观点,往往是为了回应提示性的攻击,也是为了减少幻觉和其他副作用的数量。这与你在脑力激荡时想要的情况正好相反,在脑力激荡时,远大的想法才会引发快乐作为一种变通方法,我经常提示最差的模型,并把由此产生等胡言乱语粘贴到更合理的LLM上,以扰乱这个过程。
(全文end)

(还可以叠加优惠码“QR2023”,再降500元,只要3118)

原文链接: https://mp.weixin.qq.com/s?__biz=MjM5ODczMDc1Mw==&mid=2651857109&idx=1&sn=37f46d9185c33f2ba17505911f206bd7