前言
使用AI开发游戏我大概经历了一下的过程:
- 通过Chat进行复制粘贴
- 出现Agent的雏形,通过Agent进行修改,然后逐行审查AI的修改,并进行手动修改
- Agent和模型能力变得更前,通过Agent进行修改,然后对AI的修改进行大概的审查
- Agent和模型能力变得似乎有点太猛了,通过Agent进行修改后,根本审查不过来........
可以看到模型越来越强大,Agent设计越来越精妙,对于Code Review这件事,人类会越来越难做到亲力亲为。之前我也经历过一段不进行人工审查的阶段(偷懒),但最初呈现的效果是很差的,时常会出现已经修复的Bug再次出现,改A功能却把B功能改坏,代码中一堆冗余的空检查和注释等等。但在经过后续的一些优化和尝试之后,现在已经能做到让AI持续产出质量足够稳定的代码了,所以在本文分享一些经验
上下文工程
先从LLM的原理说起,LLM的推理本质上是一个根据前文不断推导出下一个字,然后不断循环一个结构,也就是说上下文的所有内容都会影响后续生成的内容(当然在这里不会详细描述,我的这篇文章中会有稍微深入一点的讲解)。
所以总的来说,LLM生成的质量除了与模型本身的训练规模、训练语料等有关之外,还与上下文的质量有关。而对于我们LLM的使用者来说,更多是调用外部的模型,所以我们是很难调整模型的。要让LLM生成的质量更好,唯一能做的就是优化上下文。
上下文包含哪些内容呢?最直接能想到的就是用户的输入和AI的思维链和回复,一些朋友可能用Agent还会写CLAUDE.md,AGENT.md,或者在使用Cursor时会编写Rules,这些内容会在每次会话开始时,都会被加载到上下文中。当然也肯定经常会使用SKILL,SKILL的声明内容也会被加载到上下文中。Agent设计者会为Agent设计系统提示词,那么这些内容也会被加载到上下文中,最后还有一个最重要的则是工具调用。Agent最核心的工具调用是读取文件列表,读取文件内容,写入文件内容,通过调用工具,把工具执行的结果告诉LLM,也就是把这些内容载入到上下文中。
所以到这里你就会发现,Agent通过工具调用读取代码并载入到上下文中,所以代码库本身也是LLM的上下文,所以代码库的质量就会决定LLM输出的质量。
好模式与坏模式
技术社区中有一个很形象的说法,想让AI制作一个正宗苏式东坡肉,AI一顿操作,告诉你正宗苏式东坡肉做好了。但他采用了一个不正宗的做法,在东坡肉里加入了陈醋。于是你告诉他不要加入陈醋,又一顿操作后告诉你,正宗苏式东坡肉(无陈醋版)做好了。这种对于无陈醋版的备注和修改的痕迹就会长期留在代码库里。从当下来看,结果是没问题的,但会留下很大的隐患。
前面我们提到了代码库会影响LLM的输出质量,在这样的情况下,实际上是对上下文产生了污染,在后续的代码库不断增长时,这样的坏模式也会不断的增长,上下文污染会越来越严重,会让AI后续无法做出简洁并精准的修改。这里我分享一下我的常用解决办法:
- 尽可能保持Git工作区干净
- 从一个最简单的需求描述开始,我的原则是描述一些必要的背景信息、描述现状、然后再提出需求并告知AI期望的结果,然后再与AI进行需求细节的对齐 (这边建议使用Grilling的Skill)
- AI一次性将功能改好
- 如果AI改的不好,那么就通过Git放弃变更,重新再开一个会话,调整提示词,重新输出
- 审查并提交代码
也就是尽可能在3-5次对话就将任务完成,以避免无陈醋版的坏模式产生。坏模式当然不止这种,需要工程师进行更全面的甄别,当然这种模式是一种使用AI比较常见的。
还有另一种情况,这已经是一个维护迭代很久的项目了,这里面或许已经埋藏了很多的坏模式在里面,或者你的团队成员会将坏模式添加到代码库中(笑)。或者一个新的功能需要进行多轮对话和会话压缩来完成,这其中难免会产生坏模式。这样的情况我建议是以一个固定的周期对代码进行坏模式清理,也就是进行一次定期大具有规模的审查,就像是每隔一段时间对家里进行大扫除一样。这一步操作实际上也可以由AI来完成,告诉AI你项目中存在的坏模式。不过具体的坏模式的定义需要在根据不同的项目来定制,然后凝练成SKILL。例如在Unity项目中对于动态生成物体动态挂载组件而非使用预制体、使用Find而非引用获取组件等这些行为,在我们的项目中就属于坏模式。
第三种情况更多来自提示词的不够明确,例如我有一个推送消息的方法,已经有一个现成的定义好的路径或者说工具方法,但是AI还会再自己做一套新的。这一点问题通常源于上下文中没有给AI提供详细的关于规范、程序入口、不同模块的数据流状态流等。如果工程师没有注意这样的问题,那么就会给代码库留下坏模式。
除了避免坏模式的产生,我们还可以为AI提供好模式,对于一种相似的、固定的流程,做成一个标准模板,这一步可以通过SKILL来完成,但是SKILL所能涵盖的范围可能还不够细节,所以使用好模式方法是一个不错的选择。以我参与的项目举例,使用Unity进行开发的游戏,我们时常有这样的工作流:
- 先使用Agent完成这个基础功能
- 为这个新功能,单独创建一个用于测试调试的场景
- 将这个功能关联的内容引入到当前场景中(以保证这个功能正确运行)
- 在左侧添加用于调试和修改的UI面板
- 用Agent添加用于调整功能的数值的一系列选项,并能实时预览效果(就像在Unity中编辑粒子一样)
- 用Agent完善功能,为功能添加表现、音效等
- 重复步骤5、6
- 直到功能足以交付 这样的工作流我们要做很多次(因为确实有很多功能要做)。所以我们需要创建很多个针对不同功能的测试场景,如果我们已经有了第一个功能稳定的,足以具有代表性的,能称之为好模式的测试场景,那么我们后续在创建类似的场景时,大可以让AI参考这个好模式场景做一个针对新功能的场景,这样好模式就被复制下来了。
总的来说代码里面充斥了好模式和坏模式,而在AI Coding的过程中,好模式和坏模式都会不断繁殖增长,就像是代码库的基因一样,所以让代码库保持良好的基因,是现代工程师应具备的良好品质。
未来的方向
以AI目前的发展来看,我的观点是在未来是不再需要人类编写代码了(除非是兴趣使然),在未来审查代码也将不需要人类(事实上现在已经有这样的趋势了)。但代码库依旧需要一个好的基因,更多的好模式,更少的坏模式,对于未来的方向我想一个自循环自验证的Agent会是主流,自动审查,像一个巡逻警察一样发现坏模式,消除坏模式,人类只需要发挥自己的创造力就好了。现在其实已经有很多的人做了这样的尝试,也有一定的成效,但Token目前还是很贵的(笑),不过价格的下降也一定是未来的趋势,所以这个问题在某个时点一定会被解决。
文章评论
使用 GitHub 登录后即可评论、回复和点赞。评论将公开显示。
正在加载评论…
在 GitHub 查看讨论