feat: Add Input Token Limit Config Option (#281)

This commit is contained in:
mattsalt123
2024-02-29 15:06:23 +00:00
committed by GitHub
parent 011db5ad5e
commit c9b45492a5
4 changed files with 54 additions and 18 deletions
+4 -2
View File
@@ -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
View File
@@ -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,
+5 -4
View File
@@ -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);
} }
+11 -4
View File
@@ -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) {