Anthropic 如何设计抗 AI 的技术评估:三次改版 take-home 的经历
Designing AI-resistant technical evaluations
Anthropic 性能工程团队复盘了其招聘 take-home 测试被 Claude 模型逐步攻破的过程:Claude Opus 4 在 4 小时限制内超过大多数人类申请者,Claude Opus 4.5 则追平了 2 小时限制下的最佳人类成绩。
Anthropic 性能工程团队复盘三次改版招聘 take-home 的过程,呈现了模型能力提升如何逐步瓦解原有评测设计。
随着 AI 能力的提升,评估技术候选人变得越来越困难。一份今天能很好区分人类技能水平的 take-home 测试,明天可能被模型轻松解决——从而使其在评估中失去作用。
自 2024 年初以来,我们的性能工程团队一直使用一份 take-home 测试,要求候选人为一个模拟加速器优化代码。已有超过 1,000 名候选人完成了该测试,其中数十人现在在这里工作,包括搭建我们 Trainium 集群的工程师,以及自 Claude 3 Opus 以来交付每一个模型的工程师。
但每一个新的 Claude 模型都迫使我们重新设计测试。在相同时间限制下,Claude Opus 4 的表现超过了大多数人类申请者。这仍然让我们能够区分最强的候选人——但随后 Claude Opus 4.5 连那些人也追平了。在时间不受限的情况下,人类仍然可以胜过模型,但在 take-home 测试的约束下,我们已无法区分顶尖候选人的产出和我们最强模型的产出。
到目前为止,我已经迭代了三个版本的 take-home 测试,试图确保它仍然具有区分信号。每一次,我都对什么能让评估对 AI 辅助保持稳健、什么不能,有了新的认识。
本文介绍了最初的 take-home 设计、每个 Claude 模型如何攻破它,以及为确保我们的测试领先于我们最强模型的能力,我不得不采取的越来越不寻常的方法。尽管我们所做的工作随着模型一同演进,我们仍然需要更多优秀的工程师——只是需要越来越有创意的方式来找到他们。
为此,我们将最初的 take-home 作为公开挑战发布,因为在时间不受限的情况下,最佳人类表现仍然超过 Claude 所能达到的水平。如果你能胜过 Opus 4.5,我们很乐意收到你的消息——详情见本文末尾。
take-home 的起源
2023 年 11 月,我们正准备训练和发布 Claude Opus 3。我们已获得新的 TPU 和 GPU 集群,我们的大型 Trainium 集群即将到位,我们在加速器上的支出远超以往,但我们的性能工程师数量不足以支撑新的规模。我在 Twitter 上发帖请人们给我们发邮件,这带来的有希望的候选人超出了我们通过标准面试流程所能评估的数量,而该流程会消耗员工和候选人大量的时间
我们需要一种更高效地评估候选人的方式。于是,我花了两周时间设计了一份 take-home 测试,力求充分体现该岗位的要求并识别出最有能力的申请者。
设计目标
Take-home 测试名声不佳。通常它们充斥着工程师觉得无聊的通用问题,筛选效果也很差。我的目标不同:创造一些真正有吸引力的东西,让候选人乐于参与,并让我们能够以高分辨率捕捉他们的技术技能。
对于评估性能工程技能,这种形式相比现场面试也有优势:
更长的时间跨度:工程师在编码时很少面对少于一小时的截止时间。4 小时的窗口(后来缩短为 2 小时)更好地反映了工作的实际性质。它仍然比大多数真实任务短,但我们需要在这一点与其繁重程度之间取得平衡。
真实的环境:没有人在旁观看或期待解说。候选人在自己的编辑器中不受干扰地工作。
理解与工具构建的时间:性能优化需要理解现有系统,有时还需要构建调试工具。这两者在正常的 50 分钟面试中都很难被真实评估。
与 AI 辅助的兼容性:Anthropic 的通用候选人指南要求候选人在没有特别说明的情况下不使用 AI 完成 take-home。对于这个 take-home,我们明确说明可以使用 AI。
更长周期的问题更难被 AI 完全解决,因此候选人可以使用 AI 工具(就像在工作中一样),同时仍然需要展示自己的能力。
除了这些针对形式的目标之外,我在设计这个 take-home 时还应用了设计任何面试时都会用的相同原则:
代表真实工作:问题应该让候选人体验这份工作实际涉及的内容。
高信号:take-home 应避免那些只依赖单一洞察的问题,并确保候选人有多次机会展示自己的全部能力——尽可能减少偶然性。它还应该有较宽的评分分布,并确保足够的深度,即使是很强的候选人也不会完成所有内容。
不要求特定领域知识:基础扎实的人可以在工作中学习具体细节。要求狭窄的专业知识会不必要地限制候选人池。
有趣:快速的开发循环、有深度的有趣问题,以及发挥创造力的空间。
模拟机器
我为一种具有类似 TPU 特性的假想加速器构建了一个 Python 模拟器。候选人在这个机器上优化代码,使用热重载的 Perfetto trace 来显示每条指令,类似于我们在 Trainium 上的工具。
这台机器包含一些让加速器优化变得有趣的功能:手动管理的暂存器内存(与 CPU 不同,加速器通常需要显式内存管理)、VLIW(多个执行单元每个周期并行运行,需要高效的指令打包)、SIMD(每条指令对多个元素进行向量操作)以及多核(将工作分配到多个核心)。
任务是并行树遍历,刻意不带深度学习色彩,因为大多数性能工程师当时还没有做过深度学习,可以在工作中学习领域细节。这个问题受到无分支 SIMD 决策树推理的启发,这是一个经典的 ML 优化挑战,作为对过去的致敬,只有少数候选人以前遇到过。
候选人从完全串行的实现开始,逐步利用机器的并行性。热身是多核并行,然后候选人选择处理 SIMD 向量化还是 VLIW 指令打包。原始版本还包含一个 bug,候选人需要先调试它,锻炼他们构建工具的能力。
早期结果
最初的 take-home 效果很好。来自 Twitter 批次中的一个人得分远高于其他人。他在二月初开始,比我们通过标准流程招聘的第一批人晚了两周。测试被证明具有预测性:他立即开始优化内核,并找到了一个阻碍发布的编译器 bug 的解决方法,该 bug 涉及张量索引数学溢出 32 位。
在接下来的一年半里,大约有 1,000 名候选人完成了这项带回家作业,它帮助我们招聘到了目前性能工程团队的大部分成员。事实证明,它对纸面经验有限的候选人尤其有价值:我们有几位表现最出色的工程师直接来自本科,但在这项带回家作业中展现出了足够的技能,让我们能够放心地录用他们。
反馈是正面的。许多候选人因为乐在其中而超过了 4 小时的时间限制。最强的无时间限制提交中包括完整的优化迷你编译器和几个我未曾预料到的巧妙优化。
然后 Claude Opus 4 击败了它
到 2025 年 5 月,Claude 3.7 Sonnet 已经逐步提升到这样的程度:超过 50% 的候选人完全委托给 Claude Code 会做得更好。随后我在该带回家作业上测试了 Claude Opus 4 的预发布版本。它给出的解决方案比几乎所有人类在 4 小时限制内做出的都更优化。
这并非我第一次被 Claude 模型击败的面试题。我在 2023 年专门设计了一道现场面试题,因为当时我们的题目都基于早期 Claude 模型掌握大量知识的常见任务,因此它们可以轻松解决。我尝试设计一道更依赖问题解决能力而非知识的题目,仍然基于我在工作中解决过的一个真实(但小众)的问题。Claude 3 Opus 击败了该题的第 1 部分;Claude 3.5 Sonnet 击败了第 2 部分。我们仍在使用它,因为我们的其他现场面试题同样无法抵御 AI。
对于这项带回家作业,有一个直接的解决办法。这个问题的深度远超任何人在 4 小时内能探索的范围,因此我用 Claude Opus 4 来找出它开始吃力的地方。那成为了版本 2 的新起点。我编写了更清晰的起始代码,添加了新的机器特性以增加深度,并移除了多核(Claude 已经解决了这一点,而且它只会拖慢开发循环,不增加信号)。
我还将时间限制从 4 小时缩短到 2 小时。我最初选择 4 小时是基于候选人反馈,他们更希望降低因在某个 bug 或困惑上卡住一段时间而陷入困境的风险,但排期开销导致我们的流程出现数周的延迟。两小时更容易安排进一个周末。
版本 2 强调巧妙的优化洞察,而非调试和代码量。它为我们服务得很好——持续了几个月。
然后 Claude Opus 4.5 击败了它
当我测试 Claude Opus 4.5 的一个预发布检查点时,我看着 Claude Code 在该问题上工作了 2 小时,逐步改进其解决方案。它解决了最初的瓶颈,实现了所有常见的微优化,并在不到一小时内达到了我们的通过阈值。
然后它停了下来,确信自己已经撞上了一个无法逾越的内存带宽瓶颈。大多数人类也会得出同样的结论。但有一些巧妙的技巧可以利用问题的结构来绕过那个瓶颈。当我告诉 Claude 可能达到的周期数时,它思考了一会儿,找到了那个技巧。随后它进行调试、调优并实现了进一步的优化。到 2 小时节点时,它的得分与人类在该时间限制内的最佳表现相当——而那个人类大量使用了 Claude 4 并加以引导。
我们在内部测试时计算框架中进行了尝试,以获得更严格的结果,并确认它既能在 2 小时内击败人类,又能随时间继续攀升。发布后,我们甚至以通用方式改进了我们的框架,并获得了更高的分数。
我遇到了一个问题。我们即将发布一个模型,而在我们的 take-home 测试中,最佳策略竟然是委托给 Claude Code。
考虑各种选项
一些同事建议禁止使用 AI 辅助。我不想这么做。除了执行上的困难之外,我觉得既然人在我们的工作中仍然扮演着至关重要的角色,我就应该能想出某种办法,让他们在有 AI 的环境中脱颖而出——就像他们在工作中会遇到的那样。我还不想就此认输,接受那种想法:人类只在耗时超过几个小时的任务上才有优势。
其他人建议把标准提高到“显著超越 Claude Code 单独取得的成果”。这里的顾虑在于 Claude 工作得很快。人类通常要花两个小时中的一半时间来阅读和理解问题,然后才开始优化。一个试图引导 Claude 的人很可能始终落后,只能在事后才理解 Claude 做了什么。主导策略可能会变成袖手旁观。
如今,Anthropic 的性能工程师仍然有很多工作要做,但工作内容更像是艰难的调试、系统设计、性能分析、弄清楚如何验证我们系统的正确性,以及弄清楚如何让 Claude 的代码更简单、更优雅。不幸的是,如果没有大量时间或共同的背景,这些事情很难被客观地测试。设计能代表实际工作的面试一直很难,但现在比以往任何时候都更难。
但我也担心,如果我投入精力设计一个新的 take-home,要么 Claude Opus 4.5 也能解决它,要么它会变得太难,人类不可能在两小时内完成。
尝试 1:一个不同的优化问题
我意识到 Claude 可以帮我快速实现我设计的任何东西,这促使我尝试开发一个更难的 take-home。我基于自己在 Anthropic 做过的一个比较棘手的 kernel 优化来选题:在 2D TPU 寄存器上高效地进行数据转置,同时避免bank 冲突。我把它提炼成一个在模拟机器上的更简单的问题,并让 Claude 在不到一天的时间里实现了这些改动。
Claude Opus 4.5 找到了一个我甚至没想到的绝佳优化。通过仔细分析,它意识到可以转置整个计算,而不是想办法转置数据,并相应地重写了整个程序。
在我的真实案例中,这样做行不通,所以我修改了问题以移除这种方法。Claude 随后取得了进展,但找不到最高效的解决方案。看起来我有了新问题,现在只需希望人类候选人能足够快地解决它。但我有些挥之不去的疑虑,于是我用 Claude Code 的“ultrathink”功能以更长的思考预算进行了复核……结果它解决了。它甚至知道修复 bank 冲突的技巧。
事后看来,这不是一个适合尝试的问题。许多平台上的工程师都在数据转置和 bank 冲突上挣扎过,所以 Claude 有大量训练数据可以借鉴。虽然我是从第一性原理出发找到解决方案的,但 Claude 可以借助更大的经验工具箱。
尝试 2:走更古怪的路线
我需要一个人类推理能战胜 Claude 更大经验基础的问题:某种足够分布外的东西。不幸的是,这与我想要让它明显像实际工作的目标相冲突。
我回想了一下自己最喜欢的那些最不寻常的优化问题,最后想到了 Zachtronics 的游戏。这些编程解谜游戏使用不同寻常、高度受限的指令集,迫使你以非常规的方式编程。例如,在 Shenzhen I/O 中,程序被拆分到多个相互通信的芯片上,每个芯片只有大约 10 条指令和一两个状态寄存器。巧妙的优化往往涉及把状态编码进指令指针或分支标志中。
我设计了一套新的 take-home 题目,由使用极小、高度受限指令集的谜题组成,要求优化解法以达到最少的指令数。我实现了一道中等偏难的谜题,并在 Claude Opus 4.5 上进行了测试。它失败了。我补充了更多谜题,并让同事验证:对这个问题远不如我熟悉的人,仍然能超过 Claude。
与 Zachtronics 的游戏不同,我故意没有提供任何可视化或调试工具。起始代码只检查解法是否有效。构建调试工具本身就是被考察的一部分:你可以插入精心设计的打印语句,也可以让编码模型在几分钟内生成一个交互式调试器。如何投资于工具,这种判断本身就是信号的一部分。
我对这套新的 take-home 相当满意。它的方差可能比原来的更低,因为它由更多相互独立的子问题组成。早期结果令人鼓舞:分数与候选人过往工作的水准相关性很好,而我最有能力的一位同事得分高于迄今为止的任何候选人。
我仍然为放弃了原题的真实感和多样的深度而感到遗憾。但真实感或许已是我们不再拥有的奢侈品。原题之所以有效,是因为它像真实的工作。替代品之所以有效,是因为它模拟了新颖的工作。
一个公开挑战
我们将原版 take-home 公开,任何人都可以不受时间限制地尝试。在足够长的时间跨度下,人类专家仍然保持优势,胜过当前的模型。有史以来提交的最快人类解法,大幅超过了 Claude 即使在大量测试时计算下所达到的成绩。
发布的版本从零开始(像版本 1 一样),但使用版本 2 的指令集和单核设计,因此周期数与版本 2 相当。
性能基准(以模拟机器的时钟周期计):
- 2164 个周期:Claude Opus 4 在测试时计算框架中运行许多小时之后
- 1790 个周期:Claude Opus 4.5 在一次随意的 Claude Code 会话中,大约相当于人类在 2 小时内的最佳表现
- 1579 个周期:Claude Opus 4.5 在我们的测试时计算框架中运行 2 小时之后
- 1548 个周期:Claude Sonnet 4.5 在远超 2 小时的测试时计算之后
- 1487 个周期:Claude Opus 4.5 在框架中运行 11.5 小时之后
- 1363 个周期:Claude Opus 4.5 在改进后的测试时计算框架中运行许多小时之后
在 GitHub 上下载。如果你优化到 1487 个周期以下,击败 Claude 在发布时的最佳表现,请将你的代码和简历发送至 performance-recruiting@anthropic.com。
或者你也可以通过我们的常规流程申请,该流程使用我们(现在)能抵抗 Claude 的 take-home。我们很好奇它能坚持多久。
来源:Anthropic Engineering · anthropic.com