refactor: organize prompt generation to its own file
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
import https from 'https';
|
import https from 'https';
|
||||||
import type { ClientRequest, IncomingMessage } from 'http';
|
import type { ClientRequest, IncomingMessage } from 'http';
|
||||||
import type { ChatCompletionRequestMessage, CreateChatCompletionRequest, CreateChatCompletionResponse } from 'openai';
|
import type { CreateChatCompletionRequest, CreateChatCompletionResponse } from 'openai';
|
||||||
import {
|
import {
|
||||||
type TiktokenModel,
|
type TiktokenModel,
|
||||||
// encoding_for_model,
|
// encoding_for_model,
|
||||||
@@ -8,6 +8,7 @@ import {
|
|||||||
import createHttpsProxyAgent from 'https-proxy-agent';
|
import createHttpsProxyAgent from 'https-proxy-agent';
|
||||||
import { KnownError } from './error.js';
|
import { KnownError } from './error.js';
|
||||||
import type { CommitType } from './config.js';
|
import type { CommitType } from './config.js';
|
||||||
|
import { generatePrompt } from './prompt.js';
|
||||||
|
|
||||||
const httpsPost = async (
|
const httpsPost = async (
|
||||||
hostname: string,
|
hostname: string,
|
||||||
@@ -104,52 +105,6 @@ const sanitizeMessage = (message: string) => message.trim().replace(/[\n\r]/g, '
|
|||||||
|
|
||||||
const deduplicateMessages = (array: string[]) => Array.from(new Set(array));
|
const deduplicateMessages = (array: string[]) => Array.from(new Set(array));
|
||||||
|
|
||||||
const getBasePrompt = (
|
|
||||||
locale: string,
|
|
||||||
maxLength: number,
|
|
||||||
) => `${[
|
|
||||||
'Generate a concise git commit message written in present tense for the following code diff with the given specifications below:',
|
|
||||||
`Message language: ${locale}`,
|
|
||||||
`Commit message must be a maximum of ${maxLength} characters.`,
|
|
||||||
'Exclude anything unnecessary such as translation. Your entire response will be passed directly into git commit.',
|
|
||||||
].join('\n')}`;
|
|
||||||
|
|
||||||
const getCommitMessageFormatOutputExample = (type: CommitType) => `The output response must be in format:\n${getCommitMessageFormat(type)}`;
|
|
||||||
|
|
||||||
const getCommitMessageFormat = (type: CommitType) => {
|
|
||||||
if (type === 'conventional') {
|
|
||||||
return '<type>(<optional scope>): <commit message>';
|
|
||||||
}
|
|
||||||
|
|
||||||
return '<commit message>';
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* References:
|
|
||||||
* Commitlint:
|
|
||||||
* https://github.com/conventional-changelog/commitlint/blob/18fbed7ea86ac0ec9d5449b4979b762ec4305a92/%40commitlint/config-conventional/index.js#L40-L100
|
|
||||||
*
|
|
||||||
* Conventional Changelog:
|
|
||||||
* https://github.com/conventional-changelog/conventional-changelog/blob/d0e5d5926c8addba74bc962553dd8bcfba90e228/packages/conventional-changelog-conventionalcommits/writer-opts.js#L182-L193
|
|
||||||
*/
|
|
||||||
const getExtraContextForConventionalCommits = () => (
|
|
||||||
`Choose a type from the type-to-description JSON below that best describes the git diff:\n${
|
|
||||||
JSON.stringify({
|
|
||||||
docs: 'Documentation only changes',
|
|
||||||
style: 'Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)',
|
|
||||||
refactor: 'A code change that neither fixes a bug nor adds a feature',
|
|
||||||
perf: 'A code change that improves performance',
|
|
||||||
test: 'Adding missing tests or correcting existing tests',
|
|
||||||
build: 'Changes that affect the build system or external dependencies',
|
|
||||||
ci: 'Changes to our CI configuration files and scripts',
|
|
||||||
chore: "Other changes that don't modify src or test files",
|
|
||||||
revert: 'Reverts a previous commit',
|
|
||||||
feat: 'A new feature',
|
|
||||||
fix: 'A bug fix',
|
|
||||||
}, null, 2)
|
|
||||||
}`
|
|
||||||
);
|
|
||||||
|
|
||||||
// const generateStringFromLength = (length: number) => {
|
// const generateStringFromLength = (length: number) => {
|
||||||
// let result = '';
|
// let result = '';
|
||||||
// const highestTokenChar = 'z';
|
// const highestTokenChar = 'z';
|
||||||
@@ -178,31 +133,21 @@ export const generateCommitMessage = async (
|
|||||||
timeout: number,
|
timeout: number,
|
||||||
proxy?: string,
|
proxy?: string,
|
||||||
) => {
|
) => {
|
||||||
const prompt = getBasePrompt(locale, maxLength);
|
|
||||||
|
|
||||||
const conventionalCommitsExtraContext = type === 'conventional'
|
|
||||||
? getExtraContextForConventionalCommits()
|
|
||||||
: '';
|
|
||||||
|
|
||||||
const commitMessageFormatOutputExample = getCommitMessageFormatOutputExample(type);
|
|
||||||
|
|
||||||
const messages: ChatCompletionRequestMessage[] = [
|
|
||||||
{
|
|
||||||
role: 'system',
|
|
||||||
content: `${prompt}\n${conventionalCommitsExtraContext}\n${commitMessageFormatOutputExample}`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
role: 'user',
|
|
||||||
content: diff,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const completion = await createChatCompletion(
|
const completion = await createChatCompletion(
|
||||||
apiKey,
|
apiKey,
|
||||||
{
|
{
|
||||||
model,
|
model,
|
||||||
messages,
|
messages: [
|
||||||
|
{
|
||||||
|
role: 'system',
|
||||||
|
content: generatePrompt(locale, maxLength, type),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
role: 'user',
|
||||||
|
content: diff,
|
||||||
|
},
|
||||||
|
],
|
||||||
temperature: 0.7,
|
temperature: 0.7,
|
||||||
top_p: 1,
|
top_p: 1,
|
||||||
frequency_penalty: 0,
|
frequency_penalty: 0,
|
||||||
|
|||||||
48
src/utils/prompt.ts
Normal file
48
src/utils/prompt.ts
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
import type { CommitType } from './config.js';
|
||||||
|
|
||||||
|
const commitTypeFormats: Record<CommitType, string> = {
|
||||||
|
'': '<commit message>',
|
||||||
|
conventional: '<type>(<optional scope>): <commit message>',
|
||||||
|
};
|
||||||
|
const specifyCommitFormat = (type: CommitType) => `The output response must be in format:\n${commitTypeFormats[type]}`;
|
||||||
|
|
||||||
|
const commitTypes: Record<CommitType, string> = {
|
||||||
|
'': '',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* References:
|
||||||
|
* Commitlint:
|
||||||
|
* https://github.com/conventional-changelog/commitlint/blob/18fbed7ea86ac0ec9d5449b4979b762ec4305a92/%40commitlint/config-conventional/index.js#L40-L100
|
||||||
|
*
|
||||||
|
* Conventional Changelog:
|
||||||
|
* https://github.com/conventional-changelog/conventional-changelog/blob/d0e5d5926c8addba74bc962553dd8bcfba90e228/packages/conventional-changelog-conventionalcommits/writer-opts.js#L182-L193
|
||||||
|
*/
|
||||||
|
conventional: `Choose a type from the type-to-description JSON below that best describes the git diff:\n${
|
||||||
|
JSON.stringify({
|
||||||
|
docs: 'Documentation only changes',
|
||||||
|
style: 'Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)',
|
||||||
|
refactor: 'A code change that neither fixes a bug nor adds a feature',
|
||||||
|
perf: 'A code change that improves performance',
|
||||||
|
test: 'Adding missing tests or correcting existing tests',
|
||||||
|
build: 'Changes that affect the build system or external dependencies',
|
||||||
|
ci: 'Changes to our CI configuration files and scripts',
|
||||||
|
chore: "Other changes that don't modify src or test files",
|
||||||
|
revert: 'Reverts a previous commit',
|
||||||
|
feat: 'A new feature',
|
||||||
|
fix: 'A bug fix',
|
||||||
|
}, null, 2)
|
||||||
|
}`,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const generatePrompt = (
|
||||||
|
locale: string,
|
||||||
|
maxLength: number,
|
||||||
|
type: CommitType,
|
||||||
|
) => [
|
||||||
|
'Generate a concise git commit message written in present tense for the following code diff with the given specifications below:',
|
||||||
|
`Message language: ${locale}`,
|
||||||
|
`Commit message must be a maximum of ${maxLength} characters.`,
|
||||||
|
'Exclude anything unnecessary such as translation. Your entire response will be passed directly into git commit.',
|
||||||
|
commitTypes[type],
|
||||||
|
specifyCommitFormat(type),
|
||||||
|
].filter(Boolean).join('\n');
|
||||||
Reference in New Issue
Block a user