ai-utils.js
Version:
Build AI applications, chatbots, and agents with JavaScript and TypeScript.
125 lines (124 loc) • 4.72 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.OpenAIImageGenerationResponseFormat = exports.OpenAIImageGenerationModel = exports.calculateOpenAIImageGenerationCostInMillicents = void 0;
const zod_1 = require("zod");
const AbstractModel_js_1 = require("../../model-function/AbstractModel.cjs");
const callWithRetryAndThrottle_js_1 = require("../../util/api/callWithRetryAndThrottle.cjs");
const postToApi_js_1 = require("../../util/api/postToApi.cjs");
const OpenAIError_js_1 = require("./OpenAIError.cjs");
/**
* @see https://openai.com/pricing
*/
const sizeToCostInMillicents = {
"1024x1024": 2000,
"512x512": 1800,
"256x256": 1600,
};
const calculateOpenAIImageGenerationCostInMillicents = ({ settings, }) => (settings.n ?? 1) * sizeToCostInMillicents[settings.size ?? "1024x1024"];
exports.calculateOpenAIImageGenerationCostInMillicents = calculateOpenAIImageGenerationCostInMillicents;
/**
* Create an image generation model that calls the OpenAI AI image creation API.
*
* @see https://platform.openai.com/docs/api-reference/images/create
*
* @example
* const { image } = await generateImage(
* new OpenAIImageGenerationModel({ size: "512x512" }),
* "the wicked witch of the west in the style of early 19th century painting"
* );
*/
class OpenAIImageGenerationModel extends AbstractModel_js_1.AbstractModel {
constructor(settings) {
super({ settings });
Object.defineProperty(this, "provider", {
enumerable: true,
configurable: true,
writable: true,
value: "openai"
});
Object.defineProperty(this, "modelName", {
enumerable: true,
configurable: true,
writable: true,
value: null
});
}
get apiKey() {
const apiKey = this.settings.apiKey ?? process.env.OPENAI_API_KEY;
if (apiKey == null) {
throw new Error(`OpenAI API key is missing. Pass it as an argument to the constructor or set it as an environment variable named OPENAI_API_KEY.`);
}
return apiKey;
}
async callAPI(prompt, options) {
const run = options?.run;
const settings = options?.settings;
const responseFormat = options?.responseFormat;
const callSettings = Object.assign({
apiKey: this.apiKey,
user: this.settings.isUserIdForwardingEnabled ? run?.userId : undefined,
}, this.settings, settings, {
abortSignal: run?.abortSignal,
prompt,
responseFormat,
});
return (0, callWithRetryAndThrottle_js_1.callWithRetryAndThrottle)({
retry: callSettings.retry,
throttle: callSettings.throttle,
call: async () => callOpenAIImageGenerationAPI(callSettings),
});
}
generateImageResponse(prompt, options) {
return this.callAPI(prompt, {
responseFormat: exports.OpenAIImageGenerationResponseFormat.base64Json,
functionId: options?.functionId,
settings: options?.settings,
run: options?.run,
});
}
extractBase64Image(response) {
return response.data[0].b64_json;
}
withSettings(additionalSettings) {
return new OpenAIImageGenerationModel(Object.assign({}, this.settings, additionalSettings));
}
}
exports.OpenAIImageGenerationModel = OpenAIImageGenerationModel;
const openAIImageGenerationUrlSchema = zod_1.z.object({
created: zod_1.z.number(),
data: zod_1.z.array(zod_1.z.object({
url: zod_1.z.string(),
})),
});
const openAIImageGenerationBase64JsonSchema = zod_1.z.object({
created: zod_1.z.number(),
data: zod_1.z.array(zod_1.z.object({
b64_json: zod_1.z.string(),
})),
});
exports.OpenAIImageGenerationResponseFormat = {
url: {
type: "url",
handler: (0, postToApi_js_1.createJsonResponseHandler)(openAIImageGenerationUrlSchema),
},
base64Json: {
type: "b64_json",
handler: (0, postToApi_js_1.createJsonResponseHandler)(openAIImageGenerationBase64JsonSchema),
},
};
async function callOpenAIImageGenerationAPI({ baseUrl = "https://api.openai.com/v1", abortSignal, apiKey, prompt, n, size, responseFormat, user, }) {
return (0, postToApi_js_1.postJsonToApi)({
url: `${baseUrl}/images/generations`,
apiKey,
body: {
prompt,
n,
size,
response_format: responseFormat.type,
user,
},
failedResponseHandler: OpenAIError_js_1.failedOpenAICallResponseHandler,
successfulResponseHandler: responseFormat?.handler,
abortSignal,
});
}