一个AI编码怀疑论者尝试AI编码:超详细记录
你可能看过不少关于AI智能体编程(agentic coding)或“氛围编程”(vibecoding)的博文,作者们要么用模糊的个例大谈特谈智能体现在能做出多么神奇的事,要么担心编程技能会因此退化,要么质疑人类灵魂的主权被侵犯,等等等等。这篇不是那种文章。提前说好。
去年五月,我写了一篇博文,标题是《作为一个资深LLM用户,我其实并不常用生成式大语言模型》,算是对当时日益火爆的智能体编码热潮的一种反差回应。在那篇文章里,我指出:虽然大语言模型(LLM)绝非无用,它们在回答简单编程问题时比我手写更快、准确度也够,但智能体就难说了——它们不可预测、成本高昂,而且从我个人的使用效果来看,当时的炒作完全不成比例。不过我也留了个口子:如果LLM进步到能解决我所有顾虑、让智能体变得更可靠,那我也不排斥。
此后的几个月里,我一边继续数据科学家的日常工作,一边关注着OpenRouter上不断冒出来的新LLM。今年八月,谷歌宣布推出Nano Banana生成式图像AI,并配套了一个不太好用的API,于是我开源了gemimg这个Python包,作为该API的封装工具。这算不上什么激动人心的项目:实现方式没多少创意空间,我主要看重的是它能带来什么价值,而不是写这个工具本身有多爽。所以,我拿它做了个实验:把功能完整的代码扔进了OpenRouter上几款新晋LLM里,让它们找出并修复Python代码中的问题——如果失败了,正好检验一下当前LLM的真实能力;如果成功了,那就是为这个包潜在用户提升了软件质量,我也没啥道德负担。结果LLM还真帮上了忙:不仅添上了像样的函数文档和类型提示,还指出了好几段代码更符合Python风格的实现方式。
大约在那段时间,我的同事开始大力推荐在 Visual Studio Code 里使用 GitHub Copilot 辅助编码,特别是配合新出的 Claude Sonnet 4.5。但对我这种做数据科学的来说,Copilot 里的 Sonnet 4.5 并不好用——它写出来的 Jupyter Notebook 啰里啰唆,所以我没怎么当回事。不过到了 11 月,Google 发布了 Nano Banana Pro,必须立刻更新 gemimg 才能兼容这个新模型。我试用 Nano Banana Pro 后发现,这个模型能生成任意网格的图片(比如 2×2、3×2),是个非常实用的功能,于是快速写了一个脚本来支持它,顺便把每个子图单独切出来保存。我知道这种功能用 Pillow 实现虽然简单但很繁琐,所以放心地让 Copilot 帮我写一个 grid.py 文件,实现 issue #15 里描述的 Grid 类。Copilot 确实干成了,只不过在规格没提到的部分(比如行列顺序搞混)出了点小错,但通过更明确的提示很容易就修正了。就算把修 bug 的时间算进去,这次体验也实实在在地提升了我的效率,让我对智能体(agent)的能力更乐观了一些——但还远没到让我变成 AI 吹的地步。
11 月,感恩节前几天,Anthropic 发布了 Claude Opus 4.5,同事们自然好奇它比 Sonnet 4.5 强多少。Anthropic 赶在长假之前发布 Opus 4.5 这事非常可疑——因为公司通常这么干就是为了把不太亮眼的发布埋在节日里,反正用户都忙着跟家人朋友团聚,没空关注。巧的是,我在旧金山既没朋友也没家人,所以有大把带宽来测试这个新 Opus。
关于 AGENTS.md 的前言
有个关于 agent 的方面我之前没研究过,但知道它对用好 agent 至关重要,那就是 AGENTS.md 文件——这个文件可以控制 agent 的特定行为,比如代码格式。如果项目根目录里有这个文件,agent 会自动读取它,理论上会遵守里面的所有规则。这跟普通大语言模型(LLM)调用的系统提示词差不多。如果你一直在看我的文章,应该知道我对精心设计的系统提示词有点上瘾,还会搞些花样,比如用全大写来强调更重要的规则(是的,这招至今依然管用)。我找不到一个适合 Python 项目的 AGENTS.md 的好模板,于是让 Opus 4.5 帮我写了一个:
创建一个面向 Python 代码质量的 `AGENTS.md` 文件,必须写得非常细致。越重要的规则越要用大写,比如 `MUST`
然后我加了一些个人偏好和推荐工具,这些都是在之前用 Python agent 时踩坑总结出来的经验:用 uv 和 .venv 代替系统自带的 Python;数据操作用 polars 而不是 pandas;密钥、API key、密码只存在 .env 里,同时确保 .env 在 .gitignore 中;等等。这些约束大多不是告诉 agent 要做什么,而是教它怎么做。总的来说,每当我发现 agent 有某种我不喜欢的基本行为,就往 AGENTS.md 里加一条规则,效果非常好。比如,agent 喜欢用多余的表情符号,我特别反感,于是加了一条:
**绝不允许** 使用 emoji 或模拟 emoji 的 Unicode 字符(例如 ✓、✗)。
Agent 还经常留下大量冗余的代码注释,所以我加了一条规则来阻止:
**必须** 避免加入多余注释,尤其是那些同义反复或不言自明的(例如:代码功能一目了然,或者函数名已经充分说明了代码作用,那么注释除了浪费用户时间外毫无意义)。