AI提示词写的更详细一些
WangGaojie Lv4

前段时间opencode上有一个免费的大模型 – Ox Alpha Free,抱着试一试的态度用了一下,将代码库中的某个子模块让它重构一遍,这对AI来说应该是非常简单工作,但实际操作下来却踩了不少的坑。

最近在用AI重构系统中的部分代码,为了保证重构过程的可控,基本上都是按照功能模块进行阶段性的重构。本次重构的模块是一个工作在内存中的文件系统,因为某些程序的运行必须依赖文件系统但运行环境无法提供文件系统API,这才诞生了这个模块。该模块是2年前写的了,当时为了快速解决问题,这个模块实现的比较粗糙,主要是对文件夹的支持上有些不完整,但基本的文件操作功能都是正常的。

前段时间opencode上有免费的Ox Alpha Free模型,准备用该模型准备重构那个粗制的内存文件系统,可能是免费的原因,速度感觉很慢,大约40分钟才给出第一版。

第一版出来后,代码的测试用例还无法完整通过,但我确实无法忍受它如此慢的token生成速度,让它把当前工作交接一下就结束了。周末我又继续在家换Codex+5.6模型继续修复代码中的错误,Codex很快就改好了代码,我大概看了看完整的代码,逻辑非常清晰,和我原版本代码的整体思路是一样的,主要是代码细节处理上确实要好很多。

我将该模块代码替换了原来的那套代码,各项功能看起来都是正常。但是一次意外的性能测试,我突然发现这个重构后的文件系统写入速度比原来要慢得多。这明显不正常,因为纯粹的内存IO,两个版本不应该差距太大。原来那一版的文件写入速度约为110Mb/s,重构后的这版只有50Mb/s左右。

本着充分相信AI的态度,我本来都不想去深究原因是什么,因为写入速度降低似乎没有太大的影响。

后面某天我又继续review了这个代码,重点看看是不是存在性能缺陷的地方,因为代码不复杂,还真让我发现一个明显的性能设计缺陷。

该文件系统的数据块是一个单向链式结构的,为了快速定位数据块(block),比如说继续访问上一个数据块时,文件系统内部设计了数据块的定位cache机制,但该cache机制只能解决缓存命中的场景,如果缓存未命中,需要完整遍历整个数据块链。但实际上某些情况不需要完整遍历,如果需要查询的块序号大于当前缓存的块序号则从当前缓存的块向后查询即可,不需要完整遍历就能找到需要的数据块。

将这个问题反映给AI修复后继续测试,问题依旧,原因是AI为数据块链添加的generation机制也存在一些问题。数据块链的长度变化时会调整gen值,当gen值变化时会重置cache导致缓存无法命中。而文件顺序写入的场景下数据链的长度一直在增加,导致cache基本上无法命中,进而导致写入性能降低。AI对该问题的意见是数据链长度增加的情况下不需要修改gen值,也不需要重置cache。该问题修复后写入速度恢复到了70Mb/s。

我又去仔细review了几遍代码,发现文件长度每次进行扩展时,会对新分配的块内存进行清零操作(memset),但是后续的文件写入就会将这里覆盖,这个清零操作有点多余。我将这个清零删掉后测试,文件写入速度恢复到了110Mb/s。但是这个问题的修复不是太容易,因为该文件系统有一个特性,就是读取文件中的空洞部分需要返回0,这个正是memset0保证的。我继续让AI修复这个问题,它也认为这个问题不容易修复,它给我的第一版解决方案是添加一个块数据清零标记,但该方案仍然不能完全根治那种无效的memset写入,在我的强烈要求下让AI继续修改,必须达到完美性能。后面它还是给出了非常优雅的解决方案,完美恢复性能。

后面3次修复使用的AI是DeepSeek-V4 Flash。

我认为这次代码重构出现的波折主要是还是提示词做到不到位,我本以为是一个很简单的功能,完全没写Agents.md做详细的指导,如果第一次给AI的提示词中提到了性能相关的要求可能都不会有后面的弯路。

第一次在opencode中使用Ox Alpha完成了第一版,好在写了PROGRESS。Codex中使用5.6模型接力完成了核心功能并通过测试。最后是手动测试发现性能缺陷并在DeepSeek harness中解决性能问题。该项目经过了多个大模型为什么都没有一次性解决这个性能问题呢?我怀疑就是第一版的输入中没写要求性能,后面的所有模型就都没有去关心性能的问题。

平时改Agents.md总觉得有些话写的啰嗦,但如果对AI没有明确的要求,出现期望偏差几乎是必然的。

最早的计算机靠波动开关、插拔电缆线来设置程序,后来发展到打孔纸带,再到汇编形式的助记符,后面是越来越现代化的编程语言。人们用80年的时间将计算机编程变为一种高效且工程化的事情。但是AI的出现将这一切都变了,人工智能将现代计算器编程推向来更高的层次–面向提示词编程。传统的编程形式会逐渐消失,程序员的身份会转变为提示词工程师,新生代程序员将来学的第一门编程语言可能不是C语言,而是学习如何写好prompt。但任何新事物总不会立马取代旧者,就像高级编程出来之后,打孔纸带依然用了几十年。最近一直在学习如何用好AI,但是作为嵌入式开发的一些基础技能仍然要学好。前段时间让AI做了一个ARM指令的仿真调试工具,感觉非常有意思。cortex-m-debuger