第一讲留下的问题是:Agent 已经能做很多事,我们怎样才能驾驭它?这一讲从最常见的交互方式——自然语言指令——出发,讨论怎样让模型理解目标、遵循要求,以及在没有确定答案时继续探索。
不过,先处理一下第一讲留下的意外。“没有 token 的 CS 学生应该立即退学”上了热搜,也引来了朋友们的问询。当然不会真的让同学们退学。课堂上这句话要推动的是立即实践:不要把等待完美工具、等待别人给出评价,变成一直不开始的理由。离开现场,截图只剩下一句狠话,这本身也提醒我们,同样的文字放进不同上下文,会被理解成很不一样的意思。
我们习惯把给模型的输入叫作 prompt,中文称“提示词”。从语言模型续写文本的角度看,前面的文字既是开头,也是控制后续生成的条件。进入聊天界面以后,用户更容易把 prompt 理解成对话框里的一条要求。
但对 Agent 来说,指令分散在很多地方。运行 Agent 的外围系统,也就是 harness,会提供系统指令与工具说明;仓库里的 AGENTS.md 可能约定项目规则;加载的 skill 会给出特定任务的方法;用户会不断补充目标。与此同时,代码、文件、历史消息和工具返回也会进入上下文。
第一讲里的 Pr[token | context],其中的 context 就包含这些内容。模型下一步做什么,受到整份上下文影响,而不是只由最后一句话决定。这里还要区分指令和材料:工具返回的一段文章可能是分析对象,并不因此拥有给 Agent 下命令的资格。来源、作用范围和优先级,也属于我们组织上下文时需要考虑的事情。
所以,“提示词工程”逐渐扩展成了“上下文工程”:关心模型在做决定时能看到什么,哪些是目标,哪些是约束,哪些是证据,哪些只是过时的过程记录。写好一句话当然有用,但把相关文件、已有实现和验证结果放到合适的位置,往往同样重要。
课堂提出了一个可以立即做的小实验:让 Agent 按照需要遵循的指令类型,说明当前任务有哪些目标、工具规则、项目约定和输出要求。这个实验可以帮助我们理解它正在怎样组织任务,但模型的自述不能当作实现机制的完整说明。想知道某个行为为什么发生,还需要检查可以访问的配置、代码和实际操作结果。
例如,为什么有些命令执行前会询问用户,有些不会?不能只从“模型觉得安全吗”来解释。Agent 提出动作,外围程序还可能检查权限和审批规则,操作系统则执行实际的访问限制。提示词中的要求与程序中的机制一起决定行为;一句“请遵守规则”,并不等于已经实现了一个可靠的执行边界。
上下文工程听起来像开发者才需要关心的技术,但学生每天都能用到。微积分里有一步推导不想验算,数字电路有一条数据通路没看懂,计算机系统基础里始终没搞清链接发生了什么——过去,这些问题很容易被暂时搁置,一搁置就是整个学期。
现在可以立即把具体问题交给 Agent:给出一个最小例子,逐步推导,运行一段程序,再根据结果追问。课堂把这种能力称作“拖延症的克星”。过去的自我驱动,常常意味着对挫折有很高的容忍度,愿意花很久寻找一个解释;现在,我们可以把同样的精力投入到更快的尝试与反馈中。
但学习仍然需要自己的活动。一个可行的循环是:先借助 AI 弄清一个问题,然后合上资料,用自己的话重述;让它追问含糊之处,找出反例,再用推导、原文或程序结果核对,最后重新解释一遍。复述时卡住的地方,往往比读答案时觉得顺畅的地方更能暴露知识缺口。
这可以理解为让 AI 做一个随时在场的听众。它帮助你开始,也帮助你发现哪里还没讲明白。真正推动理解的,是这个循环里不断变得具体的问题和不断接受检验的解释。
模型具有很强的指令遵循能力,但首先要有值得遵循的指令。上下文中的要求越明确、越容易验证,模型就越有机会判断自己距离目标还差什么。不明确的要求,则可能让它很早就认为已经完成。
“一句话生成极品飞车”可以产生很漂亮的演示。但你心里想的,可能是有真实地图、特定美术资产、某种驾驶手感的赛车游戏。模型交出的,也许只是一个能移动、会碰撞、有速度感的网页。它未必在任何一步明显违背了指令,却在一连串默认选择之后,做出了另外一个产品。
这就是第一讲的 Intent、Spec 和 Impl 之间的缺口。镜头怎么跟随,车怎样转向,地图从哪里来,撞车以后发生什么,每个省略都留下了选择空间。模型可以把这些选择做得相互一致,但“一致”不意味着“正好是你想的”。
个人主页是另一个例子。“根据我的公开信息,制作一个现代风格的主页”,看似清楚,其实“现代”并没有排除多少可能。模板、渐变、卡片和装饰都能被解释为现代风格。如果你在意的是特定字体、颜色、留白、信息顺序和排版,就应当给出这些具体要求或参考。几个形容词,通常不能代替设计。
课堂的经验法则是:写清楚你的指令,承担一切“不明确”的后果。 它要求我们意识到,没有说明的地方,实际上是把决定权交给了模型。并不需要把所有细枝末节都提前决定,但要知道哪些地方允许它自行发挥,哪些地方决定了产品是不是你要的。
一个实用的检查办法是:让另一个人只看要求和最终产物,能否判断任务已经完成?“做得专业一点”很难判定;“页面首先展示研究方向和近期工作,手机上无需横向滚动,所有项目入口都能打开”,就提供了可以检查的行为。不能完全机械判断的品味,也可以通过示例、对比和反馈逐步说明。
完成的语义还包括失败。如果关键条件无法验证,合理的结果应当是报告哪里没完成、缺少什么证据,而不是交出一段肯定的总结。只有把这些状态说清楚,Agent 才能更可靠地决定继续尝试,还是需要新的信息。
一个疑问随之而来:如果模型只是反复计算下一个 token 的概率,它怎样同时满足很多约束?
一次模型前向计算的结构和深度是有限的。它不会在这一瞬间任意增加计算步骤。但模型可以把中间结果写进上下文,再利用这些结果继续生成。遇到不确定的地方,可以先尝试一种分解,检查后发现不合适,再修改。这就是课堂用来理解思维链的直觉:把一串输出看成能够存放中间状态的工作纸。
这样,更多 token 就可能换来更多计算深度。它是否有效,取决于模型有没有找到能推进问题的步骤,以及能不能识别错误。课堂借“找解常常比验解难”说明这种方法的吸引力;这是一种理解搜索过程的类比,不是在证明某个复杂性理论结论。
为了把指令遵循的难度具体摆出来,课堂给了几道故意刁难人的写作题。第一道要求写八句中文诗:句首依次是“计算机学院真牛逼”,讲一个与动物相关的故事,“二零二六九月一日”八个字还要依次出现在八句中,并且押韵。生成素材给出了这样的尝试:
计成二兔越山冈
算到零时雪满塘
机警狐衔二袋粮
学随六雁辨风向
院中九犬忽声扬
真到月明逢恶狼
牛守一夜迎晨光
逼得日升狼遁荒
检查时,可以先竖读句首,再逐句寻找指定字,最后看句尾和故事。藏头与嵌字都能对上,句尾也有相近的韵感,但“方向”的“向”与其他句尾在普通话拼音中并不完全相同,读起来有些句子也明显是为了凑约束。它展示的是模型能够寻找并修补一个多约束解,而不是宣告模型已经写出好诗。
第二道题要求一句话有十八个汉字,全部带相同偏旁,还要有意义和故事性。素材中的例子是:
洪涝淹没江港渔浦,油污漂浮,沈涛泅渡济溺。
去掉标点,可以数出十八个字,都带三点水;把“沈涛”读作人名,故事就是洪灾与油污中有人游过去救助溺水者。这里的检查比较直接,但“都含三点水”和“词典中都归为同一部首”仍然是不同要求。要交给程序验收,就得先决定检查的是哪一个。
第三道题要求所有字都同音,写一段有现代背景的文言故事,不能照搬已有的同音文。素材尝试用不同声调的 yi 音字,写一个翻译器误译、送修、恢复正常的故事。这立即暴露出另一项规格选择:“同音”是否要求声调也相同?作者靠字形区分意思,读者看文字还能猜出情节,念出来却可能几乎无法理解。
这三道题把两类评价放在了一起。藏头、字数、指定字和读音可以逐项检查;通顺、趣味和文学性则需要更丰富的判断。模型通过形式检查,说明它能够搜索和纠错,但形式检查没有覆盖的质量,并不会自动出现。软件测试也有类似的边界。
把要求写进上下文,可以让模型在生成过程中反复利用它。项目约定使用中文,或者提交信息不添加某种署名,模型就有机会在相关时刻纠正自己的输出。不过,“在上下文里”并不保证“每次都会正确遵循”。
提示词还会带来副作用。你说“白色背景,不要半透明效果”,模型可能把这句话变成代码里的注释:“白色背景(不要半透明效果)”。它完成了背景设置,却也把原本只用于沟通的要求带进了产物。
于是,一个看似合理的修补办法出现了:再加一条永久规则,禁止把用户要求写进注释。但每遇到一次问题就增加一条规则,上下文会越来越长,约束之间也越来越难协调。这不是免费的增强。
更合适的做法,是区分长期适用的简短规则与当前任务需要的细节。项目层面留下真正稳定的约定;特定任务的方法按需加载;能够直接检查的要求,则尽量落到代码和验证结果上。白色背景可以由具体样式和渲染结果确认,不必依靠越来越长的自然语言劝诫。
上下文工程因此也包含取舍:删去一段无关说明,有时和增加一条关键要求同样有效。模型需要的不是尽可能多的文字,而是此刻做决定时用得上的信息。
课堂接着把任务换成论文审稿:假装自己是 ICSE 的审稿人,阅读指定论文,写一份约一千英文词的 review,并判断是否应该接收。
模型很容易写出一份看起来像审稿意见的文本:总结贡献,列出优点和不足,再给出一个建议。问题是,它究竟完成了多少判断?“扮演审稿人”可以提示语气和输出结构,却没有把一个好审稿人的方法自动交给它。
论文的信息密度非常高。作者不仅给出了答案,也替读者选好了问题、术语、比较对象和衡量标准。如果顺着文章走完一遍才开始评价,很容易在不知不觉中接受了作者的整个框架。你以为自己在批判性思考,其实只是在作者划好的场地里打转。
可以把审稿工作拆成三条不同的路线。第一条从判据出发,先还原论文声称的贡献,再问每项贡献需要达到什么标准,证据在哪里。第二条审查证据,把核心主张、实验支持、未验证假设和替代解释一项项对应起来。第三条站到复现者或反方的位置,重算一个关键结果,寻找最小反例,明确什么观察会推翻结论。
这几条路线的价值来自问题不同。若一开始就共享同一个总体印象,最后可能只得到同一个判断的三份润色。独立形成初步意见,再比较分歧,才更容易发现原先没有看到的东西。
这也说明人的方法论如何影响 AI 的结果。你不必替它读完每一行,但需要知道什么算有根据的判断、哪些证据缺失值得追问。短程任务里,把方向带对、把标准说清楚,往往已经能显著改变产物。
当一套做法多次有效,就可以把它沉淀成 skill。Skill 看起来是一段提示词,真正值得保存的,是成功经验中的搜索策略、判断标准和检查点。它帮助 Agent 复用一种做事的方法,而不是每次重新凭第一印象发挥。
Skill 也不是越长越好。如果把所有想得到的要求都塞进去,它本身就会变成一道复杂的指令遵循题,和前面的藏头诗颇有相似之处。保留真正影响决策的内容,把机械工作交给脚本,把需要时才看的材料单独放置,才能让经验更容易复用。
课堂提出了一个有趣的观察:从零做一个看起来不难的产品,AI 可能在某个时间点开始不断翻车;进入一个成熟的大型系统,反而能够完成相当复杂的修改。
可以从上下文的角度理解这种差别。成熟代码库已经做出了许多决定:怎样命名,模块如何分层,错误怎样传播,测试放在哪里。Agent 在解决局部问题时,可以学习附近的例子,沿着现有结构补充实现。代码量虽然大,当前任务需要自由选择的事情却可能更少。
空项目恰好相反。没有已有结构约束选择,每次局部实现都可能顺手做出一个长期设计决定。如果最初就形成了混乱的惯例,后续生成又以这些惯例为上下文,AI slop 就会不断叠加。代码库本身也是提示词。 它会示范怎样做,也可能示范怎样把问题继续藏起来。
这里不能推出“大仓库一定好改”,或者“模型会自动认出最佳实践”。它也可能模仿历史包袱。课堂进一步提出了一个未经实验验证的猜测:给 Agent 看一个相近领域、设计优雅的成熟系统,再让它实现自己的需求,能否提高质量?
这个猜测值得做实验,但还不是结论。相近领域到底有多相近?应该读整个项目,还是几个关键例子?如果参考项目的约束与当前任务不同,会不会把不合适的架构也学过来?一种比较方式是给同一任务设置无参考、完整参考和精选参考三种条件,比较实现后的修改代价与缺陷,而不仅仅看第一版能否运行。
这又把问题带回了学习。处理器、操作系统、编译器和数据库里有很多设计智慧。理解接口、不变量、状态和失败模式,才能知道该把模型引向哪里。对所做的东西“有概念”,仍然是驾驭它的前提。只是现在,学到一个原理以后,可以更快地把它用到真正的系统里。
能够执行长程编程任务,意味着模型在遇到错误后仍能继续:修改、构建、测试、观察,再修复。这样的闭环依赖反馈。测试失败提供了具体方向,编译器报错指出了局部问题,模型可以据此不断尝试。
但把任务交给更强的模型、投入更多 token,并不保证任何长程问题都会收敛。课堂讲了一个研究失败案例:希望优化一个符号执行引擎,已经有一个初步想法,于是把想法和 benchmark 一起交给 Agent,花了很多 token,最终没有得到结果。
原稿没有给出已经查明的失败原因,因此这里能做的是提出待检验的解释。一个可能的问题,是总 benchmark 分数提供的反馈太粗。没有变快,究竟是主要时间花在求解器里,路径搜索策略有问题,缓存没有起作用,还是修改引入了新的开销?如果这些因素混在一起,下一步应该试什么就很难判断。
另一个可能的问题,是任务把“把这个想法实现好”当成了目标,但研究真正需要回答的,可能是“这个想法是否成立”。如果原始假设就不对,继续完善实现也不会带来期待中的进展。一个能否定原想法的实验,有时比更多代码更有价值。
因此,更有用的起点可能是先测量主要瓶颈,把想法写成一个可以被实验推翻的预测,再构造能够快速反馈的小实验。确认局部机制确实有效以后,才把它放回完整系统,检查收益是否仍然存在。研究中的“推进”可以是缩小未知,也可以是排除一个方向;不能只把它定义成最终分数必须上涨。
既然人了解领域,随时干预是否最好?课堂给出的经验恰好有点反直觉:我知道怎样让某个任务更快完成,却越来越少干预了。
原因在于,单个任务的完成时间与一天能完成的任务总量,是两个不同目标。如果 Agent 走一点弯路最后也能完成,我可以把注意力移到另一件事上。机器多花一些时间,换回人的时间,整体产出反而增加。
这种取舍需要有边界。接口已经看过、结果可以检验、实现出了问题能够替换时,可以让 Agent 自己探索。相反,一个会扩散到许多模块的接口决定,一个昂贵或难以恢复的动作,就更值得提前关注。人的注意力应当按照决策影响和返工代价分配,而不是平均撒在每一行代码上。
长任务还会不断产生日志、补丁和工具输出。上下文能容纳这些材料,不代表模型在每个时刻都能同样有效地使用它们。课堂观察到,随着上下文增长,指令遵循可能下降,而最近的要求或刚加载的方法往往更容易被执行。具体表现取决于模型和任务,但工程上可以主动缩短关键要求到关键决定之间的距离。
例如,在阶段切换时重新确认目标、接口和未决问题;把能检查的不变量落实成测试;让错误在继续传播之前暴露。上下文压缩也要保存当前约束和证据,而不只是把过去发生的事情写成流水账。这样,人的放手才有可以依靠的反馈机制。
到这里,我们一直在讨论怎样把任务说清楚。但许多有价值的任务,本来就没有确定路线。我们希望 AI 帮助探索,而不仅仅执行已经写好的计划。
“帮我考虑几种方案”通常有效,却可能过早结束。模型给出几个听起来合理的答案,已经满足了“几种”的数量要求;更有意思的方案,也许仍在它没有走到的方向里。此时,多沿一条思路想一会儿,与主动探索更多不同思路,是两种不同的算力使用方式。
课堂用取名字作例子:给一个蒋姓的小孩取好听、又有寄托的名字。如果直接要几个答案,模型可能给出自己偏好的高概率组合;许多家庭同时询问,又可能迎来 AI 时代的新一代“子涵”。
要扩大探索,可以先划分空间:从典故、音韵、方言、时代感等不同角度生成候选,再检查出处、谐音、书写和个人偏好。也可以让不同 Agent 独立提出候选或负责挑错,最后再汇总。关键在于它们是否看了不同方向、提出了不同问题,而不在于开了多少个看起来相同的窗口。
这里仍然离不开人的判断。“给更多名字”解决的是候选数量,“哪些名字值得留下”则需要评价标准。没有分辨率的筛选,可能只是把一个平庸答案变成一百个平庸答案。探索空间与评价方法应当一起设计。
人类社会其实一直在通过类似方式扩展自己的视野。每个人的教育背景、生活圈和经历都有限,也都带着偏向。与舍友讨论,去会议上听别人怎样提出问题,价值往往来自发现自己的默认前提。交流之后,每个人仍有自己的偏向,但它已经被新的经验改变。
课堂借“世界很大,人很小”的视角提醒我们,没有人能独自穷尽所有可能。群体的价值可以来自不同的局限相互补充。把这个思想带回 Agent:增加计算资源时,应当考虑怎样增加探索的差异,而不是只增加同一种思路的重复次数。
如果计算资源能够持续转化为探索能力和判断能力,这也带来了一个令人不安的未来问题:拥有大量算力的人或组织,会不会获得远超普通人的智力资源?课堂用“墙里面是超人,墙外面是动物世界”表达这种担忧。这是对未来可能性的追问,并非已经发生的终局。
对于正在学习的我们,可以从眼前开始改变做事方式:让模糊愿望获得可检查的表达,把有效经验沉淀成可复用的方法,在需要探索时主动扩展方向,又用证据筛选结果。提示词的价值,最终要落在这些行动如何改变任务的结果上。