CodeReviewGPT系列(二):魔法打败魔法,说说 prompt 优化

到了 CodeReviewGPT 的第二期分享了(自己鼓掌👏)

一个好消息和一个坏消息:

坏消息是,这一期技术成分很低,玄学指数很高。

好消息是,玄学看起来更有趣些,只是很难解释。

先说说背景

与其说是背景,更像是解释一下这篇文章诞生的原因。

第一期: CodeReviewGPT 工作流程的分享中,有说到 CodeReviewGPT 的工作流程非常简单,仅三步。

但是,这一切的前提,是 GPT-3.5 模型 (也可以强行理解成chatGPT) 他能够按照要求,完成对代码的评论,并输出结果。

“按照要求” 这四个字,就是这篇文章想要传达的东西。

该如何给 GPT-3.5 提要求???如何让 GPT-3.5 按照要求回答问题???

CR 是典型的补全场景

很多小伙伴应该都用过 ChatGPT 。使用场景非常之简单(不包括后续出现的Code Interpreter),就是对话,或者说聊天。

但是在 GPT-3.5 模型所对应提供的 API 中,是有两种类型的 API:

Completion - 补全

跟 chat 模式不同的是,补全模式仅限一次对话,也就是用户只会发出一句 prompt,GPT 也只会回复一次答案,然后结束。

是不是发现, CodeReview 这个过程,就是一次次的补全呢?所以说是典型的补全场景。

为什么说是玄学?

因为 GPT-3.5 这个模型是一个黑盒。

就像调用一个函数,如果我们知道函数的具体实现,那么在 debug 的时候会很容易知道错误在哪里。

但是,面对 GPT 我们只能丢一段话进去,完全不知道会得到些什么。所以说,整个过程就变成了玄学。

为了防止 CodeReviewGPT 的回答过于随机,要做的就是不断的通过各种方式优化 prompt 。

prompt优化平时都在做什么?

如何对 prompt 进行优化,我会以几个场景来展示。

太多无用 comment

有的 MR 收到了 130+ 条的 comment,然后没有一条是有用的。我知道这样的结果确实是很恼人。

其实解决 comment 太多,还准确率低的问题,是很多举措一起作用生效的。为了契合今天的主题,我们只关注 prompt。

最开始的promtp非常零散,可以简单到一句话“帮我review这段代码”。

没有任何的约束,CR 规范输入到 GPT,他只能根据毕生所学,自由发挥。

在 prompt 中明确的添加 CR 的规范之后,要求 GPT 仅关注规范内提到的问题,效果就好非常多了。(prompt中要配套添加严格遵守规范 CR 代码的提示)

对一段注释的每一行进行评论

先前遇到的一个场景, CodeReviewGPT 对着一段多行注释展开了猛烈攻击,足足评论了 18 条完全相同的 comment(掀桌.jpg。

解决这个问题,在prompt上做了相当大的改动。

原先的 prompt 保留了 diff code 的原有格式,也就是携带了很多标注 diff 的信息,如 diff 行标, ‘+’ /  ‘-‘ 行。

然后根据 GPT-3.5 返回的结果猜测,因为 diff 的  ‘+’ /  ‘-‘ 行信息, ‘+’ /  ‘-‘ 符号对 GPT 理解这段代码有影响。

把 diff code 进行处理,去掉所有标识 diff 的信息,只保留原有的代码(注意这里我把所有 删除 的代码也都过滤掉了)。

经过这样处理的 code 放入 prompt 中发给 GPT,得到的回复效果就很好了。

few shots 效果好于 zero shot

这里的 few shots 和 zero shot 是指给 GPT 的 prompt 中是否携带一些解释性的例子🌰。

在CR过程中,CodeReviewGPT 总是在判断 magic string(number) 上出现错误。

特别是在判断魔法字符串上,它会把常量等良好的代码误认为魔法字符串。

一开始, prompt 只有一句 “如果代码中有魔法字符串或魔法数字,请评论并警告。”

GPT 只能按照自己的方式去判断什么事魔法字符串。

为了修改这个问题,我在 prompt 中给出了几个特定的例子,例子都非常简短,甚至仅仅是伪代码。

效果却好了很多,GPT 会掠过一些之前会经常犯错的地方。

感受

为了让大家更好的理解,我并没有贴出任何详细的代码片段,仅抽象其中的优化方式。

但是看完三个案例的你,是不是觉得,一切都发生的莫名其妙,仅仅是修改了几句跟 GPT 的聊天内容,问题就看似解决了。

没错,面对一个黑盒模型,唯一能与它沟通的路径就是 prompt(还有其他方式,这里的唯一仅指目前的CodeReviewGPT)。

这也是为什么整个开发过程充满了不确定性,而解决方式又看似用魔法打败了魔法。