主旨
第一部分的挑战结果失败以后,总结经验,改变方法,又进行了第二次的挑战。结果可以说是基本成功完成任务。这篇文章的主旨就是分享一下第二次挑战的过程,同时也分享一下这个过程中所总结的一些最佳实践。使用的工具为免费的TRAE+qwen3.6 plus。这个挑战时间上持续了一个半月,但因为只是利用了业余时间,如果按照纯粹的时间,大概3周左右吧。这个AI工具组合未必是最强的组合,但是本次挑战也可以说明只要使用正确的方法去指导AI工具,也是可以完成复杂的任务。
最佳实践 防止AI工具浅尝辄止的行为
第一次挑战失败后,再次思考和尝试了如何让AI工具能够高效率,或者高质量地完成这个任务。比如我也尝试过让 TRAE 去阅读C语言的MUDOS内容,然后用Java语言去实现相同的内容。但是也失败了。
于是终于发现了一个规则,或者这也是目前AI工具的特点:面对一个纷繁复杂的功能的时候,AI往往注重的是速度,或者说它很容易做一个浅层次的分析和理解,然后就去产出内容。比如一个MUDOS其实非常复杂,但是无论给AI什么样的提示词,如果你想让它一句指令就完成Java版本的构建,那是不可能的。
于是,这个任务的进行方式也就回归到了传统的软件开发方式。你需要指导或者指引AI工具去逐渐地掌握任务的细节,设计好蓝图(设计文档),然后在这基础之上去做开发和测试。这就好像你不能和一个开发人员说:给我做一个和抖音一样的软件。目前来看,一句话的需求对于目前的AI工具来说不奏效。
由于Qoder收费了,所以全程都使用TRAE来进行工作。模型不要选择Auto,一定要固定一个。使用者的眼睛是雪亮的,TRAE上有效的,受欢迎的模型都是热度高的。我选了qwen3.6-plus,热度挺高,但是排队时间不那么长。
既然需要指引AI工具去行动,所以我让TRAE做的第一件事并不是立刻编写代码,而是下面这个任务内容:
# task1
## 任务内容
仔细分析 ”D:\Qoder\fluffos\fluffos“ 的代码,分析整个程序的架构。不要遗漏任何细节。
把分析结果输出到 task/fluffos_analysis.md。
最佳实践 使用文档来安排任务
给AI分配任务的时候,最好把任务写在文档里,然后让TRAE去读取任务文档,再开始工作。这有很多好处:
- 你自己对任务的内容有一个清晰的掌握,以后也可以复查任务内容,或者修改任务内容。
- 书写任务文档的时候,你可以深思熟虑,考虑好每一个细节。
- 如果是聊天窗口发给AI任务,聊天窗口上下文信息一多,很难找到最开始的任务细节。如果需要新开始一轮会话的话,就很麻烦了。
对于任务文档,还有一个最佳实践:就是每个任务单独使用一个文档。为什么呢?因为TRAE对于文档的编辑比较弱,即使 md 文档中编了章节号码,TRAE仍然会用关键字匹配的方式去阅读或者更新文档。这就导致有的时候你想让TRAE把总结的内容更新到文档某个任务里时,它会更新错误的章节。我后来也做了一个如何更新 md 文档的 skills,TRAE说它学会了,但是实践中还是错误很多,所以后来我就把每个任务都独立成一个文件了。
无需多言,任务文档的格式应该是 markdown格式,因为AI很容易读取。其实手写md文档也不难,主要记住章节的符号,代码引用的符号就行了。TRAE也有预览功能,你可以一边写一边看预览,有错误可以及时修改。
然后TRAE就开始完成第一个任务。效果还是不错的,它输出了大概1000行左右的文档。大概的内容如下:
内容太多,就展示一下上面两个截图。总的来说,TRAE对代码的理解是正确的,包括编译LPC文件的VM的架构和实现。通过这个步骤,就可以避免AI的浅尝辄止的行为。但其实在后面的测试也发现这个设计文档其实也不是很充分,所以导致很多内置函数都没有被编写。应该花些时间让TRAE继续整理更加详细的文档就好了。总之一点,在指挥AI开始具体的开发工作之前,好的设计文档是必须的。
最佳实践 不要急于开发,先规划好任务列表
有了设计文档之后,我给TRAE下达了第二个命令:
# task2
根据 task1 的分析结果,既 task/fluffos_analysis.md, 想实现一个 java版本的mudos。请先根据分析结果,整理出来开发 java 版本 mudos 的任务列表,输出到 task/dev_java_task.md。目前阶段不需要编写代码。
在理解Fluffos的C语言版本代码基础之上,让TRAE做一个Java版本开发的任务列表。同时需要告诉它先不要编写代码。有的时候,我们需要和AI去讨论一些事情,最好附带上“现在请不要进行开发的工作”这句话,否则AI会经常自己动手开始修改代码了。
对于这个任务,TRAE输出了2000行左右的文档,根据重要度分了15个大的阶段,每个阶段又分了子任务,大概是下面这些内容:
对于这个开发的任务列表,有些地方和TRAE讨论了一下,然后进行了修改,基本开发任务列表就定稿了!有了开发任务列表,就可以告诉TRAE基于这个列表开始开发。你可以让TRAE在每个阶段都停一下,然后去检查开发的内容,也可以让TRAE不用停止,一直把所有功能都开发完毕。我选择了后者。
等上述的开发工作完毕以后,我发现Java版本的mudos无法运行一个mudlib。于是继续给TRAE布置任务:
# task3
仔细分析 ”D:\Qoder\fluffos\fluffos“ 的代码,了解mudos是如何关联上一个mudlib,也就是mudos启动后,如何配置才可以调用相应mudlib的LPC文件。
可以参考的mublib文件在mud目录里。
将分析结果输出到 task/mudos_link_mudlib_analysis.md。
# task4
基于 task3的分析结果 “mudos_link_mudlib_analysis.md”,实现相应的java代码和配置文件。
注意:目前一部分java代码可能已经实现了。
配置文件放在 config 里。
“D:\Qoder\mud\mud\mudos\config.cfg" 是一个已经存在的配置文件,你可以参考它的内容。
mud 目录下是一个已经存在的mudlib,你可以参考它的内容。
为了有序地完成这个任务,请先分析代码,确定都有哪些子任务,输出到 task/dev_mudos_link_mudlib_task.md。
上述两个任务也是先让AI去分析代码,整理出来需要的任务列表,然后根据任务列表去开发,主要的目的仍然是防止AI的“浅尝辄止”的行为。就这样,TRAE把Java版本的mudos的主要功能都给实现了。接下来,是要去测试,确定这些功能真的都正确地实现了——这才是真正充满了挑战的地方。
最佳实践 规划好AI自动执行的任务内容
最初我是使用手动测试的方式:使用zmud软件客户端,连接服务,然后测试。但是这种测试方式就偏离了这次的挑战,这样的工作应该尽可能让AI去完成。我也试过简单地告诉TRAE,让它自己去做测试,虽然也能进行测试,但是方法和测试内容经常发生变化,所以导致效率非常低。于是和TRAE讨论了一下:它是不是可以做一个Telnet协议的class,然后用这个class去连接服务做测试。TRAE也同意了这个方法,然后它就做了这么一个class,名字叫 TelnetClient。
于是,接下来的测试都是创建如下task文档:
# task5
请使用 TelnetClient 来进行如下任务:
1. 使用 TelnetClient 编写一个 login 的测试程序,名字可以 TelnetClientLoginTest.java (如果已经创建了不用重复创建) 。
2. 启动 jmudos 服务。
3. 使用 TelnetClientLoginTest.java 连接 mudos 服务。
4. 如果 返回的字符串是错误信息,那么就分析 jmudos.log ,分析原因,修复错误。返回的字符串应该包含 mud/adm/etc/welcome文件里的内容。然后编译代码,停止 jmudos 服务。然后重复 第2步,一直到错误完全修复。
- 注意:由于LPC脚本是gb2312编码,所以返回的字符串也是gb2312编码。因此检查 TelnetClient的 response的字符串时,也需要使用 gb2312 编码的字符串来比较。
- 启动mudos: `d:\Qoder\jmudos3\jmudos3-2\bin\start_mudos.bat`
- 停止mudos: `d:\Qoder\jmudos3\jmudos3-2\bin\stop_mudos.bat`
在TRAE做完最初的开发以后,我们最先要解决的就是Login功能。Login里的处理其实挺复杂,为了降低人工的时间,就让TRAE按照上面的指示自己去做测试,然后发现问题以后去分析,修改代码,然后再次测试,一直到问题解决为止。通过这种方式,TRAE自己发现并解决许多问题,例如(这些内容都是TRAE自己更新的文档):
最佳实践 AI工具不是银弹,必要时人工介入
当然,AI并不能独立解决所有的问题,很多时候它会陷入循环思考,或者思路混乱。这个时候需要人工介入。比如和它一起分析原因的可能性,或者让它把目前的思考内容总结到文档里,然后新打开一个会话继续工作,它经常就会很快地解决问题。因为LPC文件都是 gb2312编码,TRAE编辑的话会保存成utf-8编码,所以我定了规则禁止它编辑LPC文件。这就导致如果LPC里代码复杂,需要增加一些调试的时候,只能手动去添加。这里也不得不说TRAE编辑文档的能力是真的需要提高。
这个过程也让我认识到作为给AI工具发布任务的“人”,是应该对任务相关的技术有所掌握的。如果没有任何的掌握,对于复杂的任务其实是很难进行下去的。至于目前网上所说的完全不懂技术的人凭借AI做出了某个产品,这个信服度几乎可以是零。即使真的做了出来,也仅仅是原型阶段的东西而已。或者已经存在了类似的产品,AI也经过相应的训练,克隆出来同样的东西——比如你让AI做一个五子棋或者贪吃蛇游戏,它就会很快做出来完整的程序。
最佳实践 准备让AI工具恢复记忆的文档
整个挑战过程大部分时间都是在测试和解决问题的过程中进行的。很多问题都是需要花费大量的上下文,甚至需要重新开启一个会话才可以。这就会导致一个问题:TRAE会忘记一些事情,比如约定好的规则,或者正常的操作(比如它经常忘记使用启动和停止mudos的脚本,或者正确的mvn编译命令)。于是我准备了一个 dev_init.md 文档,专门用于初始化它的记忆。这个文档的部分内容如下:
同时,为了确保AI真的学习了文档(很多时候它说掌握了,但实际上并没有),我还在文档最后附加了测试题:
这样我会根据测试题的回答结果来确认它真的认真阅读并掌握了这些内容。有了这个 dev_init.md,我就不怕它失忆了,上下文内容过多,发现它不正常的时候,就让它复习一下。新开启一轮会话的时候,第一步也是让它阅读这个文档,有一个初始化的记忆。
最佳实践 给AI布置清晰明了的任务内容
随着不断地给TRAE布置任务,对于任务的内容,我也总结了一个模版,一般包括如下信息:
# 任务编号
## 现象
## 期望结果
## 任务内容
## 完成任务的方式
例如下面是一个简单的任务:
# task30
## 现象
执行 go 命令,不输入方向的参数的时候,没有显示 “你要往哪个方向走?” 这个字符串。
我在 go.c 里增加了调试语句:write("You can execute the go command 01!");
这个调试的字符串可以正常显示出来。
## 任务内容
你可以模仿 TelnetClientLookCommandTest.java,写一个测试 go 命令的测试类。然后执行测试,找到问题并修复。
注意:look.c 里的调试语句已经删除掉,所以现在不会返回“You can execute the look command”之类的消息了。
此外,在 login 进入游戏后,当前的房间有一个出口是 west,所以,如果输入 "go west" 指令,应该返回移动到 west 房间的信息。
## 完成这个任务的流程
1. 创建测试程序
2. 编译代码
3. 启动 jmudos 服务 (`bin/start_mudos.bat`)
4. 运行测试程序,确保测试通过。
5. 如果有错误,分析 jmudos.log 中的错误,然后修改代码。必要的时候参考fluffos的代码。
如果任务内容过多,把任务分解成多个子任务,输出到本任务的子任务中。
6. 停止 jmudos 服务 (`bin/stop_mudos.bat`)
7. 重复步骤 2-6 直到错误修复
这样TRAE就会自己分析,修改代码,测试。当然理想的情况是这样,实际上如果问题复杂,TRAE会停住,例如“思考次数过多”,或者“陷入循环思考”,这个时候就需要手动介入了。
最佳实践 创建规则(Rules)文档,让AI时刻遵守规则
在一个会话中随着上下文内容的增加,TRAE会忘记一些重要的规则。但是又不想断断续续地提醒它复习 dev_init.md 文档。这个时候可以创建 rules 文档,每次TRAE思考的时候,会载入这个文档,这样就不会忘记重要的规则了。你可以手动自己编写,也可以在会话中告诉TRAE有哪些规则,触发的关键字是什么,然后让它自己去创建规则文档。我当然选择了后者。
其他
关于skills
在TRAE中也可以创建skills,用于完成特定的任务。但是对于本次挑战来说skills这个功能没有太大的用处。为了让TRAE能正确地更新md文档,我创建了一个skills,也描述了具体的步骤,但是作用不大。在TRAE的社区网站也可以看到很多人在吐槽它的文档编辑功能,希望以后能改善吧。
遇到AI也迷糊时别气馁
在测试和解决问题过程中,有几次真的很想放弃了。看着TRAE跑了一整天也没有解决问题,当时很怀疑这个工具的能力。这个时候别气馁,再仔细想想调查的思路,看看TRAE的总结内容是否有一些线索,可以指引它继续去调查。尤其注意不要发送“你太笨了”等没有意义的发泄情绪的消息——这不会取得任何价值,与其责备,不如想想如何与AI工具配合去找到解决问题的思路。
目前AI工具生成的代码质量如何
说实话没有去仔细看TRAE生成的代码,目前只是通过测试确保这些代码是可以运行的。但是根据设计文档来看,应该是还算规范的代码。目前的阶段对于真正的产品来说,个人认为AI工具生成的代码还是需要人工来审核的,毕竟AI生成的内容带有一定的不确定性。