🛠️ 第5章 第一个可复用工作流:在 emotional_chat 项目中稳定复用
📄 一句话概括

进一个项目之前,只问两件事:能不能一键跑起来、能不能一键验证。 两条都过,才谈得上委派;一条不过,先补那条。 Demo 里四条确认全挂,补了三十行之后全过——差别只在「有没有入口」。

📝 本章和前面几章的关系

从这一章开始,进具体项目。教材拿 emotional_chat(一个带情绪识别的聊天应用)当贯穿案例, 第 9 到 12 章四个场景都在它上面演。 沙箱里没有这个仓库,所以 Demo 另建一个等价小仓:emo.py 判情绪、main.py 回话、 test_emo.py 断言。文件名、入口形态、坏味道都照实做,只是业务代码换成了能跑通的版本。 这一节讲的是「进门之前」。很多人的顺序是反的:先让它干活,跑不起来再说。 结果第一小时全花在环境上,而且你不知道是它不行还是环境不行。

一、确认一:能不能一键跑起来

「能跑起来」和「一键能跑起来」差得很远。 前者是「作者本机能跑」,后者是「任何人 clone 下来都能跑」。 两者之间差的通常是三样东西: 没记下来的环境变量、写死的绝对路径、只在作者机器上装过的依赖。 Demo 里就是这三样。README 说「跑 main.py」, 真跑报 KeyError: 'EMO_MODE'——因为作者本机早就 export 过了,他不觉得这算「步骤」。 一键的意思很具体:一条命令,不用先想「要不要 export 什么」。 做到这一点的成本很低——一个入口脚本,把环境变量兜住就够了。

二、确认二:能不能一键验证

这一条比上一条重要,也更容易被忽略。 跑起来只证明「它没崩」,验证才证明「它做对了」。 没有验证,Agent 只能用「看起来对」来判断自己——而「看起来对」是它最擅长的错觉。 验证要满足两个条件才算「一键」: 一条命令能跑完、结果能用退出码判断。 第二条是关键——输出一堆日志但要人读的,不叫验证。 Demo 里改完之后 python tasks.py test 打出「通过 4 / 失败 0」并返回零, 这才是能交给 Agent 的验证。它能读退出码,不需要读懂你的日志。

三、两条不过就别急着委派

为什么不能「边干边补」? 因为补这两条的过程中,你会改代码。 一边改代码一边让 Agent 改代码,出了问题分不清是谁的。 正确顺序是先补入口、再委派。 补入口这件事本身很小——Demo 里三样加起来不到三十行, 但它把「这个项目能不能进」这个问题一次性定了。

状况 先做什么 别做什么
跑不起来 补入口脚本,把环境兜住 先让它读代码
跑得起来但验不出 补一条能返回退出码的验证 先让它改
两条都过 可以开始,先出计划 直接放手

一个常被追问的问题:老项目补不动怎么办? 补不动就先只补一条:验证。 哪怕只是「跑一个脚本,看它打印的数和上次一样」——有一条能判对错的线,比十条能跑的命令有用。

四、动手 Demo:两条确认:跑得起来吗、验得出来吗

这个 Demo 造一个「看起来没问题」的小仓库,然后照它的 README 走一遍。 它会跑挂,而且挂的原因不是代码错。 然后逐条查四条确认,最后补上入口再查一遍。 四条确认是我拆出来的检查项:一条命令能跑、一条命令能验、没有写死的绝对路径、 需要的环境变量有交代。后两条是前两条的常见病因。

def _checks(base):
    names = sorted(os.listdir(base))
    has_entry = u"tasks.py" in names
    cfg = get(base, u"config.py")
    readme = get(base, u"README.md")
    return [
        (u"有一条命令就能跑起来", has_entry),
        (u"有一条命令就能验证", has_entry),
        (u"没有写死的绝对路径",
         not re.search(r"[A-Za-z]:[/\\]Users", cfg)),
        (u"需要的环境变量都写进了文档或入口",
         (u"EMO_MODE" in readme) or has_entry),
    ]

实跑输出:

--------------------------------------------------------------------
两条确认:跑得起来吗、验得出来吗
--------------------------------------------------------------------


  ① 先造一个「看起来没问题」的小仓库
  --------------------------------------------------------------------
  README.md
  config.py
  emo.py
  main.py
  test_emo.py
  五个文件,一个 README 写着「装依赖,跑 main.py」。看起来挺正常。

  ② 照文档走一遍
  --------------------------------------------------------------------
  文档说「跑 main.py」 -> 退出码 1
  报错最后一行:KeyError: 'EMO_MODE'
  缺一个环境变量。README 里没写它——因为作者本机早就 export 过了。
  ! 这是最常见的「跑不起来」:代码没错,是「作者的环境」和「仓库」之间差了几样东西,
  而这几样在他脑子里。

  ③ 四条确认,逐条查
  --------------------------------------------------------------------
  [不过]   有一条命令就能跑起来
  [不过]   有一条命令就能验证
  [不过]   没有写死的绝对路径
  [不过]   需要的环境变量都写进了文档或入口
  四条挂了 4 条。
  全挂。这个项目现在的状态是:进不去(跑不起来),进去了也不敢动(验不出来)。

  ④ 改成两条命令
  --------------------------------------------------------------------
  python tasks.py test -> 退出码 0,用时 496 毫秒
  通过 4 / 失败 0
  python tasks.py run -> 退出码 0:听你这么说我也高兴
  python tasks.py run 换个输入 -> 嗯,我在听

  ⑤ 改完再查一遍
  --------------------------------------------------------------------
  [过]     有一条命令就能跑起来
  [过]     有一条命令就能验证
  [过]     没有写死的绝对路径
  [过]     需要的环境变量都写进了文档或入口
  ! 改了三样:一个 tasks.py、一处绝对路径、一段 README。
  加起来不到三十行,但它把「这个项目能不能进」这件事定了。

四条全挂。 第一条挂是因为没有入口,后两条挂是因为「作者脑子里的东西没落到仓库里」。 报错只有一行:KeyError: 'EMO_MODE'。 补的东西一共三样:一个 tasks.py、一处绝对路径改相对、一段 README。 加起来不到三十行。 改完 python tasks.py test 打出「通过 4 / 失败 0」,退出码零。 注意那个「用时 512 毫秒」。 这台机器上起一个 Python 进程就要半秒左右——下一篇量局部验证时会用到这个数, 因为它会盖住很多你以为是「计算」的时间。 沙箱里没有 make,所以入口写成 tasks.py。 真机上一般是 make run 或 npm test,形状完全一样: 一条命令、入口固定在仓库里、不用记参数。

30 秒实验

  1. 在你自己的项目里跑一次这两条确认。 「一条命令能跑」大概率不过——那就先补那个入口。
  2. 把 git clone 到一个空目录,再按 README 走。 漏掉的每一步,都是你脑子里的隐性知识。
  3. 看一眼你的验证:它返回退出码吗? 要人读日志才知道对错的,不算。

常见误区

  1. 「先让它干活,跑不起来再说。」 跑不起来的时候,你分不清是它不行还是环境不行。 先补入口,是为了让后面所有失败都能归因。
  2. 「我本机能跑啊。」 这句话的意思是「我知道要 export 什么,但没写下来」。 Agent 不知道,新同事不知道,三个月后的你也不知道。
  3. 「验证太麻烦,先看它改得对不对。」 你看得过来三个文件,看不完三十个。 而且它会用「看起来对」代替「验过了」,这是它最擅长的错觉。
自测三问(点开对答案) 1. 「能跑起来」和「一键能跑起来」差什么? —— **差三样:没记下来的环境变量、写死的绝对路径、只在作者机器上装过的依赖。** **三样加起来就是「隐性知识」,而 Agent 拿不到隐性知识。** 2. 为什么验证要能返回退出码? —— **因为 Agent 读不懂你的日志,但它读得懂零和非零。** **「通过 4 / 失败 0」加一个退出码零,才是它能用的验证。** 3. 老项目补不动两条,先补哪一条? —— **先补验证。** **哪怕只是「跑一个脚本,看打印的数和上次一样」**—— **有一条能判对错的线,比十条能跑的命令有用。**

下一篇 5.2 把这两条扩成一份清单:readiness 八条,以及「局部验证到底省多少」的真测量。

相关笔记