进一个项目之前,只问两件事:能不能一键跑起来、能不能一键验证。 两条都过,才谈得上委派;一条不过,先补那条。 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 秒实验
- 在你自己的项目里跑一次这两条确认。 「一条命令能跑」大概率不过——那就先补那个入口。
- 把
git clone到一个空目录,再按 README 走。 漏掉的每一步,都是你脑子里的隐性知识。 - 看一眼你的验证:它返回退出码吗? 要人读日志才知道对错的,不算。
常见误区
- 「先让它干活,跑不起来再说。」 跑不起来的时候,你分不清是它不行还是环境不行。 先补入口,是为了让后面所有失败都能归因。
- 「我本机能跑啊。」 这句话的意思是「我知道要 export 什么,但没写下来」。 Agent 不知道,新同事不知道,三个月后的你也不知道。
- 「验证太麻烦,先看它改得对不对。」 你看得过来三个文件,看不完三十个。 而且它会用「看起来对」代替「验过了」,这是它最擅长的错觉。
自测三问(点开对答案)
1. 「能跑起来」和「一键能跑起来」差什么? —— **差三样:没记下来的环境变量、写死的绝对路径、只在作者机器上装过的依赖。** **三样加起来就是「隐性知识」,而 Agent 拿不到隐性知识。** 2. 为什么验证要能返回退出码? —— **因为 Agent 读不懂你的日志,但它读得懂零和非零。** **「通过 4 / 失败 0」加一个退出码零,才是它能用的验证。** 3. 老项目补不动两条,先补哪一条? —— **先补验证。** **哪怕只是「跑一个脚本,看打印的数和上次一样」**—— **有一条能判对错的线,比十条能跑的命令有用。**下一篇 5.2 把这两条扩成一份清单:readiness 八条,以及「局部验证到底省多少」的真测量。
- ☐ (本篇完,下一篇 5.2 让仓库支撑 Agent:readiness、脚本与局部验证)