Skip to content
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,20 @@ oc

## Features

### Switch to Azure OpenAI

By default OpenCommit uses [OpenAI](https://openai.com).

You could switch to [Azure OpenAI Service](https://learn.microsoft.com/azure/cognitive-services/openai/)🚀

```sh
opencommit config set OPENAI_API_TYPE=azure
```

Of course need to set 'OPENAI_API_KEY'. And also need to set the
'OPENAI_BASE_PATH' for the endpoint and set the deployment name to
'model'.

### Switch to GPT-4

By default OpenCommit uses GPT-3.5-turbo (ChatGPT).
Expand Down
10 changes: 8 additions & 2 deletions src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import {
Configuration as OpenAiApiConfiguration,
OpenAIApi
} from 'openai';
import {
AzureOpenAIApi
} from './utils/AzureOpenAI';

import { CONFIG_MODES, getConfig } from './commands/config';

Expand All @@ -14,6 +17,7 @@ const config = getConfig();
let apiKey = config?.OPENAI_API_KEY;
let basePath = config?.OPENAI_BASE_PATH;
let maxTokens = config?.OPENAI_MAX_TOKENS;
let apiType = config?.OPENAI_API_TYPE || 'openai';

const [command, mode] = process.argv.slice(2);

Expand All @@ -36,13 +40,15 @@ class OpenAi {
private openAiApiConfiguration = new OpenAiApiConfiguration({
apiKey: apiKey
});
private openAI!: OpenAIApi;
private openAI!: OpenAIApi | AzureOpenAIApi;

constructor() {
if (basePath) {
this.openAiApiConfiguration.basePath = basePath;
}
this.openAI = new OpenAIApi(this.openAiApiConfiguration);
this.openAI = apiType === 'azure'
? new AzureOpenAIApi(this.openAiApiConfiguration)
: new OpenAIApi(this.openAiApiConfiguration);
}

public generateCommitMessage = async (
Expand Down
22 changes: 19 additions & 3 deletions src/commands/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export enum CONFIG_KEYS {
OPENAI_API_KEY = 'OPENAI_API_KEY',
OPENAI_MAX_TOKENS = 'OPENAI_MAX_TOKENS',
OPENAI_BASE_PATH = 'OPENAI_BASE_PATH',
OPENAI_API_TYPE = 'OPENAI_API_TYPE',
description = 'description',
emoji = 'emoji',
model = 'model',
Expand Down Expand Up @@ -102,11 +103,26 @@ export const configValidators = {
return value;
},

[CONFIG_KEYS.OPENAI_API_TYPE](value: any) {
validateConfig(
CONFIG_KEYS.OPENAI_API_TYPE,
typeof value === 'string',
'Must be string'
);
validateConfig(
CONFIG_KEYS.OPENAI_API_TYPE,
value === 'azure' || value === 'openai' || value === '',
`${value} is not supported yet, use 'azure' or 'openai' (default)`
);
return value;
},

[CONFIG_KEYS.model](value: any) {
validateConfig(
CONFIG_KEYS.OPENAI_BASE_PATH,
value === 'gpt-3.5-turbo' || value === 'gpt-4',
`${value} is not supported yet, use 'gpt-4' or 'gpt-3.5-turbo' (default)`
CONFIG_KEYS.model,
value === 'gpt-3.5-turbo' || value === 'gpt-4'
|| ( typeof value === 'string' && value.match(/^[a-zA-Z0-9~\-]{1,63}[a-zA-Z0-9]$/) ),
`${value} is not supported yet, use 'gpt-4' or 'gpt-3.5-turbo' (default) or model deployed name.`
);
return value;
}
Expand Down
75 changes: 75 additions & 0 deletions src/utils/AzureOpenAI.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/** Azure OpenAI Service API
* https://learn.microsoft.com/azure/cognitive-services/openai/
* The API version of the Azure OpenAI Service 2023-03-15-preview
*
* Note: Only make what is necessary for opencommit
*/

import {
CreateChatCompletionRequest,
Configuration,
} from "openai";
import { BaseAPI } from 'openai/dist/base';
import { AxiosRequestConfig} from 'openai/node_modules/axios';

export class AzureOpenAIApi extends BaseAPI {
constructor(configuration: Configuration) {
super(configuration);
}

/**
*
* @summary Creates a completion for the chat message
* @param {CreateChatCompletionRequest} createChatCompletionRequest
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof AzureOpenAIApi
*/
public async createChatCompletion(createChatCompletionRequest: CreateChatCompletionRequest, options?: AxiosRequestConfig) {
if (!this.configuration) {
throw new Error('Required parameter configuration was null or undefined when calling createChatCompletion.');
}
if (!this.configuration.basePath) {
throw new Error('Required parameter basePath was null or undefined when calling createChatCompletion.');
}
if (!this.configuration.apiKey) {
throw new Error('Required parameter apiKey was null or undefined when calling createChatCompletion.');
}
if (typeof this.configuration.apiKey !== 'string') {
throw new Error('Required parameter apiKey was of type string when calling createChatCompletion.');
}

const url = this.configuration.basePath + 'openai/deployments/' + createChatCompletionRequest.model + '/chat/completions';
if (!options) options = {};
if (!options.headers) options.headers = {};
if (!options.params) options.params = {};
options.headers = {
'Content-Type': 'application/json',
"api-key": this.configuration.apiKey,
...options.headers,
}
options.params = {
'api-version': '2023-03-15-preview',
...options.params,
}

// axios DEBUG
// this.axios.interceptors.request.use(request => {
// console.log('Starting Request: ', request)
// return request
// })
// this.axios.interceptors.response.use(response => {
// console.log('Response: ', response)
// return response
// })

// Azure OpenAI APIのREST呼び出し
Comment thread
takuya-o marked this conversation as resolved.
Outdated
const response = await this.axios.post(url, createChatCompletionRequest, options);

// console.log(response.data.usage);
Comment thread
takuya-o marked this conversation as resolved.
Outdated
return response;
}

}