昨天推荐的这篇《AlphaCodium:引领代码生成新境界,从提示工程到流程工程》里面提到了 6 个使用LLM代码生成的最佳实践:
1. 使用 YAML 结构输出而不是 JSON 格式输出
有两个原因:
1) YAML 格式容错率更高,JSON 很容易导致格式错误不能解析
2) YAML 格式的内容消耗的 Token 更少
2. 要点列表(Bullet points)分析
当让大语言模型 (LLM) 分析问题时,通常以要点列表(Bullet points)格式要求输出会获得更好的结果。要点促进了对问题的深入理解,并迫使模型将输出划分为逻辑上的语义区域,从而提高了结果的质量。例如,以要点自我反思问题(见图 2),每个要点代表了对问题不同部分的语义理解——一般描述、目标与规则、输入结构、输出结构。
3. 大语言模型在生成模块化代码方面更加出色
让大语言模型(LLM)去编写一个长篇的单个函数时,常常会遇到问题:代码中经常出现错误或逻辑漏洞。更严重的是,这种庞大而单一的代码块会影响到后续的迭代修复工作。即便提供了错误信息,模型也很难准确地定位和解决问题。但如果我们明确指导模型:“把生成的代码分割成多个小的子功能模块,并给它们起上有意义的名称”,结果会好得多,生成的代码错误更少,且在迭代修复的阶段有更高的成功率。
部分Prompt参考图3
4. 灵活决策和双重验证
大语言模型在处理那些需要深思熟虑、合理推断和做出严肃、非常规决策的代码任务时,往往会遇到困难。例如,在生成问题的附加测试时,模型生成的测试常常存在错误。
为了解决这个问题,可以引入了双重验证的过程。在这个过程中,模型在生成了初始输出之后,会被要求再次生成相同的输出,并在必要时进行修正。比如,模型在接收到它自己生成的 AI 测试作为输入后,需要重新生成这些测试,并及时纠正其中的错误(如果有的话)。这种双重验证的步骤,不仅促使模型进行批判性思考和推理,而且比直接提出“这个测试正确吗?”这样的是/否问题更为有效。
5. 延迟做决策,避免直接提问,给予探索空间
当我们直接向模型询问复杂问题时,经常会得到错误或不切实际的答案。因此,我们采取了类似 Karpathy 在下面的推文中所述的方法,逐步积累数据,从简单任务逐渐过渡到复杂任务:
- 首先从最简单的任务开始,即对问题进行自我反思和关于公开测试用例的推理。
- 然后转向生成附加的 AI 测试和可能的问题解决方案。
- 只有在得到模型对上述任务的回答后,我们才进入实际的代码生成和运行修复的迭代过程。
再比如,不是选择一个单一的算法解决方案,而是评估并排序多个可能的解决方案,优先考虑排名靠前的方案进行初始代码编写。由于模型可能会出错,我们更倾向于避免做出不可逆的决定,而是留出空间进行探索,以及尝试不同可能解决方案的代码迭代。
6. 流程导向的监督方式
在解决复杂问题时,不寄希望于一步解决问题,而是设计一个科学的流程,在流程的每一步中逐步积累数据,再每一个阶段都加入新的数据。
以文中解决 CodeContests 编程竞赛问题为例,设计了一个两个阶段的若干步骤的流程,每一个步骤都会引入新的数据,比如说第一步是对题目反思得到反思后的数据,第二步是分析公开测试用例得到测相关的数据,第三步生成可能解决方案得到解决方案的数据等等。
对于每一步的数据,采用验证、选择等方式来确保数据的质量和准确,每一步都是下一步的基础。但即使如此也无法保证每一步数据的正确性,所以在第二个阶段还引入了迭代的模式,这样在遇到数据错误,可以回到前面的步骤对数据进行修正。
以上就是用大语言模型生成代码的 6 个最佳实践,最后简单总结以下:
1. YAML 格式化输出要求:
模型需要能够以 YAML(一种数据表示格式)的方式输出数据,这种输出应与 Pydantic(一种 Python 数据模型库)所定义的类结构相匹配。
2. 逻辑性强的语义要点分析:
鼓励使用 YAML 格式来组织和分析关键信息,通过这种方式可以更加逻辑清晰地划分内容段落,有助于深入理解复杂的概念。
3. 编写模块化代码的推荐:
推荐将代码分解成多个小型的子功能模块,并为每个模块赋予清晰、具有描述性的名称,这样不仅使代码更易于管理,也更便于理解其功能。
4. 灵活决策与双重验证:
当模型生成了一个输出后,再次让模型生成同样的输出,同时在必要时对其进行修正。
5. 保留探索的可能性:
考虑到模型可能会犯错,应避免作出不可逆转的决策,并为寻找多种可能的解决方案提供空间。
6. 流程导向的监督方式:
支持逐步积累数据的流动方式,并在流程的不同阶段考虑加入新的数据。
完整译文参考:https://t.co/k3Ba7t01U1
点击图片查看原图
点击图片查看原图
点击图片查看原图
点击图片查看原图