修复前的游戏
背景
这个游戏你多半见过:底下一块球拍,上面一排排砖块,一个球在中间来回弹。可在这里,球落到球拍的右半边会直接穿过去,好像那里什么都没有。落在左半边,它就照常弹起来。
我们把这个游戏的文件夹交给了 AI 编程智能体(agent)Claude Code,只输入了一句话:
智能体看不到这个游戏,更别说玩了。它能请求的操作只有 种:。所以它只能从代码和游戏的测试入手。测试文件里有 个小检查,用 Node(一个运行 JavaScript 的程序)就能跑,什么都不用安装。
整个会话用了 秒,其间模型被调用了 次。录制于 ,模型是 。这个任务我们录了 次,这里展示的是第 次。选哪一次,用的是录制前就定好的规则:第一个在修复前后都跑了测试的运行。全部 次都放在代码仓库里。在一个玩具游戏上成功一次,证明不了智能体会修 bug;第七章讲的正是它们修不好的时候。
用下面的按钮、滑块或键盘方向键,一次一次地查看这些调用。也可以点“按真实速度观看”,按它们当时发生的速度重放。
逐步查看录制的会话
messages = [instructions, your_message]
while True:
reply = model(messages) # 每次都读入全部内容
messages.append(reply)
if not reply.requests: # 没有请求:结束
break
for request in reply.requests:
result = run(request) # 外壳程序来执行
messages.append(result)
show(reply.text)
修好的游戏
这是修好的游戏,其中的 和智能体改完时一模一样,别的什么都没动。再看一次第一个球。
值得注意的三件事
修改前后它都检查了
模型从来没看到过这个游戏。改动任何东西之前,它先跑了测试,传回来一个失败的测试:。修改出现在下一次调用里,同时还有第二次测试运行,这一次全部 个都通过了。这两步各是循环的一轮,每次的结果都是外壳程序贴进来的文本。规则选中这一次运行,也是这个原因:
每一次都把全部内容读一遍
模型在两次调用之间什么都不保留。对话就是它的记忆,所以外壳程序每次都把整段对话发过去。为了改 行代码, 次调用一共读了 个 token,其中 个从缓存读取。缓存在第三章讲。
“完成”是模型自己说了算
没有谁叫智能体停下。它最后一条回复里没有请求,外壳程序就停了。同一条回复说,智能体检查过快速运动的球不会越过球拍,而这项检查只以几句话的形式存在于回复里。在这里,测试和修好的游戏都支持它的主要结论。什么都无法印证的情况,第七章再讲。
下一章
第二章:上下文窗口
在一个只有 个文件的玩具项目上, 次调用下来,对话从 个 token 涨到了 个,是开始时的 倍。涨出来的大部分, 个 token,是它读的代码。真实的项目有成千上万个文件,会话一跑就是几个小时。项目是真的、会话又很长的时候,模型读到的是什么?