🛠️ 第1章 Codex 是聊天机器人,更是交付工具
📄 一句话概括

三次演进换的都是同一件事:把人搬运的颗粒度,从字符放大到任务。 补全时代搬的是几个字符,对话时代搬的是一段代码,委派时代搬的是一个任务。 颗粒度一变,「人管什么」就跟着变——从管打字,变成管验收。

📝 本章和前面几章的关系

这是全书的第一篇,先把位置摆清楚。前面 49 门课讲的多半是「某个东西怎么工作」—— SQL 怎么执行、TCP 怎么握手、FFmpeg 怎么解码。 这一门讲的是「你怎么用它」,而且用的东西本身还在变。 教材第 1 章四节,从历史讲到哲学: 三次演进、为什么它是交付工具、心智模型怎么转、规则为什么比聪明重要。 这四节合起来回答一个问题:凭什么说它不一样。 沙箱里没有装 Codex, 所以这一章几乎没有「跑命令」的内容—— 但它有一个自己能做的实验:把一个真任务,用三种颗粒度各做一遍,量轮数。 配套:22 课 Harness 技术架构原理。 那一门讲这套东西内部怎么转,读完再回来读这一章,会顺很多。

一、第一次演进:补全一个 token

最早的那一代,干的事只有一件:猜你下一个要敲什么。你在编辑器里敲了 for (int i = 0; i, 它把 < n; i++) 灰字摆在你后面,按 Tab 收下,不按就继续敲。 它的视野就是光标前后那几十行,而且它不执行、不验证、不记得上一次。 你让它写一个函数,它写完就完了—— 这个函数在别处有没有同名、调用它的地方会不会挂,它完全不知道,也不负责。 这一代的价值是真的:样板代码、重复的 getter、见过一万遍的正则,敲三个字符就能出来。 但它解决的是「打字太慢」,不是「活儿太多」。 这两件事经常被混为一谈——打字快十倍,不等于交付快十倍。

二、第二次演进:选一段再对话

第二代把「上下文」这件事交给了人:你选中一段代码,在旁边说一句话,它改这一段。 选中范围就是它的世界观——你选了三行,它只知道三行。 这一代最大的进步是「能理解意图」:你说「这段改成提前返回」,它知道要把嵌套的 if 拆平; 你说「这个循环太慢」,它知道要换个写法。补全做不到这个——补全只能接续,不能改写。 但它把搬运的活儿留给了人。 它给你一段新代码,你得自己复制、自己贴回去、自己对齐缩进、自己去别的地方看看有没有跟着改。 一段代码改六个文件,就是六次复制粘贴——机器没累,人累了。 还有一个隐性的坑: 它改的是你贴过去的那一段文本,不是你仓库里的那个文件。 所以你贴回去的时候,如果原文件在你选中之后被别人改过,你就把它覆盖了。 这一代工具没有「文件」这个概念,只有「文本」。

三、第三次演进:把任务交出去

第三代换了个单位:不是「一段代码」,是「一个任务」。你给的不是代码片段, 是一句需求加上一个仓库;它自己去读文件、自己改、自己跑测试、自己把结果拿回来。 这一代跟前面两代的分水岭是「它有了手」。 补全只有嘴(给你文字),对话也只有嘴(给你代码), 委派这一代有手——它能读文件、能写文件、能跑命令、能看命令的输出。 手一有,「验证」这件事就不需要人代劳了。 但手一有,风险也就来了。 它能在你仓库里删文件、能 git push、能连数据库。 前两代顶多给你一段错代码,这一代能给你一个错状态。 所以第三代工具的全部设计重心,最后都落在「护栏」上——这也是本书后半本的主题。 顺带说一句名字的事。 「智能体」这个词被用得很泛,做客服的、做流程自动化的都叫智能体。 这一课里说的智能体,特指「能在一个代码仓库里自主完成一次改动的程序」—— 它有三个硬条件:能读、能改、能验证。

四、三次演进换的到底是什么

代际 单位 它的视野 人管什么
补全 一个 token 光标前后几十行 管逻辑、管结构
对话 一段选中 你选中的那段 管搬运、管一致性
委派 一个任务 整个仓库 管验收、管边界

注意最后一列的变化:人管的东西在往后退,但没有退到零。 补全时代人管逻辑(因为机器只管接续);对话时代人管搬运(因为机器不知道文件在哪); 委派时代人管验收(因为机器会自己说「我做好了」)。 「人管验收」这件事是退不掉的。 因为验收的定义是「符合我的意图」,而意图在你脑子里—— 机器再强,也没法替你确认它做的是不是你想要的。 这不是能力问题,是位置问题。 所以这一课真正要练的,不是「怎么让它更聪明」,是「怎么把意图写清楚、怎么验证它做到了」。 后面每一章,说到底都在练这两件事。

五、动手 Demo:同一个改名任务,三种模式各要几轮

「三次演进」这种说法最容易变成空话。所以这个 Demo 不举例子,直接造一个真项目: 一个函数,六个调用方,然后要求「把函数改名」——改动点分散在七个文件里。 三种模式各做一遍:补全式(只改光标所在的那个文件)、对话式(一次一个文件)、 委派式(一次全改)。量三个数:人的轮数、改动的文件数、验收结果。 为什么要挑「改名」? 因为它是重构里最典型的一种:单点改动、多点牵连。 这种活儿最能看出颗粒度的差别——补全的视野根本够不着别处。

# fmt.py:一个函数
def ts(sec):
    return "%.2fs" % sec

# m1.py ~ m6.py:六个调用方,都是这一句
from fmt import ts

def run():
    return ts(1.25)

# check.py:逐个导入并调用,任何一处断链就退出码 1
for i in range(1, 7):
    try:
        importlib.import_module("m%d" % i).run()
        ok += 1
    except Exception as e:
        print("m%d 失败  %s" % (i, msg))
        fail += 1

实跑输出:

--------------------------------------------------------------------
同一个改名任务,三种模式各要几轮
--------------------------------------------------------------------


  ① 先造一个真项目:一个函数,六个调用方
  --------------------------------------------------------------------
  fmt.py 一个函数,m1~m6 六个调用方,check.py 挨个跑一遍。
  现在跑:通过 6 / 失败 0
  ! 六个调用方都正常,这是起点。

  ② 任务:把 ts 改名成 fmt_ts(六个调用方都得跟着改)
  --------------------------------------------------------------------
  改名是重构里最烦的一种——改动点分散在七个文件里,漏一个就断链。

  ③ 模式 A:补全式——光标在哪儿就改哪儿
  --------------------------------------------------------------------
  只改了 fmt.py,跑 check.py:
    m1 失败  ImportError: cannot import name 'ts' from 'fmt'
    m2 失败  ImportError: cannot import name 'ts' from 'fmt'
    m3 失败  ImportError: cannot import name 'ts' from 'fmt'
    m4 失败  ImportError: cannot import name 'ts' from 'fmt'
    …
    通过 0 / 失败 6
  六个调用方全断——因为补全的视野就是光标附近那几行,它不知道还有六个文件在 import 这个名字。
  人的补救办法是:自己 grep 一遍、自己逐个改、自己再跑一遍。
  这一步的轮数算在人头上,不叫「机器没做到」。

  ④ 模式 B:对话式——一次贴一个文件
  --------------------------------------------------------------------
  一轮改一个文件,六轮改完六个调用方,第七轮验:通过 6 / 失败 0
  结果是对的,但每一轮都要人复制、粘贴、切回编辑器——机器没省下这件事,只是把打字换成了点击。

  ⑤ 模式 C:委派式——一次把任务交出去
  --------------------------------------------------------------------
  一次改完七个文件,一轮验收:通过 6 / 失败 0

  ⑥ 三种模式摆在一起
  --------------------------------------------------------------------
| 模式 | 人的轮数 | 改动文件 | 验收结果 |
|---|---:|---:|---:|
| A 补全 | 7(自己补六处) | 1 | 失败 6 |
| B 对话 | 7(六贴一验) | 7 | 通过 6 |
| C 委派 | 2(一交一验) | 7 | 通过 6 |

  轮数是这么算的:A 与 B 每改一个文件都算一轮(人必须介入一次),C 把六处改动折进同一轮。
  注意 C 的「2」不是「不用人」——人要写任务、要看 diff、要跑验收。省掉的是逐处搬运,不是审阅。
  ! 三次演进换的其实是同一件事:把「人搬运的颗粒度」从字符放大到任务。

模式 A 的结果最关键:只改了定义,六个调用方全断。 这不是「模型笨」—— 补全的视野就是光标附近那几行,它没有任何办法知道还有六个文件在 import 这个名字。 人的补救办法是:自己 grep 一遍、自己逐个改、自己再跑一遍。 这三步是「补全模式」的隐性成本——它不写在工具的说明书里,但每次重构都得付。 模式 B 是对的,但轮数是 7。 一轮改一个文件,六轮改完,第七轮验。 每一轮都要人复制、粘贴、切回编辑器——机器没省下这件事,只是把「打字」换成了「点击」。 模式 C 是 2 轮:一交一验。 但别把这个 2 读成「不用人」——人要写任务、要看 diff、要跑验收。 省掉的是「逐处搬运」,不是「审阅」。 这两个数(7 和 2)的差距,就是三次演进真正卖掉的东西。

30 秒实验

  1. 把你手上的一个真实改动拆开数一数:它动了几个文件、几处地方? 如果超过三处,那就是「委派式」的活儿——用对话式做,你会把时间全花在复制粘贴上。
  2. 试着只用补全做一次跨文件改动,看看你能坚持多久。 大多数人做到第三处就开始用 grep 了——那一刻你就知道「视野」这件事有多要紧。
  3. 找一段你写过的代码,问自己:如果交给一个只能看这一个文件的人改,他能改对吗? 答「不能」的地方,就是需要「整个仓库视野」的地方。

常见误区

  1. 「补全不就是小一号的智能体吗?」 不是。 补全没有「文件」概念,也没有「验证」能力——它连自己写的东西能不能跑都不知道。 这三样缺一样,就还是前两代。
  2. 「模型变强了,就不需要人验收了。」 验收不是能力问题,是位置问题。 「符合我的意图」这件事,只有你能判断。 模型再强,也只能保证「代码能跑」,保证不了「这就是我要的」。
  3. 「三次演进是替代关系,新的把旧的淘汰了。」 不是。 今天你打字时仍然在用补全,改一个小地方时仍然在用对话。 三者是叠加的,按「改动的影响面」选。 影响面小就用小的,别拿大炮打蚊子。
自测三问(点开对答案) 1. 补全、对话、委派三代,最本质的差别是什么? —— **有没有「手」。** 前两代只会产出文字,第三代能读文件、能改文件、能跑命令看结果。 **手一有,「验证」就不用等人了**——但风险也跟着来了。 2. 为什么说「人管验收」这件事退不掉? —— **因为验收的标准是「符合我的意图」,而意图在人的脑子里。** **工具能保证代码能跑,保证不了这就是你要的。** 这跟模型多强没关系。 3. 一个改动动了七个文件,你该用哪种模式?为什么? —— 委派式。 **跨文件改动的成本全在「一致性」上**—— **补全和对话都要人逐处搬运,漏一处就断链;委派能让它一次看全,人只审一遍 diff。**

下一篇 1.2 往下问一层:既然它换的是「交付」,那「交付」到底比「给代码」多了什么? 答案是四样证据——变更、验证、留痕、可回滚。

相关笔记