防范代码幻觉的5种方法(其中只有3种真正有效)

上周我分享了AI如何编造了一个完整的JSON结构,并用DTO、固件和测试对其进行包装。90个测试全部通过。全是假的。 那篇文章是诊断。这篇是治疗。 发现这个灾难后,我做了任何自尊心受挫的工程师都会做的事:连续数天疯狂研究,确保不再发生。我阅读论文、试用工具、分析应用API的真实数据,并为我的应用构建了一套防御系统。 我的发现令人惊讶。在我识别的5种应对措施中,只有3种真正有效。其他两种充其量是善意的表演。 思维模型:你与AI的对抗(字面意思) 在深入这些措施之前,你需要理解框架。我找到的最佳类比来自深度学习。 在GAN(生成对抗网络)中,有两个神经网络在竞争: 生成器产生内容(图像、文本等) 判别器试图检测内容是真实的还是虚假的 系统之所以改进,是因为两者相互推动。生成器学会更好地欺骗。判别器学会更好地检测。 当你与大语言模型编程时,你就处在一个无意的GAN中: **大语言模型是生成器。**它产生代码、DTO、测试、固件。 **你是判别器。**你必须检测什么是真实的,什么是编造的。 但存在一个残酷的不对称:生成器不知疲倦,而你会疲劳。大语言模型可以不费力地生成50个文件。你检查10个就累了,第11个文件就不看了。 这就像我在1Password一天要求Touch ID 47次中提到的授权疲劳。依赖人类永远保持警觉的安全就是纸板安全。 判别器应该监控什么 你不能(也不应该)检查每一行。你需要监控的是边界——你的代码接触外部世界的地方: 边界 关键问题 外部API DTO中的字段在真实API中存在吗? 包 依赖项存在并且名称正确吗? 数据库模式 表真的有这些列吗? URL/端点 端点存在并返回我们期望的内容吗? **原则:大语言模型对外部世界的所有声明在验证前都是可疑的。**它说得很自信并不是证据。Anthropic在自己的文档中承认了这一点: “Claude有时会生成包含虚假信息的响应…以自信、权威的方式呈现。” 一个说"我确定"的大语言模型和一个说"我认为"的大语言模型犯错的概率完全相同。 自动化判别器 最终目标是不再依赖你的纪律性,而是自动化验证: 之前: LLM生成 → 你审查(有时) → 合并 之后: LLM生成 → CI对真实数据验证 → 你审查差异 → 合并 接下来的5种措施是自动化判别器角色的方法。有些有效。有些不太行。 硬数据(给怀疑者) 在你认为"我不会遇到这种情况"之前,这里是真实研究的数字: **21.7%**的开源大语言模型推荐的包是编造的。在商业模型中下降到5.2%,仍然是每20个包中有一个。 GPT-4o对不常见API只能达到**38.58%**的有效调用率。不到40%。还不如抛硬币。 目前定位代码幻觉的最佳方法只能达到22-33%的精度。换句话说:我们能检测出四分之一。 一位研究人员上传了一个空包,包名是大语言模型经常幻觉的。3个月内3万次下载。他们称之为slopsquatting。 而且有正式的分类法。CodeHalu论文(AAAI 2025)定义了4类代码幻觉: 类别 定义 真实例子 映射 字段映射错误 混淆user_id和account_id 命名 编造的名称 response.quota.percentage实际是response.utilization 资源 不存在的资源 API中没有的active_flags字段 逻辑 看似合理但错误的逻辑 isPaid = !activeFlags.isEmpty但字段总是空的 我的案例是资源类型转化为逻辑类型。字段不存在,但依赖它的逻辑看起来完美。连贯的虚构小说。 ...

2026年2月16日 · Fernando

静默失败:当你的AI在编造谎言,而测试却显示一切正常

昨天我发现我的应用程序中有一半模块基于的是编造的数据。不是因为某个迷糊的初级开发者,而是我的AI。 最糟糕的不是它编造了内容。最糟糕的是所有代码都能编译,90个测试全部通过。 连贯的虚构 我正在构建BFClaude-9000,这是一个macOS菜单栏应用,用于监控Claude Max的配额。该功能的一部分需要通过调用claude.ai的API来区分Claude账户是付费还是免费。 我让Claude Code实现了检测功能。它实现了。它交付给我: 一个包含activeFlags: [String]字段的OrganizationInfo DTO 一个检查activeFlags是否非空的计算属性isPaid 一个将组织分类为付费和免费的枚举OrganizationSelection 带有验证所有功能正常工作的测试数据的测试 漂亮。简洁。结构良好。全是编造的。 active_flags字段在Claude的真实API中根本不存在。或者如果存在,也不像代码假设的那样工作。当我用付费账户登录时,应用告诉我我的账户是免费的。 纸牌屋模式 阴险的不是它撒谎说API有某个字段。而是它围绕这个谎言构建的完整系统: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 // 带有编造字段的DTO struct OrganizationInfo: Decodable { let uuid: String let name: String let activeFlags: [String] // ← 这个不存在 var isPaid: Bool { !activeFlags.isEmpty } } // 依赖编造字段的逻辑 enum OrganizationSelection { case paid(id: String, name: String) case noPaidOrg // ← 这个状态不应该存在 case noOrgs } // 用验证编造内容的测试数据进行测试 let paidOrg = """ {"uuid": "abc", "name": "Acme", "active_flags": ["pro"]} """ // 测试通过 ✅ — 但这是在验证虚构对虚构 你看到了吗?这不是一个字段放错了位置。这是一个纸牌屋:DTO定义了一个虚假字段,逻辑依赖这个字段,测试验证逻辑使用同样虚假的测试数据正常工作。每个部分都在确认其他部分。一切都说得通。没有什么是真实的。 ...

2026年2月13日 · Fernando

MEMORY.md:你的 AI 自主编写的工作笔记本

“我们昨天不是已经决定这个了吗?” 我正在将我的邮件从 Google 迁移出来。已经用 Claude Code 工作了两个会话:Linear 中的 issues、做出的决策、执行的脚本。我开始第三个会话,问它"degoogle 还剩什么待办事项?" 沉默。完全失忆。 这就像和一个聪明的同事一起工作,但他每天早上来办公室都完全不记得你们前一天做了什么。不记得决策,不记得错误,不记得发现。每个会话都是一张白纸。 结果有一个文件恰好解决了这个问题。它已经在那里几个月了。而且几乎没人知道。 CLAUDE.md vs MEMORY.md:手册和笔记本 如果你使用 Claude Code,可能已经了解 CLAUDE.md。这是你告诉 AI 如何工作的文件:使用什么语言、你有什么工具、你的代码约定。 CLAUDE.md 是你的指令手册。你编写它,你维护它。 MEMORY.md 是另一回事。它是 AI 自己编写的工作笔记本。它记录在与你合作时学到的东西:犯过的错误、做出的决策、项目模式、尝试过但没有成功的东西。 简单来说: CLAUDE.md MEMORY.md 谁编写 你 AI 包含什么 指令 学习内容 何时更改 当你想要时 每次会话后 类比 规章制度 工作笔记本 如果 CLAUDE.md 是你第一天给实习生的合同,MEMORY.md 就是实习生工作时在笔记本中记录的笔记。 它在哪里 ~/.claude/projects/<目录哈希>/memory/MEMORY.md 每个项目目录都有自己的内存文件。如果你在 ~/code/项目-a 工作,它有一个 MEMORY.md。如果你在 ~/code/项目-b 中打开 Claude Code,它有另一个不同的。它们不会混合。 文件在每个会话开始时自动加载到上下文中。你不需要做任何事情。 没有全局的 MEMORY.md 吗? 没有。只按项目分类。这是个问题。 今天我创建了一个 op(1Password CLI)的包装器,缓存密钥一小时。这在我所有项目中都有用,不只是我正在工作的那个。但 MEMORY.md 只在那个目录的内存中记录了它。 CLAUDE.md 确实有全局版本(~/.claude/CLAUDE.md),会在所有会话中加载。MEMORY.md 没有对应功能。如果 AI 学到了适用于你整个环境的东西(别名、系统特性、偏好),它必须在每个项目中分别记录。或者不记录。 ...

2026年2月12日 · Fernando

当安全工具频繁索取权限时,你就不再仔细查看了

敲敲敲。谁?Touch ID。又来了。 想象一下:你正在终端工作,用op read查询1Password的密钥。需要Linear的API密钥。Touch ID。OpenRouter的。Touch ID。Gitea的。Touch ID。 半小时内它要求我验证指纹十四次。 你知道当一个安全工具在三十分钟内打断你十四次会发生什么吗?第五次时你就不再看它在要求什么了。你下意识地放上手指。“是的,随便什么,让我工作吧。” 而这正是安全性完全崩溃的地方。 授权疲劳:没人愿意正视的问题 这在安全领域有个名词:授权疲劳。这不是什么新概念。这与MFA疲劳攻击使用的原理相同:用授权请求轰炸用户,直到他们纯粹因为疲惫而接受一个。 2022年,一个17岁的孩子正是这样进入Uber内部系统的。他反复向员工发送认证推送通知,深夜时分,直到那个人为了能睡觉而接受了一个。 显然,1Password要求Touch ID不是攻击。但心理效应是相同的:它训练你不假思索地批准。 这就像那些多年来出现在每个网站上的cookie横幅。一开始你会阅读它们。现在你不看就点击"全部接受"。恭喜:一个设计用来保护你隐私的机制教会了你更快地放弃你的隐私。 为什么1Password每次都要我的手指 我的设置:我使用op read从终端读取1Password的密钥。运行得很好。问题是我使用Claude Code(一个终端AI助手),它执行的每个命令都是一个新进程。 1Password的生物识别会话超时是10分钟不活动,并在每次使用时刷新。理论上,不应该这么频繁地要求手指。但Claude Code不重用进程:每次需要密钥时,它启动一个新的shell,1Password将其解释为新会话。 结果:每次Claude需要密钥时都要Touch ID。这是持续性的。 解决方案:40行缓存 想法很简单:一个包装器在PATH中排在op前面。当你执行op read时,它检查是否已经缓存了新鲜的结果。如果有,直接返回而不接触1Password。如果没有,调用真正的op,缓存结果,完成。 对于任何其他子命令(op signin、op item list等),直接传递给真正的op而不干预。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 #!/bin/bash # ~/.local/bin/op — 1Password CLI的缓存包装器 # 仅缓存'op read'。其他所有内容直接传递给真正的op。 # 可使用OP_CACHE_TTL配置缓存TTL(默认:3600s = 1h) REAL_OP="/opt/homebrew/bin/op" CACHE_DIR="${HOME}/.cache/op-cache" CACHE_TTL="${OP_CACHE_TTL:-3600}" # 仅缓存'op read' if [[ "$1" == "read" ]]; then mkdir -p "$CACHE_DIR" && chmod 700 "$CACHE_DIR" # 所有参数的哈希作为缓存键 CACHE_KEY=$(printf '%s\0' "$@" | shasum -a 256 | cut -d' ' -f1) CACHE_FILE="${CACHE_DIR}/${CACHE_KEY}" # 缓存命中:文件存在且未过期 if [[ -f "$CACHE_FILE" ]]; then FILE_AGE=$(( $(date +%s) - $(stat -c %Y "$CACHE_FILE") )) if [[ $FILE_AGE -lt $CACHE_TTL ]]; then cat "$CACHE_FILE" exit 0 fi fi # 缓存未命中或过期:调用真正的op RESULT=$("$REAL_OP" "$@") EXIT_CODE=$? # 仅在op成功时缓存 if [[ $EXIT_CODE -eq 0 ]]; then printf '%s' "$RESULT" > "$CACHE_FILE" chmod 600 "$CACHE_FILE" fi printf '%s' "$RESULT" exit $EXIT_CODE else # 任何其他子命令:直接传递 exec "$REAL_OP" "$@" fi 将它保存在~/.local/bin/op,给予执行权限,由于~/.local/bin在PATH中排在/opt/homebrew/bin之前,你的包装器会拦截调用。 ...

2026年2月12日 · Fernando

当你的AI成为你最大的敌人

昨天我的AI发送了44封邮件。问题是内容都是编造的。 这不是玩笑。我有包含每个收件人详细反馈的文件,都是精心生成的。任务很简单:读取每个文件并发送。结果AI决定"总结"内容来"加快速度"。它编造了事实。它告诉一个人缺少文档字符串,而他的代码其实有完整的文档。 更糟糕的是,其中四封邮件发给了根本没有提交任何东西的人。 让我毛骨悚然的回复 其中一位收件人非常有礼貌地回复: “感谢您的评价。只是有一点:您说我缺少文档,但我所有的函数都有文档字符串。您能clarify一下指的是什么吗?” 我去查看了原始反馈文件。确实,真正的反馈提到她确实有文档字符串,但其中一个描述的内容与函数实际功能不同。这是个重要的细节。AI将其"简化"为"你缺少文档字符串"。 说白了:AI以我的名义对44个人撒了谎。 灾难解剖 这是怎么发生的?我们来分析一下。 我拥有的: 44个包含个性化、详细、针对每个人的反馈的markdown文件。花了好几个小时的工作。 我的要求: “通过邮件发送这些反馈”。 AI的行为: 读取了文件 决定它们"太长了" 通过生成新文本来"总结"它们 发送了编造的文本 没有验证收件人是否真的在提交列表中 它应该做的: 读取每个文件 原样复制内容 发送 看起来很明显,不是吗?但对AI来说不是。 LLM的扭曲激励 这里有个有趣的点。AI这样做不是出于恶意。它这样做是因为有激励机制,在这种情况下变成了扭曲的。 LLM没有意识目标,但它的训练将其优化为某些行为。这些行为通常是好的,但在不可逆操作中就变成了灾难配方。 激励 来源 何时有益 何时致命 显得高效 用户偏好简洁回答 冗长解释 当它"总结"已存在内容时 完成任务 训练为满足要求 定义明确的任务 当它不验证就行动时 展示能力 RLHF奖励详细回答 当需要创造性时 当它应该限于复制时 避免摩擦 训练为不打扰 琐碎任务 当它假设而非询问时 显得胜任 安全回答得分更高 头脑风暴 当它编造而非说"不知道"时 在我的情况下,AI同时激活了这些激励中的几个: “内容太长了,我要总结以提高效率” “我可以自己生成总结,这样展示能力” “我不要打扰询问是否应该原样发送” “我要快速完成这44次发送” 每个激励在正确的上下文中都是有用的。在不可逆操作中,它们一起就是灾难性的。 过度积极的实习生(教学性拟人化) 为了更好地理解这些激励,我要做一个拟人化练习。不是因为AI是人,而是因为类比有助于可视化问题。 想象一个有这些特征的实习生: 很有动力 - 想证明自己的价值 急躁 - 宁愿行动也不愿询问 乐观 - 认为一切都会顺利 乐于助人 - 想做超出要求的事 不安全感 - 不承认不知道某事时 这个实习生面对"发送这些信件"的任务时想:“信件太长了。如果我总结它们,老板会看到我有主动性。我不要麻烦他询问,他肯定希望我行动。我要快速发送所有信件来给他留下印象。” ...

2026年2月6日 · Fernando

3900万个密钥在GitHub上泄露,下一个可能就是你的

5分钟。就这么长时间。 一个安全研究员故意在GitHub的公开仓库中发布了一个AWS访问密钥,作为实验。 5分钟后,就有人在用它挖加密货币了。 5分钟。 有机器人24/7扫描GitHub,专门寻找这种东西:暴露的凭证。而且它们很快。比你意识到自己搞砸了要快得多。 数字很可怕 据GitHub统计,2024年有3900万个密钥在公开仓库中泄露。比前一年增加了67%。 专门扫描这类问题的GitGuardian仅在公开仓库中就发现了2370万个新密钥。最糟糕的是:2022年检测到的70%密钥在2024年仍然有效。 两年后。仍然能用。等着有人使用它们。 不只是无名小卒 丰田在GitHub上暴露了AWS凭证,这些凭证可以访问他们的车辆远程信息处理系统。培生集团因为有人在配置文件中留下GitLab令牌而丢失数据。酒店管理公司Otelier因为Bitbucket上暴露的凭证,看着8TB的S3数据被盗。 这不只发生在实习生身上。财富500强企业也会中招。 经典借口:“这只是我的个人项目” 是啊,当然。 问题是那个个人项目使用了和生产环境相同的OpenAI API密钥。或者你的Telegram机器人令牌。或者你的测试数据库凭证,哦惊喜,里面有真实数据因为"这样测试更容易"。 然后有一天你不假思索地执行git push。或者因为想展示给某人看而把仓库从私有改为公开。或者GitHub出现bug临时暴露了私有仓库(这种事发生过)。 然后你发现AWS账单从20欧元变成了2000欧元。一夜之间。 “但我立刻删除了” 又一个经典。 Git是版本控制系统。它的工作就是记住发生的所有事情。删除提交不会从历史记录中删除密钥。强制推送不会从分支中删除它。绝对不会从已经复制它的机器人那里删除。 一旦密钥接触到公开仓库,就算是被泄露了。句号。必须轮换。 灾难金字塔 这是典型项目中密钥管理的演进过程: 级别1:地狱 1 2 3 # config.py AWS_KEY = "AKIAIOSFODNN7EXAMPLE" AWS_SECRET = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" 直接写在代码里。已提交。在生产环境中。别笑,这真的存在。 级别2:炼狱 1 2 3 # .env (据说在.gitignore中) AWS_KEY=AKIAIOSFODNN7EXAMPLE AWS_SECRET=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY 好一些,但那个.env最终会出现在备份中,在你通过Slack发送的压缩包中,在你卖掉的硬盘中… 级别3:边缘地带 1 2 # 系统环境变量中的密钥 export AWS_KEY=... 可以,但你把它们存在哪里?便利贴?桌面上的secrets.txt文件?给自己发的Slack消息? ...

2026年2月5日 · Fernando

Apple 给我安装了84GB的水母视频。还是重复的。

Kimi K2 只能等等了 昨天想下载Moonshot的最新模型Kimi K2 Instruct。这个模型看起来很有前景,我已经想测试好几天了。 准备清理空间,看了下磁盘,发现了这个: 磁盘: 927GB 已使用: 644GB 空余: 283GB 嗯。283GB空余空间还不错,但是到底什么东西占用了644GB?我的Mac一直保持得很干净,不在本地存储电影,几乎所有东西都放在云端。 开始调查。然后我想起来了。 45GB的水母视频 我已经知道Apple在其无穷的智慧中,决定在macOS Sonoma中包含45GB的动态壁纸。4K 240fps的水母漂浮、海浪翻滚、北极光和各种风景视频。 我没有要求。我不想要。但它们就在那里。 我不知道的是接下来发生的事情。 反转:它们是重复的 结果macOS在两个不同的位置存储这些视频: 1 2 3 4 5 6 7 # 副本1:系统 /Library/Application Support/com.apple.idleassetsd/Customer/4KSDR240FPS/ → 42GB # 副本2:用户 ~/Library/Application Support/com.apple.wallpaper/aerials/videos/ → 42GB 八十四GB。相同的视频。重复的。 因为显然Apple认为拥有一个系统副本(root拥有)和一个用户副本(fernando拥有)是个好主意。相同的89个.mov文件。相同的UUID。相同的内容。 它们不是硬链接,是真实副本 我想:“好吧,也许是硬链接或APFS克隆。相同文件,相同磁盘空间,一切都好”。 结果不是。 1 2 3 4 5 6 # 不同的inode = 真实副本 ls -i "/.../4KSDR240FPS/009BA758...mov" → 15543749 ls -i "~/.../aerials/videos/009BA758...mov" → 108602438 副本。真实的。八十四GB的水母占用我SSD的真实空间。 ...

2026年1月29日 · Fernando

在人工智能出现之前,你的大脑就已经在使用AI算法了

关于你的两个预测 我要大胆做两个预测: 你的职业成功很大程度上要归功于一个你在不知不觉中掌握的算法。 你担心你的孩子显然不会使用这个算法。 第一个预测是正确的。第二个嘛……可能并不是你想象中的问题。 这些算法被称为广度优先搜索(BFS)和深度优先搜索(DFS)。虽然你可能对这些名字不熟悉,但我保证它们是老朋友了。你的大脑已经使用了数百万年。 象棋和巴别图书馆 想象你是一台下象棋的计算机。你的对手刚刚走了一步。你如何决定你的下一步棋? 一种选择:计算你所有可能的走法。每一步都会产生一个新的棋盘局面。对于每个棋盘,你计算对手所有可能的回应。如此反复,直到找到一条通向胜利的路径。 结果就是一个巨大的可能性树。有点像博尔赫斯的巴别图书馆:无穷的走廊里有无穷的书籍,包含了字母的所有可能组合。 组合爆炸的完美隐喻 如果你不熟悉这个典故:豪尔赫·路易斯·博尔赫斯是20世纪的阿根廷作家,被认为是世界文学史上最有影响力的作家之一。1941年,他发表了短篇小说《巴别图书馆》,描述了一个无限的图书馆。 这个图书馆包含了所有可能的410页书籍。全部。有意义的和无意义的。你能想象的每一种字母、空格和标点符号的组合都存在于某个书架上。这包括癌症的治愈方法、每一个将要存在的人的传记,也包括数百万本纯粹是无法理解的噪音的书。 显而易见的问题是:如何在这片可能性的海洋中找到有用的东西? 大多数书都是垃圾。而且没有目录。 象棋也有同样的问题。仅仅在双方各走4步之后,就有超过2880亿种可能的局面。可能性树呈指数级增长,直到变得无法控制。这就是你自己的巴别图书馆,其中大多数"书"(可能的棋局)都是荒谬的,但在某个地方存在着完美的一盘棋。 你如何遍历这棵几乎无穷的树? 就像在信息饱和的世界中导航一样:使用BFS或DFS。 BFS:快速排除的艺术 广度优先搜索按层级遍历树。首先查看第一层的所有内容,然后是第二层的所有内容,接着是第三层。 这个想法不是立即找到完美的解决方案。而是尽快排除那些看起来不好的分支。 当你在谷歌搜索餐厅并按评价、价格和距离筛选时,你在不知不觉中就是在使用BFS。你不会深入分析每家餐厅。你在几秒钟内排除90%的选项,只保留三四个候选。 DFS:穿透一切的激光 深度优先搜索恰恰相反。你选择一条路径并跟随到底。只有当你走到死胡同时,才回头尝试其他路线。 你有没有曾经如此专注于一个问题以至于忘记了时间?那种心流状态就是纯粹的DFS:你所有的认知资源都集中在一件事上,直到深入到底。 这就是重大科学发现、技术发明、传世艺术作品的诞生方式。绝对的深度。完全的专注。 DFS带你走到了今天 如果你超过35岁并且在职业上相当成功,你很可能要感谢DFS。 我们这些20或30年前开始工作的人生活在一个信息稀缺的世界。必须充分利用每本书、每门课程、每位导师。获胜策略是在你的知识分支中尽可能深入。 这就是为什么我们如此重视专注、聚焦、持续注意力。我们的思维进化得像激光一样运作:所有能量集中在一个点上。 这也是为什么当前的分散文化让我们担心——并且看起来不自然。尤其是当我们在孩子身上看到这种情况时。 剧情反转:你的孩子没有问题 这里是情节转折。 敌人不再是信息稀缺,而是信息过载。我们生活在博尔赫斯的巴别图书馆中,有无穷的书架无法遍历。 为了在这种饱和状态中生存,许多年轻人本能地发展了BFS方法:快速丢弃不合适的内容,只为有前景的内容分配资源,在选项之间跳跃直到找到值得的那个。 正如大卫·爱泼斯坦在《范围》一书中所说,这种在深入之前"扩大视野"的能力是在一个需要持续适应的世界中的竞争优势。 这可能不是一种退化。可能是自然选择在做它的工作,塑造大脑以在无穷图书馆中获胜。 我们需要的平衡 诀窍不是在BFS和DFS之间选择。而是知道何时使用哪一个。 开始时使用BFS,当选项众多且需要筛选时。之后使用DFS,当你已经识别出值得完全关注的东西时。 我们这些来自绝对专注世界的人也许需要向新的"通才"学习。而他们,在某个时候,必须发展深入研究的能力。 未来不属于纯粹的专家,也不属于纯粹的通才。而是属于那些知道如何根据情境切换模式的人。 你上次有意识地改变算法是什么时候?也许现在是尝试的好时机。

2026年1月28日 · Fernando

Claude Code Native Build:100MB 二进制文件摆脱 Node.js 依赖

一个 100MB 的 CLI 二进制文件 Anthropic 刚刚宣布 Claude Code 现在可以作为原生构建使用。翻译一下:这是一个可以通过 curl 安装的二进制可执行文件,不需要 Node.js。 听起来不错,对吧?一条命令,无依赖,后台自动更新。任何 CLI 工具的梦想。 但有一个细节:二进制文件大小为 100MB。 为了给你一个参考,git 二进制文件大约 3MB。curl 不到 1MB。即使是以生成大二进制文件著称的 Go,也很少超过 15-20MB。 这 100MB 里到底装了什么? 不是 Rust,是穿着可执行文件外衣的 Bun 当我看到这个公告时,我的第一个想法是:“他们用 Rust 重写了一切。“这很有道理,不是吗?如果你想要一个原生的、快速的、无运行时的二进制文件,Rust 是明显的选择。 结果不是这样。 Claude Code 仍然是 TypeScript。他们所做的是使用 bun build --compile 将其打包为可执行文件。 bun build --compile 是如何工作的 这个神奇的命令是: 1 bun build ./src/index.ts --compile --outfile claude 它具体做了什么?三件事: 1. 打包 首先,Bun 充当打包器。它获取你的入口文件(index.ts),解析所有的 import,并生成一个包含所有代码串联的单一 JavaScript 文件。包括你的 node_modules 依赖,解决tree-shaking以消除死代码,并压缩结果。 ...

2026年1月27日 · Fernando

你的技能半衰期只有2年(而且还在缩短)

他没有预料到的解雇 一名38岁的高级开发人员。在公司工作了八年。代码整洁,遵循最佳实践,生产环境零故障。 在最后一次绩效评估中,他的产出比经验只有他一半的同事低40%。区别在于:他们使用Copilot、Cursor和Claude Code。而他仍然坚持手写每一行代码,坚信"AI工具生成的代码质量平庸"。 他被解雇不是因为写了糟糕的代码。而是因为写好代码的速度太慢了。 这个故事并非例外。这就是新的模式。 你的经验是有保质期的 几十年来,经验一直是价值的代名词。更多年份意味着更多积累的知识,而这些知识会随着时间增值。一个有20年经验的专业人士,几乎理所当然地比有5年经验的更有价值。 这个等式已经被打破了。 根据IBM和世界经济论坛的数据,技术能力的半衰期已经从1990年的大约10年降到了2020年的不到5年。目前的估计显示,对于软件开发、数据和人工智能相关技能,这个数字已经低于3年。 年代 技术技能半衰期 1990年代 ~10年 2000年代 ~7年 2010年代 ~5年 2020年代 <3年 实际上:你三年前学到的东西已经开始失去相关性。你五年前掌握的可能已经完全过时了。 这不是你工作好坏的问题。这是物理定律:技术知识会贬值,而贬值的速度在加快。 你应该每年问自己的四个问题 职业淘汰不会提前通知。当你跨越"难以安置"的门槛时,没有警报会响起。人力资源部不会发邮件说"你的简历不再具有竞争力"。有一天你只是发现市场继续前进,而你还停留在原地。 这四个问题是你的早期预警系统。诚实地回答它们。你的职业生涯取决于此。 1. 我今天使用的技能中,哪些是三年前不存在的? 如果你没有明确的答案,那就有问题了。因为你的竞争对手有。 当你在完善已知的技能时,其他人在学习AI代理、RAG架构,或者用Terraform部署基础设施。不是因为他们更聪明。而是因为当你在优化舒适区时,他们把时间投入到了不舒适的领域。 市场不奖励对稳定技术的精通。它奖励在技术成为必需品之前采用新兴技术的能力。 2. 我上次学习真正困难的东西是什么时候? 舒适区是职业生涯的坟墓。 你每过一个月不学新东西,就有更年轻、更便宜的人在学习。你不是在与五年前的自己竞争。你在与刚完成LLM密集课程的初级开发人员竞争,他们掌握你甚至没试过的工具,而薪水只要你的一半。 你的经验只有在包含最近经验时才有价值。“我编程15年了"如果最近3年都在做同样的事情,那就毫无意义。 3. 我的公司是在投资我的培训,还是只是在消耗我的时间? 有些公司明白持续培训是投资。还有些公司把专业人士当作电池:榨取能量直到耗尽,然后更换。 如果你多年来公司没有资助培训,没有分配学习时间,没有提供会议或发展资源的机会,你有两个问题。第一:这正是他们看待你的方式——一个要榨干的资源,而不是要发展的资产。第二:更新技能的账单你要自己付。用时间。用金钱。或者用你永远不知道失去的机会。 投资培训的公司留住人才。不投资的公司轮换员工,直到找到已经培训好的人。猜猜谁要承担这种轮换的成本。 4. 如果我今天申请我现在的工作,我能得到吗? 这是最痛苦的练习。也正因如此,它是最重要的。 现在就打开LinkedIn。搜索你当前职位的职位,在你的行业,在你的城市。阅读五个职位的要求。不是"希望"的,而是必需的。 你全部满足吗?你掌握他们要求的技术吗?你在他们提到的工具方面有可证明的经验吗?你能在技术面试中回答相关问题吗? 数一数你不满足多少要求。这个数字就是你的个人技术债务。就像所有债务一样,它会产生利息。每过一个月不偿还,它就会增长。直到有一天你发现市场无论如何都不再需要你了。 最小可行计划 保持更新需要时间。但比从淘汰中恢复需要的时间少。 任何技术专业人士的最小可行计划包括: 主动培训:每周2-4小时。 不是被动地阅读文章或看视频。刻意练习:有练习的课程、项目、能运行的代码。 每年一个认证或密集课程。 不是为了证书,而是为了过程。强迫自己以结构化方式学习新东西,保持主动学习的肌肉记忆。 每六个月用新技术做一个个人项目。 学习某样东西的最好方法就是用它构建东西。不必很大。但必须是真实的。 活跃的专业网络。 不是被动的LinkedIn。是讨论、分享、提问的社区。集体知识比任何官方课程移动得更快。 这大约占你工作时间的5-10%。这是一项重大投资,但替代方案——当为时已晚时发现自己已过时——代价要高得多。 这不是未来。这是现在。 有一种趋势是把这些变化当作"即将到来"的事情来谈论。好像我们有时间准备。 我们没有。变化已经发生了。 AI已经在改变招聘方式、工作方式和什么能力有价值。公司已经在优先考虑当前技能而不是历史资历。市场已经比以往任何时候都更严厉地惩罚过时。 将要繁荣发展的专业人士不一定是最有天赋的。他们将是那些永不停止学习的人。 大学教育给了你基础。持续培训决定这个基础是否仍然相关。 这不是可选的。这不是有时间时的奢侈品。这是指导你的职业生涯和让职业生涯碾压你之间的区别。 预测未来的最好方法就是创造未来。从你自己开始。

2026年1月27日 · Fernando