Redian新闻
>
探索 prompt 编码范式:如何优雅构建测试代码生成提示词?

探索 prompt 编码范式:如何优雅构建测试代码生成提示词?

科技

从四月份到现在,我们持续为 AutoDev 编写了一系列的功能。尽管开发了三个多月,我们一直在持续思考、并重构我们管理 prompt 的方式。在即将发布的 AutoDev 0.8 里,我们进一下完善了现有的上下文构建方式,以模式化的方式重新思考并设计了新的上下文工程体系。

而测试生成正是我们的第一个新试点,以探索新的 prompt 模式是否更方便?如下是基于新 prompt 编码范式的视频:

详细代码见:https://github.com/unit-mesh/auto-dev

AutoDev 的 prompt 演进

在那篇《Prompt 编写模式:如何将思维框架赋予机器》,我总结了如何更好的编写 prmopt。于是,在 ArchGuard Co-mate 中,我们将这些模式代码化:

  1. interface BaseTemplate {

  2. fun getRole(): String = ""

  3. fun getInstruction(): String = ""

  4. fun getRequirements(): String = ""

  5. fun getSample(): String = ""

  6. fun getExtendData(): String = ""

  7. }

在开发 AutoDev 的过程中,我们发现它匹配我们所理解的编程范式:模式化。但是,在引入了规范化的代码生成之后,一部份 prompt 变成了配置,以支持不同团队配置自己的 prompt:

  1. {

  2. "spec": {

  3. "controller": "- 在 Controller 中使用 BeanUtils.copyProperties 进行 DTO 转换 Entity\n- 禁止使用 Autowired\n-使用 Swagger Annotation 表明 API 含义\n-Controller 方法应该捕获并处理业务异常,不应该抛出系统异常。",

  4. "service": "- Service 层应该使用构造函数注入或者 setter 注入,不要使用 @Autowired 注解注入。",

  5. "entity": "- Entity 类应该使用 JPA 注解进行数据库映射\n- 实体类名应该与对应的数据库表名相同。实体类应该使用注解标记主键和表名,例如:@Id、@GeneratedValue、@Table 等。",

  6. "repository": "- Repository 接口应该继承 JpaRepository 接口,以获得基本的 CRUD 操作",

  7. "ddl": "- 字段应该使用 NOT NULL 约束,确保数据的完整性"

  8. }

  9. }

而随着需求的进一步演进,我们又基于 import 与相似性,添加了所需要的代码上下文、技术框架等等。

诸如于:

  1. when (action) {

  2. ...

  3. ChatActionType.CODE_COMPLETE -> {

  4. val codeComplete = customPromptConfig?.autoComplete

  5. if (codeComplete?.instruction?.isNotEmpty() == true) {

  6. prompt = codeComplete.instruction

  7. }

  8. when {

  9. MvcUtil.isController(fileName, lang) -> {

  10. val spec = CustomPromptConfig.load().spec["controller"]

  11. if (!spec.isNullOrEmpty()) {

  12. additionContext = "requirements: \n$spec"

  13. }

  14. additionContext += mvcContextService.controllerPrompt(file)

  15. }

  16. ...

  17. }

  18. }

  19. }

而随着,我们进一步地迭代我们的功能,类似于如上的代码会变得更得更多复杂。除此,随着我们对于多语言的支持情况越来越好,我们不能再根据一个个语言创建一个复杂的 prompt。所以,我们需要思考一些新的范式。

AutoDev 新 prompt 范式

在结合了先前参考的 JetBrains AI Assistant 的设计思想之后,在编写自动测试生成的 prompt 里,我们重新设计了一部分的 prompt。一个新的 prompt 将由以下几部分构成:

  • ChatActionType。即起始的指令(instruction),如编写测试、解释代码等。

  • 特定场景要求。基于特定场景下,如 MVC 下不同分层的编写模式。

  • 技术栈上下文。根据不同语言、技术栈,生成的特定 prompt。

  • 代码上下文。精炼代码信息,以注释方式生成。

  • <代码>

  • 指令起始提示词。即用来更明确的提示 AI,人类期待的返回格式。

由此,一个最终的 prompt 示例如下(【xxx】只用于解释):

  1. ChatActionType

  2. Write unit test for following code.

  3. 【特定场景要求】

  4. You MUST return code only, not explain.

  5. You MUST use given-when-then style.

  6. You MUST use should_xx style for test method name.

  7. When testing controller, you MUST use MockMvc and test API only.

  8. 【技术栈上下文】

  9. You are working on a project that uses Spring MVC,Spring WebFlux,JDBC to build RESTful APIs.

  10. 【代码上下文】

  11. // class name: BookMeetingRoomRequest

  12. // class fields: meetingRoomId

  13. // ...

  14. // class name: BookMeetingRoomResponse

  15. // class fields: bookingId meetingRoomId userId startTime endTime

  16. // ...

  17. 【代码】

  18. ```java

  19. @PostMapping("/{meetingRoomId}/book")

  20. public ResponseEntity<BookMeetingRoomResponse> bookMeetingRoom(@PathVariable String meetingRoomId, @RequestBody BookMeetingRoomRequest request) {

  21. BookMeetingRoomResponse response = new BookMeetingRoomResponse();

  22. return new ResponseEntity<>(response, HttpStatus.CREATED);

  23. }

  24. ```

  25. 【指令起始提示词】

  26. Start with `import` syntax here

简单来说,一个复杂的 prompt,将通过一系列的依赖注入(Intellij 扩展点)来完善上下文。

ChatActionType

即根据用户的意图而创建的指令,如解释代码、重构代码、编写测试等等:

  1. when (this) {

  2. EXPLAIN -> "Explain selected $lang code"

  3. REVIEW -> "Code Review for following $lang code"

  4. REFACTOR -> "Refactor the following $lang code"

  5. CODE_COMPLETE -> "Complete $lang code, return rest code, no explaining"

  6. WRITE_TEST -> "Write unit test for following $lang code"

  7. FIX_ISSUE -> "Help me fix this issue"

  8. GEN_COMMIT_MESSAGE -> """suggest 10 commit messages based on the following diff:..."""

  9. CREATE_DDL -> "create ddl"

  10. CREATE_CHANGELOG -> "generate release note"

  11. CHAT -> ""

  12. }

随后,根据不同的类型,添加对应的指令要求,诸如于 MVC 分层下,代码应该如何编写、命令风格等等。

特定场景要求

再根据不同的场景要求,诸如于在编写 Java 的 Controller 测试时,我们期望以 MockMVC 作为 API 测试框架来生成,而在编写 Service 测试时,我们期望以 Mockito 作为 Mock 的框架来生成测试。于是乎,一个对应的代码便是:

  1. class JavaTestContextProvider : ChatContextProvider {

  2. override fun isApplicable(project: Project, creationContext: ChatCreationContext): Boolean {

  3. return creationContext.action == ChatActionType.WRITE_TEST

  4. }

  5. override fun collect(project: Project, creationContext: ChatCreationContext): List<ChatContextItem> {

  6. ...

  7. }

随后,再根据不同的类型,如 Controller、Service 提供对应的 prompt。

技术栈上下文

相似的,为了生成这一句 prompt You are working on a project that uses Spring MVC,Spring WebFlux,JDBC to build RESTful APIs. ,我们需要从依赖管理工具/构建工具(如 Gradle、Package.json)中获取项目框架,并只列出关键的技术栈,以生成符合项目技术栈的代码。也就是上述 prompt 中的: Spring MVC,Spring WebFlux,JDBC 。

所以,代码实现起来便类似于:

  1. override fun isApplicable(project: Project, creationContext: ChatCreationContext): Boolean {

  2. return hasProjectLibraries(project)

  3. }

  4. private fun hasProjectLibraries(project: Project): Boolean {

  5. prepareLibraryData(project)?.forEach {

  6. if (it.groupId?.contains("org.springframework") == true) {

  7. return true

  8. }

  9. }

  10. return false

  11. }

详细见相关的代码。

代码上下文

即与当前代码相关的代码,为了降低无用 prompt 的影响,我们并没有完全采用与 GitHub Copilot 一致的 Jaccard Similarity 方式来构建,而是通过两种策略。

  • 在关键场景下,如 CRUD 代码场景,通过 import + 选择代码的引用代码来呈现,并使用类 UML 的方式来减少上下文。

  • 在其它场景下,参考(复制) JetBrains AI Assistant 的相似 chunk 实现,以作为代码的一部分。

这部分大家都比较熟悉了。唯一差异的点是,如何支持多语言,这一点可以自己去看代码中的实现。

指令起始提示词

在针对于大的新特性时,Java 程序员通常会创建一个新的 Controller 等等的方式实现;而针对于功能点优化时,我们通常会修改现有函数,或者添加新的函数。

所以,在 AutoDev 的自动测试生成里,为了让 LLM 更能理解,我们添加了一个尾提示词。

  1. if (!testContext.isNewFile) {

  2. "Start test code with `@Test` syntax here: \n"

  3. } else {

  4. "Start ${testContext.testClassName} with `import` syntax here: \n"

  5. }

简单来说,就是让 GPT 知道接下来应该做什么,避免在过程中因为各种 prompt 失焦。

总结

由 ChatGPT 总结

AutoDev 0.8项目在持续开发中不断演进,特别关注prompt的优化与重构。通过模式化的方式重新设计了新的上下文工程体系,实现了更智能、更人性化的代码提示与生成。新的prompt范式结合了ChatActionType、特定场景要求、技术栈上下文、代码上下文和指令起始提示词等元素,使得AutoDev能够更好地理解开发者的意图,根据具体场景和技术栈生成符合期望的代码。该改进不仅提高了开发效率,降低了误差,还增强了AutoDev的智能性和实用性。


微信扫码关注该文公众号作者

戳这里提交新闻线索和高质量文章给我们。
相关阅读
只有GPT-4可以自我改进,GPT-3.5都不行,MIT&微软代码生成实验新发现趣图:调试代码的日常如何调教AI给你打工?提示词(Prompt)的秘密这个国家已经准备先倒为敬了本地生活场景下的探索之如何写好Prompt?不用4个H100!340亿参数Code Llama在Mac可跑,每秒20个token,代码生成最拿手|Karpathy转赞ChatGPT重大更新!prompt推荐瞬间解释超导,GPT-4成默认模型【广发策略】新投资范式:成因、日本启示与应对——“新投资范式”系列报告二最强开源SDXL 1.0发布!质量拉满,超简单prompt一键生成大模型生成提速2倍!单GPU几小时搞定微调,北大数院校友共同一作丨开源0提示词1张照片生成视频,Gen-2新玩法刷屏!网页版免费可玩文生图prompt不再又臭又长!LLM增强扩散模型,简单句就能生成高质量图像|ACM MM'23Llama 2第二波划重点:过于「谨慎」、代码生成改进空间大开源打败闭源?Meta即将推出开源代码生成平台Code Llama,剑指OpenAI Codex开源打败闭源?Meta 即将推出开源代码生成平台 Code Llama,剑指 OpenAI CodexPrompt解锁语音语言模型生成能力,SpeechGen实现语音翻译、修补多项任务一段乱码,竟让ChatGPT越狱!乱序prompt让LLM火速生成勒索软件,Jim Fan惊了不写代码,一句提示生成整个代码库,GPT-Engineer项目火了LLM 与架构新纪元:适应代码生成模式,突破软件开发瓶颈多编程语言代码生成神器 CodeGeeX,编码效率提升十倍!谷歌大模型云服务上线,代码生成、PaLM for Chat首次亮相Stability AI进军编程领域,发布首个用于代码生成的大语言模型拒绝花架子!盘点ChatGPT最强的七个插件:写提示词、学外语、总结视频,让ChatGPT做你的私人秘书减脂是一个长期工程微软发布基于LLM的代码生成神器,动动嘴就能写代码!不写代码,一句提示生成整个代码库,它在 GitHub 爆火PromptAppGPT重磅更新!AI助手0门槛开发+运行:几十行代码即可实现AutoGPT大峡谷漂流日记第五天夜思比 GitHub Copilot 更强大?Meta 开源 AI 编码工具,能跨多语言补全和调试代码苹果进入中国30周年 / Meta 将推出自动代码生成软件 / 视觉中国索赔事件进展 | 灵感周报PromptBench: 首个大语言模型提示鲁棒性的评测基准多GPU通信效率提升4倍,RLHF生成提升2.25倍!DeepSpeed ZeRO++重磅升级历史小说《黄裳元吉》第九十五章 寒意ACE友情宣发 | 探索高效协同工具新范式:AFFiNE硅谷专场workshop
logo
联系我们隐私协议©2024 redian.news
Redian新闻
Redian.news刊载任何文章,不代表同意其说法或描述,仅为提供更多信息,也不构成任何建议。文章信息的合法性及真实性由其作者负责,与Redian.news及其运营公司无关。欢迎投稿,如发现稿件侵权,或作者不愿在本网发表文章,请版权拥有者通知本网处理。