在开发 IDE 插件 AutoDev 时,我们一直遵循着 Unit Mesh 的基本思想,即 AI 所生成的应该是可执行的单元(Unit)。在底层构建丰富的各类单元/工具, 再结合 DevIns 来构建强大的智能体能力。
在初步完成了 AutoDev 的整体蓝图(MVP)之后,我们开始强化原来的准确性问题,即 AI 所生成的代码是否可以被编译器编译,是否可以被测试覆盖等。在这些 功能中,我们最想解决的是:AI 所生成的代码单元是否可执行?
在去年,我们在进行微调试验的时候,曾经使用 GPT-3.5 API 根据 3000 个场景生成 3000 个 PlantUML 代码,而后通过调用 PlantUML 编译器来生成图片。最终,我们发现在不考虑准确性的情况下, 3000 个代码中,大概只有 600 个代码是可以被编译器编译的, 即可执行的代码比例大概是 20%。对于剩下的 600 个数据,我们需要再次调用 GPT-3.5 API 来生成代码。重复,直到所有生成的代码都可以被编译器编译。
20% 的失败率对于个人的感知太明显了,而根据概率论的知识,我们可以通过多次尝试来提升可执行率。诸如:
考虑到成本以及生成式 AI 并没有那么聪明,所以我们选择了执行两次,即可执行率提升到 0.96。当然了,在一些高 ROI 的价值,大家可以考虑执行三次。
可执行单元校验是指通过对生成的代码进行测试和验证,确保其能够被编译器编译和执行。可执行单元校验旨在提高生成代码的准确性和可执行性, 以确保生成的代码单元符合预期并能够被有效地使用。
在 AutoDev 中,对应有结合数据库的 SQL、单元测试、功能代码生成的功能,所以我们初步设计了以下的校验机制:
考虑到单元测试是直接可执行的,因此在 AutoDev 我们是直接执行单元测试(RunService
)的,只要 IDE 速度够快,基本上是能快速检验的。
通过上述的检验机制, 可以有效地提高生成代码的准确性和可执行性,确保生成的代码单元符合预期并能够被有效地使用。
当然了,如果模型能力不够强,那么可能会带来负面的体验。
根据上述的思想,我们可以打开看看 AutoDev 中对应功能的实现。
由于,不同语言在对于测试的管理是有差异的,诸如于:
tests
目录下创建一个 test_*.py
文件。src/test/java
目录下创建一个 *.java
文件。*.rs
里有一个 mod tests
。所以,在 AutoDev 中,我们创建了 AutoTestService
接口作为不同语言的扩展点,以支持不同语言的单元测试执行。其次在执行上:
当然从最终效果来说,在 Java 测试中,AI 生成的诸多 import 函数都是有问题的,对于接受率更差的其它语言来说,效果就更差了。
我们在 AutoDev 中设计的 SQL 生成,主要是用来辅助我这种学过多种 SQL 变体,但是 SQL 反而写得更差的人。其次,也只适用于项目中的 SQL 语句, 即没有太多的复杂逻辑。
根据不同的模型能力,在 SQL 生成的可执行校验设计上还是应该所区别的:
由于是在 IDE 中,并且依赖于项目连接到数据库,所以我们可以:
如 AI 生成一个不可执行的 SQL,诸如于:SELECT * FROM table where id =;
,在 IDE
中,进行语法检查时,就会返回: Syntax error at position 30: <expression>, ALL, ANY or SOME expected, got ';'
的错误。因此,只需要使用 PsiElementVisitor
来遍历 SQL 语句,然后进行语法检查即可。最后,如果出现错误,就会直接作为第三次对话,发送给模型。
顺便一提,由于还没有设计沙盒机制,当前并不会让 AI 直接执行 SQL 语句,而是通过生成 SQL 语句,然后由开发者来执行。这个锅,必须由开发者来背。
根据上述的内容,GPT 3.5 对我们进行了一些建议。
为了进一步改进 AutoDev 的功能和实践可执行单元校验,我们可以采取以下措施:
通过以上改进措施的实施和实践,我们可以进一步提升 AutoDev 插件的功能和性能,提高生成代码的准确性和可执行性,为开发者提供更优质的开发体验。
事实上,我们在 AutoDev 中已经实现了一部分的功能,但是由于时间和精力有限,还有很多功能需要进一步完善和优化。我们将继续努力,不断改进和提升 AutoDev ,欢迎大家关注和支持我们的工作:https://github.com/unit-mesh/auto-dev
围观我的Github Idea墙, 也许,你会遇到心仪的项目