refactor(generateCommitMessageFromGitDiff.ts): rename mergeStrings to mergeDiffs and add maxDiffLength parameter
feat(generateCommitMessageFromGitDiff.ts): split file diffs into changes in files if they exceed the maximum token count The mergeStrings function was renamed to mergeDiffs to better reflect its purpose. The function now takes an additional parameter, maxDiffLength, which is used to split file diffs into changes in files if they exceed the maximum token count. This change improves the efficiency of the function and reduces the number of tokens used.
This commit is contained in:
@@ -4,7 +4,7 @@ import {
|
|||||||
} from 'openai';
|
} from 'openai';
|
||||||
import { api } from './api';
|
import { api } from './api';
|
||||||
import { getConfig } from './commands/config';
|
import { getConfig } from './commands/config';
|
||||||
import { mergeStrings } from './utils/mergeStrings';
|
import { mergeDiffs } from './utils/mergeDiffs';
|
||||||
import { i18n, I18nLocals } from './i18n';
|
import { i18n, I18nLocals } from './i18n';
|
||||||
import { tokenCount } from './utils/tokenCount';
|
import { tokenCount } from './utils/tokenCount';
|
||||||
|
|
||||||
@@ -14,45 +14,38 @@ const translation = i18n[(config?.language as I18nLocals) || 'en'];
|
|||||||
const INIT_MESSAGES_PROMPT: Array<ChatCompletionRequestMessage> = [
|
const INIT_MESSAGES_PROMPT: Array<ChatCompletionRequestMessage> = [
|
||||||
{
|
{
|
||||||
role: ChatCompletionRequestMessageRoleEnum.System,
|
role: ChatCompletionRequestMessageRoleEnum.System,
|
||||||
content: `You are to act as the author of a commit message in git. Your mission is to create clean and comprehensive commit messages in the conventional commit convention. I'll send you an output of 'git diff --staged' command, and you convert it into a commit message.
|
// prettier-ignore
|
||||||
${
|
content: `You are to act as the author of a commit message in git. Your mission is to create clean and comprehensive commit messages in the conventional commit convention and explain why a change was done. I'll send you an output of 'git diff --staged' command, and you convert it into a commit message.
|
||||||
config?.emoji
|
${config?.emoji? 'Use Gitmoji convention to preface the commit.': 'Do not preface the commit with anything.'}
|
||||||
? 'Use Gitmoji convention to preface the commit'
|
${config?.description ? 'Add a short description of why the commit is done after the commit message. Don\'t start it with "This commit", just describe the changes.': "Don't add any descriptions to the commit, only commit message."}
|
||||||
: 'Do not preface the commit with anything'
|
Use the present tense. Lines must not be longer than 74 characters. Use ${translation.localLanguage} to answer.`
|
||||||
}.
|
|
||||||
${
|
|
||||||
config?.description
|
|
||||||
? 'Add a short description of why the commit is done after the commit message. Don\'t start it with "This commit", just describe the changes'
|
|
||||||
: "Don't add any descriptions to the commit, only commit message"
|
|
||||||
}.
|
|
||||||
Use the present tense.
|
|
||||||
Lines must not be longer 74 characters.
|
|
||||||
Use ${translation.localLanguage} to answer.`
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
role: ChatCompletionRequestMessageRoleEnum.User,
|
role: ChatCompletionRequestMessageRoleEnum.User,
|
||||||
content: `diff --git a/src/server.ts b/src/server.ts
|
content: `diff --git a/src/server.ts b/src/server.ts
|
||||||
index ad4db42..f3b18a9 100644
|
index ad4db42..f3b18a9 100644
|
||||||
--- a/src/server.ts
|
--- a/src/server.ts
|
||||||
+++ b/src/server.ts
|
+++ b/src/server.ts
|
||||||
@@ -10,7 +10,7 @@ import {
|
@@ -10,7 +10,7 @@
|
||||||
initWinstonLogger();
|
import {
|
||||||
|
initWinstonLogger();
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
-const port = 7799;
|
-const port = 7799;
|
||||||
+const PORT = 7799;
|
+const PORT = 7799;
|
||||||
|
|
||||||
app.use(express.json());
|
app.use(express.json());
|
||||||
|
|
||||||
@@ -34,6 +34,6 @@ app.use((_, res, next) => {
|
@@ -34,6 +34,6 @@
|
||||||
// ROUTES
|
app.use((_, res, next) => {
|
||||||
app.use(PROTECTED_ROUTER_URL, protectedRouter);
|
// ROUTES
|
||||||
|
app.use(PROTECTED_ROUTER_URL, protectedRouter);
|
||||||
|
|
||||||
-app.listen(port, () => {
|
-app.listen(port, () => {
|
||||||
- console.log(\`Server listening on port \${port}\`);
|
- console.log(\`Server listening on port \${port}\`);
|
||||||
+app.listen(process.env.PORT || PORT, () => {
|
+app.listen(process.env.PORT || PORT, () => {
|
||||||
+ console.log(\`Server listening on port \${PORT}\`);
|
+ console.log(\`Server listening on port \${PORT}\`);
|
||||||
});`
|
});`
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
role: ChatCompletionRequestMessageRoleEnum.Assistant,
|
role: ChatCompletionRequestMessageRoleEnum.Assistant,
|
||||||
@@ -96,7 +89,10 @@ export const generateCommitMessageWithChatCompletion = async (
|
|||||||
): Promise<string | GenerateCommitMessageError> => {
|
): Promise<string | GenerateCommitMessageError> => {
|
||||||
try {
|
try {
|
||||||
if (tokenCount(diff) >= MAX_REQ_TOKENS) {
|
if (tokenCount(diff) >= MAX_REQ_TOKENS) {
|
||||||
const commitMessagePromises = getCommitMsgsPromisesFromFileDiffs(diff);
|
const commitMessagePromises = getCommitMsgsPromisesFromFileDiffs(
|
||||||
|
diff,
|
||||||
|
MAX_REQ_TOKENS
|
||||||
|
);
|
||||||
|
|
||||||
const commitMessages = await Promise.all(commitMessagePromises);
|
const commitMessages = await Promise.all(commitMessagePromises);
|
||||||
|
|
||||||
@@ -116,22 +112,28 @@ export const generateCommitMessageWithChatCompletion = async (
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function getMessagesPromisesByLines(fileDiff: string, separator: string) {
|
function getMessagesPromisesByChangesInFile(
|
||||||
const lineSeparator = '\n@@';
|
fileDiff: string,
|
||||||
const [fileHeader, ...fileDiffByLines] = fileDiff.split(lineSeparator);
|
separator: string,
|
||||||
|
maxChangeLength: number
|
||||||
|
) {
|
||||||
|
const hunkHeaderSeparator = '@@ ';
|
||||||
|
const [fileHeader, ...fileDiffByLines] = fileDiff.split(hunkHeaderSeparator);
|
||||||
|
|
||||||
// merge multiple line-diffs into 1 to save tokens
|
// merge multiple line-diffs into 1 to save tokens
|
||||||
const mergedLines = mergeStrings(
|
const mergedChanges = mergeDiffs(
|
||||||
fileDiffByLines.map((line) => lineSeparator + line),
|
fileDiffByLines.map((line) => hunkHeaderSeparator + line),
|
||||||
MAX_REQ_TOKENS
|
maxChangeLength
|
||||||
);
|
);
|
||||||
|
|
||||||
const lineDiffsWithHeader = mergedLines.map(
|
const lineDiffsWithHeader = mergedChanges.map(
|
||||||
(d) => fileHeader + lineSeparator + d
|
(change) => fileHeader + change
|
||||||
);
|
);
|
||||||
|
|
||||||
const commitMsgsFromFileLineDiffs = lineDiffsWithHeader.map((d) => {
|
const commitMsgsFromFileLineDiffs = lineDiffsWithHeader.map((lineDiff) => {
|
||||||
const messages = generateCommitMessageChatCompletionPrompt(separator + d);
|
const messages = generateCommitMessageChatCompletionPrompt(
|
||||||
|
separator + lineDiff
|
||||||
|
);
|
||||||
|
|
||||||
return api.generateCommitMessage(messages);
|
return api.generateCommitMessage(messages);
|
||||||
});
|
});
|
||||||
@@ -139,20 +141,27 @@ function getMessagesPromisesByLines(fileDiff: string, separator: string) {
|
|||||||
return commitMsgsFromFileLineDiffs;
|
return commitMsgsFromFileLineDiffs;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCommitMsgsPromisesFromFileDiffs(diff: string) {
|
export function getCommitMsgsPromisesFromFileDiffs(
|
||||||
|
diff: string,
|
||||||
|
maxDiffLength: number
|
||||||
|
) {
|
||||||
const separator = 'diff --git ';
|
const separator = 'diff --git ';
|
||||||
|
|
||||||
const diffByFiles = diff.split(separator).slice(1);
|
const diffByFiles = diff.split(separator).slice(1);
|
||||||
|
|
||||||
// merge multiple files-diffs into 1 prompt to save tokens
|
// merge multiple files-diffs into 1 prompt to save tokens
|
||||||
const mergedFilesDiffs = mergeStrings(diffByFiles, MAX_REQ_TOKENS);
|
const mergedFilesDiffs = mergeDiffs(diffByFiles, maxDiffLength);
|
||||||
|
|
||||||
const commitMessagePromises = [];
|
const commitMessagePromises = [];
|
||||||
|
|
||||||
for (const fileDiff of mergedFilesDiffs) {
|
for (const fileDiff of mergedFilesDiffs) {
|
||||||
if (tokenCount(fileDiff) >= MAX_REQ_TOKENS) {
|
if (tokenCount(fileDiff) >= maxDiffLength) {
|
||||||
// if file-diff is bigger than gpt context — split fileDiff into lineDiff
|
// if file-diff is bigger than gpt context — split fileDiff into lineDiff
|
||||||
const messagesPromises = getMessagesPromisesByLines(fileDiff, separator);
|
const messagesPromises = getMessagesPromisesByChangesInFile(
|
||||||
|
fileDiff,
|
||||||
|
separator,
|
||||||
|
maxDiffLength
|
||||||
|
);
|
||||||
|
|
||||||
commitMessagePromises.push(...messagesPromises);
|
commitMessagePromises.push(...messagesPromises);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user