AI 不会吞掉软件,只会吞掉入口
“AI 会吞掉所有软件”这个说法很有传播力,但技术上不够准确。更可能发生的事情是:软件本体继续存在,软件入口被 AI 重写。 计算器、数据库、编译器、PDF 库、浏览器、CAD、CI、权限系统、ERP 不太会因为 LLM 出现而消失。它们处理的是确定性状态、格式、权限、计算和副作用。LLM 不适合直接替代这些系统,却很适合成为它们上方的意图入口。 确定性系统不会消失 裸模型不是确定性程序。它可以写出计算器代码,但不应该代替计算器执行财务计算;它可以解释 PDF 结构,但不应该靠想象修改 PDF 二进制;它可以生成 SQL,但实际执行、回滚、审计和加锁的仍然是数据库。 这不是模型能力不够强时的临时现象,而是范式边界。真实软件世界需要可复现、可审计、可回滚、可授权。神经网络输出可以生成候选方案,却很难成为这些确定性承诺本身。 Claude Code Skills 的 PDF 示例很能说明问题。一个 PDF skill 会把操作流程写进 SKILL.md,再借助 pypdf、pdfplumber、脚本和参考资料处理文件。实际改 PDF 的不是模型“懂了 PDF”,而是模型调度了确定...
Agent Teams 为什么有效
多 Agent 不是把同一个模型多开几份,也不是给系统加几个“人格”。它有效的地方,是把一个会互相稀释的上下文问题,拆成几个更窄、更干净、更容易验证的工作单元。 复杂任务不是信息越多越好。一个 Agent 同时负责需求、架构、编码、测试、文档和发布,很容易在同一个窗口里把角色、证据和目标搅在一起。Agent Teams 的价值,是让每个工作单元只面对一个足够小的世界。 注意力需要降维 考虑一个频谱分析的类比:复杂任务像一段混合信号,包含多个频率分量叠加。单 Agent 试图同时处理所有频率,相当于用一个宽带滤波器——信噪比低,各分量互相干扰。多 Agent 相当于用一组窄带滤波器,每个只提取自己负责的频段,互不干扰,最后再合成输出。 模型的注意力也有这个问题。任务越大,上下文里越容易同时出现目标、反例、日志、旧方案、失败尝试、代码片段和用户补充。它们都在争夺同一个窗口里的注意力。多 Agent 的第一层收益,就是把同一团上下文切成几个局部上下文。 flowchart TB U[用户目标] --> O[Orchestrator: 保持全局目标] O --&...
环境可供性:智能的一半是取到正确数据
没有工具的模型,只能靠提示词获得额外信息。提示词工程在那个阶段几乎是唯一杠杆:把背景写清楚,把例子给够,把格式约束好,让模型在已有上下文里尽量选对路径。 一旦模型拥有主动提取外部数据的能力,问题就变了。智能不再只取决于模型内部能处理多少信息,也取决于它能不能从环境里拿到正确的信息。 Prompt 是喂信息,工具是取信息 prompt-only 系统的工作方式像开卷考试,但试卷、教材和草稿纸都必须提前塞进同一个信封。用户没塞进去的信息,模型默认看不见。它可以猜,可以泛化,可以从训练数据里补常识,但无法可靠知道当前项目、当前日志、当前数据库、当前 API 文档发生了什么。 工具调用改变了边界。ReAct 把 reasoning 和 acting 交织起来,让模型一边推理,一边对外部知识库或环境采取动作获取观察结果。Toolformer 进一步证明,语言模型可以学习在合适时机调用 API,并把结果纳入后续预测。SWE-agent 的核心贡献也不是“又写了一个 coding prompt”,而是强调 Agent-Computer Interface:给 agent 一个适合读文件、改...
上下文换入换出:下一代 scaling
上一篇说裸模型像抽卡,因为它把概率输出直接暴露给用户。抽卡感解释的是一次任务里的波动;上下文问题解释的是长程任务为什么会累、会乱、会跑偏。 LLM 和人都有一个共同约束:它们都在上下文里工作。区别在于,模型的上下文 refill 是读写问题,人的上下文 refill 是注意力问题。机器可以把一段摘要重新塞进 message array,人却要重新把目标、材料、约束和下一步动作装回工作记忆。这个过程有磨损。 人也有 context window 把 LLM 说成统计模型是对的,但这种说法容易遮住它和人的相似工作形态。人从长期通识积累到领域学习,再到职业训练和反馈,很像预训练、继续预训练和后训练的分层。拥有推理能力以后,人也不是在真空中推理,而是在一个被任务材料填充出来的上下文里推理。 上下文质量决定注意力预算能不能被调动。APA 对 multitasking 的综述把任务切换带来的时间成本叫 switching costs。换到工程语境里,context switching 的问题不是“同时做两件事”这么简单,而是每次切换都要重新加载一组任务状态:目标是什么,做到哪里,哪些约束不...
裸模型为什么像抽卡
大模型写代码有一种很危险的爽感:同一个问题,上一轮胡说八道,下一轮突然给出一段漂亮实现。失败的时候像差一点,成功的时候像中奖了。 这种体验很像抽卡。不是因为使用 AI 等同于赌博,而是因为裸模型的反馈结构具备几个相似特征:结果有波动,高分样本偶尔出现,用户很难提前判断下一轮是不是高分,于是自然产生“再试一次”的冲动。 把这种冲动看清楚,比单纯争论模型聪不聪明更重要。很多 AI coding 的燃尽感,不来自模型太弱,而来自人把自己的注意力押在一次又一次低可见度的重试上。工程工作被悄悄改造成了抽卡循环。 flowchart LR A[一次任务] --> B[裸模型采样] B --> C{输出质量} C -->|低分| D[补 prompt / 换模型 / 重试] C -->|高分| E[强奖励: 这次出货了] D --> B E --> F[提高下一轮期望] F --> D D --> G[隐藏成本: review / 归因 / 修复 / 焦虑] ...
Harness 的本质:把随机模型锁进可验证的箱体
把大模型当成一个确定性函数,很容易高估它。更合适的工程抽象是:模型在当前上下文、参数和工具环境给出的概率空间里,采样出一个看起来最合适的结果。 这意味着同一个模型在同一类任务上的能力并不是一个点,而是一段分布。一个平均能做 70 分的模型,在某个具体任务上可能落到 50 分,也可能冲到 90 分。Harness Engineering 的价值,不是把 70 分模型魔法般变成 95 分模型,而是把它的行为压进一个更小、更可验证的区间,让低分尾部少出现,让高分路径更容易复现。 这个区间可以叫“箱体”。Spec、测试、工具、循环、权限、外部状态、子 Agent、hook,都是箱体的不同面。没有箱体时,模型在荒野里寻路;有箱体时,模型在一条被标出边界和检查点的路线上前进。 flowchart TB A[用户目标] --> B[Spec: 目标 / 非目标 / 边界] B --> C[Plan / Tasks] C --> D[模型生成候选方案] D --> E[确定性工具: 编译 / 测试 / schema / 日志] ...
AI 编程让人类更累——从 Vibe Coding 到 Brain Fry 的认知负荷真相
导语 2025 年初,Andrej Karpathy 在 X 上定义了一个词——Vibe Coding:"完全交给 vibes,拥抱指数级增长,忘记代码的存在。"他用语音输入加上 Cursor Composer 与 Claude Sonnet 协作,"Accept All"不读 diff,代码超出自己理解范围。这个定义专门标注了适用场景:throwaway weekend projects。 一年后,这个词被 Collins Dictionary 评为 2025 年度词汇。Y Combinator W25 批次 25% 的创业公司代码库 95% 由 AI 生成。Vibe Coding 从周末实验变成了产业现实。 与此同时,另一条叙事线在英文科技世界悄悄展开:用 AI 写代码的人,开始报告一种新类型的疲惫。不是传统意义上"加班太久"的 burnout,而是一种此前在编程工作中几乎不曾出现的认知消耗。 Andrew Ng 在 LangChain Interrupt 会议(2025 年 6 月)说了两句话,一句承认疲惫——“W...
回到工程:计算理论怎样改变写代码的眼光
这个系列从《计算的本质》重新出发,用 Python 重写核心实验,再把每个模型映射到 Java 程序员熟悉的工程结构。一路走下来,主题并不是记住更多术语,而是换一种方式观察程序。 程序可以是语法树,执行可以是规约,协议可以是自动机,嵌套可以靠栈,通用计算可以由解释器承载,分析工具也可以承认不精确并保持有用。 本文不再引入新模型,只把前面十几篇文章收束成一张工程地图。 概念地图 先把系列里最重要的模型压成一段可运行的概念地图。 12345678910concept_map = [ ("AST / 语义", "解释器、DSL、规则执行"), ("DFA / NFA / 正则", "协议状态、校验器、词法分析"), ("PDA / 栈", "parser、嵌套结构、调用栈"), ("图灵机 / 通用性", "VM、脚本引擎、程序作为数据"), ("停机问题 / 抽象解释", &...
抽象解释:用保守近似理解程序
停机问题说明,对任意程序做完备且正确的停机判断是不可能的。工程分析工具并没有因此失去意义。它们换了目标:不追求精确理解所有程序,而是用可计算的抽象信息给出有用结论。 抽象解释就是这个方向的代表。它把具体值集合映射到抽象域里,用保守规则模拟程序执行。只要抽象规则覆盖了所有可能的具体行为,分析结果就可以用于告警、优化或拒绝高风险程序。 本文用区间分析做一个最小模型:变量不再保存单个整数,而是保存可能取值范围。 从具体值到抽象值 具体执行关心单个值: 123x = 3y = 5z = x + y = 8 抽象执行关心值的集合。若只知道 x 在 0 到 10 之间,y 等于 5,就可以推出: 123x in [0, 10]y in [5, 5]z = x + y => z in [5, 15] 这个结果不精确。z 不一定等于区间里的每个数,但所有可能结果都被包含在 [5, 15] 里。保守性比精确性更重要:不能漏掉可能发生的值。 区间抽象域 区间可以用两个端点表示。 12345678910111213141516from dataclasses import dataclass@...
停机问题:为什么某些判断没有通用程序
上一篇文章用寄存器机解释器说明了通用性:程序可以编码成数据,解释器可以读取这份数据并模拟执行。通用性带来强大表达能力,也带来一个边界问题:能不能写一个程序,判断任意程序在任意输入上是否会停机。 答案是否定的。停机问题说明,不存在一个对所有程序和输入都正确的通用停机判定器。工程里可以做超时、步数限制、静态分析和资源预算,但这些方法要么不完整,要么会保守拒绝,要么只覆盖有限范围。 本文先用一个可运行的有界检查器展示工程近似,再用自引用反证解释为什么通用判定器不存在。 问题形式 停机问题可以写成一个理想函数: 1halts(program, input_data) -> True / False 它的承诺是: 返回值 含义 True program(input_data) 最终会停机 False program(input_data) 会一直运行 难点在“任意程序”和“任意输入”。判断某个具体程序很容易;判断所有程序则会遇到自引用。 工程里常见的近似:有界执行 最朴素的方法是只运行有限步。如果步数内停机,就返回 True;如果步数用完还没停,就返回 Fa...





