Skip to content

Commit

Permalink
Add support for custom OpenAI URL
Browse files Browse the repository at this point in the history
Allows to run local OpenAI-compatible server. Since these local
instances most likely lack proper certificates, allow using non-HTTPS
endpoints as well.

Signed-off-by: Alexander Bokovoy <[email protected]>
  • Loading branch information
abbra committed Mar 13, 2024
1 parent 604def8 commit b6ded16
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 6 deletions.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,14 @@ Required

The OpenAI API key. You can retrieve it from [OpenAI API Keys page](https://platform.openai.com/account/api-keys).

For local OpenAI-compatible API server an empty key should be specified as `no_api_key`.

#### OPENAI_URL

Optional

The OpenAI server URL. Defaults to `https://api.openai.com`. Both `https` and `http` protocols supported.

#### locale

Default: `en`
Expand Down
1 change: 1 addition & 0 deletions src/commands/aicommits.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export default async (
let messages: string[];
try {
messages = await generateCommitMessage(
config.OPENAI_URL,
config.OPENAI_KEY,
config.model,
config.locale,
Expand Down
11 changes: 10 additions & 1 deletion src/utils/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const configParsers = {
'Please set your OpenAI API key via `aicommits config set OPENAI_KEY=<your token>`'
);
}
parseAssert('OPENAI_KEY', key.startsWith('sk-'), 'Must start with "sk-"');
parseAssert('OPENAI_KEY', /^((sk-|no_api_key){1}[a-zA-Z0-9]*)$/.test(key), 'Must start with "sk-" or "no_api_key"');
// Key can range from 43~51 characters. There's no spec to assert this.

return key;
Expand Down Expand Up @@ -115,6 +115,15 @@ const configParsers = {

return parsed;
},
OPENAI_URL(url?: string) {
if (!url || url.length === 0) {
return undefined;
}

parseAssert('OPENAI_URL', /^https?:\/\//.test(url), 'Must be a valid URL');

return url;
},
} as const;

type ConfigKeys = keyof typeof configParsers;
Expand Down
22 changes: 17 additions & 5 deletions src/utils/openai.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import https from 'https';
import http from 'http';
import type { ClientRequest, IncomingMessage } from 'http';
import type {
CreateChatCompletionRequest,
Expand All @@ -14,7 +15,7 @@ import type { CommitType } from './config.js';
import { generatePrompt } from './prompt.js';

const httpsPost = async (
hostname: string,
url: URL,
path: string,
headers: Record<string, string>,
json: unknown,
Expand All @@ -27,10 +28,14 @@ const httpsPost = async (
data: string;
}>((resolve, reject) => {
const postContent = JSON.stringify(json);
const request = https.request(
var connector = https;
if (url.protocol != 'https') {
connector = http;
}
const request = connector.request(
{
port: 443,
hostname,
hostname: url.hostname,
port: Number(url.port || '443'),
path,
method: 'POST',
headers: {
Expand Down Expand Up @@ -68,13 +73,18 @@ const httpsPost = async (
});

const createChatCompletion = async (
openai_url: string,
apiKey: string,
json: CreateChatCompletionRequest,
timeout: number,
proxy?: string
) => {
if (!openai_url || openai_url.length === 0) {
openai_url = 'https://api.openai.com/';
}
const url = new URL(openai_url);
const { response, data } = await httpsPost(
'api.openai.com',
url,
'/v1/chat/completions',
{
Authorization: `Bearer ${apiKey}`,
Expand Down Expand Up @@ -131,6 +141,7 @@ const deduplicateMessages = (array: string[]) => Array.from(new Set(array));
// };

export const generateCommitMessage = async (
openai_url: string,
apiKey: string,
model: TiktokenModel,
locale: string,
Expand All @@ -143,6 +154,7 @@ export const generateCommitMessage = async (
) => {
try {
const completion = await createChatCompletion(
openai_url,
apiKey,
{
model,
Expand Down

0 comments on commit b6ded16

Please sign in to comment.