Skip to content

Commit

Permalink
feat: ET-1426: Added Azure support and updated readme (#2)
Browse files Browse the repository at this point in the history
* fix: ET-1426: Updated README.md with instructions for getting API key from OpenAI or Azure and added additional config options for OpenAI and Azure. Also, modified api.ts to handle different API types (OpenAI or Azure) based on the config.

* feat: ET-1426: Add Azure API version and engine to config for better Azure integration

* refactor: ET-1426: rename OCO_AZURE_ENGINE to OCO_AZURE_DEPLOYMENT for clarity

* fix: ET-1426: Refactor variable names and improve code readability in api.ts and config.ts files

---------

Co-authored-by: Matthew Salter <matthew.salter@dvla.gov.uk>
  • Loading branch information
mattsalt123 and Matthew Salter authored Oct 26, 2023
1 parent 99da69e commit fabb481
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 25 deletions.
36 changes: 29 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
## DVLA Usage
This is a fork of [OpenCommit](https://github.com/di-sukharev/opencommit).
- It includes functionality to use Azure OpenAPI service as a backend.
- It includes functionality to use Azure OpenAPI service as a backend originating from this [pull request](https://github.com/di-sukharev/opencommit/pull/167).
- The package has been renamed to `@dvla/opencommit` for internal use.
- The MIT License still applies and references the contribution from the original author ` Dima Sukharev`.
- The MIT License still applies and references the contribution from the original author `Dima Sukharev`.

&nbsp;
&nbsp;
&nbsp;
&nbsp;

<div align="center">
<div>
Expand Down Expand Up @@ -37,7 +41,8 @@ You can use OpenCommit by simply running it via the CLI like this `oco`. 2 secon

MacOS may ask to run the command with `sudo` when installing a package globally.

2. Get your API key from [OpenAI](https://platform.openai.com/account/api-keys). Make sure that you add your payment details, so the API works.
2. Get your API key from [OpenAI](https://platform.openai.com/account/api-keys) or Azure.
For OpenAI - Make sure that you add your payment details, so the API works. And for Azure - ensure you set up the additional config in the [section](/README.md#configuration) below.

3. Set the key to OpenCommit config:

Expand Down Expand Up @@ -70,15 +75,32 @@ oco
Create a `.env` file and add OpenCommit config variables there like this:

```env
OCO_OPENAI_API_KEY=<your OpenAI API token>
OCO_OPENAI_MAX_TOKENS=<max response tokens from 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_EMOJI=<boolean, add GitMoji>
OCO_MODEL=<either 'gpt-4', 'gpt-3.5-turbo-16k' (default), 'gpt-3.5-turbo-0613' or 'gpt-3.5-turbo'>
OCO_LANGUAGE=<locale, scroll to the bottom to see options>
OCO_MESSAGE_TEMPLATE_PLACEHOLDER=<message template placeholder, default: '$msg'>
OCO_PROMPT_MODULE=<either conventional-commit or @commitlint, default: conventional-commit>
OCO_OPENAI_MAX_TOKENS=<max response tokens (default: 500)>
```

In addition to these config options, OpenAI and Azure can be set up with the following config variables:

#### OpenAI Config

```env
OCO_OPENAI_API_KEY=<your OpenAI API token>
OCO_OPENAI_BASE_PATH=<may be used to set proxy path to OpenAI api>
OCO_MODEL=<either 'gpt-4', 'gpt-3.5-turbo-16k' (default), 'gpt-3.5-turbo-0613' or 'gpt-3.5-turbo'>
```

#### Azure Config

```env
OCO_OPENAI_API_TYPE='azure'
OCO_OPENAI_API_KEY=<your Azure API token>
OCO_OPENAI_BASE_PATH=<azure path for example: https://EXAMPLE.openai.azure.com/>
OCO_AZURE_DEPLOYMENT=<azure deployment name>
OCO_AZURE_API_VERSION=<azure api version>
```

### Global config for all repos
Expand Down
44 changes: 32 additions & 12 deletions src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { intro, outro } from '@clack/prompts';

import {
CONFIG_MODES,
AI_TYPE,
DEFAULT_MODEL_TOKEN_LIMIT,
getConfig
} from './commands/config';
Expand All @@ -19,13 +20,17 @@ import { tokenCount } from './utils/tokenCount';

const config = getConfig();

let maxTokens = config?.OCO_OPENAI_MAX_TOKENS;
let basePath = config?.OCO_OPENAI_BASE_PATH;
let apiKey = config?.OCO_OPENAI_API_KEY;
const MAX_TOKENS = config?.OCO_OPENAI_MAX_TOKENS;
const BASE_PATH = config?.OCO_OPENAI_BASE_PATH;
const API_KEY = config?.OCO_OPENAI_API_KEY;
const API_TYPE = config?.OCO_OPENAI_API_TYPE || AI_TYPE.OPENAI;
const API_VERSION = config?.OCO_AZURE_API_VERSION || '2023-07-01-preview';
const MODEL = config?.OCO_MODEL || 'gpt-3.5-turbo';
const DEPLOYMENT = config?.OCO_AZURE_DEPLOYMENT;

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

if (!apiKey && command !== 'config' && mode !== CONFIG_MODES.set) {
if (!API_KEY && command !== 'config' && mode !== CONFIG_MODES.set) {
intro('opencommit');

outro(
Expand All @@ -37,18 +42,33 @@ if (!apiKey && command !== 'config' && mode !== CONFIG_MODES.set) {

process.exit(1);
}

const MODEL = config?.OCO_MODEL || 'gpt-3.5-turbo';

class OpenAi {
private openAiApiConfiguration = new OpenAiApiConfiguration({
apiKey: apiKey
apiKey: API_KEY
});
private openAI!: OpenAIApi;

constructor() {
if (basePath) {
this.openAiApiConfiguration.basePath = basePath;
switch (API_TYPE) {
case AI_TYPE.AZURE:
this.openAiApiConfiguration.baseOptions = {
headers: {
"api-key": API_KEY,
},
params: {
'api-version': API_VERSION,
}
};
if (BASE_PATH) {
this.openAiApiConfiguration.basePath = BASE_PATH + 'openai/deployments/' + DEPLOYMENT;
}
break;
case AI_TYPE.OPENAI:
// fall through to default
default:
if (BASE_PATH) {
this.openAiApiConfiguration.basePath = BASE_PATH;
}
}
this.openAI = new OpenAIApi(this.openAiApiConfiguration);
}
Expand All @@ -61,14 +81,14 @@ class OpenAi {
messages,
temperature: 0,
top_p: 0.1,
max_tokens: maxTokens || 500
max_tokens: MAX_TOKENS || 500
};
try {
const REQUEST_TOKENS = messages
.map((msg) => tokenCount(msg.content) + 4)
.reduce((a, b) => a + b, 0);

if (REQUEST_TOKENS > DEFAULT_MODEL_TOKEN_LIMIT - maxTokens) {
if (REQUEST_TOKENS > DEFAULT_MODEL_TOKEN_LIMIT - MAX_TOKENS) {
throw new Error(GenerateCommitMessageErrorEnum.tooMuchTokens);
}

Expand Down
59 changes: 53 additions & 6 deletions src/commands/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,20 @@ export enum CONFIG_KEYS {
OCO_OPENAI_API_KEY = 'OCO_OPENAI_API_KEY',
OCO_OPENAI_MAX_TOKENS = 'OCO_OPENAI_MAX_TOKENS',
OCO_OPENAI_BASE_PATH = 'OCO_OPENAI_BASE_PATH',
OCO_OPENAI_API_TYPE = 'OCO_OPENAI_API_TYPE',
OCO_DESCRIPTION = 'OCO_DESCRIPTION',
OCO_EMOJI = 'OCO_EMOJI',
OCO_AZURE_DEPLOYMENT = 'OCO_AZURE_DEPLOYMENT',
OCO_MODEL = 'OCO_MODEL',
OCO_LANGUAGE = 'OCO_LANGUAGE',
OCO_MESSAGE_TEMPLATE_PLACEHOLDER = 'OCO_MESSAGE_TEMPLATE_PLACEHOLDER',
OCO_PROMPT_MODULE = 'OCO_PROMPT_MODULE'
OCO_PROMPT_MODULE = 'OCO_PROMPT_MODULE',
OCO_AZURE_API_VERSION = 'OCO_AZURE_API_VERSION'
}

export enum AI_TYPE {
OPENAI = 'openai',
AZURE = 'azure'
}

export const DEFAULT_MODEL_TOKEN_LIMIT = 4096;
Expand All @@ -32,6 +40,9 @@ export enum CONFIG_MODES {
set = 'set'
}

const OPENAI_API_KEY_REGEX = /^[a-z0-9]{32}$/;
const AZURE_DEPLOYMENT_REGEX = /^[a-zA-Z0-9]+([-_][a-zA-Z0-9]+)*[a-zA-Z0-9]$/;

const validateConfig = (
key: string,
condition: any,
Expand All @@ -51,13 +62,13 @@ export const configValidators = {
validateConfig(CONFIG_KEYS.OCO_OPENAI_API_KEY, value, 'Cannot be empty');
validateConfig(
CONFIG_KEYS.OCO_OPENAI_API_KEY,
value.startsWith('sk-'),
'Must start with "sk-"'
value.startsWith('sk-') || value.match(OPENAI_API_KEY_REGEX),
'Must start with "sk-" or a valid 32 character Azure OpenAI API key'
);
validateConfig(
CONFIG_KEYS.OCO_OPENAI_API_KEY,
config[CONFIG_KEYS.OCO_OPENAI_BASE_PATH] || value.length === 51,
'Must be 51 characters long'
config[CONFIG_KEYS.OCO_OPENAI_BASE_PATH] || value.length === 51 || value.length === 32,
'Must be 51 (OpenAI) or 32 (Azure) characters long'
);

return value;
Expand Down Expand Up @@ -120,6 +131,29 @@ export const configValidators = {
return value;
},

[CONFIG_KEYS.OCO_AZURE_API_VERSION](value: any) {
validateConfig(
CONFIG_KEYS.OCO_AZURE_API_VERSION,
typeof value === 'string',
'Must be string'
);
return value;
},

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

[CONFIG_KEYS.OCO_MODEL](value: any) {
validateConfig(
CONFIG_KEYS.OCO_MODEL,
Expand All @@ -129,10 +163,20 @@ export const configValidators = {
'gpt-3.5-turbo-16k',
'gpt-3.5-turbo-0613'
].includes(value),
`${value} is not supported yet, use 'gpt-4', 'gpt-3.5-turbo-16k' (default), 'gpt-3.5-turbo-0613' or 'gpt-3.5-turbo'`
`${value} is not supported yet, use models: 'gpt-4', 'gpt-3.5-turbo-16k' (default), 'gpt-3.5-turbo-0613' or 'gpt-3.5-turbo'`
);
return value;
},

[CONFIG_KEYS.OCO_AZURE_DEPLOYMENT](value: any) {
validateConfig(
CONFIG_KEYS.OCO_AZURE_DEPLOYMENT,
( typeof value === 'string' && value.match(AZURE_DEPLOYMENT_REGEX) ),
`${value} is not a valid deployment name, it should only include alphanumeric characters, _ character and - character. It can't end with '_' or '-'.`
);
return value;
},

[CONFIG_KEYS.OCO_MESSAGE_TEMPLATE_PLACEHOLDER](value: any) {
validateConfig(
CONFIG_KEYS.OCO_MESSAGE_TEMPLATE_PLACEHOLDER,
Expand Down Expand Up @@ -166,9 +210,12 @@ export const getConfig = (): ConfigType | null => {
? Number(process.env.OCO_OPENAI_MAX_TOKENS)
: undefined,
OCO_OPENAI_BASE_PATH: process.env.OCO_OPENAI_BASE_PATH,
OCO_OPENAI_API_TYPE: process.env.OCO_OPENAI_API_TYPE || 'openai',
OCO_DESCRIPTION: process.env.OCO_DESCRIPTION === 'true' ? true : false,
OCO_EMOJI: process.env.OCO_EMOJI === 'true' ? true : false,
OCO_MODEL: process.env.OCO_MODEL || 'gpt-3.5-turbo-16k',
OCO_AZURE_API_VERSION: process.env.OCO_AZURE_API_VERSION || '2023-07-01-preview',
OCO_AZURE_DEPLOYMENT: process.env.OCO_AZURE_DEPLOYMENT,
OCO_LANGUAGE: process.env.OCO_LANGUAGE || 'en',
OCO_MESSAGE_TEMPLATE_PLACEHOLDER:
process.env.OCO_MESSAGE_TEMPLATE_PLACEHOLDER || '$msg',
Expand Down

0 comments on commit fabb481

Please sign in to comment.