本文同步自个人博客怎么让GPT帮你生成模版代码,转载请注明出处。
Motivation
本文所述的GPT是指OpenAI的GPT-x模型,详见platform.openai.com/docs/models…
GPT是一个强壮的自然言语处理东西,它能够依据你的注释或许代码片段等帮你完结代码,但有时分期望机器能够辅助咱们完结一些重复性作业,比方编程中的模板代码生成。可是OpenAI的API有token数量约束,例如,gpt-3.5只支撑4096个tokens,不适合一次性生成整个文件的代码。虽然gpt-4能够支撑8k乃至32k tokens,但一个巨大的代码文件很容易就超越这个约束。
那么怎么让GPT帮咱们依据巨大的代码生成模板代码呢?中心思维是将代码拆分红小片段,然后将这些小片段输入给GPT。GPT会依据prompt处理代码片段,并输出成果。最后,咱们将生成后的代码片段拼接到模版中,输出最终的代码文件。为了防止GPT输出模棱两可的成果,咱们需求保证代码片段有满足的上下文信息。
依据以上思路,我开发了一个名为gpt_code_gen的东西,目前只支撑C++代码生成。下面我将共享一下实现这个东西的进程中所做的一些思考和经历。
拆分代码片段
大多数情况下,咱们能够运用正则表达式来拆分代码片段,假如需求愈加精确地获取代码信息,咱们能够运用对应言语的AST东西来进行拆分。详细实现细节不在本文评论范围之内。
拆分代码片段粒度
-
按代码界说来拆分
咱们能够将
class
,struct
,enum
等界说作为一个代码块。 -
拆分子代码片段
在一个大型、长期保护的项目中,
class
的界说通常会超越几百个办法,因而咱们需求将class
拆分红子代码片段。-
将一个办法作为一个代码块。
-
将宏界说作为一个代码块。这儿的宏界说指被宏界说包裹的代码,如下所示:
#if defined(__ANDROID__) virtual void func3() = 0; #endif
-
以下是示例代码:
struct MyStruct {
int field1;
int field2;
};
enum MyEnum {
ENUM1 = 1;
}
class MyClass {
virtual void func1() = 0;
virtual void func2(const MyStruct& my_struct) = 0;
#if defined(__ANDROID__)
virtual void func3() = 0;
#endif
};
咱们能够将上述代码拆分红以下代码片段:
代码片段1:
struct MyStruct {
int field1;
int field2;
};
代码片段2:
enum MyEnum {
ENUM1 = 1;
}
代码片段3:
class MyClass {
virtual void func1() = 0;
virtual void func2(const MyStruct& my_struct) = 0;
#if defined(__ANDROID__)
virtual void func3() = 0;
#endif
};
咱们能够将class
拆分红以下子代码片段:
子代码片段1:
virtual void func1() = 0;
子代码片段2:
virtual void func2(const MyStruct& my_struct) = 0;
子代码片段3:
#if defined(__ANDROID__)
virtual void func3() = 0;
#endif
保证代码片段具有满足的上下文
为了保证准确性,咱们尽可能将代码片段中涉及到用户自界说的struct
和 enum
的信息提供给GPT。例如,在子代码片段2中,咱们会将代码片段1的信息包括进去:
struct MyStruct {
int field1;
int field2;
};
virtual void func2(const MyStruct& my_struct) = 0;
自然言语生成模版代码
在前面咱们现已介绍了怎么拆分代码块,现在咱们来看看怎么运用拆分后的代码块来生成代码。在AI年代,自然言语编程成为可能,只需求编写Prompt就能够灵敏地控制代码生成(你能够参阅awesome-chatgpt-prompts或许凭借ChatGPT来编写比较准确的Prompt)。
在本项目中,主要运用Chat Completion API来完结代码生成。运用YAML格局能够省去符号转义的费事,同时还能更方便地将代码作为输入,更好地支撑Few-shot prompting。因而,本项目中选用了YAML作为Prompt输入文件格局,然后将其转换成JSON格局以发送给Chat Completion API。详细格局如下:
- role: system
content: The system content
- role: user
content: This is the user content
- role: assistant
content: This is the assistant content
上述子代码片段1将会被转换成以下JSON格局并发送到Chat Completion API:
[
{"role": "system", "content": "The system content"},
{"role": "user", "content": "This is the user content"},
{"role": "assistant", "content": "This is the assistant content"},
{"role": "user", "content": "virtual void func1() = 0;"}
]
以下是项目中生成gMock MOCK_METHOD
的Prompt例子:
- role: system
content: |
Write a gMock mock method definition in C++. The mock method should take C++ function code snippets as inputs and return the mock method definition. Use your knowledge of C++ and gMock to write the exact gMock mock function declaration. Your solution should be in the form of a C++ code snippet that defines the mock method.
The mock method should should also handle any macro declarations in the input and include them in the output.
I want you to only reply the mock method definition. Do not write explanations.
- role: user
content: |
virtual void release(bool sync = false) = 0;
- role: assistant
content: |
MOCK_METHOD(void, release, (bool sync), (override));
以上Prompt为每个办法代码块生成了MOCK_METHOD
。最后一步是将生成的MOCK_METHOD
拼接起来,如文章最初所说,咱们需求一个模版类来承载这些生成后的办法,模版类也能够通过Prompt来生成。以下是本项目中生成整个gMock Mock类模版的Prompt例子:
- role: system
content: |
Given the class name, replace the {{ CLASS_NAME }} in the following template:
/// GENERATED BY gpt_code_gen, DO NOT MODIFY BY HAND.
class Mock{{ CLASS_NAME }} : public {{ CLASS_NAME }} {
public:
{{ BODY }}
};
I want you to only reply the replaced template Do not write explanations.
- role: user
content: IRtcEngine
- role: assistant
content: |
/// GENERATED BY gpt_code_gen, DO NOT MODIFY BY HAND.
class MockIRtcEngine : public IRtcEngine {
public:
{{ BODY }}
};
最终将生成的办法代码替换模版中的{{ BODY }}
并输出即可:
/// GENERATED BY gpt_code_gen, DO NOT MODIFY BY HAND.
class MockIRtcEngine : public IRtcEngine {
public:
MOCK_METHOD(void, release, (bool sync), (override));
MOCK_METHOD(int, queryInterface, (INTERFACE_ID_TYPE iid, void** inter), (override));
...
};
TL;DR
这篇文章是ChatGPT帮我写的,写得不好请见谅。
以上,是我共享的关于gpt_code_gen项目的一些经历。期望对你有协助。
项目地址:github.com/littleGnAl/…
demo见:github.com/littleGnAl/…