|
- import fetchPonyfill from 'fetch-ponyfill';
- import { EventEmitter } from 'events';
- import { PassThrough } from 'stream';
- import { PlatformEventEmitter } from './events';
- import { createTextCompletion, TextCompletion } from './features/text-completion';
- import { createImage } from './features/image';
- import { createChatCompletion, ChatCompletion } from './features/chat-completion';
- import { createEdit } from './features/edit';
-
- export * from './message';
- export * from './models';
- export { PlatformEventEmitter, ChatCompletion, TextCompletion };
- export {
- ChatCompletionChunkDataEvent,
- DataEventObjectType as ChatCompletionDataEventObjectType,
- } from './features/chat-completion';
- export {
- TextCompletionChunkDataEvent,
- DataEventObjectType as TextCompletionDataEventObjectType,
- } from './features/text-completion';
- export {
- CreateEditDataEvent,
- DataEventObjectType as EditDataEventObjectType,
- } from './features/edit';
- export { CreateImageDataEvent, CreateImageSize } from './features/image';
- export * from './common';
-
- export enum ApiVersion {
- V1 = 'v1',
- }
-
- export const PLATFORM_ID = 'openai' as const;
-
- export interface PlatformConfig {
- platform: typeof PLATFORM_ID;
- platformConfiguration: Configuration;
- }
-
- export interface Configuration {
- organizationId?: string;
- apiVersion: ApiVersion;
- apiKey: string;
- baseUrl?: string;
- }
-
- export class PlatformEventEmitterImpl extends EventEmitter implements PlatformEventEmitter {
- readonly createCompletion: PlatformEventEmitter['createCompletion'];
-
- readonly createImage: PlatformEventEmitter['createImage'];
-
- readonly createChatCompletion: PlatformEventEmitter['createChatCompletion'];
-
- readonly createEdit: PlatformEventEmitter['createEdit'];
-
- constructor(configParams: Configuration) {
- super();
- const headers: Record<string, string> = {
- Authorization: `Bearer ${configParams.apiKey}`,
- };
-
- if (configParams.organizationId) {
- headers['OpenAI-Organization'] = configParams.organizationId;
- }
-
- const { fetch: fetchInstance } = fetchPonyfill();
- const doFetch = (method: string, path: string, body: Record<string, unknown>) => {
- const theFetchParams = {
- method,
- headers: {
- ...headers,
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify(body),
- };
-
- const url = new URL(
- `/${configParams.apiVersion}${path}`,
- configParams.baseUrl ?? 'https://api.openai.com',
- ).toString();
-
- this.emit('start', {
- ...theFetchParams,
- url,
- });
-
- return fetchInstance(url, theFetchParams);
- };
-
- const consumeStream = async (response: Response) => {
- // eslint-disable-next-line no-restricted-syntax
- for await (const chunk of response.body as unknown as PassThrough) {
- const chunkStringMaybeMultiple = chunk.toString();
- const chunkStrings = chunkStringMaybeMultiple
- .split('\n')
- .filter((chunkString: string) => chunkString.length > 0);
- chunkStrings.forEach((chunkString: string) => {
- const dataRaw = chunkString.split('data: ').at(1);
- if (!dataRaw) {
- return;
- }
- if (dataRaw === '[DONE]') {
- return;
- }
- const data = JSON.parse(dataRaw);
- this.emit('data', data);
- });
- }
- };
- this.createImage = createImage.bind(this, doFetch);
- this.createCompletion = createTextCompletion.bind(this, doFetch, consumeStream);
- this.createChatCompletion = createChatCompletion.bind(this, doFetch, consumeStream);
- this.createEdit = createEdit.bind(this, doFetch);
- }
- }
|