gpt-simple-api-ts
Version:
A simple client GPT API written in TypeScript
302 lines (301 loc) • 15.6 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.maxTokensModels = void 0;
const openai_old_1 = require("openai-old");
const abort_controller_1 = require("abort-controller");
const openai_1 = require("openai");
exports.maxTokensModels = {
"gpt-3.5-turbo": 4096,
"gpt-4": 8192,
"gpt-3.5-turbo-16k": 16384
};
class SimpleGPT {
get chatModels() {
return ["gpt-3.5-turbo", "gpt-4"];
}
get defaultOptsGPT() {
return {
model: "gpt-3.5-turbo-0613",
temperature: 0,
max_tokens: 500,
top_p: 1,
frequency_penalty: 0.5,
presence_penalty: 0
};
}
constructor({ key }) {
this.abortController = new abort_controller_1.default();
this.getFirst = this.get;
this._key = "";
this._configuration = null;
this._openai = null;
this.__openai = null;
this.setApiKey(key);
}
transcribe(formData) {
return __awaiter(this, void 0, void 0, function* () {
const requestOptions = {
method: "POST",
headers: {
Authorization: `Bearer ${this._key}`,
},
body: formData,
};
const response = yield fetch("https://api.openai.com/v1/audio/transcriptions", requestOptions).then((response) => {
var _a;
if (response.ok) {
return (_a = response === null || response === void 0 ? void 0 : response.json) === null || _a === void 0 ? void 0 : _a.call(response);
}
else {
Promise.reject(response);
}
});
return response.text;
});
}
getStream(prompt, fData, fEnd, opts) {
return __awaiter(this, void 0, void 0, function* () {
return new Promise((resolve, reject) => {
const model = (opts === null || opts === void 0 ? void 0 : opts.model) || this.defaultOptsGPT.model || "";
const isChatModel = this.chatModels.find((chatModel) => model.includes(chatModel));
const _prompt = (prompt || (opts === null || opts === void 0 ? void 0 : opts.prompt));
const messages = (opts === null || opts === void 0 ? void 0 : opts.messages) || [{ role: "user", content: _prompt }];
const endpoint = isChatModel ? "/v1/chat/completions" : "/v1/completions";
const signal = this.abortController.signal;
const bodyRaw = {
model,
prompt: isChatModel ? undefined : _prompt,
messages: isChatModel ? messages : undefined,
temperature: (opts === null || opts === void 0 ? void 0 : opts.temperature) || this.defaultOptsGPT.temperature,
max_tokens: (opts === null || opts === void 0 ? void 0 : opts.max_tokens) || this.defaultOptsGPT.max_tokens || 0,
top_p: (opts === null || opts === void 0 ? void 0 : opts.top_p) || 1,
frequency_penalty: (opts === null || opts === void 0 ? void 0 : opts.frequency_penalty) || this.defaultOptsGPT.frequency_penalty,
presence_penalty: (opts === null || opts === void 0 ? void 0 : opts.presence_penalty) || this.defaultOptsGPT.presence_penalty,
stream: (opts === null || opts === void 0 ? void 0 : opts.stream) || true,
logit_bias: (opts === null || opts === void 0 ? void 0 : opts.logit_bias) || {},
function_call: (opts === null || opts === void 0 ? void 0 : opts.function_call) || undefined,
functions: (opts === null || opts === void 0 ? void 0 : opts.functions) || undefined,
};
const body = JSON.stringify(bodyRaw);
fetch("https://api.openai.com" + endpoint, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer " + this._key
},
body: body,
}).then((response) => __awaiter(this, void 0, void 0, function* () {
var _a, _b, _c, _d;
this.reader = (_a = response.body) === null || _a === void 0 ? void 0 : _a.pipeThrough(new TextDecoderStream()).getReader();
const choices = [];
const cancelled = false;
while (true) {
if (!this.reader)
break;
const { value, done } = yield this.reader.read();
if (done) {
break;
}
if (value.startsWith("{")) {
yield this.reader.cancel();
// As far as I can tell, if the response is an object, then it is an unrecoverable error.
throw new Error(value);
}
const chunks = value.split("\n").map((chunk) => chunk.trim()).filter(Boolean);
for (const chunk of chunks) {
if (done) {
break;
}
if (chunk === "") {
continue;
}
if (chunk === "data: [DONE]") {
yield this.reader.cancel();
break;
}
if (!chunk.startsWith("data: ")) {
throw new Error(`Unexpected message: ${chunk}`);
}
try {
const responseChunk = JSON.parse(chunk.toString().slice("data: ".length));
fData(((_d = (_c = (_b = responseChunk.choices) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.delta) === null || _d === void 0 ? void 0 : _d.content) || '', responseChunk, chunk);
}
catch (e) {
throw new Error(`Unexpected message: ${chunk}`);
}
}
}
resolve();
}));
});
});
}
abortStream() {
var _a;
(_a = this.reader) === null || _a === void 0 ? void 0 : _a.cancel();
}
// async get(prompt: string, opts?: Partial<CreateCompletionRequest & CreateChatCompletionRequest>): Promise<null | string[]> {
// if (!this._openai) return null;
// const model = opts?.model || this.defaultOptsGPT.model || ''
// const isChatModel = this.chatModels.find((chatModel) => model.includes(chatModel))
// const _prompt = (prompt || opts?.prompt)
// const messages = opts?.messages || [{role: "user", content: _prompt as string}]
// const response = await this._openai[isChatModel ? "createChatCompletion" : "createCompletion"]({
// model,
// prompt: isChatModel ? undefined : _prompt,
// messages: isChatModel ? messages : undefined,
// temperature: opts?.temperature ?? this.defaultOptsGPT.temperature,
// max_tokens: opts?.max_tokens ?? this.defaultOptsGPT.max_tokens ?? 0,
// top_p: opts?.top_p ?? 1,
// frequency_penalty: opts?.frequency_penalty ?? this.defaultOptsGPT.frequency_penalty,
// presence_penalty: opts?.presence_penalty ?? this.defaultOptsGPT.presence_penalty,
// } as any);
// return response.data.choices.map((choice: any) => choice.text || choice.message?.content).filter(Boolean) as string[];
// }
getFull(prompt, opts = {}) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
const chatCompletion = yield ((_a = this.__openai) === null || _a === void 0 ? void 0 : _a.chat.completions.create(Object.assign({ messages: opts.messages || [{ role: 'user', content: prompt }], model: opts.model || 'gpt-3.5-turbo' }, opts)));
return chatCompletion === null || chatCompletion === void 0 ? void 0 : chatCompletion.choices;
});
}
getAll(prompt, opts = {}) {
return __awaiter(this, void 0, void 0, function* () {
const res = yield this.getFull(prompt, opts);
return res === null || res === void 0 ? void 0 : res.map((re) => re === null || re === void 0 ? void 0 : re.message.content).filter(Boolean);
});
}
getCompletions(prompt, opts) {
var _a, _b, _c;
return __awaiter(this, void 0, void 0, function* () {
if (!this._openai)
return null;
const response = yield this._openai.createCompletion({
model: (opts === null || opts === void 0 ? void 0 : opts.model) || "curie:ft-user-1.0.0",
prompt: prompt || (opts === null || opts === void 0 ? void 0 : opts.prompt),
temperature: (_a = opts === null || opts === void 0 ? void 0 : opts.temperature) !== null && _a !== void 0 ? _a : 0,
max_tokens: (opts === null || opts === void 0 ? void 0 : opts.max_tokens) || 256,
top_p: (opts === null || opts === void 0 ? void 0 : opts.top_p) || 1,
frequency_penalty: (_b = opts === null || opts === void 0 ? void 0 : opts.frequency_penalty) !== null && _b !== void 0 ? _b : 0,
presence_penalty: (_c = opts === null || opts === void 0 ? void 0 : opts.presence_penalty) !== null && _c !== void 0 ? _c : 0,
});
return response.data.choices.map((choice) => choice.text).filter(Boolean);
});
}
getWithTools(prompt, opts, functions) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
const newOpts = opts ? Object.assign({}, opts) : {};
if (functions && !(newOpts === null || newOpts === void 0 ? void 0 : newOpts.tools)) {
if (!newOpts) {
opts = {};
}
newOpts.tools = Object.entries(functions).map((f) => {
return {
type: "function",
function: {
name: f[0],
parameters: {}
}
};
});
}
const res = (_a = (yield this.getFull(prompt, newOpts))) === null || _a === void 0 ? void 0 : _a[0].message;
const toolsResult = {};
if (functions && (res === null || res === void 0 ? void 0 : res.tool_calls)) {
const fs = Object.keys(functions);
for (const tool of fs) {
const f = res === null || res === void 0 ? void 0 : res.tool_calls.find((tool_call) => tool_call.function.name === tool);
if (f) {
const args = JSON.parse(f.function.arguments);
try {
const toolRes = yield functions[tool](args);
toolsResult[tool] = toolRes;
}
catch (e) {
console.error("Error occurred in getWithTools:", e);
}
}
}
}
return {
content: res === null || res === void 0 ? void 0 : res.content,
toolsResult
};
});
}
get(prompt, opts, functions) {
return __awaiter(this, void 0, void 0, function* () {
return (yield this.getWithTools(prompt, opts, functions)).content;
});
}
getCode(prompt, opts) {
var _a, _b, _c;
return __awaiter(this, void 0, void 0, function* () {
if (!this._openai)
return null;
const response = yield this._openai.createCompletion({
model: (opts === null || opts === void 0 ? void 0 : opts.model) || "code-davinci-002",
prompt: prompt || (opts === null || opts === void 0 ? void 0 : opts.prompt),
temperature: (_a = opts === null || opts === void 0 ? void 0 : opts.temperature) !== null && _a !== void 0 ? _a : 0,
max_tokens: (opts === null || opts === void 0 ? void 0 : opts.max_tokens) || 256,
top_p: (opts === null || opts === void 0 ? void 0 : opts.top_p) || 1,
frequency_penalty: (_b = opts === null || opts === void 0 ? void 0 : opts.frequency_penalty) !== null && _b !== void 0 ? _b : 0,
presence_penalty: (_c = opts === null || opts === void 0 ? void 0 : opts.presence_penalty) !== null && _c !== void 0 ? _c : 0,
});
return response.data.choices.map((choice) => choice.text).filter(Boolean);
});
}
getCodeFirst(prompt, opts) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
return (_a = (yield this.getCode(prompt, opts))) === null || _a === void 0 ? void 0 : _a[0];
});
}
getImages(prompt, n = 1, size = 512, model = 'dall-e-3') {
var _a, _b;
return __awaiter(this, void 0, void 0, function* () {
const response = yield ((_a = this._openai) === null || _a === void 0 ? void 0 : _a.createImage)({
prompt,
n,
model,
size: `${size}x${size}`,
});
return ((_b = response === null || response === void 0 ? void 0 : response.data) === null || _b === void 0 ? void 0 : _b.data.map((responseOne) => responseOne.url || '')) || [];
});
}
getImage(prompt, size = 512, model = 'dall-e-3') {
var _a;
return __awaiter(this, void 0, void 0, function* () {
return (_a = (yield this.getImages(prompt, 1, size, model))) === null || _a === void 0 ? void 0 : _a[0];
});
}
setApiKey(key) {
this._key = key;
this._configuration = new openai_old_1.Configuration({
apiKey: this._key,
});
this._openai = new openai_old_1.OpenAIApi(this._configuration);
this.__openai = new openai_1.default({
apiKey: this._key,
});
}
getModels() {
return __awaiter(this, void 0, void 0, function* () {
if (!this._openai)
return null;
const response = yield this._openai.listModels();
return response.data.data.map((datum) => datum.id) || null;
});
}
}
exports.default = SimpleGPT;