UNPKG

@ai-ml.api/aimlapi-vercel-ai

Version:

AI SDK provider for AI/ML API: 300+ models via OpenAI-compatible API.

181 lines (178 loc) 5.87 kB
// src/aimlapi-provider.ts import { OpenAICompatibleChatLanguageModel, OpenAICompatibleCompletionLanguageModel, OpenAICompatibleEmbeddingModel } from "@ai-sdk/openai-compatible"; import "@ai-sdk/provider"; import { loadApiKey, withoutTrailingSlash } from "@ai-sdk/provider-utils"; // src/aimlapi-error.ts import { z } from "zod"; var aimlapiErrorSchema = z.object({ error: z.object({ message: z.string(), code: z.string().optional(), type: z.string().optional() }) }); // src/aimlapi-image-model.ts import { combineHeaders, createJsonErrorResponseHandler, createJsonResponseHandler, postJsonToApi, resolve } from "@ai-sdk/provider-utils"; import { z as z2 } from "zod"; var AimlapiImageModel = class { constructor(modelId, settings = {}, config) { this.modelId = modelId; this.settings = settings; this.config = config; } specificationVersion = "v2"; maxImagesPerCall = 1; get provider() { return this.config.provider; } async doGenerate({ prompt, n, aspectRatio, size, seed, providerOptions, headers, abortSignal }) { const warnings = []; const modelSupportsAspectRatio = true; if (!modelSupportsAspectRatio && aspectRatio != null) { warnings.push({ type: "unsupported-setting", setting: "aspectRatio", details: "This model does not support `aspectRatio`. Use `size` instead." }); } if (size != null && aspectRatio != null) { warnings.push({ type: "other", message: "Both `size` and `aspectRatio` were provided. The API will prioritize `size`." }); } const currentDate = this.config._internal?.currentDate?.() ?? /* @__PURE__ */ new Date(); const splitSize = size?.split("x"); const resolvedProviderHeaders = await resolve(this.config.headers); const { value: response, responseHeaders } = await postJsonToApi({ url: `${this.config.baseURL}/images/generations`, headers: combineHeaders(resolvedProviderHeaders, headers), body: { model: this.modelId, prompt, seed, n, ...splitSize && { width: parseInt(splitSize[0], 10), height: parseInt(splitSize[1], 10) }, ...aspectRatio && { aspect_ratio: aspectRatio }, // Don't force base64: some models will return the url anyway ...providerOptions?.aimlapi ?? {} }, successfulResponseHandler: createJsonResponseHandler(aimlapiImageResponseSchema), failedResponseHandler: createJsonErrorResponseHandler({ errorSchema: aimlapiErrorSchema, errorToMessage: (e) => e.error.message, isRetryable: (res, e) => { if (res.status === 429) return true; if (res.status >= 500) return true; if (e?.error?.code === "overloaded" || e?.error?.code === "timeout") return true; return false; } }), abortSignal, fetch: this.config.fetch }); return { images: response.normalized, warnings, response: { timestamp: currentDate, modelId: this.modelId, headers: responseHeaders } }; } }; var aimlapiImageResponseSchema = z2.union([ // Option A: OpenAI-compatible base64 z2.object({ data: z2.array(z2.object({ b64_json: z2.string() })) }).transform((v) => ({ normalized: v.data.map((d) => d.b64_json) })), // Option B: AIMLAPI format with images (url or b64_json) z2.object({ images: z2.array( z2.object({ b64_json: z2.string().optional(), url: z2.string().url().optional() }) ) }).transform((v) => ({ normalized: v.images.map((i) => i.b64_json ?? i.url ?? "").filter((x) => x.length > 0) })) ]); // src/aimlapi-provider.ts import "zod"; var defaultBaseURL = "https://api.aimlapi.com/v1"; var aimlapiErrorStructure = { errorSchema: aimlapiErrorSchema, errorToMessage: (data) => data.error.message // isRetryable: (res) => res.status === 429 || res.status >= 500, }; function createAIMLAPI(options = {}) { const rawBaseURL = options.baseURL ?? defaultBaseURL; const strictBaseURL = withoutTrailingSlash(rawBaseURL) ?? defaultBaseURL; const getHeadersLoose = () => ({ Authorization: `Bearer ${loadApiKey({ apiKey: options.apiKey, environmentVariableName: "AIMLAPI_API_KEY", description: "AIMLAPI API key" })}`, "X-Title": "vercel", ...typeof options.headers === "function" ? options.headers() : options.headers }); const getHeadersStrict = () => Object.fromEntries( Object.entries(getHeadersLoose()).filter( ([, v]) => v !== void 0 ) ); const getCommonModelConfig = (modelType) => ({ provider: `aimlapi.${modelType}`, url: ({ path }) => `${strictBaseURL}${path}`, headers: getHeadersStrict, fetch: options.fetch, errorStructure: aimlapiErrorStructure }); const createChat = (modelId) => new OpenAICompatibleChatLanguageModel(modelId, getCommonModelConfig("chat")); const createCompletion = (modelId) => new OpenAICompatibleCompletionLanguageModel( modelId, getCommonModelConfig("completion") ); const createEmbedding = (modelId) => new OpenAICompatibleEmbeddingModel( modelId, getCommonModelConfig("embedding") ); const createImage = (modelId, settings = {}) => new AimlapiImageModel(modelId, settings, { provider: "aimlapi.image", baseURL: strictBaseURL, headers: getHeadersStrict, fetch: options.fetch }); const providerFunc = (modelId) => createChat(modelId); providerFunc.chat = createChat; providerFunc.completion = createCompletion; providerFunc.languageModel = createChat; providerFunc.textEmbeddingModel = createEmbedding; providerFunc.imageModel = createImage; return providerFunc; } var aimlapi = createAIMLAPI(); export { aimlapi, createAIMLAPI }; //# sourceMappingURL=index.mjs.map