fix: content-length miscalculation bug (#147)

This commit is contained in:
hiroki osame
2023-03-10 08:25:38 -05:00
committed by GitHub
parent 4a91fbdd30
commit fed577b960

View File

@@ -1,46 +1,42 @@
import https from 'https'; import https from 'https';
import type { ClientRequest, IncomingMessage } from 'http';
import type { CreateCompletionRequest, CreateCompletionResponse } from 'openai'; import type { CreateCompletionRequest, CreateCompletionResponse } from 'openai';
import { encoding_for_model as encodingForModel } from '@dqbd/tiktoken'; import { encoding_for_model as encodingForModel } from '@dqbd/tiktoken';
import { KnownError } from './error.js'; import { KnownError } from './error.js';
const createCompletion = ( const httpsPost = async (
apiKey: string, hostname: string,
json: CreateCompletionRequest, path: string,
) => new Promise<CreateCompletionResponse>((resolve, reject) => { headers: Record<string, string>,
json: unknown,
) => new Promise<{
request: ClientRequest;
response: IncomingMessage;
data: string;
}>((resolve, reject) => {
const postContent = JSON.stringify(json); const postContent = JSON.stringify(json);
const request = https.request( const request = https.request(
{ {
port: 443, port: 443,
hostname: 'api.openai.com', hostname,
path: '/v1/completions', path,
method: 'POST', method: 'POST',
headers: { headers: {
...headers,
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'Content-Length': postContent.length, 'Content-Length': Buffer.byteLength(postContent),
Authorization: `Bearer ${apiKey}`,
}, },
timeout: 10_000, // 10s timeout: 10_000, // 10s
}, },
(response) => { (response) => {
if (
!response.statusCode
|| response.statusCode < 200
|| response.statusCode > 299
) {
let errorMessage = `OpenAI API Error: ${response.statusCode} - ${response.statusMessage}`;
if (response.statusCode === 500) {
errorMessage += '; Check the API status: https://status.openai.com';
}
return reject(new KnownError(errorMessage));
}
const body: Buffer[] = []; const body: Buffer[] = [];
response.on('data', chunk => body.push(chunk)); response.on('data', chunk => body.push(chunk));
response.on('end', () => { response.on('end', () => {
resolve( resolve({
JSON.parse(Buffer.concat(body).toString()), request,
); response,
data: Buffer.concat(body).toString(),
});
}); });
}, },
); );
@@ -54,6 +50,40 @@ const createCompletion = (
request.end(); request.end();
}); });
const createCompletion = async (
apiKey: string,
json: CreateCompletionRequest,
) => {
const { response, data } = await httpsPost(
'api.openai.com',
'/v1/completions',
{
Authorization: `Bearer ${apiKey}`,
},
json,
);
if (
!response.statusCode
|| response.statusCode < 200
|| response.statusCode > 299
) {
let errorMessage = `OpenAI API Error: ${response.statusCode} - ${response.statusMessage}`;
if (data) {
errorMessage += `\n\n${data}`;
}
if (response.statusCode === 500) {
errorMessage += '\n\nCheck the API status: https://status.openai.com';
}
throw new KnownError(errorMessage);
}
return JSON.parse(data) as CreateCompletionResponse;
};
const sanitizeMessage = (message: string) => message.trim().replace(/[\n\r]/g, '').replace(/(\w)\.$/, '$1'); const sanitizeMessage = (message: string) => message.trim().replace(/[\n\r]/g, '').replace(/(\w)\.$/, '$1');
const deduplicateMessages = (array: string[]) => Array.from(new Set(array)); const deduplicateMessages = (array: string[]) => Array.from(new Set(array));