[控场AI]
· 16 分钟阅读· 8,075 字

AI时代面试博弈:人类专家的核心价值在哪里

AI时代面试博弈:人类专家的核心价值在哪里

当候选人开始用AI工具应对技术面试

当候选人开始用AI工具应对技术面试,招聘方与求职者之间正在上演一场前所未有的"斗智斗勇"。这不仅是面试环节的猫鼠游戏,更折射出一个深层的时代命题:在Agent Coding能力日益强大的今天,学生和从业者到底该如何学习,人类专家的价值又在哪里?

本文基于一位技术团队负责人的亲身面试经历,聊聊AI时代面试的荒诞现实,以及一个值得每个技术人深思的问题。

一道15秒的题,筛掉一半候选人

故事从一篇引发争议的文章说起。一位前CTO设计了一个15秒的coding小测试,声称快速筛掉了50%不合格的候选人。

题目本身极其简单——判断一个循环最终会输出什么结果。但这里藏着一个精心设计的陷阱:题目中的判断条件在网页上肉眼看到的是 x > 3,但通过CSS隐藏了一个等号,实际代码是 x >= 3。

这一技巧利用了CSS视觉渲染与DOM实际内容之间的分离特性。要理解这个陷阱的底层逻辑,需要先理解现代浏览器的渲染架构:浏览器在处理一个网页时,会分别构建两棵树——描述页面语义结构的DOM树(Document Object Model)和描述样式规则的CSSOM树(CSS Object Model),随后将两者合并为渲染树(Render Tree),再经过布局(Layout)和绘制(Paint)阶段输出最终像素。关键在于,DOM树中的文本节点在这个流程的"合并"环节就已经固定,视觉上的不可见操作(如将字符颜色设为与背景相同的白色、设置font-size: 0或opacity: 0)只发生在渲染阶段的后半段,并不影响DOM中文本节点本身的存在。

浏览器在处理文本选择、复制以及向外部程序暴露剪贴板内容时,操作的对象是DOM文本节点而非最终像素输出,因此那些视觉上不可见的字符会被完整地带走。这一特性在无障碍技术(如屏幕阅读器逐字朗读页面)中被广泛依赖,但也构成了所谓"视觉欺骗"(Visual Spoofing)攻击的技术基础——在网络钓鱼或代码供应链攻击场景中,攻击者会利用这一特性在看似无害的代码中嵌入不可见的恶意逻辑。值得注意的是,2023年前后安全研究人员已记录了多起利用Unicode双向控制字符(BiDi)实现类似视觉欺骗的真实供应链攻击案例。

BiDi攻击的原理与CSS隐藏手法属于同一攻击面族群,但更为隐蔽:Unicode标准为支持阿拉伯语、希伯来语等从右向左书写的语言,定义了一组双向控制字符(如U+202A至U+202E、U+2066至U+2069),这些字符本身不可打印,却能改变周围文本在屏幕上的渲染方向。攻击者可以利用它们让一段代码在编辑器中呈现为无害的注释,但实际执行逻辑却完全不同。2021年,剑桥大学研究人员将此命名为"Trojan Source"攻击,并证明了GCC、Clang、Python、Rust等主流编译器和解释器均受影响。这与CSS隐藏手法的底层逻辑完全一致:两者都在利用"语义层内容"与"视觉呈现层内容"之间的裂缝。

而AI工具处理的同样是结构化文本流(token序列)而非人眼所见的视觉呈现,因此和复制粘贴一样,会将那个隐藏的等号一并纳入处理,这正是此类"陷阱题"的设计根基。

如果候选人直接把题目复制粘贴到AI工具或Coding Agent里求答案,那个被隐藏的等号会一起被复制过去,得出的答案就是错的。而那些认真手算的人,反而能给出正确结果。

这位CTO靠这个小把戏排除了一半"把工作直接扔给AI、自己看都不看"的人。有意思的是,他最满意的候选人既不是手算派,也不是AI派——而是那个先给出错误答案、随后又发邮件主动修正的人。在他看来,这个人具备了review AI结果的习惯,这恰恰是AI时代最稀缺的能力。

这个测试是否真的有效见仁见智,但它至少说明:被AI工具"逼疯"的面试官,绝不止一个。

神之一手:一场人与AI的实时对战

真正让人印象深刻的,是两位校招前端候选人的表现。

面试题是一个典型的JS基础题:如何改进原生的 JSON.stringify 方法,来处理对象循环引用导致序列化失败的场景。这道题的妙处在于循序渐进——从会不会高效遍历对象,到懂不懂用指针全等比较来识别循环引用,再到用什么数据结构(数组 vs Set/WeakSet)存储出现过的引用,不同层次的候选人都能展现出自己的知识边界。

面试中的候选人

第一位候选人基础偏弱,却带着鲜明的"AI时代特征"。他选择手动敲代码作答,但整个键盘敲击过程极其生涩。真正诡异的是:他上来第一行就写出了 let cache = new WeakSet() 这样最核心的解法。

作者用了一个绝妙的类比——日本围棋动画《棋魂》里追寻的"神之一手",就像AlphaGo在成名之战中下出的那步让人类难以读懂的棋。

神之一手的类比

为什么说这是"神之一手"?这要从LLM的生成机制说起。当前主流大语言模型均基于Transformer解码器架构,采用自回归(Autoregressive)方式生成文本。所谓自回归,是指模型在生成序列时逐token向前推进,每一步预测下一个token时,以所有已生成的历史token为条件——且无法"回头修改"已输出的内容。这种机制有一个深刻的推论:Transformer中的注意力机制(Attention Mechanism)在生成第一个token之前,已经对整个输入提示(Prompt)进行了完整的全局关注计算,形成了对整体解法结构的概率分布"预期"。

这里有一个值得深入理解的技术细节:Transformer的注意力机制通过计算Query、Key、Value三组矩阵的加权点积,让序列中每个位置都能"看到"其他所有位置的信息。在编码输入Prompt的阶段,这一计算是双向、并行完成的,模型得以在生成第一个输出token之前就形成对整个问题的全局表征。这与循环神经网络(RNN)的顺序处理方式形成鲜明对比——RNN只能逐步积累上下文,对问题末尾的信息存在"遗忘"风险,而Transformer的全局注意力天然消除了这一问题。这也正是为什么LLM能在代码第一行就"锁定"全局最优解:它在落笔前已完成了全局推理,输出过程只是将这个内部状态"解码"为线性文本序列的过程。

因此,LLM往往能在代码的第一行就输出整个解法中最关键的设计决策——例如选用WeakSet而非数组。这种"从结论向过程展开"的线性输出特征,与人类工程师的认知过程存在本质差异。真正的人在思考中写代码时,思维是探索性和增量修正的:你会先定义函数签名、处理基础遍历逻辑,在真正遇到"需要追踪已访问对象"的那一刻,才会意识到需要一个cache结构,然后纠结它该是数组还是Set,最后才可能想到WeakSet的内存优势。

这种由需求驱动的认知跳跃,以及代码结构与思维顺序之间的"不同步",是人类写代码的典型特征。认知科学将这种逐步缩小问题空间的思维模式称为"启发式搜索"(Heuristic Search),它天然伴随着试错、回溯和局部修正。这位候选人显然是在照抄屏幕另一侧AI的流式输出,才会在完全不知道下一步的情况下,先写出了最终答案——这种由果推因的线性确定性,不符合人类认知的探索性特征,暴露了他的真实状态。

当候选人成为AI的"传声筒"

作者没有当场戳穿,而是继续追问:"为什么用WeakSet而不是更常规的数组?"

这个问题触及了一个重要的技术细节。WeakSet是ES6引入的集合类型,其核心特性在于对成员对象持有的是"弱引用"(Weak Reference)。理解这一概念需要先了解JavaScript的垃圾回收机制:V8等JS引擎采用分代式垃圾回收(Generational GC)策略,将对象按生命周期分为新生代(New Space)和老生代(Old Space),并结合标记-清除(Mark-Sweep)算法来处理老生代对象。

判断一个对象能否被回收的核心依据是可达性分析(Reachability Analysis):从一组根节点(如全局对象、当前调用栈中的局部变量)出发,能够被引用链到达的对象会被标记为"存活",无法到达的对象则在清除阶段被回收。普通的数组(Array)或ES6的Set对其存储的对象持有强引用(Strong Reference),这些引用会被计入可达性分析,从而阻止GC回收被引用的对象;而WeakSet持有的弱引用不会被计入可达性图,一旦某个对象在WeakSet以外不存在任何强引用,GC便可在下一个回收周期中自动回收该对象,WeakSet也会将其隐式移除(因此WeakSet是不可迭代的,其大小随GC行为动态变化)。

这一设计哲学并非JavaScript独创。Java的WeakReference、Python的weakref模块、C++的std::weak_ptr均体现了同样的思路:在需要"观察"某个对象但不希望因此延长其生命周期的场景下,弱引用是语义正确的工具选择。值得一提的是,WeakMap与WeakSet在JavaScript中还有另一个重要用途:实现对象级别的私有数据存储。在ES2022正式引入类私有字段(#field语法)之前,开发者常常通过WeakMap将私有数据与对象实例关联,同时确保实例被垃圾回收后,关联的私有数据也自动释放,避免内存泄漏。这一模式进一步印证了弱引用在"不干扰对象生命周期"场景下的不可替代性。这正是为什么在遍历对象图追踪循环引用的场景下,WeakSet是"语义正确"的选择——它让cache本身不成为阻止被遍历对象被回收的原因。这也解释了为什么会用它和知道为什么用它,在这个场景下必然同时出现——如果你真的理解对象引用追踪的内存语义,答案显而易见;如果你不理解,根本就不会往那个方向想。

候选人"思考"了一会(实际是背后的AI在思考),给出了一个标准答案:WeakSet不会内存泄漏,数组如果不清理可能会泄漏。

于是作者进一步追问:"那你能把它换成数组,构造一个会内存泄漏的场景给我看吗?"

我比较喜欢这样写

这里有个精妙的技术细节:候选人当时的写法是把cache放在函数内部,函数执行完就自然销毁,根本不具备泄漏空间。若使用普通数组存储对象引用,只有当cache变量被提升到函数外部并持续存活时,那些已遍历对象的强引用才无法被GC回收,形成内存泄漏。因此AI不得不把这行代码挪到函数外部。此时作者的问题通过候选人"透传"给了背后的AI,变成了作者和AI的直接对战。

当作者追问"为什么一定要移到函数外"时,AI的输出越来越长,候选人的思路彻底跟不上,最后只能倔强地回答:"因为我觉得这样写比较好,我比较喜欢这样写。"面试到此为止。

另一位候选人则坦诚得多,被点破后主动承认使用了AI辅助。作者反而更欣赏这种坦诚。

为什么不建议在面试中"作弊"

这里需要澄清一个态度:作者并不反对在做题时使用AI,反对的是伪装自己没有用AI——这本质上是一种作弊。

更值得关注的是,坦诚的候选人提出了一个直击灵魂的问题:

"在Agent Coding时代,你问的这个问题AI显然能写对。那我作为AI的驾驶员,本身还需要具备这些知识吗?"

这是一个值得认真探讨的问题,简单粗暴地回答"如果AI会那还要你干嘛"显然不够。

AI采纳率75%,为何仍然离不开人类专家

作者用一组数据和一个思想实验回答了这个问题。

先看行业信号:谷歌公开表示,其新生成代码中由AI产出的比例持续攀升,国内外许多科技公司都在财报和新闻中强调类似的"AI采纳率",以此向市场证明自己没有掉队。

Agent生成的代码patch

但作者一针见血地指出:企业内部最终不可能靠这个数字来衡量AI的价值。25%也好、75%也好,本身不直接产生商业价值。商业公司真正追求的是端到端指标——同样周期内多交付了多少功能、Bug减少了多少、人力成本下降了多少。

这里就出现了一个关键的"不挂钩"现象。设想Agent生成了一个3万行的代码patch,其中2万9千7百行完全正确,但有300行存在问题:可能与需求不完全匹配、可能性能不佳、可能扩展性差。

这本质上是一个上下文问题,在技术层面远比"上下文窗口不够长"要深刻。软件工程中大量的设计约束以默会知识(Tacit Knowledge)的形式存在于工程师脑中——这一概念由哲学家迈克尔·波兰尼(Michael Polanyi)在其1958年著作《个人知识》中提出,用以描述那些"我们所知道的比我们所能言说的更多"的知识形态。

值得注意的是,默会知识与"可编码知识"(Explicit Knowledge)之间的张力,在知识管理领域有更系统的理论框架。野中郁次郎(Ikujiro Nonaka)在其1995年著作《知识创造的企业》中提出了著名的SECI模型,将知识在"默会-显性"两个维度之间的转化描述为组织学习的核心引擎。SECI模型指出,默会知识的传递主要依赖"社会化"(Socialization)——即人与人在共同工作场景中的直接互动,而非文档化或口头讲授。这一理论对AI辅助编程时代有直接的现实意义:当AI承担了越来越多的显性编码任务后,工程团队中"社会化"的机会反而被压缩了——新人不再需要通过结对编程向资深工程师学习如何逐行思考,那些通过代码审查传递的架构直觉、通过事故复盘内化的安全意识,都因为"AI已经写好了"而失去了传递载体。这或许是AI提升工程效率的同时,悄悄侵蚀组织知识再生产能力的深层机制。

在软件工程语境中,这类知识包括:某个接口的调用方约定(散落在历史PR评论中)、某个模块的延迟SLA要求(只存在于某次架构评审的会议纪要里)、安全团队对特定编码模式的禁令(通过口头传播而非文档)、以及某位架构师对"可扩展性"的直觉判断(只能通过结对编程传授)。组织行为学研究者将这类知识的积累过程称为"情境化学习"(Situated Learning),它只能在真实工作场景的反复实践中内化,无法通过阅读文档或提示词工程来等效替代。这类知识天然难以被结构化记录,因此几乎不可能被完整地"喂给"Agent作为上下文。我们在做Agent Coding时,很难保证已经把关于需求的所有上下文都输入给了AI——性能要求、安全性要求、稳定性要求、未来扩展性要求,往往不会在开发早期就进入上下文,而是到中后期甚至出问题后才反过来补充。这是当前大语言模型与真实工程环境之间最难逾越的鸿沟之一,也是"上下文窗口长度"这一技术路线所无法单独解决的问题。

而要从3万行里精准找出那300行,需要人类专家具备两个前提:完全理解这3万行代码,并且能快速定位其中有问题的部分。你可以不亲自修改,但你必须能指出问题在哪、方向是什么。做到这一点,一次性采纳率就能达到99%——但这恰恰更依赖那个能"找出300行"的专家。

换句话说,那2万9千7百行人写和AI写没区别,但能否从3万行中找出300行,才是人类价值的核心。这种能力对知识和经验的要求,比过去更高,而非更低。行业的普遍观察也印证了这一点:AI显著提升了初级工程师的产出下限,但同时拉高了对顶级工程师判断力的需求上限。

写在最后:旧路径消失后的迷茫

这篇杂谈留下了一个没有标准答案的问题。

在Agent爆发之前,技术学习路径是相对固定的:看文档、学知识、进入工作场景反复打磨练习,人与人的差距在细节方法和技术品位中慢慢拉开。但到了Agent时代,这条路径突然失效了——你坚持手写代码确实能获得和以前一样的知识,但产出效率完全跟不上工业需求;你跟随大家快速Agent Coding,却发现资深同事早已在传统时代积累了十年的知识底子,作为学生该如何"补课"变得异常困难。

这种两难困境在教育学中并不陌生。认知学徒制(Cognitive Apprenticeship)理论指出,专业能力的核心是将隐性的思维过程"外显化",让学习者在观察和模仿中内化专家的判断框架。当AI代替了大量显性的编码动作后,这个外显化的过程反而变得更难设计——新人看到的只有AI的输出结果,而非专家在与AI协作中所做的那些关键判断和取舍。

认知学徒制理论(由Collins、Brown和Newman于1989年提出)具体描述了专家思维外显化的六个核心教学动作:建模(Modeling,专家当众演示完整思维过程)、脚手架(Scaffolding,为学习者提供恰到好处的支撑)、淡出(Fading,逐步撤除支撑让学习者独立)、阐明(Articulation,要求学习者说出自己的推理过程)、反思(Reflection,对比自己与专家的解题路径)和探索(Exploration,让学习者面对新问题自主求解)。当AI Agent承担了"建模"这一最关键的步骤后——或者说,当学习者习惯于让AI直接输出答案而不是观察人类专家逐步解题——整个认知学徒制的起点就被抽空了。学习者缺乏了"阐明"和"反思"的对象:他们不再有机会将自己的推理过程与专家过程进行比对,因为他们接触到的只有AI的结论,而非任何一个活生生的人类认知过程。这或许正是AI时代技术教育面临的最深层的结构性挑战。

作为招聘方,作者也只能提出"希望编程能力更强"的要求,却给不出具体的实现路径。这份坦诚,或许正是这个时代最真实的写照:我们都知道需要更多能驾驭AI、能找出那300行的专家,但通往这个能力的道路,还在摸索之中。

核心要点

  • CSS隐藏陷阱的技术本质:浏览器DOM与视觉渲染的分离使得不可见字符在复制和AI处理中被完整保留,这一特性同时是无障碍技术的基础和视觉欺骗攻击的根源;Unicode BiDi攻击(Trojan Source)与CSS隐藏手法属于同一攻击面族群,均利用了"机器读取"与"人眼所见"之间的语义鸿沟。
  • LLM「神之一手」现象:Transformer的全局注意力机制使模型在生成第一个token前已完成对整个问题的全局推理,自回归解码过程只是将这一内部表征线性展开的过程——这与人类探索性、启发式的编码认知过程存在可识别的本质差异。
  • WeakSet的语义正确性:弱引用不参与可达性分析,使cache结构本身不阻碍GC对被遍历对象的回收,「会用」与「知道为何用」在内存语义层面必然同时出现;这一设计哲学在Java、Python、C++等多种语言中均有对应实现。
  • 默会知识是AI上下文的系统性盲区:大量工程约束以非结构化形式存在于团队集体记忆中,无法被完整输入给Agent;野中郁次郎的SECI模型进一步指出,AI承担显性编码任务后,组织内部"社会化"传递默会知识的机会也在同步萎缩,这是AI提升效率的同时可能侵蚀的深层能力。
  • 人类价值的重心转移:AI拉平了显性编码能力的门槛,但「从3万行中找出300行」所需的判断力对专业知识和工程经验的要求比以往更高,而非更低;认知学徒制理论揭示,当AI抽空了"建模"这一教学起点后,新一代工程师如何习得这种判断力,是当前技术教育面临的最深层结构性挑战。
分享:

相关推荐