Skip to content

Commit dda7f8d

Browse files
committed
refactor: organize prompt generation to its own file
1 parent eda3462 commit dda7f8d

File tree

2 files changed

+60
-67
lines changed

2 files changed

+60
-67
lines changed

src/utils/openai.ts

Lines changed: 12 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import https from 'https';
22
import type { ClientRequest, IncomingMessage } from 'http';
3-
import type { ChatCompletionRequestMessage, CreateChatCompletionRequest, CreateChatCompletionResponse } from 'openai';
3+
import type { CreateChatCompletionRequest, CreateChatCompletionResponse } from 'openai';
44
import {
55
type TiktokenModel,
66
// encoding_for_model,
77
} from '@dqbd/tiktoken';
88
import createHttpsProxyAgent from 'https-proxy-agent';
99
import { KnownError } from './error.js';
1010
import type { CommitType } from './config.js';
11+
import { generatePrompt } from './prompt.js';
1112

1213
const httpsPost = async (
1314
hostname: string,
@@ -104,52 +105,6 @@ const sanitizeMessage = (message: string) => message.trim().replace(/[\n\r]/g, '
104105

105106
const deduplicateMessages = (array: string[]) => Array.from(new Set(array));
106107

107-
const getBasePrompt = (
108-
locale: string,
109-
maxLength: number,
110-
) => `${[
111-
'Generate a concise git commit message written in present tense for the following code diff with the given specifications below:',
112-
`Message language: ${locale}`,
113-
`Commit message must be a maximum of ${maxLength} characters.`,
114-
'Exclude anything unnecessary such as translation. Your entire response will be passed directly into git commit.',
115-
].join('\n')}`;
116-
117-
const getCommitMessageFormatOutputExample = (type: CommitType) => `The output response must be in format:\n${getCommitMessageFormat(type)}`;
118-
119-
const getCommitMessageFormat = (type: CommitType) => {
120-
if (type === 'conventional') {
121-
return '<type>(<optional scope>): <commit message>';
122-
}
123-
124-
return '<commit message>';
125-
};
126-
127-
/**
128-
* References:
129-
* Commitlint:
130-
* https://github.com/conventional-changelog/commitlint/blob/18fbed7ea86ac0ec9d5449b4979b762ec4305a92/%40commitlint/config-conventional/index.js#L40-L100
131-
*
132-
* Conventional Changelog:
133-
* https://github.com/conventional-changelog/conventional-changelog/blob/d0e5d5926c8addba74bc962553dd8bcfba90e228/packages/conventional-changelog-conventionalcommits/writer-opts.js#L182-L193
134-
*/
135-
const getExtraContextForConventionalCommits = () => (
136-
`Choose a type from the type-to-description JSON below that best describes the git diff:\n${
137-
JSON.stringify({
138-
docs: 'Documentation only changes',
139-
style: 'Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)',
140-
refactor: 'A code change that neither fixes a bug nor adds a feature',
141-
perf: 'A code change that improves performance',
142-
test: 'Adding missing tests or correcting existing tests',
143-
build: 'Changes that affect the build system or external dependencies',
144-
ci: 'Changes to our CI configuration files and scripts',
145-
chore: "Other changes that don't modify src or test files",
146-
revert: 'Reverts a previous commit',
147-
feat: 'A new feature',
148-
fix: 'A bug fix',
149-
}, null, 2)
150-
}`
151-
);
152-
153108
// const generateStringFromLength = (length: number) => {
154109
// let result = '';
155110
// const highestTokenChar = 'z';
@@ -178,31 +133,21 @@ export const generateCommitMessage = async (
178133
timeout: number,
179134
proxy?: string,
180135
) => {
181-
const prompt = getBasePrompt(locale, maxLength);
182-
183-
const conventionalCommitsExtraContext = type === 'conventional'
184-
? getExtraContextForConventionalCommits()
185-
: '';
186-
187-
const commitMessageFormatOutputExample = getCommitMessageFormatOutputExample(type);
188-
189-
const messages: ChatCompletionRequestMessage[] = [
190-
{
191-
role: 'system',
192-
content: `${prompt}\n${conventionalCommitsExtraContext}\n${commitMessageFormatOutputExample}`,
193-
},
194-
{
195-
role: 'user',
196-
content: diff,
197-
},
198-
];
199-
200136
try {
201137
const completion = await createChatCompletion(
202138
apiKey,
203139
{
204140
model,
205-
messages,
141+
messages: [
142+
{
143+
role: 'system',
144+
content: generatePrompt(locale, maxLength, type),
145+
},
146+
{
147+
role: 'user',
148+
content: diff,
149+
},
150+
],
206151
temperature: 0.7,
207152
top_p: 1,
208153
frequency_penalty: 0,

src/utils/prompt.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import type { CommitType } from './config.js';
2+
3+
const commitTypeFormats: Record<CommitType, string> = {
4+
'': '<commit message>',
5+
conventional: '<type>(<optional scope>): <commit message>',
6+
};
7+
const specifyCommitFormat = (type: CommitType) => `The output response must be in format:\n${commitTypeFormats[type]}`;
8+
9+
const commitTypes: Record<CommitType, string> = {
10+
'': '',
11+
12+
/**
13+
* References:
14+
* Commitlint:
15+
* https://github.com/conventional-changelog/commitlint/blob/18fbed7ea86ac0ec9d5449b4979b762ec4305a92/%40commitlint/config-conventional/index.js#L40-L100
16+
*
17+
* Conventional Changelog:
18+
* https://github.com/conventional-changelog/conventional-changelog/blob/d0e5d5926c8addba74bc962553dd8bcfba90e228/packages/conventional-changelog-conventionalcommits/writer-opts.js#L182-L193
19+
*/
20+
conventional: `Choose a type from the type-to-description JSON below that best describes the git diff:\n${
21+
JSON.stringify({
22+
docs: 'Documentation only changes',
23+
style: 'Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)',
24+
refactor: 'A code change that neither fixes a bug nor adds a feature',
25+
perf: 'A code change that improves performance',
26+
test: 'Adding missing tests or correcting existing tests',
27+
build: 'Changes that affect the build system or external dependencies',
28+
ci: 'Changes to our CI configuration files and scripts',
29+
chore: "Other changes that don't modify src or test files",
30+
revert: 'Reverts a previous commit',
31+
feat: 'A new feature',
32+
fix: 'A bug fix',
33+
}, null, 2)
34+
}`,
35+
};
36+
37+
export const generatePrompt = (
38+
locale: string,
39+
maxLength: number,
40+
type: CommitType,
41+
) => [
42+
'Generate a concise git commit message written in present tense for the following code diff with the given specifications below:',
43+
`Message language: ${locale}`,
44+
`Commit message must be a maximum of ${maxLength} characters.`,
45+
'Exclude anything unnecessary such as translation. Your entire response will be passed directly into git commit.',
46+
commitTypes[type],
47+
specifyCommitFormat(type),
48+
].filter(Boolean).join('\n');

0 commit comments

Comments
 (0)