feat: Add Input Token Limit Config Option (#281)
This commit is contained in:
@@ -77,7 +77,8 @@ Create a `.env` file and add OpenCommit config variables there like this:
|
|||||||
|
|
||||||
```env
|
```env
|
||||||
OCO_OPENAI_API_KEY=<your OpenAI API token>
|
OCO_OPENAI_API_KEY=<your OpenAI API token>
|
||||||
OCO_OPENAI_MAX_TOKENS=<max response tokens from OpenAI API>
|
OCO_TOKENS_MAX_INPUT=<max model token limit (default: 4096)>
|
||||||
|
OCO_TOKENS_MAX_OUTPUT=<max response tokens (default: 500)>
|
||||||
OCO_OPENAI_BASE_PATH=<may be used to set proxy path to OpenAI api>
|
OCO_OPENAI_BASE_PATH=<may be used to set proxy path to OpenAI api>
|
||||||
OCO_DESCRIPTION=<postface a message with ~3 sentences description of the changes>
|
OCO_DESCRIPTION=<postface a message with ~3 sentences description of the changes>
|
||||||
OCO_EMOJI=<boolean, add GitMoji>
|
OCO_EMOJI=<boolean, add GitMoji>
|
||||||
@@ -329,7 +330,8 @@ jobs:
|
|||||||
OCO_OPENAI_API_KEY: ${{ secrets.OCO_OPENAI_API_KEY }}
|
OCO_OPENAI_API_KEY: ${{ secrets.OCO_OPENAI_API_KEY }}
|
||||||
|
|
||||||
# customization
|
# customization
|
||||||
OCO_OPENAI_MAX_TOKENS: 500
|
OCO_TOKENS_MAX_INPUT: 4096
|
||||||
|
OCO_TOKENS_MAX_OUTPUT: 500
|
||||||
OCO_OPENAI_BASE_PATH: ''
|
OCO_OPENAI_BASE_PATH: ''
|
||||||
OCO_DESCRIPTION: false
|
OCO_DESCRIPTION: false
|
||||||
OCO_EMOJI: false
|
OCO_EMOJI: false
|
||||||
|
|||||||
+34
-8
@@ -15,7 +15,8 @@ dotenv.config();
|
|||||||
|
|
||||||
export enum CONFIG_KEYS {
|
export enum CONFIG_KEYS {
|
||||||
OCO_OPENAI_API_KEY = 'OCO_OPENAI_API_KEY',
|
OCO_OPENAI_API_KEY = 'OCO_OPENAI_API_KEY',
|
||||||
OCO_OPENAI_MAX_TOKENS = 'OCO_OPENAI_MAX_TOKENS',
|
OCO_TOKENS_MAX_INPUT = 'OCO_TOKENS_MAX_INPUT',
|
||||||
|
OCO_TOKENS_MAX_OUTPUT = 'OCO_TOKENS_MAX_OUTPUT',
|
||||||
OCO_OPENAI_BASE_PATH = 'OCO_OPENAI_BASE_PATH',
|
OCO_OPENAI_BASE_PATH = 'OCO_OPENAI_BASE_PATH',
|
||||||
OCO_DESCRIPTION = 'OCO_DESCRIPTION',
|
OCO_DESCRIPTION = 'OCO_DESCRIPTION',
|
||||||
OCO_EMOJI = 'OCO_EMOJI',
|
OCO_EMOJI = 'OCO_EMOJI',
|
||||||
@@ -26,13 +27,16 @@ export enum CONFIG_KEYS {
|
|||||||
OCO_AI_PROVIDER = 'OCO_AI_PROVIDER',
|
OCO_AI_PROVIDER = 'OCO_AI_PROVIDER',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DEFAULT_MODEL_TOKEN_LIMIT = 4096;
|
|
||||||
|
|
||||||
export enum CONFIG_MODES {
|
export enum CONFIG_MODES {
|
||||||
get = 'get',
|
get = 'get',
|
||||||
set = 'set'
|
set = 'set'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum DEFAULT_TOKEN_LIMITS {
|
||||||
|
DEFAULT_MAX_TOKENS_INPUT = 4096,
|
||||||
|
DEFAULT_MAX_TOKENS_OUTPUT = 500
|
||||||
|
}
|
||||||
|
|
||||||
const validateConfig = (
|
const validateConfig = (
|
||||||
key: string,
|
key: string,
|
||||||
condition: any,
|
condition: any,
|
||||||
@@ -75,18 +79,37 @@ export const configValidators = {
|
|||||||
return value;
|
return value;
|
||||||
},
|
},
|
||||||
|
|
||||||
[CONFIG_KEYS.OCO_OPENAI_MAX_TOKENS](value: any) {
|
[CONFIG_KEYS.OCO_TOKENS_MAX_INPUT](value: any) {
|
||||||
// If the value is a string, convert it to a number.
|
// If the value is a string, convert it to a number.
|
||||||
if (typeof value === 'string') {
|
if (typeof value === 'string') {
|
||||||
value = parseInt(value);
|
value = parseInt(value);
|
||||||
validateConfig(
|
validateConfig(
|
||||||
CONFIG_KEYS.OCO_OPENAI_MAX_TOKENS,
|
CONFIG_KEYS.OCO_TOKENS_MAX_INPUT,
|
||||||
!isNaN(value),
|
!isNaN(value),
|
||||||
'Must be a number'
|
'Must be a number'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
validateConfig(
|
validateConfig(
|
||||||
CONFIG_KEYS.OCO_OPENAI_MAX_TOKENS,
|
CONFIG_KEYS.OCO_TOKENS_MAX_INPUT,
|
||||||
|
value ? typeof value === 'number' : undefined,
|
||||||
|
'Must be a number'
|
||||||
|
);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
},
|
||||||
|
|
||||||
|
[CONFIG_KEYS.OCO_TOKENS_MAX_OUTPUT](value: any) {
|
||||||
|
// If the value is a string, convert it to a number.
|
||||||
|
if (typeof value === 'string') {
|
||||||
|
value = parseInt(value);
|
||||||
|
validateConfig(
|
||||||
|
CONFIG_KEYS.OCO_TOKENS_MAX_OUTPUT,
|
||||||
|
!isNaN(value),
|
||||||
|
'Must be a number'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
validateConfig(
|
||||||
|
CONFIG_KEYS.OCO_TOKENS_MAX_OUTPUT,
|
||||||
value ? typeof value === 'number' : undefined,
|
value ? typeof value === 'number' : undefined,
|
||||||
'Must be a number'
|
'Must be a number'
|
||||||
);
|
);
|
||||||
@@ -178,8 +201,11 @@ const configPath = pathJoin(homedir(), '.opencommit');
|
|||||||
export const getConfig = (): ConfigType | null => {
|
export const getConfig = (): ConfigType | null => {
|
||||||
const configFromEnv = {
|
const configFromEnv = {
|
||||||
OCO_OPENAI_API_KEY: process.env.OCO_OPENAI_API_KEY,
|
OCO_OPENAI_API_KEY: process.env.OCO_OPENAI_API_KEY,
|
||||||
OCO_OPENAI_MAX_TOKENS: process.env.OCO_OPENAI_MAX_TOKENS
|
OCO_TOKENS_MAX_INPUT: process.env.OCO_TOKENS_MAX_INPUT
|
||||||
? Number(process.env.OCO_OPENAI_MAX_TOKENS)
|
? Number(process.env.OCO_TOKENS_MAX_INPUT)
|
||||||
|
: undefined,
|
||||||
|
OCO_TOKENS_MAX_OUTPUT: process.env.OCO_TOKENS_MAX_OUTPUT
|
||||||
|
? Number(process.env.OCO_TOKENS_MAX_OUTPUT)
|
||||||
: undefined,
|
: undefined,
|
||||||
OCO_OPENAI_BASE_PATH: process.env.OCO_OPENAI_BASE_PATH,
|
OCO_OPENAI_BASE_PATH: process.env.OCO_OPENAI_BASE_PATH,
|
||||||
OCO_DESCRIPTION: process.env.OCO_DESCRIPTION === 'true' ? true : false,
|
OCO_DESCRIPTION: process.env.OCO_DESCRIPTION === 'true' ? true : false,
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import { intro, outro } from '@clack/prompts';
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
CONFIG_MODES,
|
CONFIG_MODES,
|
||||||
DEFAULT_MODEL_TOKEN_LIMIT,
|
DEFAULT_TOKEN_LIMITS,
|
||||||
getConfig
|
getConfig
|
||||||
} from '../commands/config';
|
} from '../commands/config';
|
||||||
import { GenerateCommitMessageErrorEnum } from '../generateCommitMessageFromGitDiff';
|
import { GenerateCommitMessageErrorEnum } from '../generateCommitMessageFromGitDiff';
|
||||||
@@ -20,7 +20,8 @@ import { AiEngine } from './Engine';
|
|||||||
|
|
||||||
const config = getConfig();
|
const config = getConfig();
|
||||||
|
|
||||||
let maxTokens = config?.OCO_OPENAI_MAX_TOKENS;
|
const MAX_TOKENS_OUTPUT = config?.OCO_TOKENS_MAX_OUTPUT || DEFAULT_TOKEN_LIMITS.DEFAULT_MAX_TOKENS_OUTPUT;
|
||||||
|
const MAX_TOKENS_INPUT = config?.OCO_TOKENS_MAX_INPUT || DEFAULT_TOKEN_LIMITS.DEFAULT_MAX_TOKENS_INPUT;
|
||||||
let basePath = config?.OCO_OPENAI_BASE_PATH;
|
let basePath = config?.OCO_OPENAI_BASE_PATH;
|
||||||
let apiKey = config?.OCO_OPENAI_API_KEY
|
let apiKey = config?.OCO_OPENAI_API_KEY
|
||||||
|
|
||||||
@@ -65,14 +66,14 @@ class OpenAi implements AiEngine {
|
|||||||
messages,
|
messages,
|
||||||
temperature: 0,
|
temperature: 0,
|
||||||
top_p: 0.1,
|
top_p: 0.1,
|
||||||
max_tokens: maxTokens || 500
|
max_tokens: MAX_TOKENS_OUTPUT
|
||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
const REQUEST_TOKENS = messages
|
const REQUEST_TOKENS = messages
|
||||||
.map((msg) => tokenCount(msg.content) + 4)
|
.map((msg) => tokenCount(msg.content) + 4)
|
||||||
.reduce((a, b) => a + b, 0);
|
.reduce((a, b) => a + b, 0);
|
||||||
|
|
||||||
if (REQUEST_TOKENS > DEFAULT_MODEL_TOKEN_LIMIT - maxTokens) {
|
if (REQUEST_TOKENS > MAX_TOKENS_INPUT - MAX_TOKENS_OUTPUT) {
|
||||||
throw new Error(GenerateCommitMessageErrorEnum.tooMuchTokens);
|
throw new Error(GenerateCommitMessageErrorEnum.tooMuchTokens);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,13 +3,15 @@ import {
|
|||||||
ChatCompletionRequestMessageRoleEnum
|
ChatCompletionRequestMessageRoleEnum
|
||||||
} from 'openai';
|
} from 'openai';
|
||||||
|
|
||||||
import { DEFAULT_MODEL_TOKEN_LIMIT, getConfig } from './commands/config';
|
import { DEFAULT_TOKEN_LIMITS, getConfig } from './commands/config';
|
||||||
import { getMainCommitPrompt } from './prompts';
|
import { getMainCommitPrompt } from './prompts';
|
||||||
import { mergeDiffs } from './utils/mergeDiffs';
|
import { mergeDiffs } from './utils/mergeDiffs';
|
||||||
import { tokenCount } from './utils/tokenCount';
|
import { tokenCount } from './utils/tokenCount';
|
||||||
import { getEngine } from './utils/engine';
|
import { getEngine } from './utils/engine';
|
||||||
|
|
||||||
const config = getConfig();
|
const config = getConfig();
|
||||||
|
const MAX_TOKENS_INPUT = config?.OCO_TOKENS_MAX_INPUT || DEFAULT_TOKEN_LIMITS.DEFAULT_MAX_TOKENS_INPUT;
|
||||||
|
const MAX_TOKENS_OUTPUT = config?.OCO_TOKENS_MAX_OUTPUT || DEFAULT_TOKEN_LIMITS.DEFAULT_MAX_TOKENS_OUTPUT;
|
||||||
|
|
||||||
const generateCommitMessageChatCompletionPrompt = async (
|
const generateCommitMessageChatCompletionPrompt = async (
|
||||||
diff: string
|
diff: string
|
||||||
@@ -29,7 +31,8 @@ const generateCommitMessageChatCompletionPrompt = async (
|
|||||||
export enum GenerateCommitMessageErrorEnum {
|
export enum GenerateCommitMessageErrorEnum {
|
||||||
tooMuchTokens = 'TOO_MUCH_TOKENS',
|
tooMuchTokens = 'TOO_MUCH_TOKENS',
|
||||||
internalError = 'INTERNAL_ERROR',
|
internalError = 'INTERNAL_ERROR',
|
||||||
emptyMessage = 'EMPTY_MESSAGE'
|
emptyMessage = 'EMPTY_MESSAGE',
|
||||||
|
outputTokensTooHigh = `Token limit exceeded, OCO_TOKENS_MAX_OUTPUT must not be much higher than the default ${DEFAULT_TOKEN_LIMITS.DEFAULT_MAX_TOKENS_OUTPUT} tokens.`
|
||||||
}
|
}
|
||||||
|
|
||||||
const ADJUSTMENT_FACTOR = 20;
|
const ADJUSTMENT_FACTOR = 20;
|
||||||
@@ -45,10 +48,10 @@ export const generateCommitMessageByDiff = async (
|
|||||||
).reduce((a, b) => a + b, 0);
|
).reduce((a, b) => a + b, 0);
|
||||||
|
|
||||||
const MAX_REQUEST_TOKENS =
|
const MAX_REQUEST_TOKENS =
|
||||||
DEFAULT_MODEL_TOKEN_LIMIT -
|
MAX_TOKENS_INPUT -
|
||||||
ADJUSTMENT_FACTOR -
|
ADJUSTMENT_FACTOR -
|
||||||
INIT_MESSAGES_PROMPT_LENGTH -
|
INIT_MESSAGES_PROMPT_LENGTH -
|
||||||
config?.OCO_OPENAI_MAX_TOKENS;
|
MAX_TOKENS_OUTPUT;
|
||||||
|
|
||||||
if (tokenCount(diff) >= MAX_REQUEST_TOKENS) {
|
if (tokenCount(diff) >= MAX_REQUEST_TOKENS) {
|
||||||
const commitMessagePromises = await getCommitMsgsPromisesFromFileDiffs(
|
const commitMessagePromises = await getCommitMsgsPromisesFromFileDiffs(
|
||||||
@@ -124,6 +127,10 @@ function splitDiff(diff: string, maxChangeLength: number) {
|
|||||||
const splitDiffs = [];
|
const splitDiffs = [];
|
||||||
let currentDiff = '';
|
let currentDiff = '';
|
||||||
|
|
||||||
|
if (maxChangeLength <= 0) {
|
||||||
|
throw new Error(GenerateCommitMessageErrorEnum.outputTokensTooHigh);
|
||||||
|
}
|
||||||
|
|
||||||
for (let line of lines) {
|
for (let line of lines) {
|
||||||
// If a single line exceeds maxChangeLength, split it into multiple lines
|
// If a single line exceeds maxChangeLength, split it into multiple lines
|
||||||
while (tokenCount(line) > maxChangeLength) {
|
while (tokenCount(line) > maxChangeLength) {
|
||||||
|
|||||||
Reference in New Issue
Block a user