注册并分享邀请链接,可获得视频播放与邀请奖励。

yibie 的个人资料封面
yibie 的头像

yibie (@yibie)

@yibie
2.4K 正在关注    4K 粉丝
推荐这篇,Dan McKinley(前 Etsy 工程师)写的经典工程文化文章。他说每个公司大约有三次"创新 token"的机会——你选了 NodeJS、MongoDB、使用不到一年的服务发现技术,每次都是花掉一次。而选 MySQL、Postgres、Python、Cron……这些无聊技术的好处在于,不仅功能被充分理解,失败模式也被充分理解。这不是一篇反对新技术的文章——是教你什么时候该用新技术、为什么要给团队设定"使用新东西需要全公司知道"的文化。 选择无聊的技术 我职业生涯中发生的最好的事,大概是有 Kellan 管我。我在那里待得够久,看到了 Kellan 的技术决策开始结出果实。我从中并且作为其结果学到了很多东西。 离开 Etsy 一年后,我重新恢复了对技术的关注能力。我的思考已经结晶到可以连贯地写下来的程度。以下是 Kellan 式思考的总结——希望不会让他太过尴尬。 拥抱无聊 设想每个公司大约有三个创新 token。你可以随心所欲地花它们,但供应量在一段长时间内是固定的。你也许在达到一定程度的稳定和成熟之后能再多拿到几个,但一般倾向是高估你钱包里有多少。 如果你选择用 NodeJS 写你的网站,你刚花掉了一个创新 token。如果你选择用 MongoDB,你刚花掉了一个创新 token。如果你选择用存在了一年或不到的服务发现技术,你刚花掉了一个创新 token。如果你选择自己写数据库——天哪,你麻烦大了。 这些选择中任何一个对一家 JavaScript 咨询公司或一家数据库公司可能是合理的。但你大概率不是。你大概率在为一家至少表面上是"重新思考全球商务"或"重新发明网络支付"或推进某个同样适当宏大的使命的公司工作。在这个背景下,把你有限的注意力用在创新 SSH 上,是一种极好的失败方式。或者至少是延迟成功的方式。 什么算无聊?这有点微妙。"无聊"不应该和"坏"混为一谈。世界上有既无聊又坏的技术——你不应该用这些。但有很多无聊且好的技术选择,或至少足够好。MySQL 是无聊的。Postgres 是无聊的。PHP 是无聊的。Python 是无聊的。Memcached 是无聊的。Squid 是无聊的。Cron 是无聊的。 无聊的美妙之处(如此定义下)在于这些工具的能力是被充分理解的。但更重要的是,它们的失败模式也是被充分理解的。 在选择技术时,你既有已知的未知,也有未知的未知。 • 已知的未知是类似这样的:"我们不知道这个数据库达到 100% CPU 时会发生什么。" • 未知的未知是类似这样的:"老天,我们甚至没有想到写统计量会导致 GC 暂停。" 哪怕对于已经存在了几十年的技术,这两种集合通常都是非空的。但对于闪亮的新技术来说,未知的未知的量级要大得多——这很重要。 全局优化 我毫无歉意地认为偏袒无聊技术是一件好事,但它不是唯一需要考虑的因素。技术选择不是在孤立状态下发生的。它们有一个影响范围,触及整个团队、组织,以及从你所有选择之和里涌现出的系统。 向公司添加技术是带成本的。作为一个抽象陈述这很显而易见:如果我们已经在用 Ruby,再加 Python 感觉不合理,因为增加的复杂性会超过 Python 的边际效用。但不知何故当我们谈论 Python 和 Scala 或 MySQL 和 Redis 时,人们失去了理智,抛弃了所有约束,开始狂热地谈论为任务选最佳工具。 你的工作本质上是将业务问题映射到一个涉及软件选择的解空间上。如果软件选择真的没有包袱,你确实可以为你各种各样问题挑一堆局部最佳的工具。 但在现实世界里——那个运维是严重关切的世界——你是在全局优化。问题在于"最佳工具"思维对它眼中的"最佳"和"任务"是近视的。你的任务是保持公司运转。而"最佳"工具是那个在尽可能多的问题上占据"最不差"位置的工具。 保持系统可靠运行的长期成本基本上总是远远超过你在构建时遇到的任何不便。成熟和多产的开发者理解这一点。 有时选择新技术 把这种推理推到归谬的极端,就是选 Java,然后尝试不借助任何其他东西来实现一个网站。那将是疯狂的。你需要一些向工具箱里添加东西的方法。 重要的第一步是承认这是一个过程,以及一场对话。新技术最终会产生公司层面的影响,所以添加技术是一个需要公司层面可见度的决定。 最值得推荐的练习之一是:考虑如何在不添加任何新东西的情况下解决你的当前问题。 首先,提出这个问题应该能检测到"问题"其实是有人真的想用这项技术的情况。如果是这样,你应该立即否决。 一个小的技术选择集合能走多远,可能令人惊讶。实践中这个问题的答案几乎从来不是"我们做不到",它通常只是某种程度上的"嗯,我们可以做到,但会太难了"。如果你认为你用现有的工具无法实现你的目标,你大概只是不够有创造力地思考。 写下到底是什么让当前技术栈如此昂贵和困难地解决问题,这会有帮助。这和上一个练习相关,但有微妙的不同。 新技术选择可能是纯增量式的(比如:"我们还没有缓存,所以让我们加 memcached")。但它们也可能与你已经在使用的东西重叠或替换它。如果是这样,你应该为将旧功能迁移到新系统设定明确的期望。 策略通常应该是"我们承诺迁移",带有建议的时间线。这一步的目的是把残骸保持在可管理的水平,并避免局部最优解的泛滥。 这个过程并不令人生畏,也不麻烦。就是几个填空题作为作业,然后开个会讨论一下。我认为,如果一项新技术能毫发无损地通过这个挑战,加入它是可以的。 发版就好 多语言编程被包装成一个承诺:让开发者以完全的自由选择自己的工具,会使他们更有效地解决问题。这个问题的定义往好了说是幼稚的,往坏了说是动机性推理。这种方式产生的日常运维苦力的重量把你压死。 有意识地选择技术给了工程头脑真正的自由:沉思更大问题的自由。为技术而技术是万金油。 原文:Dan McKinley, "Choose Boring Technology", 2015 #工程文化# #技术选型# #无聊技术#
显示更多
LangChain 开源了 OpenWiki——一个专门给 agent 用的 CLI,自动为你的代码库写文档并持续维护。不是让你手写文档,是让 agent 写、agent 维护、agent 参考。 OpenWiki:LangChain 开源的 Agent 自维护文档系统 LangChain 昨天发了个新项目,477 star,MIT 开源。OpenWiki 是一个 CLI,专门为 agent 设计——自动给代码库生成文档并持续更新。 安装: npm install -g openwiki 怎么用: openwiki --init 配置模型和 API key → openwiki 生成文档到 openwiki/ 目录 → 之后自动在 AGENTS.md / CLAUDE.md 里追加提示,让 coding agent 知道参考这个 wiki 关键设计: • 支持 GLM 5.2、Kimi K2.6、Sonnet 5 等,默认预配好的模型列表 • 支持 OpenRouter、Fireworks、Baseten、OpenAI、Anthropic • GitHub Action 集成——每天自动开 PR 更新文档 • 文档目录存在就做增量更新,不存在就从头创建 跟我们今天翻译的主题全部呼应: • Karpathy 的 LLM Knowledge Base(同样的概念,这次做成了自动化工具) • EXM7777 的 Agent OS 原则"keep memory in files" • 20 个 Loop 模式里的 Memory Update Loop 这个工具把"让 AI 记住你的代码库"这件事从概念推进到了 npm install 一步。LangChain 说它 built specifically for agents——不是为人类写的 wiki。477 star 说明这件事正好是痛点。 原文: #OpenWiki# #LangChain# #Agent文档#
显示更多
0
21
227
40
转发到社区
推荐这篇文章,Flask 作者 Armin Ronacher 写了这两天我看到最诚实的 loops 反思。之前两篇都在讲 loop 怎么搭、工程怎么落地,这篇问了一个没人敢问的问题:loop 写出来的代码你真的喜欢吗?如果你在用 AI 写代码,这篇可能会让你停下来想一下。 即将到来的 Loop 我不再给 Claude 写 prompt 了。我跑着一些 loop,它们负责给 Claude 写 prompt 并决定做什么。我的工作是写 loop。 — Boris Cherny 过去几个月,我看到越来越多的人在 coding agent 之上构建一些感觉上跟"直接用 coding agent"有本质区别的东西。模式到处都一样:任务被放进某种队列,机器捡起来、尝试、停下来,然后 harness 判断那是不是真的结束。 如果不是,harness 继续同一个 session、注入另一条消息、用修改过的 context 启动一个新的 session、或者把任务发给另一台机器。任务在模型自己本该说"我做完了"的那个点之后,继续活着。 我想这种 loop 想到自己都不好意思承认。 每个 coding agent 内部已经有一个 agent loop 了。模型调用工具、整合结果、再调用工具、读文件、改文件、跑测试、最终生成答案。那个 loop 我们已经相当熟悉了。另一种 loop 是 harness 级别的 loop:agent loop 之外的 loop。那个 loop 也不是新的。从 Claude Code 早期我们就一直在做各种版本,但那个 loop 在 agentic engineering 中越来越重要,最近几周已经开始主导 Twitter discourse。 我还不擅长这个 我目前的状况是:对于我真正在意的代码,我还没怎么成功用过这种工作方式——而这恰好是我相当大一部分代码。 部分原因是品味,部分原因是控制。我对我想要的代码样子设了一个很高的标准,我想理解我交付的代码。在压力下,或者跟另一个人讨论时,我想能够解释清楚系统做了什么,而不是先让一个 clanker 解释给我听。显然,这种"想理解代码"的愿望是否会在几年后依旧存在,是一个问题。但现在,我还没有越过"理解对我来说很重要"这个阶段。 基于这个愿望,对于没有我关注时写出来的代码,尤其是由 loops 产生的代码,我感觉有些东西缺失了。当前模型倾向于产生过于防御性、过于复杂、推理过于局部的代码。它们避免强不变量。它们添加 fallback 而不是让坏状态变得不可能。它们重复代码、发明糟糕的抽象、用更多 machinery 掩盖不清晰的设计。更糟的是:我几乎看不到这方面有什么进步。如果有什么变化的话,我觉得我们可能还在往错误的方向走。至少以我的品味,当前像 Claude Code with ultracode 这样的无人值守 harness 产出的代码,比去年秋天我们产出的还要差。因为 Claude Code 加 Fable 会连续不停地在一个问题上工作 30 分钟甚至更久,而过去这个过程会有更多人参与。 此外,一个众所周知的问题是模型倾向于观察到某个局部失败然后添加局部防御。Karpathy 提到他们"对异常感到极度恐惧"。在具有重要不变量的系统中,尤其是持久化数据格式或核心基础设施,正确的修复不是"处理每个异常情况"。正确的修复是让异常情况一开始就无法被表达或写入。但即便有大量人工引导,LLM 也不会自然地产生那种代码,而且即使代码自然地像那样产生了,它们仍然会试图处理现在已不可能的错误。 当你把这种行为放到 loops 后面时,你往往会放大它。如果每次迭代都添加一个小防御,系统会慢慢变得更不透明,同时表面看起来更健壮。你越放手,这种情况就越严重。当这样的工具交给没有清晰指导的初级开发者时,它还会教给他们非常糟糕的实践。因为如果你问他们为什么做所有这些,他们会令人信服地论证自己的做法。 Loop 在哪里有效 但与此同时,假装 loop 模式不管用也是不诚实的——它在某些领域已经好得惊人。 代码移植就是其中之一。已经有令人印象深刻的大规模自动化移植案例,包括报道中把 Bun 的部分代码从 Zig 移植到 Rust 的工作。我自己也成功用它把 MiniJinja 移植到了 Go。性能探索是另一个效果惊艳的场景。机器可以尝试实验、跑 benchmark、丢弃失败、继续搜索。安全扫描也自然适合,几乎任何类型的研究也一样:让系统探索一个复杂的问题空间然后汇报回来,不一定要提交持久化的代码。 这些场景的共性是:它们要么不生成新代码,而是转换已有代码;要么产生的代码有意不需要长期存活。它们要么产出 PoC 或想法,要么呈现发现,或者更像机械性的转换。 我相信,产出不需要长寿的 artifacts 的 loop,或者产出某种可清晰验证的机械性翻译的 loop,比 harness 机械性地衡量某个目标的一般能力更重要。很多成功的 loop 应用用另一个 LLM 作为 judge 或 orchestrator。机械性翻译场景可以用二元测试用例验证,但它也可以用 LLM 来评判! Claude Code 在创建完整的实验性工作流并执行它们方面,变得越来越好。当然,它生成的代码是 slop,但那更多是模型的问题,而不是 harness 不能很好地判断工作流中的某一步是否带来了净改进或完成。 Harness 只需要一些信号让它能继续。不需要客观或二元——只需要足够有用来驱动下一次迭代。 我非常喜欢那些能把我日常中的无聊部分拿走的 loops——做实验、测量、给我灵感。 软件作为有机体 另一方面,用同样的 loop 方法来写持久化的代码,我还不觉得舒服。我喜欢的比喻是:从软件作为确定性机器,到软件作为有机体。 我成为一名软件工程师的环境鼓励我理解机器。总有一层你可以剥开来加深理解。不展现确定性可观测行为的机器也许被接受,但一般不被认为是最优的。在软件架构上,我认为追求更多的确定性而不是更少是可取的。同样,理解代码的能力一直是一个不可否认的目标。实践中并不总是可能,但我们仍然以写出好的代码为荣,使得即使是新工程师也能通过巧妙的架构在复杂的代码库中导航。在设计良好的系统上,总有一些工程师知道不变量在哪里,哪些部分是承重的,哪些改动是安全的。理想情况下所有这些都是有良好文档的。在缺乏这种理解的地方,通常被认为是需要改进的事情。 显然,那个理想一直都很紧张。许多软件系统,尤其是非常成功的系统,在工程师能让它保持干净的时期过后,常常变得太大、太动态、太依赖外部服务,无法装进任何人的脑袋。即使没有 LLM,我们在诊断分布式系统时也已经有点像医生了:观察症状、提出假设、"开更多检查"、尝试一些补救措施、再次观察。 但有了 LLM,我们正在沿着这个方向走得更远更快。我们用它们来写代码,也用它们来诊断和治疗。已经有大量工程师生活在这样一个世界里:生产问题发生后的第一步是让 clanker 读日志、提出根因、主动提出 patch。结果 patch 通常被另一台机器捡起来审查,有时甚至没有任何人工监督就合并到了 main。 显然这很强大,我不能否认它听起来很诱人。但屈服于这个想法,特别是随着人类监督越来越少,意味着接受我们可能无法再以同样的方式理解整个系统。我们治疗它、监控它、稳定它,但我们不一定理解它。 我毫不怀疑对于某些软件来说,这没问题。不是每一行代码都值得人类作者身份,而且过去也可能写过更差的代码。 但我希望所有软件都这样写吗? 你无法完全退出 非常令人不安的是,选择退出这个全机器驱动的未来可能不是一个选项。 安全是最清晰的例子。即使你不用 loops 来构建你的软件,别人也会用 loops 来攻击你的软件。攻击者会持续运行机器,即使不是攻击者,安全研究人员也会,而其中一些自动化工作会产生大量噪音但也会发现真正的问题。信号和噪音都会以如此大的规模涌向你,以至于你几乎不得不也扔一台机器来处理。 Daniel Stenberg 关于 curl 的 summer of bliss 的帖子是一个很好的例子,展示了维护者已经承受的压力。据我所知,AI 在 curl 的核心开发中并没有扮演重要角色。但尽管如此,维护者还是被报告淹没了——其中大部分是 AI 生成的。 如果攻击者和报告者都在 loop,防御者最终也需要 loop 才能跟上。也许不是直接写 patch,也许只是用来 triage 和复现——但压力会增加。 竞争也是一样。有些团队会通过原始速度超越其他团队。有些项目会突然加速,因为一个小团队搞清楚了如何有效编排机器。有些 startup 可以用五个人做到过去需要五十个人的事。有些人可能会直接把一台机器放在一个 loop 里对着你的产品,告诉它"把它做得像那个一样"。而如果他们的用户很开心,这真的重要吗? 不是所有软件都会受到同等影响。有些领域会惩罚草率,要求信任和责任,但很多软件生活在一个原始速度、快速实验和大面积覆盖至关重要的世界里。 建立新的依赖 最可怕的部分是,我们以新的方式变得依赖于这些新机器。软件一直依赖工具。我还记得我不得不为编译器付费的时候。这些新工具让人回想起那些创造软件需要真实成本的日子。但现在不再是一次性付款了——它是一种持续的依赖。不只是对钱包的依赖,还有认知依赖。 如果一个代码库由 loops 产生、由 loops 审查、由 loops 打补丁、由 loops 维护,当你不再能访问同等级别的系统时会发生什么?当某些贸易限制剥夺了对最强模型的访问时?如果只是成本变得不可接受呢?如果你和你的团队只是丧失了不用机器理解代码的最后一点能力呢? 我们可能会创建出不仅人类难以维护、而且把机器参与作为其维护模型前提的代码库。这已经在发生了!不是在所有地方都发生,甚至可能不是以被视为有问题的方式在发生,但我们看到越来越多。人们越来越多地合并他们不能完全解释的代码。人们失去了创建 issue 报告或在聊天中讨论事情的能力,而不借助 clanker 增强或改写他们的消息。太多人越来越依赖机器来总结或提供上下文。我越来越多地遇到通过 LLM 这个中间人与我交流的人。 再说一次,也许这甚至不一定是错的,但它对我们做事的方式是一个巨大的改变。 未来的 Harness 我毫不怀疑这就是方向,但朝着这个方向走需要我们在所有地方都改善我们的工具,而不只是在 coding agent 里。 仅仅编排更多的 loops 是不够的。更好的变更可视化或编排或 agent 不会恢复我们的理解。要么我们需要找到巧妙的方法把人拉回 loop,让 loop 的变更长期可读,要么我们需要找到更好的方法来组合这些越来越复杂的系统。 这也是我对 Pi 的角色的想法在变化的地方。Pi 一直很谨慎,我认为这种谨慎是好的。我不希望一个每一次交互都变成不受控制的机器 swarm、做出我无法跟上的变更的未来。我不希望 Pi 为了赢得"软件自己写自己"的竞赛而变成一个不可维护的混乱,我也不希望 Pi 推广这类工程。但与此同时,Pi 是一个 harness,而 harness 正处在人们运行这些新型实验的中心。 编码任务的任务队列、agent 编排、子 agent、持久化 session 会变得越来越重要。即使是我们这些有保留意见、没有盲目拥抱 loops 的人,也必须要开始做这些实验了。因为我们需要理解如何让这个未来有边界、可生存。 控制 Loop 正如你从这篇文章中读到的,我对这个未来非常不安。不是因为恐惧,而是因为基于对这项技术至今的经验而产生的谨慎。 采用 harness loop 的想法意味着 harness 决定工作何时完成。在 agent loop 中,模型最终说"完成"然后我审查。即使在那之前,我通常也在沿途引导。我参与其中,我喜欢在学习中前行。在 harness 操作的 loop 中,我不确定我的角色到底是什么。甚至"完成"信号也失去了所有意义,只是变成了传递给另一台机器进行评判的信息。我的角色被简化为一个信使。 今天,我不喜欢我看到的那种用这种方式构建的系统产生的代码,我也不喜欢与太多用 AI 辅助构建的软件交互。Loop 很强大,但它越来越多地移除责任,至少在当下它非常鼓励我们向机器投降。 然而,我毫不怀疑这个 loop 化的未来就是我们的未来——尽管我目前对此感到反感。我已经看到惊人小的团队以不可能的速度在构建,我看到代码库正在变成越来越模糊和混乱的有机体,只能由更多机器来诊断。这些代码库同时既有用又混乱。 所以我想我开始接受一个事实:问题不是我们会不会 loop——显然我们会的。也许问题是:在一个 loops 的未来里,我们如何不放弃判断,如何在其中保留良好工程的原则,如何确保负责任的人能够继续监督,如何重新思考我们架构代码的方式以在其中保持清醒。 原文:Armin Ronacher, "The Coming Loop", 2026-06-23 链接: #AI# #Loops# #软件工程# #反思#
显示更多
我有一个观点,最终大家都会跑来用 Pi 的。 Pi 就是 Agent 届的 Android。
0
46
144
9
转发到社区