@huggingface/inference 3.14.0 → 4.0.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 (130) hide show
  1. package/README.md +104 -1
  2. package/dist/commonjs/errors.d.ts +46 -0
  3. package/dist/commonjs/errors.d.ts.map +1 -0
  4. package/dist/commonjs/errors.js +70 -0
  5. package/dist/commonjs/index.d.ts +1 -1
  6. package/dist/commonjs/index.d.ts.map +1 -1
  7. package/dist/commonjs/index.js +2 -3
  8. package/dist/commonjs/lib/getInferenceProviderMapping.d.ts.map +1 -1
  9. package/dist/commonjs/lib/getInferenceProviderMapping.js +27 -16
  10. package/dist/commonjs/lib/getProviderHelper.d.ts.map +1 -1
  11. package/dist/commonjs/lib/getProviderHelper.js +5 -3
  12. package/dist/commonjs/lib/makeRequestOptions.d.ts.map +1 -1
  13. package/dist/commonjs/lib/makeRequestOptions.js +12 -11
  14. package/dist/commonjs/package.d.ts +1 -1
  15. package/dist/commonjs/package.d.ts.map +1 -1
  16. package/dist/commonjs/package.js +1 -1
  17. package/dist/commonjs/providers/black-forest-labs.d.ts.map +1 -1
  18. package/dist/commonjs/providers/black-forest-labs.js +4 -4
  19. package/dist/commonjs/providers/fal-ai.d.ts.map +1 -1
  20. package/dist/commonjs/providers/fal-ai.js +29 -17
  21. package/dist/commonjs/providers/featherless-ai.d.ts.map +1 -1
  22. package/dist/commonjs/providers/featherless-ai.js +10 -4
  23. package/dist/commonjs/providers/hf-inference.d.ts.map +1 -1
  24. package/dist/commonjs/providers/hf-inference.js +27 -30
  25. package/dist/commonjs/providers/hyperbolic.d.ts.map +1 -1
  26. package/dist/commonjs/providers/hyperbolic.js +3 -3
  27. package/dist/commonjs/providers/nebius.d.ts.map +1 -1
  28. package/dist/commonjs/providers/nebius.js +2 -2
  29. package/dist/commonjs/providers/novita.d.ts +5 -6
  30. package/dist/commonjs/providers/novita.d.ts.map +1 -1
  31. package/dist/commonjs/providers/novita.js +66 -16
  32. package/dist/commonjs/providers/nscale.d.ts.map +1 -1
  33. package/dist/commonjs/providers/nscale.js +2 -2
  34. package/dist/commonjs/providers/ovhcloud.d.ts.map +1 -1
  35. package/dist/commonjs/providers/ovhcloud.js +2 -2
  36. package/dist/commonjs/providers/providerHelper.js +3 -3
  37. package/dist/commonjs/providers/replicate.js +4 -4
  38. package/dist/commonjs/providers/sambanova.d.ts +16 -0
  39. package/dist/commonjs/providers/sambanova.d.ts.map +1 -1
  40. package/dist/commonjs/providers/sambanova.js +2 -18
  41. package/dist/commonjs/providers/together.d.ts.map +1 -1
  42. package/dist/commonjs/providers/together.js +3 -3
  43. package/dist/commonjs/tasks/audio/automaticSpeechRecognition.d.ts.map +1 -1
  44. package/dist/commonjs/tasks/audio/automaticSpeechRecognition.js +2 -2
  45. package/dist/commonjs/utils/request.d.ts.map +1 -1
  46. package/dist/commonjs/utils/request.js +77 -12
  47. package/dist/commonjs/vendor/type-fest/basic.d.ts +33 -0
  48. package/dist/commonjs/vendor/type-fest/basic.d.ts.map +1 -0
  49. package/dist/commonjs/vendor/type-fest/basic.js +2 -0
  50. package/dist/esm/errors.d.ts +46 -0
  51. package/dist/esm/errors.d.ts.map +1 -0
  52. package/dist/esm/errors.js +62 -0
  53. package/dist/esm/index.d.ts +1 -1
  54. package/dist/esm/index.d.ts.map +1 -1
  55. package/dist/esm/index.js +1 -1
  56. package/dist/esm/lib/getInferenceProviderMapping.d.ts.map +1 -1
  57. package/dist/esm/lib/getInferenceProviderMapping.js +27 -16
  58. package/dist/esm/lib/getProviderHelper.d.ts.map +1 -1
  59. package/dist/esm/lib/getProviderHelper.js +5 -3
  60. package/dist/esm/lib/makeRequestOptions.d.ts.map +1 -1
  61. package/dist/esm/lib/makeRequestOptions.js +12 -11
  62. package/dist/esm/package.d.ts +1 -1
  63. package/dist/esm/package.d.ts.map +1 -1
  64. package/dist/esm/package.js +1 -1
  65. package/dist/esm/providers/black-forest-labs.d.ts.map +1 -1
  66. package/dist/esm/providers/black-forest-labs.js +4 -4
  67. package/dist/esm/providers/fal-ai.d.ts.map +1 -1
  68. package/dist/esm/providers/fal-ai.js +29 -17
  69. package/dist/esm/providers/featherless-ai.d.ts.map +1 -1
  70. package/dist/esm/providers/featherless-ai.js +10 -4
  71. package/dist/esm/providers/hf-inference.d.ts.map +1 -1
  72. package/dist/esm/providers/hf-inference.js +27 -30
  73. package/dist/esm/providers/hyperbolic.d.ts.map +1 -1
  74. package/dist/esm/providers/hyperbolic.js +3 -3
  75. package/dist/esm/providers/nebius.d.ts.map +1 -1
  76. package/dist/esm/providers/nebius.js +2 -2
  77. package/dist/esm/providers/novita.d.ts +5 -6
  78. package/dist/esm/providers/novita.d.ts.map +1 -1
  79. package/dist/esm/providers/novita.js +66 -16
  80. package/dist/esm/providers/nscale.d.ts.map +1 -1
  81. package/dist/esm/providers/nscale.js +2 -2
  82. package/dist/esm/providers/ovhcloud.d.ts.map +1 -1
  83. package/dist/esm/providers/ovhcloud.js +2 -2
  84. package/dist/esm/providers/providerHelper.js +3 -3
  85. package/dist/esm/providers/replicate.js +4 -4
  86. package/dist/esm/providers/sambanova.d.ts +16 -0
  87. package/dist/esm/providers/sambanova.d.ts.map +1 -1
  88. package/dist/esm/providers/sambanova.js +2 -18
  89. package/dist/esm/providers/together.d.ts.map +1 -1
  90. package/dist/esm/providers/together.js +3 -3
  91. package/dist/esm/tasks/audio/automaticSpeechRecognition.d.ts.map +1 -1
  92. package/dist/esm/tasks/audio/automaticSpeechRecognition.js +2 -2
  93. package/dist/esm/utils/request.d.ts.map +1 -1
  94. package/dist/esm/utils/request.js +77 -12
  95. package/dist/esm/vendor/type-fest/basic.d.ts +33 -0
  96. package/dist/esm/vendor/type-fest/basic.d.ts.map +1 -0
  97. package/dist/esm/vendor/type-fest/basic.js +1 -0
  98. package/package.json +2 -2
  99. package/src/errors.ts +82 -0
  100. package/src/index.ts +1 -1
  101. package/src/lib/getInferenceProviderMapping.ts +42 -22
  102. package/src/lib/getProviderHelper.ts +9 -3
  103. package/src/lib/makeRequestOptions.ts +20 -11
  104. package/src/package.ts +1 -1
  105. package/src/providers/black-forest-labs.ts +14 -4
  106. package/src/providers/fal-ai.ts +59 -23
  107. package/src/providers/featherless-ai.ts +10 -4
  108. package/src/providers/hf-inference.ts +75 -34
  109. package/src/providers/hyperbolic.ts +3 -4
  110. package/src/providers/nebius.ts +2 -2
  111. package/src/providers/novita.ts +103 -23
  112. package/src/providers/nscale.ts +2 -2
  113. package/src/providers/ovhcloud.ts +2 -2
  114. package/src/providers/providerHelper.ts +3 -3
  115. package/src/providers/replicate.ts +4 -4
  116. package/src/providers/sambanova.ts +3 -4
  117. package/src/providers/together.ts +3 -3
  118. package/src/tasks/audio/automaticSpeechRecognition.ts +2 -2
  119. package/src/tasks/cv/textToVideo.ts +2 -2
  120. package/src/utils/request.ts +127 -14
  121. package/src/vendor/type-fest/basic.ts +31 -0
  122. package/src/vendor/type-fest/license-cc0 +121 -0
  123. package/src/vendor/type-fest/license-mit +9 -0
  124. package/dist/commonjs/lib/InferenceOutputError.d.ts +0 -4
  125. package/dist/commonjs/lib/InferenceOutputError.d.ts.map +0 -1
  126. package/dist/commonjs/lib/InferenceOutputError.js +0 -10
  127. package/dist/esm/lib/InferenceOutputError.d.ts +0 -4
  128. package/dist/esm/lib/InferenceOutputError.d.ts.map +0 -1
  129. package/dist/esm/lib/InferenceOutputError.js +0 -6
  130. package/src/lib/InferenceOutputError.ts +0 -8
@@ -1,6 +1,6 @@
1
- import { InferenceOutputError } from "../lib/InferenceOutputError.js";
2
1
  import { omit } from "../utils/omit.js";
3
2
  import { BaseConversationalTask, BaseTextGenerationTask, TaskProviderHelper, } from "./providerHelper.js";
3
+ import { InferenceClientProviderOutputError } from "../errors.js";
4
4
  const TOGETHER_API_BASE_URL = "https://api.together.xyz";
5
5
  export class TogetherConversationalTask extends BaseConversationalTask {
6
6
  constructor() {
@@ -28,7 +28,7 @@ export class TogetherTextGenerationTask extends BaseTextGenerationTask {
28
28
  generated_text: completion.text,
29
29
  };
30
30
  }
31
- throw new InferenceOutputError("Expected Together text generation response format");
31
+ throw new InferenceClientProviderOutputError("Received malformed response from Together text generation API");
32
32
  }
33
33
  }
34
34
  export class TogetherTextToImageTask extends TaskProviderHelper {
@@ -60,6 +60,6 @@ export class TogetherTextToImageTask extends TaskProviderHelper {
60
60
  }
61
61
  return fetch(`data:image/jpeg;base64,${base64Data}`).then((res) => res.blob());
62
62
  }
63
- throw new InferenceOutputError("Expected Together text-to-image response format");
63
+ throw new InferenceClientProviderOutputError("Received malformed response from Together text-to-image API");
64
64
  }
65
65
  }
@@ -1 +1 @@
1
- {"version":3,"file":"automaticSpeechRecognition.d.ts","sourceRoot":"","sources":["../../../../src/tasks/audio/automaticSpeechRecognition.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,+BAA+B,EAAE,gCAAgC,EAAE,MAAM,oBAAoB,CAAC;AAI5G,OAAO,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAExD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD,MAAM,MAAM,8BAA8B,GAAG,QAAQ,GAAG,CAAC,+BAA+B,GAAG,gBAAgB,CAAC,CAAC;AAC7G;;;GAGG;AACH,wBAAsB,0BAA0B,CAC/C,IAAI,EAAE,8BAA8B,EACpC,OAAO,CAAC,EAAE,OAAO,GACf,OAAO,CAAC,gCAAgC,CAAC,CAa3C"}
1
+ {"version":3,"file":"automaticSpeechRecognition.d.ts","sourceRoot":"","sources":["../../../../src/tasks/audio/automaticSpeechRecognition.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,+BAA+B,EAAE,gCAAgC,EAAE,MAAM,oBAAoB,CAAC;AAG5G,OAAO,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAExD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAGnD,MAAM,MAAM,8BAA8B,GAAG,QAAQ,GAAG,CAAC,+BAA+B,GAAG,gBAAgB,CAAC,CAAC;AAC7G;;;GAGG;AACH,wBAAsB,0BAA0B,CAC/C,IAAI,EAAE,8BAA8B,EACpC,OAAO,CAAC,EAAE,OAAO,GACf,OAAO,CAAC,gCAAgC,CAAC,CAa3C"}
@@ -1,7 +1,7 @@
1
1
  import { resolveProvider } from "../../lib/getInferenceProviderMapping.js";
2
2
  import { getProviderHelper } from "../../lib/getProviderHelper.js";
3
- import { InferenceOutputError } from "../../lib/InferenceOutputError.js";
4
3
  import { innerRequest } from "../../utils/request.js";
4
+ import { InferenceClientProviderOutputError } from "../../errors.js";
5
5
  /**
6
6
  * This task reads some audio input and outputs the said words within the audio files.
7
7
  * Recommended model (english language): facebook/wav2vec2-large-960h-lv60-self
@@ -16,7 +16,7 @@ export async function automaticSpeechRecognition(args, options) {
16
16
  });
17
17
  const isValidOutput = typeof res?.text === "string";
18
18
  if (!isValidOutput) {
19
- throw new InferenceOutputError("Expected {text: string}");
19
+ throw new InferenceClientProviderOutputError("Received malformed response from automatic-speech-recognition API");
20
20
  }
21
21
  return providerHelper.getResponse(res);
22
22
  }
@@ -1 +1 @@
1
- {"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../../src/utils/request.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAErE,OAAO,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAIvE,MAAM,WAAW,eAAe,CAAC,CAAC;IACjC,IAAI,EAAE,CAAC,CAAC;IACR,cAAc,EAAE;QACf,GAAG,EAAE,MAAM,CAAC;QACZ,IAAI,EAAE,WAAW,CAAC;KAClB,CAAC;CACF;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,CAAC,EACnC,IAAI,EAAE,WAAW,EACjB,cAAc,EAAE,UAAU,CAAC,OAAO,iBAAiB,CAAC,EACpD,OAAO,CAAC,EAAE,OAAO,GAAG;IACnB,oEAAoE;IACpE,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,oCAAoC;IACpC,cAAc,CAAC,EAAE,OAAO,CAAC;CACzB,GACC,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAoC7B;AAED;;GAEG;AACH,wBAAuB,qBAAqB,CAAC,CAAC,EAC7C,IAAI,EAAE,WAAW,EACjB,cAAc,EAAE,UAAU,CAAC,OAAO,iBAAiB,CAAC,EACpD,OAAO,CAAC,EAAE,OAAO,GAAG;IACnB,oEAAoE;IACpE,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,oCAAoC;IACpC,cAAc,CAAC,EAAE,OAAO,CAAC;CACzB,GACC,cAAc,CAAC,CAAC,CAAC,CAuFnB"}
1
+ {"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../../src/utils/request.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAErE,OAAO,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAMvE,MAAM,WAAW,eAAe,CAAC,CAAC;IACjC,IAAI,EAAE,CAAC,CAAC;IACR,cAAc,EAAE;QACf,GAAG,EAAE,MAAM,CAAC;QACZ,IAAI,EAAE,WAAW,CAAC;KAClB,CAAC;CACF;AAaD;;GAEG;AACH,wBAAsB,YAAY,CAAC,CAAC,EACnC,IAAI,EAAE,WAAW,EACjB,cAAc,EAAE,UAAU,CAAC,OAAO,iBAAiB,CAAC,EACpD,OAAO,CAAC,EAAE,OAAO,GAAG;IACnB,oEAAoE;IACpE,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,oCAAoC;IACpC,cAAc,CAAC,EAAE,OAAO,CAAC;CACzB,GACC,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAwE7B;AAED;;GAEG;AACH,wBAAuB,qBAAqB,CAAC,CAAC,EAC7C,IAAI,EAAE,WAAW,EACjB,cAAc,EAAE,UAAU,CAAC,OAAO,iBAAiB,CAAC,EACpD,OAAO,CAAC,EAAE,OAAO,GAAG;IACnB,oEAAoE;IACpE,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,oCAAoC;IACpC,cAAc,CAAC,EAAE,OAAO,CAAC;CACzB,GACC,cAAc,CAAC,CAAC,CAAC,CAuJnB"}
@@ -1,5 +1,14 @@
1
1
  import { makeRequestOptions } from "../lib/makeRequestOptions.js";
2
2
  import { getLines, getMessages } from "../vendor/fetch-event-source/parse.js";
3
+ import { InferenceClientProviderApiError } from "../errors.js";
4
+ function requestArgsToJson(args) {
5
+ // Convert the entire args object to a JSON-serializable format
6
+ const argsWithData = args;
7
+ return JSON.parse(JSON.stringify({
8
+ ...argsWithData,
9
+ data: argsWithData.data ? "[Blob or ArrayBuffer]" : null,
10
+ }));
11
+ }
3
12
  /**
4
13
  * Primitive to make custom calls to the inference provider
5
14
  */
@@ -15,17 +24,37 @@ export async function innerRequest(args, providerHelper, options) {
15
24
  if (["application/json", "application/problem+json"].some((ct) => contentType?.startsWith(ct))) {
16
25
  const output = await response.json();
17
26
  if ([400, 422, 404, 500].includes(response.status) && options?.chatCompletion) {
18
- throw new Error(`Server ${args.model} does not seem to support chat completion. Error: ${JSON.stringify(output.error)}`);
27
+ throw new InferenceClientProviderApiError(`Provider ${args.provider} does not seem to support chat completion for model ${args.model} . Error: ${JSON.stringify(output.error)}`, {
28
+ url,
29
+ method: info.method ?? "GET",
30
+ headers: info.headers,
31
+ body: requestArgsToJson(args),
32
+ }, { requestId: response.headers.get("x-request-id") ?? "", status: response.status, body: output });
19
33
  }
20
- if (output.error || output.detail) {
21
- throw new Error(JSON.stringify(output.error ?? output.detail));
34
+ if (typeof output.error === "string" || typeof output.detail === "string") {
35
+ throw new InferenceClientProviderApiError(`Failed to perform inference: ${output.error ?? output.detail}`, {
36
+ url,
37
+ method: info.method ?? "GET",
38
+ headers: info.headers,
39
+ body: requestArgsToJson(args),
40
+ }, { requestId: response.headers.get("x-request-id") ?? "", status: response.status, body: output });
22
41
  }
23
42
  else {
24
- throw new Error(output);
43
+ throw new InferenceClientProviderApiError(`Failed to perform inference: an HTTP error occurred when requesting the provider.`, {
44
+ url,
45
+ method: info.method ?? "GET",
46
+ headers: info.headers,
47
+ body: requestArgsToJson(args),
48
+ }, { requestId: response.headers.get("x-request-id") ?? "", status: response.status, body: output });
25
49
  }
26
50
  }
27
51
  const message = contentType?.startsWith("text/plain;") ? await response.text() : undefined;
28
- throw new Error(message ?? "An error occurred while fetching the blob");
52
+ throw new InferenceClientProviderApiError(`Failed to perform inference: ${message ?? "an HTTP error occurred when requesting the provider"}`, {
53
+ url,
54
+ method: info.method ?? "GET",
55
+ headers: info.headers,
56
+ body: requestArgsToJson(args),
57
+ }, { requestId: response.headers.get("x-request-id") ?? "", status: response.status, body: message ?? "" });
29
58
  }
30
59
  if (response.headers.get("Content-Type")?.startsWith("application/json")) {
31
60
  const data = (await response.json());
@@ -47,24 +76,55 @@ export async function* innerStreamingRequest(args, providerHelper, options) {
47
76
  if (response.headers.get("Content-Type")?.startsWith("application/json")) {
48
77
  const output = await response.json();
49
78
  if ([400, 422, 404, 500].includes(response.status) && options?.chatCompletion) {
50
- throw new Error(`Server ${args.model} does not seem to support chat completion. Error: ${output.error}`);
79
+ throw new InferenceClientProviderApiError(`Provider ${args.provider} does not seem to support chat completion for model ${args.model} . Error: ${JSON.stringify(output.error)}`, {
80
+ url,
81
+ method: info.method ?? "GET",
82
+ headers: info.headers,
83
+ body: requestArgsToJson(args),
84
+ }, { requestId: response.headers.get("x-request-id") ?? "", status: response.status, body: output });
51
85
  }
52
86
  if (typeof output.error === "string") {
53
- throw new Error(output.error);
87
+ throw new InferenceClientProviderApiError(`Failed to perform inference: ${output.error}`, {
88
+ url,
89
+ method: info.method ?? "GET",
90
+ headers: info.headers,
91
+ body: requestArgsToJson(args),
92
+ }, { requestId: response.headers.get("x-request-id") ?? "", status: response.status, body: output });
54
93
  }
55
94
  if (output.error && "message" in output.error && typeof output.error.message === "string") {
56
95
  /// OpenAI errors
57
- throw new Error(output.error.message);
96
+ throw new InferenceClientProviderApiError(`Failed to perform inference: ${output.error.message}`, {
97
+ url,
98
+ method: info.method ?? "GET",
99
+ headers: info.headers,
100
+ body: requestArgsToJson(args),
101
+ }, { requestId: response.headers.get("x-request-id") ?? "", status: response.status, body: output });
58
102
  }
59
103
  // Sambanova errors
60
104
  if (typeof output.message === "string") {
61
- throw new Error(output.message);
105
+ throw new InferenceClientProviderApiError(`Failed to perform inference: ${output.message}`, {
106
+ url,
107
+ method: info.method ?? "GET",
108
+ headers: info.headers,
109
+ body: requestArgsToJson(args),
110
+ }, { requestId: response.headers.get("x-request-id") ?? "", status: response.status, body: output });
62
111
  }
63
112
  }
64
- throw new Error(`Server response contains error: ${response.status}`);
113
+ throw new InferenceClientProviderApiError(`Failed to perform inference: an HTTP error occurred when requesting the provider.`, {
114
+ url,
115
+ method: info.method ?? "GET",
116
+ headers: info.headers,
117
+ body: requestArgsToJson(args),
118
+ }, { requestId: response.headers.get("x-request-id") ?? "", status: response.status, body: "" });
65
119
  }
66
120
  if (!response.headers.get("content-type")?.startsWith("text/event-stream")) {
67
- throw new Error(`Server does not support event stream content type, it returned ` + response.headers.get("content-type"));
121
+ throw new InferenceClientProviderApiError(`Failed to perform inference: server does not support event stream content type, it returned ` +
122
+ response.headers.get("content-type"), {
123
+ url,
124
+ method: info.method ?? "GET",
125
+ headers: info.headers,
126
+ body: requestArgsToJson(args),
127
+ }, { requestId: response.headers.get("x-request-id") ?? "", status: response.status, body: "" });
68
128
  }
69
129
  if (!response.body) {
70
130
  return;
@@ -98,7 +158,12 @@ export async function* innerStreamingRequest(args, providerHelper, options) {
98
158
  typeof data.error.message === "string"
99
159
  ? data.error.message
100
160
  : JSON.stringify(data.error);
101
- throw new Error(`Error forwarded from backend: ` + errorStr);
161
+ throw new InferenceClientProviderApiError(`Failed to perform inference: an occurred while streaming the response: ${errorStr}`, {
162
+ url,
163
+ method: info.method ?? "GET",
164
+ headers: info.headers,
165
+ body: requestArgsToJson(args),
166
+ }, { requestId: response.headers.get("x-request-id") ?? "", status: response.status, body: data });
102
167
  }
103
168
  yield data;
104
169
  }
@@ -0,0 +1,33 @@
1
+ /**
2
+ Matches a JSON object.
3
+
4
+ This type can be useful to enforce some input to be JSON-compatible or as a super-type to be extended from. Don't use this as a direct return type as the user would have to double-cast it: `jsonObject as unknown as CustomResponse`. Instead, you could extend your CustomResponse type from it to ensure your type only uses JSON-compatible types: `interface CustomResponse extends JsonObject { … }`.
5
+
6
+ @category JSON
7
+ */
8
+ export type JsonObject = {
9
+ [Key in string]: JsonValue;
10
+ } & {
11
+ [Key in string]?: JsonValue | undefined;
12
+ };
13
+ /**
14
+ Matches a JSON array.
15
+
16
+ @category JSON
17
+ */
18
+ export type JsonArray = JsonValue[] | readonly JsonValue[];
19
+ /**
20
+ Matches any valid JSON primitive value.
21
+
22
+ @category JSON
23
+ */
24
+ export type JsonPrimitive = string | number | boolean | null;
25
+ /**
26
+ Matches any valid JSON value.
27
+
28
+ @see `Jsonify` if you need to transform a type to one that is assignable to `JsonValue`.
29
+
30
+ @category JSON
31
+ */
32
+ export type JsonValue = JsonPrimitive | JsonObject | JsonArray;
33
+ //# sourceMappingURL=basic.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"basic.d.ts","sourceRoot":"","sources":["../../../../src/vendor/type-fest/basic.ts"],"names":[],"mappings":"AAAA;;;;;;EAME;AACF,MAAM,MAAM,UAAU,GAAG;KAAG,GAAG,IAAI,MAAM,GAAG,SAAS;CAAE,GAAG;KAAG,GAAG,IAAI,MAAM,CAAC,CAAC,EAAE,SAAS,GAAG,SAAS;CAAE,CAAC;AAEtG;;;;EAIE;AACF,MAAM,MAAM,SAAS,GAAG,SAAS,EAAE,GAAG,SAAS,SAAS,EAAE,CAAC;AAE3D;;;;EAIE;AACF,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;AAE7D;;;;;;EAME;AACF,MAAM,MAAM,SAAS,GAAG,aAAa,GAAG,UAAU,GAAG,SAAS,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@huggingface/inference",
3
- "version": "3.14.0",
3
+ "version": "4.0.0",
4
4
  "license": "MIT",
5
5
  "author": "Hugging Face and Tim Mikeladze <tim.mikeladze@gmail.com>",
6
6
  "description": "Typescript client for the Hugging Face Inference Providers and Inference Endpoints",
@@ -40,7 +40,7 @@
40
40
  },
41
41
  "type": "module",
42
42
  "dependencies": {
43
- "@huggingface/tasks": "^0.19.8",
43
+ "@huggingface/tasks": "^0.19.11",
44
44
  "@huggingface/jinja": "^0.5.0"
45
45
  },
46
46
  "devDependencies": {
package/src/errors.ts ADDED
@@ -0,0 +1,82 @@
1
+ import type { JsonObject } from "./vendor/type-fest/basic.js";
2
+
3
+ /**
4
+ * Base class for all inference-related errors.
5
+ */
6
+ export abstract class InferenceClientError extends Error {
7
+ constructor(message: string) {
8
+ super(message);
9
+ this.name = "InferenceClientError";
10
+ }
11
+ }
12
+
13
+ export class InferenceClientInputError extends InferenceClientError {
14
+ constructor(message: string) {
15
+ super(message);
16
+ this.name = "InputError";
17
+ }
18
+ }
19
+
20
+ interface HttpRequest {
21
+ url: string;
22
+ method: string;
23
+ headers?: Record<string, string>;
24
+ body?: JsonObject;
25
+ }
26
+
27
+ interface HttpResponse {
28
+ requestId: string;
29
+ status: number;
30
+ body: JsonObject | string;
31
+ }
32
+
33
+ abstract class InferenceClientHttpRequestError extends InferenceClientError {
34
+ httpRequest: HttpRequest;
35
+ httpResponse: HttpResponse;
36
+ constructor(message: string, httpRequest: HttpRequest, httpResponse: HttpResponse) {
37
+ super(message);
38
+ this.httpRequest = {
39
+ ...httpRequest,
40
+ ...(httpRequest.headers
41
+ ? {
42
+ headers: {
43
+ ...httpRequest.headers,
44
+ ...("Authorization" in httpRequest.headers ? { Authorization: `Bearer [redacted]` } : undefined),
45
+ /// redact authentication in the request headers
46
+ },
47
+ }
48
+ : undefined),
49
+ };
50
+ this.httpResponse = httpResponse;
51
+ }
52
+ }
53
+
54
+ /**
55
+ * Thrown when the HTTP request to the provider fails, e.g. due to API issues or server errors.
56
+ */
57
+ export class InferenceClientProviderApiError extends InferenceClientHttpRequestError {
58
+ constructor(message: string, httpRequest: HttpRequest, httpResponse: HttpResponse) {
59
+ super(message, httpRequest, httpResponse);
60
+ this.name = "ProviderApiError";
61
+ }
62
+ }
63
+
64
+ /**
65
+ * Thrown when the HTTP request to the hub fails, e.g. due to API issues or server errors.
66
+ */
67
+ export class InferenceClientHubApiError extends InferenceClientHttpRequestError {
68
+ constructor(message: string, httpRequest: HttpRequest, httpResponse: HttpResponse) {
69
+ super(message, httpRequest, httpResponse);
70
+ this.name = "HubApiError";
71
+ }
72
+ }
73
+
74
+ /**
75
+ * Thrown when the inference output returned by the provider is invalid / does not match the expectations
76
+ */
77
+ export class InferenceClientProviderOutputError extends InferenceClientError {
78
+ constructor(message: string) {
79
+ super(message);
80
+ this.name = "ProviderOutputError";
81
+ }
82
+ }
package/src/index.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export { InferenceClient, InferenceClientEndpoint, HfInference } from "./InferenceClient.js";
2
- export { InferenceOutputError } from "./lib/InferenceOutputError.js";
2
+ export * from "./errors.js";
3
3
  export * from "./types.js";
4
4
  export * from "./tasks/index.js";
5
5
  import * as snippets from "./snippets/index.js";
@@ -4,6 +4,7 @@ import { HARDCODED_MODEL_INFERENCE_MAPPING } from "../providers/consts.js";
4
4
  import { EQUIVALENT_SENTENCE_TRANSFORMERS_TASKS } from "../providers/hf-inference.js";
5
5
  import type { InferenceProvider, InferenceProviderOrPolicy, ModelId } from "../types.js";
6
6
  import { typedInclude } from "../utils/typedInclude.js";
7
+ import { InferenceClientHubApiError, InferenceClientInputError } from "../errors.js";
7
8
 
8
9
  export const inferenceProviderMappingCache = new Map<ModelId, InferenceProviderMapping>();
9
10
 
@@ -32,27 +33,46 @@ export async function fetchInferenceProviderMappingForModel(
32
33
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
33
34
  inferenceProviderMapping = inferenceProviderMappingCache.get(modelId)!;
34
35
  } else {
35
- const resp = await (options?.fetch ?? fetch)(
36
- `${HF_HUB_URL}/api/models/${modelId}?expand[]=inferenceProviderMapping`,
37
- {
38
- headers: accessToken?.startsWith("hf_") ? { Authorization: `Bearer ${accessToken}` } : {},
36
+ const url = `${HF_HUB_URL}/api/models/${modelId}?expand[]=inferenceProviderMapping`;
37
+ const resp = await (options?.fetch ?? fetch)(url, {
38
+ headers: accessToken?.startsWith("hf_") ? { Authorization: `Bearer ${accessToken}` } : {},
39
+ });
40
+ if (!resp.ok) {
41
+ if (resp.headers.get("Content-Type")?.startsWith("application/json")) {
42
+ const error = await resp.json();
43
+ if ("error" in error && typeof error.error === "string") {
44
+ throw new InferenceClientHubApiError(
45
+ `Failed to fetch inference provider mapping for model ${modelId}: ${error.error}`,
46
+ { url, method: "GET" },
47
+ { requestId: resp.headers.get("x-request-id") ?? "", status: resp.status, body: error }
48
+ );
49
+ }
50
+ } else {
51
+ throw new InferenceClientHubApiError(
52
+ `Failed to fetch inference provider mapping for model ${modelId}`,
53
+ { url, method: "GET" },
54
+ { requestId: resp.headers.get("x-request-id") ?? "", status: resp.status, body: await resp.text() }
55
+ );
39
56
  }
40
- );
41
- if (resp.status === 404) {
42
- throw new Error(`Model ${modelId} does not exist`);
43
57
  }
44
- inferenceProviderMapping = await resp
45
- .json()
46
- .then((json) => json.inferenceProviderMapping)
47
- .catch(() => null);
48
-
49
- if (inferenceProviderMapping) {
50
- inferenceProviderMappingCache.set(modelId, inferenceProviderMapping);
58
+ let payload: { inferenceProviderMapping?: InferenceProviderMapping } | null = null;
59
+ try {
60
+ payload = await resp.json();
61
+ } catch {
62
+ throw new InferenceClientHubApiError(
63
+ `Failed to fetch inference provider mapping for model ${modelId}: malformed API response, invalid JSON`,
64
+ { url, method: "GET" },
65
+ { requestId: resp.headers.get("x-request-id") ?? "", status: resp.status, body: await resp.text() }
66
+ );
51
67
  }
52
- }
53
-
54
- if (!inferenceProviderMapping) {
55
- throw new Error(`We have not been able to find inference provider information for model ${modelId}.`);
68
+ if (!payload?.inferenceProviderMapping) {
69
+ throw new InferenceClientHubApiError(
70
+ `We have not been able to find inference provider information for model ${modelId}.`,
71
+ { url, method: "GET" },
72
+ { requestId: resp.headers.get("x-request-id") ?? "", status: resp.status, body: await resp.text() }
73
+ );
74
+ }
75
+ inferenceProviderMapping = payload.inferenceProviderMapping;
56
76
  }
57
77
  return inferenceProviderMapping;
58
78
  }
@@ -83,7 +103,7 @@ export async function getInferenceProviderMapping(
83
103
  ? EQUIVALENT_SENTENCE_TRANSFORMERS_TASKS
84
104
  : [params.task];
85
105
  if (!typedInclude(equivalentTasks, providerMapping.task)) {
86
- throw new Error(
106
+ throw new InferenceClientInputError(
87
107
  `Model ${params.modelId} is not supported for task ${params.task} and provider ${params.provider}. Supported task: ${providerMapping.task}.`
88
108
  );
89
109
  }
@@ -104,7 +124,7 @@ export async function resolveProvider(
104
124
  ): Promise<InferenceProvider> {
105
125
  if (endpointUrl) {
106
126
  if (provider) {
107
- throw new Error("Specifying both endpointUrl and provider is not supported.");
127
+ throw new InferenceClientInputError("Specifying both endpointUrl and provider is not supported.");
108
128
  }
109
129
  /// Defaulting to hf-inference helpers / API
110
130
  return "hf-inference";
@@ -117,13 +137,13 @@ export async function resolveProvider(
117
137
  }
118
138
  if (provider === "auto") {
119
139
  if (!modelId) {
120
- throw new Error("Specifying a model is required when provider is 'auto'");
140
+ throw new InferenceClientInputError("Specifying a model is required when provider is 'auto'");
121
141
  }
122
142
  const inferenceProviderMapping = await fetchInferenceProviderMappingForModel(modelId);
123
143
  provider = Object.keys(inferenceProviderMapping)[0] as InferenceProvider | undefined;
124
144
  }
125
145
  if (!provider) {
126
- throw new Error(`No Inference Provider available for model ${modelId}.`);
146
+ throw new InferenceClientInputError(`No Inference Provider available for model ${modelId}.`);
127
147
  }
128
148
  return provider;
129
149
  }
@@ -48,6 +48,7 @@ import * as Replicate from "../providers/replicate.js";
48
48
  import * as Sambanova from "../providers/sambanova.js";
49
49
  import * as Together from "../providers/together.js";
50
50
  import type { InferenceProvider, InferenceProviderOrPolicy, InferenceTask } from "../types.js";
51
+ import { InferenceClientInputError } from "../errors.js";
51
52
 
52
53
  export const PROVIDERS: Record<InferenceProvider, Partial<Record<InferenceTask, TaskProviderHelper>>> = {
53
54
  "black-forest-labs": {
@@ -120,6 +121,7 @@ export const PROVIDERS: Record<InferenceProvider, Partial<Record<InferenceTask,
120
121
  novita: {
121
122
  conversational: new Novita.NovitaConversationalTask(),
122
123
  "text-generation": new Novita.NovitaTextGenerationTask(),
124
+ "text-to-video": new Novita.NovitaTextToVideoTask(),
123
125
  },
124
126
  nscale: {
125
127
  "text-to-image": new Nscale.NscaleTextToImageTask(),
@@ -280,14 +282,18 @@ export function getProviderHelper(
280
282
  return new HFInference.HFInferenceTask();
281
283
  }
282
284
  if (!task) {
283
- throw new Error("you need to provide a task name when using an external provider, e.g. 'text-to-image'");
285
+ throw new InferenceClientInputError(
286
+ "you need to provide a task name when using an external provider, e.g. 'text-to-image'"
287
+ );
284
288
  }
285
289
  if (!(provider in PROVIDERS)) {
286
- throw new Error(`Provider '${provider}' not supported. Available providers: ${Object.keys(PROVIDERS)}`);
290
+ throw new InferenceClientInputError(
291
+ `Provider '${provider}' not supported. Available providers: ${Object.keys(PROVIDERS)}`
292
+ );
287
293
  }
288
294
  const providerTasks = PROVIDERS[provider];
289
295
  if (!providerTasks || !(task in providerTasks)) {
290
- throw new Error(
296
+ throw new InferenceClientInputError(
291
297
  `Task '${task}' not supported for provider '${provider}'. Available tasks: ${Object.keys(providerTasks ?? {})}`
292
298
  );
293
299
  }
@@ -5,6 +5,7 @@ import type { InferenceProviderModelMapping } from "./getInferenceProviderMappin
5
5
  import { getInferenceProviderMapping } from "./getInferenceProviderMapping.js";
6
6
  import type { getProviderHelper } from "./getProviderHelper.js";
7
7
  import { isUrl } from "./isUrl.js";
8
+ import { InferenceClientHubApiError, InferenceClientInputError } from "../errors.js";
8
9
 
9
10
  /**
10
11
  * Lazy-loaded from huggingface.co/api/tasks when needed
@@ -33,10 +34,10 @@ export async function makeRequestOptions(
33
34
 
34
35
  // Validate inputs
35
36
  if (args.endpointUrl && provider !== "hf-inference") {
36
- throw new Error(`Cannot use endpointUrl with a third-party provider.`);
37
+ throw new InferenceClientInputError(`Cannot use endpointUrl with a third-party provider.`);
37
38
  }
38
39
  if (maybeModel && isUrl(maybeModel)) {
39
- throw new Error(`Model URLs are no longer supported. Use endpointUrl instead.`);
40
+ throw new InferenceClientInputError(`Model URLs are no longer supported. Use endpointUrl instead.`);
40
41
  }
41
42
 
42
43
  if (args.endpointUrl) {
@@ -51,14 +52,14 @@ export async function makeRequestOptions(
51
52
  }
52
53
 
53
54
  if (!maybeModel && !task) {
54
- throw new Error("No model provided, and no task has been specified.");
55
+ throw new InferenceClientInputError("No model provided, and no task has been specified.");
55
56
  }
56
57
 
57
58
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
58
59
  const hfModel = maybeModel ?? (await loadDefaultModel(task!));
59
60
 
60
61
  if (providerHelper.clientSideRoutingOnly && !maybeModel) {
61
- throw new Error(`Provider ${provider} requires a model ID to be passed directly.`);
62
+ throw new InferenceClientInputError(`Provider ${provider} requires a model ID to be passed directly.`);
62
63
  }
63
64
 
64
65
  const inferenceProviderMapping = providerHelper.clientSideRoutingOnly
@@ -82,7 +83,9 @@ export async function makeRequestOptions(
82
83
  { fetch: options?.fetch }
83
84
  );
84
85
  if (!inferenceProviderMapping) {
85
- throw new Error(`We have not been able to find inference provider information for model ${hfModel}.`);
86
+ throw new InferenceClientInputError(
87
+ `We have not been able to find inference provider information for model ${hfModel}.`
88
+ );
86
89
  }
87
90
 
88
91
  // Use the sync version with the resolved model
@@ -122,9 +125,8 @@ export function makeRequestOptionsFromResolvedModel(
122
125
  if (providerHelper.clientSideRoutingOnly) {
123
126
  // Closed-source providers require an accessToken (cannot be routed).
124
127
  if (accessToken && accessToken.startsWith("hf_")) {
125
- throw new Error(`Provider ${provider} is closed-source and does not support HF tokens.`);
128
+ throw new InferenceClientInputError(`Provider ${provider} is closed-source and does not support HF tokens.`);
126
129
  }
127
- return "provider-key";
128
130
  }
129
131
  if (accessToken) {
130
132
  return accessToken.startsWith("hf_") ? "hf-token" : "provider-key";
@@ -197,23 +199,30 @@ async function loadDefaultModel(task: InferenceTask): Promise<string> {
197
199
  }
198
200
  const taskInfo = tasks[task];
199
201
  if ((taskInfo?.models.length ?? 0) <= 0) {
200
- throw new Error(`No default model defined for task ${task}, please define the model explicitly.`);
202
+ throw new InferenceClientInputError(
203
+ `No default model defined for task ${task}, please define the model explicitly.`
204
+ );
201
205
  }
202
206
  return taskInfo.models[0].id;
203
207
  }
204
208
 
205
209
  async function loadTaskInfo(): Promise<Record<string, { models: { id: string }[] }>> {
206
- const res = await fetch(`${HF_HUB_URL}/api/tasks`);
210
+ const url = `${HF_HUB_URL}/api/tasks`;
211
+ const res = await fetch(url);
207
212
 
208
213
  if (!res.ok) {
209
- throw new Error("Failed to load tasks definitions from Hugging Face Hub.");
214
+ throw new InferenceClientHubApiError(
215
+ "Failed to load tasks definitions from Hugging Face Hub.",
216
+ { url, method: "GET" },
217
+ { requestId: res.headers.get("x-request-id") ?? "", status: res.status, body: await res.text() }
218
+ );
210
219
  }
211
220
  return await res.json();
212
221
  }
213
222
 
214
223
  function removeProviderPrefix(model: string, provider: string): string {
215
224
  if (!model.startsWith(`${provider}/`)) {
216
- throw new Error(`Models from ${provider} must be prefixed by "${provider}/". Got "${model}".`);
225
+ throw new InferenceClientInputError(`Models from ${provider} must be prefixed by "${provider}/". Got "${model}".`);
217
226
  }
218
227
  return model.slice(provider.length + 1);
219
228
  }
package/src/package.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  // Generated file from package.json. Issues importing JSON directly when publishing on commonjs/ESM - see https://github.com/microsoft/TypeScript/issues/51783
2
- export const PACKAGE_VERSION = "3.14.0";
2
+ export const PACKAGE_VERSION = "4.0.0";
3
3
  export const PACKAGE_NAME = "@huggingface/inference";
@@ -14,7 +14,11 @@
14
14
  *
15
15
  * Thanks!
16
16
  */
17
- import { InferenceOutputError } from "../lib/InferenceOutputError.js";
17
+ import {
18
+ InferenceClientInputError,
19
+ InferenceClientProviderApiError,
20
+ InferenceClientProviderOutputError,
21
+ } from "../errors.js";
18
22
  import type { BodyParams, HeaderParams, UrlParams } from "../types.js";
19
23
  import { delay } from "../utils/delay.js";
20
24
  import { omit } from "../utils/omit.js";
@@ -52,7 +56,7 @@ export class BlackForestLabsTextToImageTask extends TaskProviderHelper implement
52
56
 
53
57
  makeRoute(params: UrlParams): string {
54
58
  if (!params) {
55
- throw new Error("Params are required");
59
+ throw new InferenceClientInputError("Params are required");
56
60
  }
57
61
  return `/v1/${params.model}`;
58
62
  }
@@ -70,7 +74,11 @@ export class BlackForestLabsTextToImageTask extends TaskProviderHelper implement
70
74
  urlObj.searchParams.set("attempt", step.toString(10));
71
75
  const resp = await fetch(urlObj, { headers: { "Content-Type": "application/json" } });
72
76
  if (!resp.ok) {
73
- throw new InferenceOutputError("Failed to fetch result from black forest labs API");
77
+ throw new InferenceClientProviderApiError(
78
+ "Failed to fetch result from black forest labs API",
79
+ { url: urlObj.toString(), method: "GET", headers: { "Content-Type": "application/json" } },
80
+ { requestId: resp.headers.get("x-request-id") ?? "", status: resp.status, body: await resp.text() }
81
+ );
74
82
  }
75
83
  const payload = await resp.json();
76
84
  if (
@@ -92,6 +100,8 @@ export class BlackForestLabsTextToImageTask extends TaskProviderHelper implement
92
100
  return await image.blob();
93
101
  }
94
102
  }
95
- throw new InferenceOutputError("Failed to fetch result from black forest labs API");
103
+ throw new InferenceClientProviderOutputError(
104
+ `Timed out while waiting for the result from black forest labs API - aborting after 5 attempts`
105
+ );
96
106
  }
97
107
  }