@huggingface/inference 4.0.6 → 4.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/dist/commonjs/index.d.ts +2 -0
  2. package/dist/commonjs/index.d.ts.map +1 -1
  3. package/dist/commonjs/index.js +2 -0
  4. package/dist/commonjs/lib/getProviderHelper.d.ts.map +1 -1
  5. package/dist/commonjs/lib/getProviderHelper.js +2 -0
  6. package/dist/commonjs/package.d.ts +1 -1
  7. package/dist/commonjs/package.js +1 -1
  8. package/dist/commonjs/providers/fal-ai.d.ts +16 -2
  9. package/dist/commonjs/providers/fal-ai.d.ts.map +1 -1
  10. package/dist/commonjs/providers/fal-ai.js +93 -43
  11. package/dist/commonjs/providers/providerHelper.d.ts.map +1 -1
  12. package/dist/commonjs/providers/providerHelper.js +4 -1
  13. package/dist/commonjs/providers/replicate.d.ts +8 -2
  14. package/dist/commonjs/providers/replicate.d.ts.map +1 -1
  15. package/dist/commonjs/providers/replicate.js +46 -1
  16. package/dist/commonjs/snippets/templates.exported.d.ts.map +1 -1
  17. package/dist/commonjs/snippets/templates.exported.js +5 -2
  18. package/dist/commonjs/tasks/cv/imageToImage.d.ts.map +1 -1
  19. package/dist/commonjs/tasks/cv/imageToImage.js +3 -1
  20. package/dist/esm/index.d.ts +2 -0
  21. package/dist/esm/index.d.ts.map +1 -1
  22. package/dist/esm/index.js +2 -0
  23. package/dist/esm/lib/getProviderHelper.d.ts.map +1 -1
  24. package/dist/esm/lib/getProviderHelper.js +2 -0
  25. package/dist/esm/package.d.ts +1 -1
  26. package/dist/esm/package.js +1 -1
  27. package/dist/esm/providers/fal-ai.d.ts +16 -2
  28. package/dist/esm/providers/fal-ai.d.ts.map +1 -1
  29. package/dist/esm/providers/fal-ai.js +91 -42
  30. package/dist/esm/providers/providerHelper.d.ts.map +1 -1
  31. package/dist/esm/providers/providerHelper.js +4 -1
  32. package/dist/esm/providers/replicate.d.ts +8 -2
  33. package/dist/esm/providers/replicate.d.ts.map +1 -1
  34. package/dist/esm/providers/replicate.js +45 -1
  35. package/dist/esm/snippets/templates.exported.d.ts.map +1 -1
  36. package/dist/esm/snippets/templates.exported.js +5 -2
  37. package/dist/esm/tasks/cv/imageToImage.d.ts.map +1 -1
  38. package/dist/esm/tasks/cv/imageToImage.js +3 -1
  39. package/package.json +2 -2
  40. package/src/index.ts +2 -0
  41. package/src/lib/getProviderHelper.ts +2 -0
  42. package/src/package.ts +1 -1
  43. package/src/providers/fal-ai.ts +132 -57
  44. package/src/providers/providerHelper.ts +4 -1
  45. package/src/providers/replicate.ts +63 -2
  46. package/src/snippets/templates.exported.ts +5 -2
  47. package/src/tasks/cv/imageToImage.ts +3 -1
@@ -18,9 +18,10 @@ import { base64FromBytes } from "../utils/base64FromBytes.js";
18
18
 
19
19
  import type { AutomaticSpeechRecognitionOutput } from "@huggingface/tasks";
20
20
  import { isUrl } from "../lib/isUrl.js";
21
- import type { BodyParams, HeaderParams, ModelId, RequestArgs, UrlParams } from "../types.js";
21
+ import type { BodyParams, HeaderParams, InferenceTask, ModelId, RequestArgs, UrlParams } from "../types.js";
22
22
  import { delay } from "../utils/delay.js";
23
23
  import { omit } from "../utils/omit.js";
24
+ import type { ImageToImageTaskHelper } from "./providerHelper.js";
24
25
  import {
25
26
  type AutomaticSpeechRecognitionTaskHelper,
26
27
  TaskProviderHelper,
@@ -34,6 +35,7 @@ import {
34
35
  InferenceClientProviderApiError,
35
36
  InferenceClientProviderOutputError,
36
37
  } from "../errors.js";
38
+ import type { ImageToImageArgs } from "../tasks/index.js";
37
39
 
38
40
  export interface FalAiQueueOutput {
39
41
  request_id: string;
@@ -82,6 +84,75 @@ abstract class FalAITask extends TaskProviderHelper {
82
84
  }
83
85
  }
84
86
 
87
+ abstract class FalAiQueueTask extends FalAITask {
88
+ abstract task: InferenceTask;
89
+
90
+ async getResponseFromQueueApi(
91
+ response: FalAiQueueOutput,
92
+ url?: string,
93
+ headers?: Record<string, string>
94
+ ): Promise<unknown> {
95
+ if (!url || !headers) {
96
+ throw new InferenceClientInputError(`URL and headers are required for ${this.task} task`);
97
+ }
98
+ const requestId = response.request_id;
99
+ if (!requestId) {
100
+ throw new InferenceClientProviderOutputError(
101
+ `Received malformed response from Fal.ai ${this.task} API: no request ID found in the response`
102
+ );
103
+ }
104
+ let status = response.status;
105
+
106
+ const parsedUrl = new URL(url);
107
+ const baseUrl = `${parsedUrl.protocol}//${parsedUrl.host}${
108
+ parsedUrl.host === "router.huggingface.co" ? "/fal-ai" : ""
109
+ }`;
110
+
111
+ // extracting the provider model id for status and result urls
112
+ // from the response as it might be different from the mapped model in `url`
113
+ const modelId = new URL(response.response_url).pathname;
114
+ const queryParams = parsedUrl.search;
115
+
116
+ const statusUrl = `${baseUrl}${modelId}/status${queryParams}`;
117
+ const resultUrl = `${baseUrl}${modelId}${queryParams}`;
118
+
119
+ while (status !== "COMPLETED") {
120
+ await delay(500);
121
+ const statusResponse = await fetch(statusUrl, { headers });
122
+
123
+ if (!statusResponse.ok) {
124
+ throw new InferenceClientProviderApiError(
125
+ "Failed to fetch response status from fal-ai API",
126
+ { url: statusUrl, method: "GET" },
127
+ {
128
+ requestId: statusResponse.headers.get("x-request-id") ?? "",
129
+ status: statusResponse.status,
130
+ body: await statusResponse.text(),
131
+ }
132
+ );
133
+ }
134
+ try {
135
+ status = (await statusResponse.json()).status;
136
+ } catch (error) {
137
+ throw new InferenceClientProviderOutputError(
138
+ "Failed to parse status response from fal-ai API: received malformed response"
139
+ );
140
+ }
141
+ }
142
+
143
+ const resultResponse = await fetch(resultUrl, { headers });
144
+ let result: unknown;
145
+ try {
146
+ result = await resultResponse.json();
147
+ } catch (error) {
148
+ throw new InferenceClientProviderOutputError(
149
+ "Failed to parse result response from fal-ai API: received malformed response"
150
+ );
151
+ }
152
+ return result;
153
+ }
154
+ }
155
+
85
156
  function buildLoraPath(modelId: ModelId, adapterWeightsPath: string): string {
86
157
  return `${HF_HUB_URL}/${modelId}/resolve/main/${adapterWeightsPath}`;
87
158
  }
@@ -130,21 +201,29 @@ export class FalAITextToImageTask extends FalAITask implements TextToImageTaskHe
130
201
  }
131
202
  }
132
203
 
133
- export class FalAITextToVideoTask extends FalAITask implements TextToVideoTaskHelper {
204
+ export class FalAIImageToImageTask extends FalAiQueueTask implements ImageToImageTaskHelper {
205
+ task: InferenceTask;
134
206
  constructor() {
135
207
  super("https://queue.fal.run");
208
+ this.task = "image-to-image";
136
209
  }
210
+
137
211
  override makeRoute(params: UrlParams): string {
138
212
  if (params.authMethod !== "provider-key") {
139
213
  return `/${params.model}?_subdomain=queue`;
140
214
  }
141
215
  return `/${params.model}`;
142
216
  }
143
- override preparePayload(params: BodyParams): Record<string, unknown> {
217
+
218
+ async preparePayloadAsync(args: ImageToImageArgs): Promise<RequestArgs> {
219
+ const mimeType = args.inputs instanceof Blob ? args.inputs.type : "image/png";
144
220
  return {
145
- ...omit(params.args, ["inputs", "parameters"]),
146
- ...(params.args.parameters as Record<string, unknown>),
147
- prompt: params.args.inputs,
221
+ ...omit(args, ["inputs", "parameters"]),
222
+ image_url: `data:${mimeType};base64,${base64FromBytes(
223
+ new Uint8Array(args.inputs instanceof ArrayBuffer ? args.inputs : await (args.inputs as Blob).arrayBuffer())
224
+ )}`,
225
+ ...args.parameters,
226
+ ...args,
148
227
  };
149
228
  }
150
229
 
@@ -153,63 +232,59 @@ export class FalAITextToVideoTask extends FalAITask implements TextToVideoTaskHe
153
232
  url?: string,
154
233
  headers?: Record<string, string>
155
234
  ): Promise<Blob> {
156
- if (!url || !headers) {
157
- throw new InferenceClientInputError("URL and headers are required for text-to-video task");
158
- }
159
- const requestId = response.request_id;
160
- if (!requestId) {
235
+ const result = await this.getResponseFromQueueApi(response, url, headers);
236
+
237
+ if (
238
+ typeof result === "object" &&
239
+ !!result &&
240
+ "images" in result &&
241
+ Array.isArray(result.images) &&
242
+ result.images.length > 0 &&
243
+ typeof result.images[0] === "object" &&
244
+ !!result.images[0] &&
245
+ "url" in result.images[0] &&
246
+ typeof result.images[0].url === "string" &&
247
+ isUrl(result.images[0].url)
248
+ ) {
249
+ const urlResponse = await fetch(result.images[0].url);
250
+ return await urlResponse.blob();
251
+ } else {
161
252
  throw new InferenceClientProviderOutputError(
162
- "Received malformed response from Fal.ai text-to-video API: no request ID found in the response"
253
+ `Received malformed response from Fal.ai image-to-image API: expected { images: Array<{ url: string }> } result format, got instead: ${JSON.stringify(
254
+ result
255
+ )}`
163
256
  );
164
257
  }
165
- let status = response.status;
166
-
167
- const parsedUrl = new URL(url);
168
- const baseUrl = `${parsedUrl.protocol}//${parsedUrl.host}${
169
- parsedUrl.host === "router.huggingface.co" ? "/fal-ai" : ""
170
- }`;
171
-
172
- // extracting the provider model id for status and result urls
173
- // from the response as it might be different from the mapped model in `url`
174
- const modelId = new URL(response.response_url).pathname;
175
- const queryParams = parsedUrl.search;
176
-
177
- const statusUrl = `${baseUrl}${modelId}/status${queryParams}`;
178
- const resultUrl = `${baseUrl}${modelId}${queryParams}`;
179
-
180
- while (status !== "COMPLETED") {
181
- await delay(500);
182
- const statusResponse = await fetch(statusUrl, { headers });
258
+ }
259
+ }
183
260
 
184
- if (!statusResponse.ok) {
185
- throw new InferenceClientProviderApiError(
186
- "Failed to fetch response status from fal-ai API",
187
- { url: statusUrl, method: "GET" },
188
- {
189
- requestId: statusResponse.headers.get("x-request-id") ?? "",
190
- status: statusResponse.status,
191
- body: await statusResponse.text(),
192
- }
193
- );
194
- }
195
- try {
196
- status = (await statusResponse.json()).status;
197
- } catch (error) {
198
- throw new InferenceClientProviderOutputError(
199
- "Failed to parse status response from fal-ai API: received malformed response"
200
- );
201
- }
261
+ export class FalAITextToVideoTask extends FalAiQueueTask implements TextToVideoTaskHelper {
262
+ task: InferenceTask;
263
+ constructor() {
264
+ super("https://queue.fal.run");
265
+ this.task = "text-to-video";
266
+ }
267
+ override makeRoute(params: UrlParams): string {
268
+ if (params.authMethod !== "provider-key") {
269
+ return `/${params.model}?_subdomain=queue`;
202
270
  }
271
+ return `/${params.model}`;
272
+ }
273
+ override preparePayload(params: BodyParams): Record<string, unknown> {
274
+ return {
275
+ ...omit(params.args, ["inputs", "parameters"]),
276
+ ...(params.args.parameters as Record<string, unknown>),
277
+ prompt: params.args.inputs,
278
+ };
279
+ }
280
+
281
+ override async getResponse(
282
+ response: FalAiQueueOutput,
283
+ url?: string,
284
+ headers?: Record<string, string>
285
+ ): Promise<Blob> {
286
+ const result = await this.getResponseFromQueueApi(response, url, headers);
203
287
 
204
- const resultResponse = await fetch(resultUrl, { headers });
205
- let result: unknown;
206
- try {
207
- result = await resultResponse.json();
208
- } catch (error) {
209
- throw new InferenceClientProviderOutputError(
210
- "Failed to parse result response from fal-ai API: received malformed response"
211
- );
212
- }
213
288
  if (
214
289
  typeof result === "object" &&
215
290
  !!result &&
@@ -115,7 +115,10 @@ export abstract class TaskProviderHelper {
115
115
  * Prepare the headers for the request
116
116
  */
117
117
  prepareHeaders(params: HeaderParams, isBinary: boolean): Record<string, string> {
118
- const headers: Record<string, string> = { Authorization: `Bearer ${params.accessToken}` };
118
+ const headers: Record<string, string> = {};
119
+ if (params.authMethod !== "none") {
120
+ headers["Authorization"] = `Bearer ${params.accessToken}`;
121
+ }
119
122
  if (!isBinary) {
120
123
  headers["Content-Type"] = "application/json";
121
124
  }
@@ -16,9 +16,16 @@
16
16
  */
17
17
  import { InferenceClientProviderOutputError } from "../errors.js";
18
18
  import { isUrl } from "../lib/isUrl.js";
19
- import type { BodyParams, HeaderParams, UrlParams } from "../types.js";
19
+ import type { BodyParams, HeaderParams, RequestArgs, UrlParams } from "../types.js";
20
20
  import { omit } from "../utils/omit.js";
21
- import { TaskProviderHelper, type TextToImageTaskHelper, type TextToVideoTaskHelper } from "./providerHelper.js";
21
+ import {
22
+ TaskProviderHelper,
23
+ type ImageToImageTaskHelper,
24
+ type TextToImageTaskHelper,
25
+ type TextToVideoTaskHelper,
26
+ } from "./providerHelper.js";
27
+ import type { ImageToImageArgs } from "../tasks/cv/imageToImage.js";
28
+ import { base64FromBytes } from "../utils/base64FromBytes.js";
22
29
  export interface ReplicateOutput {
23
30
  output?: string | string[];
24
31
  }
@@ -152,3 +159,57 @@ export class ReplicateTextToVideoTask extends ReplicateTask implements TextToVid
152
159
  throw new InferenceClientProviderOutputError("Received malformed response from Replicate text-to-video API");
153
160
  }
154
161
  }
162
+
163
+ export class ReplicateImageToImageTask extends ReplicateTask implements ImageToImageTaskHelper {
164
+ override preparePayload(params: BodyParams<ImageToImageArgs>): Record<string, unknown> {
165
+ return {
166
+ input: {
167
+ ...omit(params.args, ["inputs", "parameters"]),
168
+ ...params.args.parameters,
169
+ input_image: params.args.inputs, // This will be processed in preparePayloadAsync
170
+ },
171
+ version: params.model.includes(":") ? params.model.split(":")[1] : undefined,
172
+ };
173
+ }
174
+
175
+ async preparePayloadAsync(args: ImageToImageArgs): Promise<RequestArgs> {
176
+ const { inputs, ...restArgs } = args;
177
+
178
+ // Convert Blob to base64 data URL
179
+ const bytes = new Uint8Array(await inputs.arrayBuffer());
180
+ const base64 = base64FromBytes(bytes);
181
+ const imageInput = `data:${inputs.type || "image/jpeg"};base64,${base64}`;
182
+
183
+ return {
184
+ ...restArgs,
185
+ inputs: imageInput,
186
+ };
187
+ }
188
+
189
+ override async getResponse(response: ReplicateOutput): Promise<Blob> {
190
+ if (
191
+ typeof response === "object" &&
192
+ !!response &&
193
+ "output" in response &&
194
+ Array.isArray(response.output) &&
195
+ response.output.length > 0 &&
196
+ typeof response.output[0] === "string"
197
+ ) {
198
+ const urlResponse = await fetch(response.output[0]);
199
+ return await urlResponse.blob();
200
+ }
201
+
202
+ if (
203
+ typeof response === "object" &&
204
+ !!response &&
205
+ "output" in response &&
206
+ typeof response.output === "string" &&
207
+ isUrl(response.output)
208
+ ) {
209
+ const urlResponse = await fetch(response.output);
210
+ return await urlResponse.blob();
211
+ }
212
+
213
+ throw new InferenceClientProviderOutputError("Received malformed response from Replicate image-to-image API");
214
+ }
215
+ }
@@ -5,6 +5,7 @@ export const templates: Record<string, Record<string, Record<string, string>>> =
5
5
  "basic": "async function query(data) {\n\tconst response = await fetch(\n\t\t\"{{ fullUrl }}\",\n\t\t{\n\t\t\theaders: {\n\t\t\t\tAuthorization: \"{{ authorizationHeader }}\",\n\t\t\t\t\"Content-Type\": \"application/json\",\n{% if billTo %}\n\t\t\t\t\"X-HF-Bill-To\": \"{{ billTo }}\",\n{% endif %}\t\t\t},\n\t\t\tmethod: \"POST\",\n\t\t\tbody: JSON.stringify(data),\n\t\t}\n\t);\n\tconst result = await response.json();\n\treturn result;\n}\n\nquery({ inputs: {{ providerInputs.asObj.inputs }} }).then((response) => {\n console.log(JSON.stringify(response));\n});",
6
6
  "basicAudio": "async function query(data) {\n\tconst response = await fetch(\n\t\t\"{{ fullUrl }}\",\n\t\t{\n\t\t\theaders: {\n\t\t\t\tAuthorization: \"{{ authorizationHeader }}\",\n\t\t\t\t\"Content-Type\": \"audio/flac\",\n{% if billTo %}\n\t\t\t\t\"X-HF-Bill-To\": \"{{ billTo }}\",\n{% endif %}\t\t\t},\n\t\t\tmethod: \"POST\",\n\t\t\tbody: JSON.stringify(data),\n\t\t}\n\t);\n\tconst result = await response.json();\n\treturn result;\n}\n\nquery({ inputs: {{ providerInputs.asObj.inputs }} }).then((response) => {\n console.log(JSON.stringify(response));\n});",
7
7
  "basicImage": "async function query(data) {\n\tconst response = await fetch(\n\t\t\"{{ fullUrl }}\",\n\t\t{\n\t\t\theaders: {\n\t\t\t\tAuthorization: \"{{ authorizationHeader }}\",\n\t\t\t\t\"Content-Type\": \"image/jpeg\",\n{% if billTo %}\n\t\t\t\t\"X-HF-Bill-To\": \"{{ billTo }}\",\n{% endif %}\t\t\t},\n\t\t\tmethod: \"POST\",\n\t\t\tbody: JSON.stringify(data),\n\t\t}\n\t);\n\tconst result = await response.json();\n\treturn result;\n}\n\nquery({ inputs: {{ providerInputs.asObj.inputs }} }).then((response) => {\n console.log(JSON.stringify(response));\n});",
8
+ "imageToImage": "const image = fs.readFileSync(\"{{inputs.asObj.inputs}}\");\n\nasync function query(data) {\n\tconst response = await fetch(\n\t\t\"{{ fullUrl }}\",\n\t\t{\n\t\t\theaders: {\n\t\t\t\tAuthorization: \"{{ authorizationHeader }}\",\n\t\t\t\t\"Content-Type\": \"image/jpeg\",\n{% if billTo %}\n\t\t\t\t\"X-HF-Bill-To\": \"{{ billTo }}\",\n{% endif %}\t\t\t},\n\t\t\tmethod: \"POST\",\n\t\t\tbody: {\n\t\t\t\t\"inputs\": `data:image/png;base64,${data.inputs.encode(\"base64\")}`,\n\t\t\t\t\"parameters\": data.parameters,\n\t\t\t}\n\t\t}\n\t);\n\tconst result = await response.json();\n\treturn result;\n}\n\nquery({ \n\tinputs: image,\n\tparameters: {\n\t\tprompt: \"{{ inputs.asObj.parameters.prompt }}\",\n\t}\n}).then((response) => {\n console.log(JSON.stringify(response));\n});",
8
9
  "textToAudio": "{% if model.library_name == \"transformers\" %}\nasync function query(data) {\n\tconst response = await fetch(\n\t\t\"{{ fullUrl }}\",\n\t\t{\n\t\t\theaders: {\n\t\t\t\tAuthorization: \"{{ authorizationHeader }}\",\n\t\t\t\t\"Content-Type\": \"application/json\",\n{% if billTo %}\n\t\t\t\t\"X-HF-Bill-To\": \"{{ billTo }}\",\n{% endif %}\t\t\t},\n\t\t\tmethod: \"POST\",\n\t\t\tbody: JSON.stringify(data),\n\t\t}\n\t);\n\tconst result = await response.blob();\n return result;\n}\n\nquery({ inputs: {{ providerInputs.asObj.inputs }} }).then((response) => {\n // Returns a byte object of the Audio wavform. Use it directly!\n});\n{% else %}\nasync function query(data) {\n\tconst response = await fetch(\n\t\t\"{{ fullUrl }}\",\n\t\t{\n\t\t\theaders: {\n\t\t\t\tAuthorization: \"{{ authorizationHeader }}\",\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t},\n\t\t\tmethod: \"POST\",\n\t\t\tbody: JSON.stringify(data),\n\t\t}\n\t);\n const result = await response.json();\n return result;\n}\n\nquery({ inputs: {{ providerInputs.asObj.inputs }} }).then((response) => {\n console.log(JSON.stringify(response));\n});\n{% endif %} ",
9
10
  "textToImage": "async function query(data) {\n\tconst response = await fetch(\n\t\t\"{{ fullUrl }}\",\n\t\t{\n\t\t\theaders: {\n\t\t\t\tAuthorization: \"{{ authorizationHeader }}\",\n\t\t\t\t\"Content-Type\": \"application/json\",\n{% if billTo %}\n\t\t\t\t\"X-HF-Bill-To\": \"{{ billTo }}\",\n{% endif %}\t\t\t},\n\t\t\tmethod: \"POST\",\n\t\t\tbody: JSON.stringify(data),\n\t\t}\n\t);\n\tconst result = await response.blob();\n\treturn result;\n}\n\n\nquery({ {{ providerInputs.asTsString }} }).then((response) => {\n // Use image\n});",
10
11
  "textToSpeech": "{% if model.library_name == \"transformers\" %}\nasync function query(data) {\n\tconst response = await fetch(\n\t\t\"{{ fullUrl }}\",\n\t\t{\n\t\t\theaders: {\n\t\t\t\tAuthorization: \"{{ authorizationHeader }}\",\n\t\t\t\t\"Content-Type\": \"application/json\",\n{% if billTo %}\n\t\t\t\t\"X-HF-Bill-To\": \"{{ billTo }}\",\n{% endif %}\t\t\t},\n\t\t\tmethod: \"POST\",\n\t\t\tbody: JSON.stringify(data),\n\t\t}\n\t);\n\tconst result = await response.blob();\n return result;\n}\n\nquery({ text: {{ inputs.asObj.inputs }} }).then((response) => {\n // Returns a byte object of the Audio wavform. Use it directly!\n});\n{% else %}\nasync function query(data) {\n\tconst response = await fetch(\n\t\t\"{{ fullUrl }}\",\n\t\t{\n\t\t\theaders: {\n\t\t\t\tAuthorization: \"{{ authorizationHeader }}\",\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t},\n\t\t\tmethod: \"POST\",\n\t\t\tbody: JSON.stringify(data),\n\t\t}\n\t);\n const result = await response.json();\n return result;\n}\n\nquery({ text: {{ inputs.asObj.inputs }} }).then((response) => {\n console.log(JSON.stringify(response));\n});\n{% endif %} ",
@@ -16,6 +17,7 @@ export const templates: Record<string, Record<string, Record<string, string>>> =
16
17
  "basicImage": "import { InferenceClient } from \"@huggingface/inference\";\n\nconst client = new InferenceClient(\"{{ accessToken }}\");\n\nconst data = fs.readFileSync({{inputs.asObj.inputs}});\n\nconst output = await client.{{ methodName }}({\n{% if endpointUrl %}\n endpointUrl: \"{{ endpointUrl }}\",\n{% endif %}\n\tdata,\n\tmodel: \"{{ model.id }}\",\n\tprovider: \"{{ provider }}\",\n}{% if billTo %}, {\n\tbillTo: \"{{ billTo }}\",\n}{% endif %});\n\nconsole.log(output);",
17
18
  "conversational": "import { InferenceClient } from \"@huggingface/inference\";\n\nconst client = new InferenceClient(\"{{ accessToken }}\");\n\nconst chatCompletion = await client.chatCompletion({\n{% if endpointUrl %}\n endpointUrl: \"{{ endpointUrl }}\",\n{% endif %}\n provider: \"{{ provider }}\",\n model: \"{{ model.id }}\",\n{{ inputs.asTsString }}\n}{% if billTo %}, {\n billTo: \"{{ billTo }}\",\n}{% endif %});\n\nconsole.log(chatCompletion.choices[0].message);",
18
19
  "conversationalStream": "import { InferenceClient } from \"@huggingface/inference\";\n\nconst client = new InferenceClient(\"{{ accessToken }}\");\n\nlet out = \"\";\n\nconst stream = client.chatCompletionStream({\n{% if endpointUrl %}\n endpointUrl: \"{{ endpointUrl }}\",\n{% endif %}\n provider: \"{{ provider }}\",\n model: \"{{ model.id }}\",\n{{ inputs.asTsString }}\n}{% if billTo %}, {\n billTo: \"{{ billTo }}\",\n}{% endif %});\n\nfor await (const chunk of stream) {\n\tif (chunk.choices && chunk.choices.length > 0) {\n\t\tconst newContent = chunk.choices[0].delta.content;\n\t\tout += newContent;\n\t\tconsole.log(newContent);\n\t}\n}",
20
+ "imageToImage": "import { InferenceClient } from \"@huggingface/inference\";\n\nconst client = new InferenceClient(\"{{ accessToken }}\");\n\nconst data = fs.readFileSync(\"{{inputs.asObj.inputs}}\");\n\nconst image = await client.imageToImage({\n{% if endpointUrl %}\n\tendpointUrl: \"{{ endpointUrl }}\",\n{% endif %}\n\tprovider: \"{{provider}}\",\n\tmodel: \"{{model.id}}\",\n\tinputs: data,\n\tparameters: { prompt: \"{{inputs.asObj.parameters.prompt}}\", },\n}{% if billTo %}, {\n\tbillTo: \"{{ billTo }}\",\n}{% endif %});\n/// Use the generated image (it's a Blob)\n// For example, you can save it to a file or display it in an image element\n",
19
21
  "textToImage": "import { InferenceClient } from \"@huggingface/inference\";\n\nconst client = new InferenceClient(\"{{ accessToken }}\");\n\nconst image = await client.textToImage({\n{% if endpointUrl %}\n endpointUrl: \"{{ endpointUrl }}\",\n{% endif %}\n provider: \"{{ provider }}\",\n model: \"{{ model.id }}\",\n\tinputs: {{ inputs.asObj.inputs }},\n\tparameters: { num_inference_steps: 5 },\n}{% if billTo %}, {\n billTo: \"{{ billTo }}\",\n}{% endif %});\n/// Use the generated image (it's a Blob)",
20
22
  "textToSpeech": "import { InferenceClient } from \"@huggingface/inference\";\n\nconst client = new InferenceClient(\"{{ accessToken }}\");\n\nconst audio = await client.textToSpeech({\n{% if endpointUrl %}\n endpointUrl: \"{{ endpointUrl }}\",\n{% endif %}\n provider: \"{{ provider }}\",\n model: \"{{ model.id }}\",\n\tinputs: {{ inputs.asObj.inputs }},\n}{% if billTo %}, {\n billTo: \"{{ billTo }}\",\n}{% endif %});\n// Use the generated audio (it's a Blob)",
21
23
  "textToVideo": "import { InferenceClient } from \"@huggingface/inference\";\n\nconst client = new InferenceClient(\"{{ accessToken }}\");\n\nconst video = await client.textToVideo({\n{% if endpointUrl %}\n endpointUrl: \"{{ endpointUrl }}\",\n{% endif %}\n provider: \"{{ provider }}\",\n model: \"{{ model.id }}\",\n\tinputs: {{ inputs.asObj.inputs }},\n}{% if billTo %}, {\n billTo: \"{{ billTo }}\",\n}{% endif %});\n// Use the generated video (it's a Blob)"
@@ -27,6 +29,7 @@ export const templates: Record<string, Record<string, Record<string, string>>> =
27
29
  },
28
30
  "python": {
29
31
  "fal_client": {
32
+ "imageToImage": "{%if provider == \"fal-ai\" %}\nimport fal_client\nimport base64\n\ndef on_queue_update(update):\n if isinstance(update, fal_client.InProgress):\n for log in update.logs:\n print(log[\"message\"])\n\nwith open(\"{{inputs.asObj.inputs}}\", \"rb\") as image_file:\n image_base_64 = base64.b64encode(image_file.read()).decode('utf-8')\n\nresult = fal_client.subscribe(\n \"fal-ai/flux-kontext/dev\",\n arguments={\n \"prompt\": f\"data:image/png;base64,{image_base_64}\",\n \"image_url\": \"{{ providerInputs.asObj.inputs }}\",\n },\n with_logs=True,\n on_queue_update=on_queue_update,\n)\nprint(result)\n{%endif%}\n",
30
33
  "textToImage": "{% if provider == \"fal-ai\" %}\nimport fal_client\n\n{% if providerInputs.asObj.loras is defined and providerInputs.asObj.loras != none %}\nresult = fal_client.subscribe(\n \"{{ providerModelId }}\",\n arguments={\n \"prompt\": {{ inputs.asObj.inputs }},\n \"loras\":{{ providerInputs.asObj.loras | tojson }},\n },\n)\n{% else %}\nresult = fal_client.subscribe(\n \"{{ providerModelId }}\",\n arguments={\n \"prompt\": {{ inputs.asObj.inputs }},\n },\n)\n{% endif %} \nprint(result)\n{% endif %} "
31
34
  },
32
35
  "huggingface_hub": {
@@ -36,7 +39,7 @@ export const templates: Record<string, Record<string, Record<string, string>>> =
36
39
  "conversational": "completion = client.chat.completions.create(\n model=\"{{ model.id }}\",\n{{ inputs.asPythonString }}\n)\n\nprint(completion.choices[0].message) ",
37
40
  "conversationalStream": "stream = client.chat.completions.create(\n model=\"{{ model.id }}\",\n{{ inputs.asPythonString }}\n stream=True,\n)\n\nfor chunk in stream:\n print(chunk.choices[0].delta.content, end=\"\") ",
38
41
  "documentQuestionAnswering": "output = client.document_question_answering(\n \"{{ inputs.asObj.image }}\",\n question=\"{{ inputs.asObj.question }}\",\n model=\"{{ model.id }}\",\n) ",
39
- "imageToImage": "# output is a PIL.Image object\nimage = client.image_to_image(\n \"{{ inputs.asObj.inputs }}\",\n prompt=\"{{ inputs.asObj.parameters.prompt }}\",\n model=\"{{ model.id }}\",\n) ",
42
+ "imageToImage": "with open(\"{{ inputs.asObj.inputs }}\", \"rb\") as image_file:\n input_image = image_file.read()\n\n# output is a PIL.Image object\nimage = client.image_to_image(\n input_image,\n prompt=\"{{ inputs.asObj.parameters.prompt }}\",\n model=\"{{ model.id }}\",\n) ",
40
43
  "importInferenceClient": "from huggingface_hub import InferenceClient\n\nclient = InferenceClient(\n{% if endpointUrl %}\n base_url=\"{{ baseUrl }}\",\n{% endif %}\n provider=\"{{ provider }}\",\n api_key=\"{{ accessToken }}\",\n{% if billTo %}\n bill_to=\"{{ billTo }}\",\n{% endif %}\n)",
41
44
  "questionAnswering": "answer = client.question_answering(\n question=\"{{ inputs.asObj.question }}\",\n context=\"{{ inputs.asObj.context }}\",\n model=\"{{ model.id }}\",\n) ",
42
45
  "tableQuestionAnswering": "answer = client.table_question_answering(\n query=\"{{ inputs.asObj.query }}\",\n table={{ inputs.asObj.table }},\n model=\"{{ model.id }}\",\n) ",
@@ -55,7 +58,7 @@ export const templates: Record<string, Record<string, Record<string, string>>> =
55
58
  "conversational": "def query(payload):\n response = requests.post(API_URL, headers=headers, json=payload)\n return response.json()\n\nresponse = query({\n{{ providerInputs.asJsonString }}\n})\n\nprint(response[\"choices\"][0][\"message\"])",
56
59
  "conversationalStream": "def query(payload):\n response = requests.post(API_URL, headers=headers, json=payload, stream=True)\n for line in response.iter_lines():\n if not line.startswith(b\"data:\"):\n continue\n if line.strip() == b\"data: [DONE]\":\n return\n yield json.loads(line.decode(\"utf-8\").lstrip(\"data:\").rstrip(\"/n\"))\n\nchunks = query({\n{{ providerInputs.asJsonString }},\n \"stream\": True,\n})\n\nfor chunk in chunks:\n print(chunk[\"choices\"][0][\"delta\"][\"content\"], end=\"\")",
57
60
  "documentQuestionAnswering": "def query(payload):\n with open(payload[\"image\"], \"rb\") as f:\n img = f.read()\n payload[\"image\"] = base64.b64encode(img).decode(\"utf-8\")\n response = requests.post(API_URL, headers=headers, json=payload)\n return response.json()\n\noutput = query({\n \"inputs\": {\n \"image\": \"{{ inputs.asObj.image }}\",\n \"question\": \"{{ inputs.asObj.question }}\",\n },\n}) ",
58
- "imageToImage": "def query(payload):\n with open(payload[\"inputs\"], \"rb\") as f:\n img = f.read()\n payload[\"inputs\"] = base64.b64encode(img).decode(\"utf-8\")\n response = requests.post(API_URL, headers=headers, json=payload)\n return response.content\n\nimage_bytes = query({\n{{ providerInputs.asJsonString }}\n})\n\n# You can access the image with PIL.Image for example\nimport io\nfrom PIL import Image\nimage = Image.open(io.BytesIO(image_bytes)) ",
61
+ "imageToImage": "with open(\"{{inputs.asObj.inputs}}\", \"rb\") as image_file:\n image_base_64 = base64.b64encode(image_file.read()).decode('utf-8')\n\ndef query(payload):\n with open(payload[\"inputs\"], \"rb\") as f:\n img = f.read()\n payload[\"inputs\"] = base64.b64encode(img).decode(\"utf-8\")\n response = requests.post(API_URL, headers=headers, json=payload)\n return response.content\n\nimage_bytes = query({\n{{ providerInputs.asJsonString }}\n})\n\n# You can access the image with PIL.Image for example\nimport io\nfrom PIL import Image\nimage = Image.open(io.BytesIO(image_bytes)) ",
59
62
  "importRequests": "{% if importBase64 %}\nimport base64\n{% endif %}\n{% if importJson %}\nimport json\n{% endif %}\nimport requests\n\nAPI_URL = \"{{ fullUrl }}\"\nheaders = {\n \"Authorization\": \"{{ authorizationHeader }}\",\n{% if billTo %}\n \"X-HF-Bill-To\": \"{{ billTo }}\"\n{% endif %}\n}",
60
63
  "tabular": "def query(payload):\n response = requests.post(API_URL, headers=headers, json=payload)\n return response.content\n\nresponse = query({\n \"inputs\": {\n \"data\": {{ providerInputs.asObj.inputs }}\n },\n}) ",
61
64
  "textToAudio": "{% if model.library_name == \"transformers\" %}\ndef query(payload):\n response = requests.post(API_URL, headers=headers, json=payload)\n return response.content\n\naudio_bytes = query({\n \"inputs\": {{ inputs.asObj.inputs }},\n})\n# You can access the audio with IPython.display for example\nfrom IPython.display import Audio\nAudio(audio_bytes)\n{% else %}\ndef query(payload):\n response = requests.post(API_URL, headers=headers, json=payload)\n return response.json()\n\naudio, sampling_rate = query({\n \"inputs\": {{ inputs.asObj.inputs }},\n})\n# You can access the audio with IPython.display for example\nfrom IPython.display import Audio\nAudio(audio, rate=sampling_rate)\n{% endif %} ",
@@ -3,6 +3,7 @@ import { resolveProvider } from "../../lib/getInferenceProviderMapping.js";
3
3
  import { getProviderHelper } from "../../lib/getProviderHelper.js";
4
4
  import type { BaseArgs, Options } from "../../types.js";
5
5
  import { innerRequest } from "../../utils/request.js";
6
+ import { makeRequestOptions } from "../../lib/makeRequestOptions.js";
6
7
 
7
8
  export type ImageToImageArgs = BaseArgs & ImageToImageInput;
8
9
 
@@ -18,5 +19,6 @@ export async function imageToImage(args: ImageToImageArgs, options?: Options): P
18
19
  ...options,
19
20
  task: "image-to-image",
20
21
  });
21
- return providerHelper.getResponse(res);
22
+ const { url, info } = await makeRequestOptions(args, providerHelper, { ...options, task: "image-to-image" });
23
+ return providerHelper.getResponse(res, url, info.headers as Record<string, string>);
22
24
  }