训练机器:OpenBayes(用我的专用邀请链接,注册 OpenBayes,双方各获得 60 分钟 RTX 3090 使用时长,支持累积,永久有效: https://openbayes.com/console/signup?r=phodal_uVxU) A100 大概 1 小时,使用 A0390 大概 3 小时。
训练步骤可以直接使用: alpaca-lora.ipynb 或者直接使用 OpenBayes 容器:https://openbayes.com/console/phodal/containers/JBx5YD7HTdS
代码生成测试用例的 Lora 见:https://github.com/unit-mesh/unit-minions/releases/tag/v0.0.1
基本思路:
- 在时间有限的情况下,基于 OpenAI 的数据来完善。但是,OpenAI 编写的测试用例不一定靠谱,所以让他生成业务代码。
- 在时间充裕的情况下,可以分析 AST 来合并第一和第二步,也是比较合理的方案,毕竟 OpenAI 的 API 很贵。
- 下载 GitHub 上的项目(需要包含测试用例)
- 建立每个项目的
src/main
下的 Java 文件 map,如果同时存在对应的测试文件,则拉入的数据集中。 - 并生成每个测试对应的类的基本信息(以减少 OpenAI Token 使用):
org.unitmesh.processor.TestClass(String, Int)
- fields: field1:String, field2:Int
- methods: method1(String, Int): String, method2(): Int
- 按测试用例(即 @Test 方法)拆分每个测试文件,拆成 N 个(即 test1、test2 是两个不同的数据)
class TestProcessorTest {
@Test
void test1() {
}
@Test
void test2() {
}
}
最后,生成的数据如下:
{"classInfo": "com.thoughtworks.go.security.AESEncrypter(AESCipherProvider)\n- fields: ENCODER:Base64.Encoder, DECODER:Base64.Decoder, cipherProvider:AESCipherProvider, ivProvider:IVProvider\n- methods: createIVProviderInstance(): IVProvider, canDecrypt(String): boolean, encrypt(String): String, decrypt(String): String, createSecretKeySpec(): SecretKeySpec", "testMethod": "public class AESEncrypterTest {\n\n private AESEncrypter aesEncrypter;\n\n @Test\n public void shouldGenerateEncryptedText() throws CryptoException {\n String encrypt = aesEncrypter.encrypt(\"p@ssw0rd\");\n assertThat(encrypt).startsWith(\"AES\");\n assertThat(encrypt.split(\":\")).hasSize(3);\n }\n}\n", "id": "task_0"}
步骤 2. 使用 OpenAI Davinci 编写实现代码(代码见:test-to-code.py)
- 将上面的数据转换为 JSONL,合并成 prompt。
- 让 Davinci 完成填空题。
最后生成的 prompt 示例如下:
You are a programmer and implementation a method with TDD. Here are the requirements:
1. According follows class information and tests code to write a method.
2. Try you best to thinking corner case.
3. You only return the code, no explain.
class information:
###
io.github.robwin.swagger.test.AbstractContractValidator()
- methods: findExpectedPaths(Swagger, SwaggerAssertionConfig): Map<String,Path>, getPathsIncludingBasePath(Swagger): Map<String,Path>, getPathsWithPrefix(Swagger, String): Map<String,Path>, isBlankOrSlash(String): boolean
###
test code:
###
/**
* Tests AbstractContractValidator.
*/
@RunWith(Enclosed.class)
public class AbstractContractValidatorTest {
/**
* Tests getPathsIncludingBasePath().
*/
public static class GetPathsIncludingBasePath {
@Test
public void shouldReturnPathsPrefixedIfBasePathSet() {
// given
Swagger swagger = buildSwaggerFrom("/swagger.json");
// when
Map<String, Path> paths = new DummyValidator().getPathsIncludingBasePath(swagger);
// then
paths.entrySet().forEach(e -> assertThat(e.getKey(), startsWith(swagger.getBasePath())));
}
}
/**
* Tests findExpectedPaths().
*/
public static class FindExpectedPaths {
}
private static class DummyValidator extends AbstractContractValidator {
}
}
###
训练步骤可以直接使用: alpaca-lora.ipynb