UNPKG

@ai-sdk/fireworks

Version:

The **[Fireworks provider](https://ai-sdk.dev/providers/ai-sdk-providers/fireworks)** for the [AI SDK](https://ai-sdk.dev/docs) contains language model and image model support for the [Fireworks](https://fireworks.ai) platform.

471 lines (465 loc) 14.6 kB
// src/fireworks-image-model.ts import { combineHeaders, convertImageModelFileToDataUri, createBinaryResponseHandler, createJsonResponseHandler, createStatusCodeErrorResponseHandler, delay, getFromApi, isSameOrigin, parseProviderOptions, postJsonToApi, serializeModelOptions, WORKFLOW_SERIALIZE, WORKFLOW_DESERIALIZE } from "@ai-sdk/provider-utils"; // src/fireworks-image-api.ts import { lazySchema, zodSchema } from "@ai-sdk/provider-utils"; import { z } from "zod/v4"; var asyncSubmitResponseSchema = lazySchema( () => zodSchema( z.object({ request_id: z.string() }) ) ); var asyncPollResponseSchema = lazySchema( () => zodSchema( z.object({ id: z.string(), status: z.string(), result: z.object({ sample: z.string().optional() }).nullable() }) ) ); // src/fireworks-image-model-options.ts import { lazySchema as lazySchema2, zodSchema as zodSchema2 } from "@ai-sdk/provider-utils"; import { z as z2 } from "zod/v4"; var fireworksImageModelOptionsSchema = lazySchema2( () => zodSchema2( z2.looseObject({ /** * Classifier-free guidance scale for the image diffusion process. */ guidance_scale: z2.number().optional(), /** * Number of denoising steps for the image generation process. */ num_inference_steps: z2.number().int().optional(), /** * Desired output image format. */ output_format: z2.enum(["jpeg", "png"]).optional(), /** * URL to receive webhook notifications for async Kontext requests. */ webhook_url: z2.string().optional(), /** * Secret for webhook signature verification. */ webhook_secret: z2.string().optional(), /** * Whether Fireworks should automatically modify the prompt for more creative generation. */ prompt_upsampling: z2.boolean().optional(), /** * Moderation tolerance level for inputs and outputs. */ safety_tolerance: z2.number().int().min(0).max(6).optional(), /** * Guidance scale for legacy image_generation models. */ cfg_scale: z2.number().optional(), /** * Number of generation steps for legacy image_generation models. */ steps: z2.number().int().optional() }) ) ); // src/fireworks-image-model.ts var DEFAULT_POLL_INTERVAL_MILLIS = 500; var DEFAULT_POLL_TIMEOUT_MILLIS = 12e4; var modelToBackendConfig = { "accounts/fireworks/models/flux-1-dev-fp8": { urlFormat: "workflows" }, "accounts/fireworks/models/flux-1-schnell-fp8": { urlFormat: "workflows" }, "accounts/fireworks/models/flux-kontext-pro": { urlFormat: "workflows_async", supportsEditing: true }, "accounts/fireworks/models/flux-kontext-max": { urlFormat: "workflows_async", supportsEditing: true }, "accounts/fireworks/models/playground-v2-5-1024px-aesthetic": { urlFormat: "image_generation", supportsSize: true }, "accounts/fireworks/models/japanese-stable-diffusion-xl": { urlFormat: "image_generation", supportsSize: true }, "accounts/fireworks/models/playground-v2-1024px-aesthetic": { urlFormat: "image_generation", supportsSize: true }, "accounts/fireworks/models/stable-diffusion-xl-1024-v1-0": { urlFormat: "image_generation", supportsSize: true }, "accounts/fireworks/models/SSD-1B": { urlFormat: "image_generation", supportsSize: true } }; function getUrlForModel(baseUrl, modelId) { const config = modelToBackendConfig[modelId]; switch (config == null ? void 0 : config.urlFormat) { case "image_generation": return `${baseUrl}/image_generation/${modelId}`; case "workflows_async": return `${baseUrl}/workflows/${modelId}`; case "workflows": default: return `${baseUrl}/workflows/${modelId}/text_to_image`; } } function getPollUrlForModel(baseUrl, modelId) { return `${baseUrl}/workflows/${modelId}/get_result`; } var FireworksImageModel = class _FireworksImageModel { constructor(modelId, config) { this.modelId = modelId; this.config = config; this.specificationVersion = "v4"; this.maxImagesPerCall = 1; } get provider() { return this.config.provider; } static [WORKFLOW_SERIALIZE](model) { return serializeModelOptions({ modelId: model.modelId, config: model.config }); } static [WORKFLOW_DESERIALIZE](options) { return new _FireworksImageModel(options.modelId, options.config); } async doGenerate({ prompt, n, size, aspectRatio, seed, providerOptions, headers, abortSignal, files, mask }) { var _a, _b, _c, _d, _e, _f; const warnings = []; const backendConfig = modelToBackendConfig[this.modelId]; if (!(backendConfig == null ? void 0 : backendConfig.supportsSize) && size != null) { warnings.push({ type: "unsupported", feature: "size", details: "This model does not support the `size` option. Use `aspectRatio` instead." }); } if ((backendConfig == null ? void 0 : backendConfig.supportsSize) && aspectRatio != null) { warnings.push({ type: "unsupported", feature: "aspectRatio", details: "This model does not support the `aspectRatio` option." }); } const hasInputImage = files != null && files.length > 0; let inputImage; if (hasInputImage) { inputImage = convertImageModelFileToDataUri(files[0]); if (files.length > 1) { warnings.push({ type: "other", message: "Fireworks only supports a single input image. Additional images are ignored." }); } } if (mask != null) { warnings.push({ type: "unsupported", feature: "mask", details: "Fireworks Kontext models do not support explicit masks. Use the prompt to describe the areas to edit." }); } const splitSize = size == null ? void 0 : size.split("x"); const currentDate = (_c = (_b = (_a = this.config._internal) == null ? void 0 : _a.currentDate) == null ? void 0 : _b.call(_a)) != null ? _c : /* @__PURE__ */ new Date(); const combinedHeaders = combineHeaders((_e = (_d = this.config).headers) == null ? void 0 : _e.call(_d), headers); const fireworksOptions = (_f = await parseProviderOptions({ provider: "fireworks", providerOptions, schema: fireworksImageModelOptionsSchema })) != null ? _f : {}; const body = { prompt, aspect_ratio: aspectRatio, seed, samples: n, ...inputImage && { input_image: inputImage }, ...splitSize && { width: splitSize[0], height: splitSize[1] }, ...fireworksOptions }; if ((backendConfig == null ? void 0 : backendConfig.urlFormat) === "workflows_async") { return this.doGenerateAsync({ body, headers: combinedHeaders, abortSignal, warnings, currentDate }); } const { value: response, responseHeaders } = await postJsonToApi({ url: getUrlForModel(this.config.baseURL, this.modelId), headers: combinedHeaders, body, failedResponseHandler: createStatusCodeErrorResponseHandler(), successfulResponseHandler: createBinaryResponseHandler(), abortSignal, fetch: this.config.fetch }); return { images: [response], warnings, response: { timestamp: currentDate, modelId: this.modelId, headers: responseHeaders } }; } /** * Handles async image generation for models like flux-kontext-* that return * a request_id and require polling for results. */ async doGenerateAsync({ body, headers, abortSignal, warnings, currentDate }) { const { value: submitResponse } = await postJsonToApi({ url: getUrlForModel(this.config.baseURL, this.modelId), headers, body, failedResponseHandler: createStatusCodeErrorResponseHandler(), successfulResponseHandler: createJsonResponseHandler( asyncSubmitResponseSchema ), abortSignal, fetch: this.config.fetch }); const requestId = submitResponse.request_id; const imageUrl = await this.pollForImageUrl({ requestId, headers, abortSignal }); const { value: imageBytes, responseHeaders } = await getFromApi({ url: imageUrl, headers: isSameOrigin(imageUrl, this.config.baseURL) ? headers : void 0, abortSignal, failedResponseHandler: createStatusCodeErrorResponseHandler(), successfulResponseHandler: createBinaryResponseHandler(), fetch: this.config.fetch }); return { images: [imageBytes], warnings, response: { timestamp: currentDate, modelId: this.modelId, headers: responseHeaders } }; } /** * Polls the get_result endpoint until the image is ready. */ async pollForImageUrl({ requestId, headers, abortSignal }) { var _a, _b, _c; const pollIntervalMillis = (_a = this.config.pollIntervalMillis) != null ? _a : DEFAULT_POLL_INTERVAL_MILLIS; const pollTimeoutMillis = (_b = this.config.pollTimeoutMillis) != null ? _b : DEFAULT_POLL_TIMEOUT_MILLIS; const maxPollAttempts = Math.ceil( pollTimeoutMillis / Math.max(1, pollIntervalMillis) ); const pollUrl = getPollUrlForModel(this.config.baseURL, this.modelId); for (let i = 0; i < maxPollAttempts; i++) { const { value: pollResponse } = await postJsonToApi({ url: pollUrl, headers, body: { id: requestId }, failedResponseHandler: createStatusCodeErrorResponseHandler(), successfulResponseHandler: createJsonResponseHandler( asyncPollResponseSchema ), abortSignal, fetch: this.config.fetch }); const status = pollResponse.status; if (status === "Ready") { const imageUrl = (_c = pollResponse.result) == null ? void 0 : _c.sample; if (typeof imageUrl === "string") { return imageUrl; } throw new Error( "Fireworks poll response is Ready but missing result.sample" ); } if (status === "Error" || status === "Failed") { throw new Error( `Fireworks image generation failed with status: ${status}` ); } await delay(pollIntervalMillis); } throw new Error( `Fireworks image generation timed out after ${pollTimeoutMillis}ms` ); } }; // src/fireworks-provider.ts import { OpenAICompatibleChatLanguageModel, OpenAICompatibleCompletionLanguageModel, OpenAICompatibleEmbeddingModel } from "@ai-sdk/openai-compatible"; import { loadApiKey, withoutTrailingSlash, withUserAgentSuffix } from "@ai-sdk/provider-utils"; import { z as z3 } from "zod/v4"; // src/version.ts var VERSION = true ? "3.0.8" : "0.0.0-test"; // src/fireworks-provider.ts var fireworksErrorSchema = z3.object({ error: z3.string() }); var fireworksErrorStructure = { errorSchema: fireworksErrorSchema, errorToMessage: (data) => data.error }; var defaultBaseURL = "https://api.fireworks.ai/inference/v1"; function createFireworks(options = {}) { var _a; const baseURL = withoutTrailingSlash((_a = options.baseURL) != null ? _a : defaultBaseURL); const getHeaders = () => withUserAgentSuffix( { Authorization: `Bearer ${loadApiKey({ apiKey: options.apiKey, environmentVariableName: "FIREWORKS_API_KEY", description: "Fireworks API key" })}`, ...options.headers }, `ai-sdk/fireworks/${VERSION}` ); const getCommonModelConfig = (modelType) => ({ provider: `fireworks.${modelType}`, url: ({ path }) => `${baseURL}${path}`, headers: getHeaders, fetch: options.fetch }); const createChatModel = (modelId) => { return new OpenAICompatibleChatLanguageModel(modelId, { ...getCommonModelConfig("chat"), includeUsage: true, errorStructure: fireworksErrorStructure, transformRequestBody: (args) => { const thinking = args.thinking; const reasoningHistory = args.reasoningHistory; const promptCacheKey = args.promptCacheKey; const serviceTier = args.serviceTier; const { thinking: _, reasoningHistory: __, promptCacheKey: ___, serviceTier: ____, reasoning_effort, ...rest } = args; return { ...rest, ...reasoning_effort != null && { // Workaround since OpenAI spec allows for 5 reasoning levels, but Fireworks only supports 3 of them. reasoning_effort: reasoning_effort === "minimal" ? "low" : reasoning_effort === "xhigh" ? "high" : reasoning_effort }, ...promptCacheKey !== void 0 && { prompt_cache_key: promptCacheKey }, ...serviceTier !== void 0 && { service_tier: serviceTier }, ...thinking && { thinking: { type: thinking.type, ...thinking.budgetTokens !== void 0 && { budget_tokens: thinking.budgetTokens } } }, ...reasoningHistory && { reasoning_history: reasoningHistory } }; } }); }; const createCompletionModel = (modelId) => new OpenAICompatibleCompletionLanguageModel(modelId, { ...getCommonModelConfig("completion"), includeUsage: true, errorStructure: fireworksErrorStructure }); const createEmbeddingModel = (modelId) => new OpenAICompatibleEmbeddingModel(modelId, { ...getCommonModelConfig("embedding"), errorStructure: fireworksErrorStructure }); const createImageModel = (modelId) => new FireworksImageModel(modelId, { ...getCommonModelConfig("image"), baseURL: baseURL != null ? baseURL : defaultBaseURL }); const provider = (modelId) => createChatModel(modelId); provider.specificationVersion = "v4"; provider.completionModel = createCompletionModel; provider.chatModel = createChatModel; provider.languageModel = createChatModel; provider.embeddingModel = createEmbeddingModel; provider.textEmbeddingModel = createEmbeddingModel; provider.image = createImageModel; provider.imageModel = createImageModel; return provider; } var fireworks = createFireworks(); export { FireworksImageModel, VERSION, createFireworks, fireworks }; //# sourceMappingURL=index.js.map