Files
opencommit/src/engine/azure.ts
2024-08-27 17:04:36 +03:00

78 lines
2.1 KiB
TypeScript

import {
AzureKeyCredential,
OpenAIClient as AzureOpenAIClient
} from '@azure/openai';
import { outro } from '@clack/prompts';
import axios from 'axios';
import chalk from 'chalk';
import { OpenAI } from 'openai';
import { GenerateCommitMessageErrorEnum } from '../generateCommitMessageFromGitDiff';
import { tokenCount } from '../utils/tokenCount';
import { AiEngine, AiEngineConfig } from './Engine';
interface AzureAiEngineConfig extends AiEngineConfig {
baseURL: string;
apiKey: string;
}
export class AzureEngine implements AiEngine {
config: AzureAiEngineConfig;
client: AzureOpenAIClient;
constructor(config: AzureAiEngineConfig) {
this.config = config;
this.client = new AzureOpenAIClient(
this.config.baseURL,
new AzureKeyCredential(this.config.apiKey)
);
}
generateCommitMessage = async (
messages: Array<OpenAI.Chat.Completions.ChatCompletionMessageParam>
): Promise<string | undefined> => {
try {
const REQUEST_TOKENS = messages
.map((msg) => tokenCount(msg.content as string) + 4)
.reduce((a, b) => a + b, 0);
if (
REQUEST_TOKENS >
this.config.maxTokensInput - this.config.maxTokensOutput
) {
throw new Error(GenerateCommitMessageErrorEnum.tooMuchTokens);
}
const data = await this.client.getChatCompletions(
this.config.model,
messages
);
const message = data.choices[0].message;
if (message?.content === null) {
return undefined;
}
return message?.content;
} catch (error) {
outro(`${chalk.red('✖')} ${this.config.model}`);
const err = error as Error;
outro(`${chalk.red('✖')} ${JSON.stringify(error)}`);
if (
axios.isAxiosError<{ error?: { message: string } }>(error) &&
error.response?.status === 401
) {
const openAiError = error.response.data.error;
if (openAiError?.message) outro(openAiError.message);
outro(
'For help look into README https://github.com/di-sukharev/opencommit#setup'
);
}
throw err;
}
};
}