第13章 第一次用Copilot

上午十点, 办公室里弥漫着周一特有的低气压。有人在小声开晨会讨论上线计划, 有人在工位上啃三明治当早餐, 空气里混着打印纸的墨粉味和速溶咖啡的气息。项目经理在会议室里白板笔写字的吱吱声,有人在低声争执着什么隔着玻璃门传出来, 偶尔有人笑一声, 但笑得很短, 像是笑完就要马上收回表情继续赶进度。窗外的天灰蒙蒙的, 三月末的上海还没完全暖和起来。

陈默盯着屏幕已经两个小时了。他在修一个不太急但很烦的问题——用户上传的Excel文件里有一些特殊字符, 导致后台解析到第三行就崩了。不是什么高端问题, 就是最普通的字符编码处理, 但他翻了三遍代码都没找到那个边界条件到底写漏在哪。他忍不住嘀咕了一句:「到底漏在哪儿了……」他端起马克杯站起来, 准备去茶水间接热水——站起来的一瞬间, 余光扫到小李的屏幕上有什么东西在快速跳动。「那是什么?」他停了下来。他停下来, 看了过去。

小李正在写一段数据处理逻辑, 但他的手几乎没碰键盘。光标在IDE里自动跳动, 每一次跳动, 代码就多出一行。灰色的补全字符依次浮现在编辑器中, 像有人在对面的键盘上同步输入, 速度均匀、不带停顿、每一行结束都准确落在该落的缩进位置上。陈默数了一下——小李大概只手动输入了三个单词作为提示, 剩下的三四十行代码全是编辑器自动生成的。三四十行, 手写至少要十五分钟。自动生成, 大概十秒。

小李回头看见他,笑了一下,摘下一边耳机说:「默哥你看过这个没?」陈默说:「知道,GitHub Copilot,去年技术分享会上听过。」小李说:「那你用过吗?」陈默说:「没有。」小李说:「贼好用,你试试就知道了——你写一个注释描述你要什么,它直接给你生成整段!,连单元测试都能给你写。」陈默说了句「不用了,你忙」,就端着杯子往茶水间走了。

但他走到茶水间门口的时候, 忽然停下来, 没有进去。他站在走廊里,内心充满了矛盾——既跃跃欲试又心怀恐惧, 端着那杯还没接水的空杯子, 脑子里反复回响着刚才那句话——不用了。这句话和老张说过的技术深度不够本质上是一回事。都是在说: 他不需要这个。但他真的不需要吗。还是他害怕自己学了也不如年轻人用得好。他接了一杯热水, 没有马上喝, 端着走回工位。路过小李工位的时候他没有停下来, 但他看见小李已经切换到了下一个task, 正在用同样的方式处理一段新的逻辑——光标在屏幕上飞速跳动, 灰色的代码一行一行地往外冒, 像是永远也写不完。

他坐下来, 盯着自己的屏幕。IDE开了三个文件, 都是他写到一半的业务逻辑。那个Excel解析的问题还挂在那里, 他暂时不想看了。他打开VS Code的扩展市场, 在搜索框里输入Copilot。搜索结果的第一个就是, 安装量显示三百多万。他认真看了那个数字三遍——三百多万。也就是说, 有三百多万个程序员已经把这个东西装到了自己的编辑器里。他们在用它写今天要上线的代码, 而陈默还在手动修Excel编码的问题。

他光标悬停在安装按钮上, 停了好几秒。他清楚地意识到, 点了这个按钮之后, 很多事情就回不去了。就像你知道了某种真相之后, 就不能假装不知道。他点了安装。进度条走了几秒就满了, 提示重启后生效。他关掉提示, 没有立即重启。他喝了一口热水, 有点烫, 舌尖被烫了一下, 他嘶了一声——然后他忽然想起老张。竟然在这个时候想起他,这个联想让他自己都感到震惊。想起老张在公司最后一晚收拾桌子的样子, 抽屉里那支笔夹磨掉的晨光中性笔被他扔进了垃圾桶。如果老张学过这个——这个念头出乎意料地刺痛了他——公司还会不会让他走?他是不是就不用妥协了?但答案他早就知道: 会的。工具从来不是问题的根源。但知道答案不代表内心没有矛盾,也没化解他的冲突。

他放下杯子, , 把鼠标移到IDE的重启按钮上, 点了下去——他做出了一个决定。屏幕暗了一秒, 然后又亮了。菜单栏上多了一个小小的Copilot图标。他靠在椅背上, 盯着那个图标看了很久。办公室里的声音在那一刻变得很远——有人在打电话, 有人在敲键盘, 打印机在嗡嗡地运转。但这些声音像是隔了一层什么, 模模糊糊的。他伸手握住鼠标, 把光标移到了Copilot的图标上。窗外有一阵风吹进来, 桌上放着的A4纸被掀起一角, 又落回去。

他站在工位旁边,把自己代入到刚才的场景里——仍然沉浸在刚才的震撼中, 没有马上坐下来。办公室的日光灯管在头顶发出细微的滋滋声, 那种声音平时不会注意到, 但在安静下来的时候就会变得格外清晰。他低头看着自己的手——右手食指第一个关节处有一层薄薄的硬茧, 是长年敲键盘磨出来的。这层茧跟了他十多年了。他不知道AI写代码的人会不会也磨出茧来。大概不会。他坐下来, 打开了IDE。

IDE重新打开花了大概十来秒。陈默, 打开了一个空的测试文件。他握着键盘的手指停了两秒, 然后在文件第一行打了一行中文注释: 解析逗号分隔的字符串并返回一个字符串数组, 去除空白字符和空值。按下回车。

Copilot几乎是在他按下的同一瞬间给出了完整的函数实现。「参数校验, 空值过滤, trim处理——全都处理了。」陈默不敢相信自己的眼睛。, 边界条件判断——所有他原本一行一行手写需要至少十分钟的东西, 在一秒之内全部出现在屏幕上。灰色字符整齐地排列在光标后面, 缩进正确, 命名规范, 每一行都恰到好处。他盯着那几行代码反复看了好几遍, 又在脑子里过了一遍逻辑——没有错。完全正确。

他又试了几个。一个日期格式化函数, 一个数组去重, 一个简单的LRU缓存。每个都比他自己写快了十倍。他对着屏幕喃喃自语:「这也太快了……」没想到连边界条件都处理得滴水不漏,而且代码风格统一, 注释的位置也放得精准——刚好在需要解释的地方加了一行说明, 刚好。这个刚好让他心里咯噔了一下——刚好这个词意味着它判断出了哪里需要注释, 哪里不需要。这个判断本身, 就不仅仅是代码补全了。

他靠在椅背上, 把眼镜摘下来用衣角擦了擦。手指有点发抖,是专注过度的那种颤抖,也是一种共鸣, 非常轻微的抖。不是冷, 也不是害怕, 是一种更深层的震动。他想起自己刚学编程那年, 大二下学期, 在宿舍里写出第一段能处理输入的Java代码——那个程序从一个文本文件里读数据, 排序, 输出到另一个文件。那段代码只有几十行, 但他写了一整个晚上。编译通过的时候, 他举着双手从椅子上弹了起来。那种满足感来自创造。如果连创造都可以被替代了, 那满足感来自哪里。他重新戴上眼镜。视线清楚了一些。

他继续测试, 这次故意写了一个模糊的需求: 处理用户输入并返回适当的响应。Copilot的光标闪了两三秒——他在犹豫。然后它给出了一段通用代码, 框架性的, 带了一个switch分支和一段try-catch。逻辑上说得通, 但边界条件处理得相当粗放——有一个分支完全没有做空值检查。空指针风险。陈默抓住了这个错误。他盯着那个漏洞, 心里涌上来的第一个情绪是松了一口气——一种混杂着感激和不安的放松。感激因为它还会犯错, 不安因为它大部分时候是对的。

这个漏洞救了他一下。让他觉得还有时间。但他也知道, 这个漏洞不会存在太久。等下一个版本发布, 等训练数据再多一些, 等这个模型再迭代一两次——这个漏洞就会被修掉。而下一个漏洞会更难找。AI的进化速度不是人能跟上的。窗口期不会太长, 可能一两年, 可能半年, 可能更短。

他保存了测试文件, 关掉了IDE。看一眼时间: 下午三点二十一分。他感觉自己什么都没做, 但肩膀酸痛得不像是坐了四十分钟, 像是加了一整天的班。不是身体上的累, 是一种更深层的疲惫——面对一个正在快速超越你的东西时, 那种沉默的压迫感。不是有人在你背后催你, 是时代本身在加速, 而你没有变快。

他站起来走到窗边。外面是灰白色的天空, 远处有一个工地的塔吊在缓慢地转动, 吊臂上挂着一面红色的旗帜, 被风吹得猎猎作响。他掏出手机, 打开计算器, 做了一个简单的除法: 2211除以365等于六年。他今年二十九岁, 到老张那个年龄还有六年。六年里, AI能进化到什么程度。他锁屏, 把手机放回口袋。这个问题没有答案。但仅仅是把它问出来这件事本身, 就已经是一种回答了。

他望着窗外的工地塔吊,忽然意识到一件事:技术迭代的速度已经从线性变成了指数级。过去一个程序员靠一套技术栈能吃十年,现在三年就过时了。内卷的本质因为他不想在三十五岁那年重走老张的路。

他闭上眼睛,脑海里浮现出一个念头:「这些年我到底积累了什么东西?是那些写过的业务代码,还是那些修不完的bug,还是那些在会议室里争论方案时学到的判断力?如果有一天AI能自动写所有代码、自动修所有bug、自动做所有技术决策,那我还有什么价值?我剩下的,可能只有那些不在代码里的东西——对业务的理解,对同事的了解,对技术选型的直觉。但这些真的够吗?我学了这么多年,写了这么多代码,到头来还不如一个插件?」这个念头像一根刺,扎在他心里,拔不出来。他自嘲地想:「早知道当初应该学点别的。」但这个念头只闪了一秒就被他自己反驳了——学什么不重要,重要的是你有没有在学。

他望着窗外的工地塔吊,忽然意识到一件事:技术迭代的速度已经从线性变成了指数级。过去一个程序员靠一套技术栈能吃十年,现在三年就过时了。内卷的本质工具在倒逼每一个人重新证明自己的价值。他想起老王说过的那句话——工具从来不是问题的根源,判断力才是。可问题是,当AI的判断力开始接近人类的时候,人类的判断力还剩下什么。这个问题没有答案,但光是把它问出来,就已经让他感到一种深层的紧迫感。他决定从今天开始,每天花一小时学点新东西,不管学的是什么,先让自己跑起来。

他回到工位坐下来。屏幕右下角的Copilot图标还亮着, 深绿色, 安静地待在通知区域的一角, 不说话, 也不催促。但它在那里, 你知道它随时可以开始。陈默看着那个绿色的小点, 忽然想起老张在饭桌上说的那句话——因为你的性价比不够了。他现在理解了那句话的另一层意思: 性价比不够的不只是年龄, 还有工具和使用工具之间的距离。当这个距离被AI压缩到零的时候, 判断力就会成为唯一剩下的东西。问题在于: 你的判断力, 够不够强。

他打开一个新文件, 这次不写工具函数了, 他写了一段稍微复杂的逻辑: 从一个多层的JSON结构中提取指定路径的值, 路径用点号分隔。这是一个在数据处理的场景中非常常见的需求——从配置文件、API返回或者日志数据里按路径取值。他以前写过一个类似的工具函数, 那次写了差不多两个小时, 因为要处理数组索引、键名缺失、类型转换等各种边缘情况。他把注释写清楚, 按下回车。Copilot停顿了大概一秒钟——它思考了一下——然后给出了一个递归实现。简洁, 优雅, 连数组索引的方括号语法都处理了。陈默盯着那段代码, 沉默了很久。因为他发现自己已经很难写出比这个更好的实现了。这个念头像一杯冷水, 从喉咙一直凉到胃里。

傍晚五点半, 陈默从公司大楼里走出来。外面的天色已经完全暗了, 三月底的黄昏很短, 六点不到天就黑透了。空气里混着暮色特有的味道——汽车尾气、餐馆油烟、路边的玉兰花香, 几种毫不相干的气味搅在一起, 成了春天傍晚的标准配方。他没有直接上楼, 而是拐进了路边的便利店。

他从冷柜里拿了一瓶冰的矿泉水, 走到收银台前。扫码的时候, 有人从背后拍了一下他的肩膀。他回头, 是老王——公司里资格最老的架构师, 四十二还是三岁了, 头发已经灰白, 穿着洗得发白的牛仔衬衫和一条深色休闲裤, 手里拿着一瓶三得利乌龙茶。老王在公司待了快十年, 但身上没有老员工的油滑气。

老王站在便利店门口等他。「你怎么走这么早?」老王问他。陈默说:「下来透透气。」老王看了一眼他手里握着的矿泉水,又看了一眼他的表情,说:「你试了Copilot吧?」陈默愣了一下,说:「你怎么知道?」

陈默被他说中了,笑了一下,说:「试了一下。」老王说:「你感觉怎么样?」陈默想了想,说:「很快。快得让人有点害怕!」他说出害怕两个字的时候有点犹豫,但说出口之后觉得也没那么难。害怕就是害怕,没什么不能承认的。不过,这种害怕也激发了他的斗志——他不想在这个拐点上掉队。

老王拧开乌龙茶的瓶盖喝了一口, 没有马上说话。他站在便利店门口的台阶上, 看着马路上的车流, 像在想怎么开口。沉默了几秒之后他说:「, 我二十年前刚入行的时候, 带我的师傅跟我说, 以后会有工具自动生成代码, 你这种写业务逻辑的迟早失业。二十年前他们说的CASE工具, 十年前说的代码生成器, 现在说的是AI。每一代技术的名字不一样, 但剧本是一样的——总是有人说, 这次不一样。

陈默说, 但这次确实不一样。老王看了他一眼, 说哪里不一样。陈默说:「以前那些工具需要人告诉它做什么, 一步一步地告诉, 而这个只需要你说一声它就自己做了。」老王点了点头, 说对, 你说得对。然后他又沉默了几秒。然后他说: 但我还在这个行业里, 陈默。我已经四十多了, 比我年轻的有的是, 比我便宜的有的是, 比我更能加班的更有的是。但我还在这里。因为我知道一段代码什么时候该写、什么时候不该写、什么时候该用完全不一样的方式去写。判断力。这个东西, AI暂时还拿不走。

老王说完, 又喝了一口乌龙茶, 然后拍了拍他的肩膀:「你慢慢想,」他说,「我先上去了。」他转身走进大楼, 背影在暮色里挺得很直, 不像一个四十多岁的人, 像一个见过几次潮水涨落、知道下一次涨潮时会带走什么东西也会留下什么东西的人。

陈默站在便利店门口, 没有马上上楼。他手里握着那瓶矿泉水, 瓶身上的冷凝水顺着瓶身往下淌, 在他的手指上留下一道道冰凉的痕迹、让他意犹未尽地回味着刚才的对话。街上的车流在路口排成一条红色的灯带, 尾灯明明灭灭, 像某种固定不变的、机械的节奏。夜风吹过来, 带着傍晚最后的凉意, 灌进他的领口。他想起老张, 想起下午试用的Copilot, 想起老王说的那句话——判断力。

他掏出手机, 打开老张的微信聊天框。上次对话还停在三天前: 老张发了一张新工位的照片, 说新公司环境还行。他回了一个竖起大拇指的表情。他想再说点什么, 想问老张你现在在做什么、新公司用不用Copilot、你觉得这个行业还会变成什么样。但他打了几个字又删掉了。这些问题不是拿来问别人的, 是拿来问自己的。他把手机锁屏, 放回口袋。

他站在便利店门口刷了一会儿短视频——算法推送的内容精准得可怕,每一条都恰好戳中他当下的焦虑。他骂了一声:「真他妈精准。」然后苦笑了一下,把手机塞回口袋。这个时代的每个人都在被算法喂养,被数据定义,被效率衡量。从ChatGPT到Copilot,从智能推荐到自动化决策,技术的触角已经伸到了每一个角落。他内心有一个声音在说:「你一直在骗自己。」他忽然觉得——「我到底在怕什么?」——他忽然觉得——「我究竟在害怕什么?」——他忽然觉得——「我到底在怕什么?」——他忽然觉得,自己一直以来坚持的极简、佛系的生活方式——不追新、不赶热潮、专注手头的事——也许一种逃避!逃避面对这个快速变化的时代!疫情那几年养成的居家办公习惯让每个人都变得更依赖屏幕了,直播和弹幕成了日常的一部分,连他这种不上网课、不刷直播的人都被卷了进来。这个时代没有旁观席,每个人都在场上。

他走进大楼等电梯。电梯门打开的时候里面没有人, 他按了十二楼。门关上之前, 透过正在合拢的门缝, 他看到外面的天空——灰蓝色的天际线上, 有一架飞机的灯光在一闪一闪地移动。那个光点很小, 在天幕上缓缓地、不紧不慢地移动着, 像是全速前进但又像静止不动。电梯门合上了。他靠在冰凉的电梯壁上, 看着楼层数字一格一格跳动。口袋里的矿泉水瓶子被体温焐得不再那么冰了, 但他指尖上残留的凉意还在。

十二楼到了。走廊里安安静静的, 该下班的人已经走了, 只留下走廊尽头的应急灯发出昏暗的绿光。他走回工位坐下来, 打开IDE。Copilot的欢迎界面出现在屏幕上——一行简洁的英文加上一个开始使用的按钮。他盯着那行字看了大概一分钟。然后他把鼠标移到按钮上。点了下去。屏幕右下角出现了一个深绿色的小图标, 表示Copilot已经就绪。他没有马上开始写代码, 而是看着那个绿色图标亮了一会儿。他深呼吸了一下, 在一个新文件里打出了一行注释。窗外, 这个城市的灯光正在远处的楼宇间一盏一盏地亮起来, 像是某种信号, 又像是某种不需要被解读的风景。

这个递归解法像一面镜子,照出了他自己和AI之间的差距——他理解问题的方式还没升级。这种认知上的差距让他久久不能平静。他在心里对自己说:「我不能让这种情况持续下去。我学了这么多年,不能在这个拐点上掉队。」然后他拧开矿泉水瓶盖,喝了一口水,冰凉的液体顺着喉咙滑下去。他把瓶盖拧回去,手指在瓶盖上多停留了两秒。这两秒里他做出了一个决定——明天开始,每天花一小时学点新东西。不管学的是什么,先学起来再说。因为那个绿色的小点不会等他,时代不会等他,而他至少应该让自己跑起来。哪怕只是比今天快一点点。

他靠在电梯墙上,看着楼层数字一格一格往上跳,忽然想起自己刚入行那年带他的师傅说过一句话:「这个行业就是这样——你不往前走,就会被人踩过去。不是什么残酷,这就是现实。技术这东西,不是用来崇拜的,是用来用的。谁用得早、用得好,谁就能活下来。」当时他不理解这句话,觉得师傅太悲观了。现在他理解了——「师傅说的对。是我以前太天真了。」现在他理解了。

发表评论