Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ feat(api.ts): add support for Azure OpenAI API #167

Open
wants to merge 5 commits into
base: dev
Choose a base branch
from
Open
Changes from 1 commit
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
Next Next commit
✨ feat(api.ts): add support for Azure OpenAI API
The Azure OpenAI API is now supported in addition to the OpenAI API. The API type can be specified in the configuration file using the OPENAI_API_TYPE key. If the key is not specified, the default value is 'openai'. The AzureOpenAIApi class is added to the utils folder to handle the Azure OpenAI API calls. The createChatCompletion method is implemented in the AzureOpenAIApi class to handle the chat completion requests. The method is called in the generateCommitMessage method in the OpenAi class if the apiType is set to 'azure'.
  • Loading branch information
takuya-o committed May 6, 2023
commit 6519441289788c3ed5e8706c4ef4c0e6dd687f08
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -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).
10 changes: 8 additions & 2 deletions src/api.ts
Original file line number Diff line number Diff line change
@@ -6,6 +6,9 @@ import {
Configuration as OpenAiApiConfiguration,
OpenAIApi
} from 'openai';
import {
AzureOpenAIApi
} from './utils/AzureOpenAI';

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

@@ -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);

@@ -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 (
22 changes: 19 additions & 3 deletions src/commands/config.ts
Original file line number Diff line number Diff line change
@@ -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',
@@ -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;
}
77 changes: 77 additions & 0 deletions src/utils/AzureOpenAI.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/** 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 {
BaseAPI,
} from 'openai/dist/base';
import {
CreateChatCompletionRequest,
Configuration,
} from "openai";
import { AxiosRequestConfig} from '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呼び出し
const response = await this.axios.post(url, createChatCompletionRequest, options);

// console.log(response.data.usage);
return response;
}

}