@huggingface/inference 1.8.0 → 2.0.0-rc2

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 (34) hide show
  1. package/README.md +57 -8
  2. package/dist/index.js +440 -354
  3. package/dist/index.mjs +423 -353
  4. package/package.json +7 -9
  5. package/src/HfInference.ts +43 -1112
  6. package/src/index.ts +3 -1
  7. package/src/lib/InferenceOutputError.ts +8 -0
  8. package/src/lib/makeRequestOptions.ts +55 -0
  9. package/src/tasks/audio/audioClassification.ts +41 -0
  10. package/src/tasks/audio/automaticSpeechRecognition.ts +33 -0
  11. package/src/tasks/custom/request.ts +39 -0
  12. package/src/tasks/custom/streamingRequest.ts +76 -0
  13. package/src/tasks/cv/imageClassification.ts +40 -0
  14. package/src/tasks/cv/imageSegmentation.ts +45 -0
  15. package/src/tasks/cv/imageToText.ts +30 -0
  16. package/src/tasks/cv/objectDetection.ts +58 -0
  17. package/src/tasks/cv/textToImage.ts +48 -0
  18. package/src/tasks/index.ts +29 -0
  19. package/src/tasks/nlp/conversational.ts +81 -0
  20. package/src/tasks/nlp/featureExtraction.ts +51 -0
  21. package/src/tasks/nlp/fillMask.ts +48 -0
  22. package/src/tasks/nlp/questionAnswering.ts +48 -0
  23. package/src/tasks/nlp/sentenceSimilarity.ts +36 -0
  24. package/src/tasks/nlp/summarization.ts +59 -0
  25. package/src/tasks/nlp/tableQuestionAnswering.ts +58 -0
  26. package/src/tasks/nlp/textClassification.ts +37 -0
  27. package/src/tasks/nlp/textGeneration.ts +67 -0
  28. package/src/tasks/nlp/textGenerationStream.ts +92 -0
  29. package/src/tasks/nlp/tokenClassification.ts +78 -0
  30. package/src/tasks/nlp/translation.ts +29 -0
  31. package/src/tasks/nlp/zeroShotClassification.ts +55 -0
  32. package/src/types.ts +42 -0
  33. package/src/utils/distributive-omit.d.ts +15 -0
  34. package/dist/index.d.ts +0 -677
package/dist/index.js CHANGED
@@ -21,16 +21,117 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var src_exports = {};
22
22
  __export(src_exports, {
23
23
  HfInference: () => HfInference,
24
- TextGenerationStreamFinishReason: () => TextGenerationStreamFinishReason
24
+ HfInferenceEndpoint: () => HfInferenceEndpoint,
25
+ audioClassification: () => audioClassification,
26
+ automaticSpeechRecognition: () => automaticSpeechRecognition,
27
+ conversational: () => conversational,
28
+ featureExtraction: () => featureExtraction,
29
+ fillMask: () => fillMask,
30
+ imageClassification: () => imageClassification,
31
+ imageSegmentation: () => imageSegmentation,
32
+ imageToText: () => imageToText,
33
+ objectDetection: () => objectDetection,
34
+ questionAnswering: () => questionAnswering,
35
+ request: () => request,
36
+ sentenceSimilarity: () => sentenceSimilarity,
37
+ streamingRequest: () => streamingRequest,
38
+ summarization: () => summarization,
39
+ tableQuestionAnswering: () => tableQuestionAnswering,
40
+ textClassification: () => textClassification,
41
+ textGeneration: () => textGeneration,
42
+ textGenerationStream: () => textGenerationStream,
43
+ textToImage: () => textToImage,
44
+ tokenClassification: () => tokenClassification,
45
+ translation: () => translation,
46
+ zeroShotClassification: () => zeroShotClassification
25
47
  });
26
48
  module.exports = __toCommonJS(src_exports);
27
49
 
28
- // src/utils/toArray.ts
29
- function toArray(obj) {
30
- if (Array.isArray(obj)) {
31
- return obj;
50
+ // src/tasks/index.ts
51
+ var tasks_exports = {};
52
+ __export(tasks_exports, {
53
+ audioClassification: () => audioClassification,
54
+ automaticSpeechRecognition: () => automaticSpeechRecognition,
55
+ conversational: () => conversational,
56
+ featureExtraction: () => featureExtraction,
57
+ fillMask: () => fillMask,
58
+ imageClassification: () => imageClassification,
59
+ imageSegmentation: () => imageSegmentation,
60
+ imageToText: () => imageToText,
61
+ objectDetection: () => objectDetection,
62
+ questionAnswering: () => questionAnswering,
63
+ request: () => request,
64
+ sentenceSimilarity: () => sentenceSimilarity,
65
+ streamingRequest: () => streamingRequest,
66
+ summarization: () => summarization,
67
+ tableQuestionAnswering: () => tableQuestionAnswering,
68
+ textClassification: () => textClassification,
69
+ textGeneration: () => textGeneration,
70
+ textGenerationStream: () => textGenerationStream,
71
+ textToImage: () => textToImage,
72
+ tokenClassification: () => tokenClassification,
73
+ translation: () => translation,
74
+ zeroShotClassification: () => zeroShotClassification
75
+ });
76
+
77
+ // src/lib/makeRequestOptions.ts
78
+ var HF_INFERENCE_API_BASE_URL = "https://api-inference.huggingface.co/models/";
79
+ function makeRequestOptions(args, options) {
80
+ const { model, accessToken, ...otherArgs } = args;
81
+ const headers = {};
82
+ if (accessToken) {
83
+ headers["Authorization"] = `Bearer ${accessToken}`;
32
84
  }
33
- return [obj];
85
+ const binary = "data" in args && !!args.data;
86
+ if (!binary) {
87
+ headers["Content-Type"] = "application/json";
88
+ } else {
89
+ if (options?.wait_for_model) {
90
+ headers["X-Wait-For-Model"] = "true";
91
+ }
92
+ if (options?.use_cache === false) {
93
+ headers["X-Use-Cache"] = "false";
94
+ }
95
+ if (options?.dont_load_model) {
96
+ headers["X-Load-Model"] = "0";
97
+ }
98
+ }
99
+ const url = /^http(s?):/.test(model) ? model : `${HF_INFERENCE_API_BASE_URL}${model}`;
100
+ const info = {
101
+ headers,
102
+ method: "POST",
103
+ body: binary ? args.data : JSON.stringify({
104
+ ...otherArgs,
105
+ options
106
+ }),
107
+ credentials: options?.includeCredentials ? "include" : "same-origin"
108
+ };
109
+ return { url, info };
110
+ }
111
+
112
+ // src/tasks/custom/request.ts
113
+ async function request(args, options) {
114
+ const { url, info } = makeRequestOptions(args, options);
115
+ const response = await fetch(url, info);
116
+ if (options?.retry_on_error !== false && response.status === 503 && !options?.wait_for_model) {
117
+ return request(args, {
118
+ ...options,
119
+ wait_for_model: true
120
+ });
121
+ }
122
+ if (!response.ok) {
123
+ if (response.headers.get("Content-Type")?.startsWith("application/json")) {
124
+ const output = await response.json();
125
+ if (output.error) {
126
+ throw new Error(output.error);
127
+ }
128
+ }
129
+ throw new Error("An error occurred while fetching the blob");
130
+ }
131
+ if (response.headers.get("Content-Type")?.startsWith("application/json")) {
132
+ return await response.json();
133
+ }
134
+ return await response.blob();
34
135
  }
35
136
 
36
137
  // src/vendor/fetch-event-source/parse.ts
@@ -132,390 +233,375 @@ function newMessage() {
132
233
  };
133
234
  }
134
235
 
135
- // src/HfInference.ts
136
- var HF_INFERENCE_API_BASE_URL = "https://api-inference.huggingface.co/models/";
137
- var TextGenerationStreamFinishReason = /* @__PURE__ */ ((TextGenerationStreamFinishReason2) => {
138
- TextGenerationStreamFinishReason2["Length"] = "length";
139
- TextGenerationStreamFinishReason2["EndOfSequenceToken"] = "eos_token";
140
- TextGenerationStreamFinishReason2["StopSequence"] = "stop_sequence";
141
- return TextGenerationStreamFinishReason2;
142
- })(TextGenerationStreamFinishReason || {});
143
- var HfInference = class {
144
- apiKey;
145
- defaultOptions;
146
- constructor(apiKey = "", defaultOptions = {}) {
147
- this.apiKey = apiKey;
148
- this.defaultOptions = defaultOptions;
236
+ // src/tasks/custom/streamingRequest.ts
237
+ async function* streamingRequest(args, options) {
238
+ const { url, info } = makeRequestOptions({ ...args, stream: true }, options);
239
+ const response = await fetch(url, info);
240
+ if (options?.retry_on_error !== false && response.status === 503 && !options?.wait_for_model) {
241
+ return streamingRequest(args, {
242
+ ...options,
243
+ wait_for_model: true
244
+ });
149
245
  }
150
- /**
151
- * Tries to fill in a hole with a missing word (token to be precise). That’s the base task for BERT models.
152
- */
153
- async fillMask(args, options) {
154
- const res = await this.request(args, options);
155
- const isValidOutput = Array.isArray(res) && res.every(
156
- (x) => typeof x.score === "number" && typeof x.sequence === "string" && typeof x.token === "number" && typeof x.token_str === "string"
157
- );
158
- if (!isValidOutput) {
159
- throw new TypeError(
160
- "Invalid inference output: output must be of type Array<score: number, sequence:string, token:number, token_str:string>"
161
- );
246
+ if (!response.ok) {
247
+ if (response.headers.get("Content-Type")?.startsWith("application/json")) {
248
+ const output = await response.json();
249
+ if (output.error) {
250
+ throw new Error(output.error);
251
+ }
162
252
  }
163
- return res;
253
+ throw new Error(`Server response contains error: ${response.status}`);
164
254
  }
165
- /**
166
- * This task is well known to summarize longer text into shorter text. Be careful, some models have a maximum length of input. That means that the summary cannot handle full books for instance. Be careful when choosing your model.
167
- */
168
- async summarization(args, options) {
169
- const res = await this.request(args, options);
170
- const isValidOutput = Array.isArray(res) && res.every((x) => typeof x.summary_text === "string");
171
- if (!isValidOutput) {
172
- throw new TypeError("Invalid inference output: output must be of type Array<summary_text: string>");
173
- }
174
- return res?.[0];
255
+ if (response.headers.get("content-type") !== "text/event-stream") {
256
+ throw new Error(
257
+ `Server does not support event stream content type, it returned ` + response.headers.get("content-type")
258
+ );
175
259
  }
176
- /**
177
- * Want to have a nice know-it-all bot that can answer any question?. Recommended model: deepset/roberta-base-squad2
178
- */
179
- async questionAnswer(args, options) {
180
- const res = await this.request(args, options);
181
- const isValidOutput = typeof res.answer === "string" && typeof res.end === "number" && typeof res.score === "number" && typeof res.start === "number";
182
- if (!isValidOutput) {
183
- throw new TypeError(
184
- "Invalid inference output: output must be of type <answer: string, end: number, score: number, start: number>"
185
- );
186
- }
187
- return res;
260
+ if (!response.body) {
261
+ return;
188
262
  }
189
- /**
190
- * Don’t know SQL? Don’t want to dive into a large spreadsheet? Ask questions in plain english! Recommended model: google/tapas-base-finetuned-wtq.
191
- */
192
- async tableQuestionAnswer(args, options) {
193
- const res = await this.request(args, options);
194
- const isValidOutput = typeof res.aggregator === "string" && typeof res.answer === "string" && Array.isArray(res.cells) && res.cells.every((x) => typeof x === "string") && Array.isArray(res.coordinates) && res.coordinates.every((coord) => Array.isArray(coord) && coord.every((x) => typeof x === "number"));
195
- if (!isValidOutput) {
196
- throw new TypeError(
197
- "Invalid inference output: output must be of type <aggregator: string, answer: string, cells: string[], coordinates: number[][]>"
198
- );
263
+ const reader = response.body.getReader();
264
+ let events = [];
265
+ const onEvent = (event) => {
266
+ events.push(event);
267
+ };
268
+ const onChunk = getLines(
269
+ getMessages(
270
+ () => {
271
+ },
272
+ () => {
273
+ },
274
+ onEvent
275
+ )
276
+ );
277
+ try {
278
+ while (true) {
279
+ const { done, value } = await reader.read();
280
+ if (done)
281
+ return;
282
+ onChunk(value);
283
+ for (const event of events) {
284
+ if (event.data.length > 0) {
285
+ yield JSON.parse(event.data);
286
+ }
287
+ }
288
+ events = [];
199
289
  }
200
- return res;
290
+ } finally {
291
+ reader.releaseLock();
201
292
  }
202
- /**
203
- * Usually used for sentiment-analysis this will output the likelihood of classes of an input. Recommended model: distilbert-base-uncased-finetuned-sst-2-english
204
- */
205
- async textClassification(args, options) {
206
- const res = (await this.request(args, options))?.[0];
207
- const isValidOutput = Array.isArray(res) && res.every((x) => typeof x.label === "string" && typeof x.score === "number");
208
- if (!isValidOutput) {
209
- throw new TypeError("Invalid inference output: output must be of type Array<label: string, score: number>");
210
- }
211
- return res;
293
+ }
294
+
295
+ // src/lib/InferenceOutputError.ts
296
+ var InferenceOutputError = class extends TypeError {
297
+ constructor(message) {
298
+ super(
299
+ `Invalid inference output: ${message}. Use the 'request' method with the same parameters to do a custom call with no type checking.`
300
+ );
301
+ this.name = "InferenceOutputError";
212
302
  }
213
- /**
214
- * Use to continue text from a prompt. This is a very generic task. Recommended model: gpt2 (it’s a simple model, but fun to play with).
215
- */
216
- async textGeneration(args, options) {
217
- const res = await this.request(args, options);
218
- const isValidOutput = Array.isArray(res) && res.every((x) => typeof x.generated_text === "string");
219
- if (!isValidOutput) {
220
- throw new TypeError("Invalid inference output: output must be of type Array<generated_text: string>");
221
- }
222
- return res?.[0];
303
+ };
304
+
305
+ // src/tasks/audio/audioClassification.ts
306
+ async function audioClassification(args, options) {
307
+ const res = await request(args, options);
308
+ const isValidOutput = Array.isArray(res) && res.every((x) => typeof x.label === "string" && typeof x.score === "number");
309
+ if (!isValidOutput) {
310
+ throw new InferenceOutputError("Expected Array<{label: string, score: number}>");
223
311
  }
224
- /**
225
- * Use to continue text from a prompt. Same as `textGeneration` but returns generator that can be read one token at a time
226
- */
227
- async *textGenerationStream(args, options) {
228
- yield* this.streamingRequest(args, options);
312
+ return res;
313
+ }
314
+
315
+ // src/tasks/audio/automaticSpeechRecognition.ts
316
+ async function automaticSpeechRecognition(args, options) {
317
+ const res = await request(args, options);
318
+ const isValidOutput = typeof res?.text === "string";
319
+ if (!isValidOutput) {
320
+ throw new InferenceOutputError("Expected {text: string}");
229
321
  }
230
- /**
231
- * Usually used for sentence parsing, either grammatical, or Named Entity Recognition (NER) to understand keywords contained within text. Recommended model: dbmdz/bert-large-cased-finetuned-conll03-english
232
- */
233
- async tokenClassification(args, options) {
234
- const res = toArray(await this.request(args, options));
235
- const isValidOutput = Array.isArray(res) && res.every(
236
- (x) => typeof x.end === "number" && typeof x.entity_group === "string" && typeof x.score === "number" && typeof x.start === "number" && typeof x.word === "string"
237
- );
238
- if (!isValidOutput) {
239
- throw new TypeError(
240
- "Invalid inference output: output must be of type Array<end: number, entity_group: string, score: number, start: number, word: string>"
241
- );
242
- }
243
- return res;
322
+ return res;
323
+ }
324
+
325
+ // src/tasks/cv/imageClassification.ts
326
+ async function imageClassification(args, options) {
327
+ const res = await request(args, options);
328
+ const isValidOutput = Array.isArray(res) && res.every((x) => typeof x.label === "string" && typeof x.score === "number");
329
+ if (!isValidOutput) {
330
+ throw new InferenceOutputError("Expected Array<{label: string, score: number}>");
244
331
  }
245
- /**
246
- * This task is well known to translate text from one language to another. Recommended model: Helsinki-NLP/opus-mt-ru-en.
247
- */
248
- async translation(args, options) {
249
- const res = await this.request(args, options);
250
- const isValidOutput = Array.isArray(res) && res.every((x) => typeof x.translation_text === "string");
251
- if (!isValidOutput) {
252
- throw new TypeError("Invalid inference output: output must be of type Array<translation_text: string>");
253
- }
254
- return res?.[0];
332
+ return res;
333
+ }
334
+
335
+ // src/tasks/cv/imageSegmentation.ts
336
+ async function imageSegmentation(args, options) {
337
+ const res = await request(args, options);
338
+ const isValidOutput = Array.isArray(res) && res.every((x) => typeof x.label === "string" && typeof x.mask === "string" && typeof x.score === "number");
339
+ if (!isValidOutput) {
340
+ throw new InferenceOutputError("Expected Array<{label: string, mask: string, score: number}>");
255
341
  }
256
- /**
257
- * This task is super useful to try out classification with zero code, you simply pass a sentence/paragraph and the possible labels for that sentence, and you get a result. Recommended model: facebook/bart-large-mnli.
258
- */
259
- async zeroShotClassification(args, options) {
260
- const res = toArray(
261
- await this.request(args, options)
342
+ return res;
343
+ }
344
+
345
+ // src/tasks/cv/imageToText.ts
346
+ async function imageToText(args, options) {
347
+ const res = (await request(args, options))?.[0];
348
+ if (typeof res?.generated_text !== "string") {
349
+ throw new InferenceOutputError("Expected {generated_text: string}");
350
+ }
351
+ return res;
352
+ }
353
+
354
+ // src/tasks/cv/objectDetection.ts
355
+ async function objectDetection(args, options) {
356
+ const res = await request(args, options);
357
+ const isValidOutput = Array.isArray(res) && res.every(
358
+ (x) => typeof x.label === "string" && typeof x.score === "number" && typeof x.box.xmin === "number" && typeof x.box.ymin === "number" && typeof x.box.xmax === "number" && typeof x.box.ymax === "number"
359
+ );
360
+ if (!isValidOutput) {
361
+ throw new InferenceOutputError(
362
+ "Expected Array<{label:string; score:number; box:{xmin:number; ymin:number; xmax:number; ymax:number}}>"
262
363
  );
263
- const isValidOutput = Array.isArray(res) && res.every(
264
- (x) => Array.isArray(x.labels) && x.labels.every((_label) => typeof _label === "string") && Array.isArray(x.scores) && x.scores.every((_score) => typeof _score === "number") && typeof x.sequence === "string"
364
+ }
365
+ return res;
366
+ }
367
+
368
+ // src/tasks/cv/textToImage.ts
369
+ async function textToImage(args, options) {
370
+ const res = await request(args, options);
371
+ const isValidOutput = res && res instanceof Blob;
372
+ if (!isValidOutput) {
373
+ throw new InferenceOutputError("Expected Blob");
374
+ }
375
+ return res;
376
+ }
377
+
378
+ // src/tasks/nlp/conversational.ts
379
+ async function conversational(args, options) {
380
+ const res = await request(args, options);
381
+ const isValidOutput = Array.isArray(res.conversation.generated_responses) && res.conversation.generated_responses.every((x) => typeof x === "string") && Array.isArray(res.conversation.past_user_inputs) && res.conversation.past_user_inputs.every((x) => typeof x === "string") && typeof res.generated_text === "string" && Array.isArray(res.warnings) && res.warnings.every((x) => typeof x === "string");
382
+ if (!isValidOutput) {
383
+ throw new InferenceOutputError(
384
+ "Expected {conversation: {generated_responses: string[], past_user_inputs: string[]}, generated_text: string, warnings: string[]}"
265
385
  );
266
- if (!isValidOutput) {
267
- throw new TypeError(
268
- "Invalid inference output: output must be of type Array<labels: string[], scores: number[], sequence: string>"
269
- );
270
- }
271
- return res;
272
386
  }
273
- /**
274
- * This task corresponds to any chatbot like structure. Models tend to have shorter max_length, so please check with caution when using a given model if you need long range dependency or not. Recommended model: microsoft/DialoGPT-large.
275
- *
276
- */
277
- async conversational(args, options) {
278
- const res = await this.request(args, options);
279
- const isValidOutput = Array.isArray(res.conversation.generated_responses) && res.conversation.generated_responses.every((x) => typeof x === "string") && Array.isArray(res.conversation.past_user_inputs) && res.conversation.past_user_inputs.every((x) => typeof x === "string") && typeof res.generated_text === "string" && Array.isArray(res.warnings) && res.warnings.every((x) => typeof x === "string");
280
- if (!isValidOutput) {
281
- throw new TypeError(
282
- "Invalid inference output: output must be of type <conversation: {generated_responses: string[], past_user_inputs: string[]}, generated_text: string, warnings: string[]>"
283
- );
387
+ return res;
388
+ }
389
+
390
+ // src/tasks/nlp/featureExtraction.ts
391
+ async function featureExtraction(args, options) {
392
+ const res = await request(args, options);
393
+ let isValidOutput = true;
394
+ if (Array.isArray(res)) {
395
+ for (const e of res) {
396
+ if (Array.isArray(e)) {
397
+ isValidOutput = e.every((x) => typeof x === "number");
398
+ if (!isValidOutput) {
399
+ break;
400
+ }
401
+ } else if (typeof e !== "number") {
402
+ isValidOutput = false;
403
+ break;
404
+ }
284
405
  }
285
- return res;
406
+ } else {
407
+ isValidOutput = false;
286
408
  }
287
- /**
288
- * This task reads some text and outputs raw float values, that are usually consumed as part of a semantic database/semantic search.
289
- */
290
- async featureExtraction(args, options) {
291
- const res = await this.request(args, options);
292
- return res;
409
+ if (!isValidOutput) {
410
+ throw new InferenceOutputError("Expected Array<number[] | number>");
293
411
  }
294
- /**
295
- * This task reads some audio input and outputs the said words within the audio files.
296
- * Recommended model (english language): facebook/wav2vec2-large-960h-lv60-self
297
- */
298
- async automaticSpeechRecognition(args, options) {
299
- const res = await this.request(args, {
300
- ...options,
301
- binary: true
302
- });
303
- const isValidOutput = typeof res.text === "string";
304
- if (!isValidOutput) {
305
- throw new TypeError("Invalid inference output: output must be of type <text: string>");
306
- }
307
- return res;
412
+ return res;
413
+ }
414
+
415
+ // src/tasks/nlp/fillMask.ts
416
+ async function fillMask(args, options) {
417
+ const res = await request(args, options);
418
+ const isValidOutput = Array.isArray(res) && res.every(
419
+ (x) => typeof x.score === "number" && typeof x.sequence === "string" && typeof x.token === "number" && typeof x.token_str === "string"
420
+ );
421
+ if (!isValidOutput) {
422
+ throw new InferenceOutputError(
423
+ "Expected Array<{score: number, sequence: string, token: number, token_str: string}>"
424
+ );
308
425
  }
309
- /**
310
- * This task reads some audio input and outputs the likelihood of classes.
311
- * Recommended model: superb/hubert-large-superb-er
312
- */
313
- async audioClassification(args, options) {
314
- const res = await this.request(args, {
315
- ...options,
316
- binary: true
317
- });
318
- const isValidOutput = Array.isArray(res) && res.every((x) => typeof x.label === "string" && typeof x.score === "number");
319
- if (!isValidOutput) {
320
- throw new TypeError("Invalid inference output: output must be of type Array<label: string, score: number>");
321
- }
322
- return res;
426
+ return res;
427
+ }
428
+
429
+ // src/tasks/nlp/questionAnswering.ts
430
+ async function questionAnswering(args, options) {
431
+ const res = await request(args, options);
432
+ const isValidOutput = typeof res?.answer === "string" && typeof res.end === "number" && typeof res.score === "number" && typeof res.start === "number";
433
+ if (!isValidOutput) {
434
+ throw new InferenceOutputError("Expected {answer: string, end: number, score: number, start: number}");
323
435
  }
324
- /**
325
- * This task reads some image input and outputs the likelihood of classes.
326
- * Recommended model: google/vit-base-patch16-224
327
- */
328
- async imageClassification(args, options) {
329
- const res = await this.request(args, {
330
- ...options,
331
- binary: true
332
- });
333
- const isValidOutput = Array.isArray(res) && res.every((x) => typeof x.label === "string" && typeof x.score === "number");
334
- if (!isValidOutput) {
335
- throw new TypeError("Invalid inference output: output must be of type Array<label: string, score: number>");
336
- }
337
- return res;
436
+ return res;
437
+ }
438
+
439
+ // src/tasks/nlp/sentenceSimilarity.ts
440
+ async function sentenceSimilarity(args, options) {
441
+ const res = await request(args, options);
442
+ const isValidOutput = Array.isArray(res) && res.every((x) => typeof x === "number");
443
+ if (!isValidOutput) {
444
+ throw new InferenceOutputError("Expected number[]");
338
445
  }
339
- /**
340
- * This task reads some image input and outputs the likelihood of classes & bounding boxes of detected objects.
341
- * Recommended model: facebook/detr-resnet-50
342
- */
343
- async objectDetection(args, options) {
344
- const res = await this.request(args, {
345
- ...options,
346
- binary: true
347
- });
348
- const isValidOutput = Array.isArray(res) && res.every(
349
- (x) => typeof x.label === "string" && typeof x.score === "number" && typeof x.box.xmin === "number" && typeof x.box.ymin === "number" && typeof x.box.xmax === "number" && typeof x.box.ymax === "number"
446
+ return res;
447
+ }
448
+
449
+ // src/tasks/nlp/summarization.ts
450
+ async function summarization(args, options) {
451
+ const res = await request(args, options);
452
+ const isValidOutput = Array.isArray(res) && res.every((x) => typeof x?.summary_text === "string");
453
+ if (!isValidOutput) {
454
+ throw new InferenceOutputError("Expected Array<{summary_text: string}>");
455
+ }
456
+ return res?.[0];
457
+ }
458
+
459
+ // src/tasks/nlp/tableQuestionAnswering.ts
460
+ async function tableQuestionAnswering(args, options) {
461
+ const res = await request(args, options);
462
+ const isValidOutput = typeof res?.aggregator === "string" && typeof res.answer === "string" && Array.isArray(res.cells) && res.cells.every((x) => typeof x === "string") && Array.isArray(res.coordinates) && res.coordinates.every((coord) => Array.isArray(coord) && coord.every((x) => typeof x === "number"));
463
+ if (!isValidOutput) {
464
+ throw new InferenceOutputError(
465
+ "Expected {aggregator: string, answer: string, cells: string[], coordinates: number[][]}"
350
466
  );
351
- if (!isValidOutput) {
352
- throw new TypeError(
353
- "Invalid inference output: output must be of type Array<{label:string; score:number; box:{xmin:number; ymin:number; xmax:number; ymax:number}}>"
354
- );
355
- }
356
- return res;
357
467
  }
358
- /**
359
- * This task reads some image input and outputs the likelihood of classes & bounding boxes of detected objects.
360
- * Recommended model: facebook/detr-resnet-50-panoptic
361
- */
362
- async imageSegmentation(args, options) {
363
- const res = await this.request(args, {
364
- ...options,
365
- binary: true
366
- });
367
- const isValidOutput = Array.isArray(res) && res.every((x) => typeof x.label === "string" && typeof x.mask === "string" && typeof x.score === "number");
368
- if (!isValidOutput) {
369
- throw new TypeError(
370
- "Invalid inference output: output must be of type Array<label: string, mask: string, score: number>"
371
- );
372
- }
373
- return res;
468
+ return res;
469
+ }
470
+
471
+ // src/tasks/nlp/textClassification.ts
472
+ async function textClassification(args, options) {
473
+ const res = (await request(args, options))?.[0];
474
+ const isValidOutput = Array.isArray(res) && res.every((x) => typeof x?.label === "string" && typeof x.score === "number");
475
+ if (!isValidOutput) {
476
+ throw new InferenceOutputError("Expected Array<{label: string, score: number}>");
374
477
  }
375
- /**
376
- * This task reads some text input and outputs an image.
377
- * Recommended model: stabilityai/stable-diffusion-2
378
- */
379
- async textToImage(args, options) {
380
- const res = await this.request(args, {
381
- ...options,
382
- blob: true
383
- });
384
- const isValidOutput = res && res instanceof Blob;
385
- if (!isValidOutput) {
386
- throw new TypeError("Invalid inference output: output must be of type object & of instance Blob");
387
- }
388
- return res;
478
+ return res;
479
+ }
480
+
481
+ // src/tasks/nlp/textGeneration.ts
482
+ async function textGeneration(args, options) {
483
+ const res = await request(args, options);
484
+ const isValidOutput = Array.isArray(res) && res.every((x) => typeof x?.generated_text === "string");
485
+ if (!isValidOutput) {
486
+ throw new InferenceOutputError("Expected Array<{generated_text: string}>");
389
487
  }
390
- /**
391
- * This task reads some image input and outputs the text caption.
392
- */
393
- async imageToText(args, options) {
394
- return (await this.request(args, {
395
- ...options,
396
- binary: true
397
- }))?.[0];
488
+ return res?.[0];
489
+ }
490
+
491
+ // src/tasks/nlp/textGenerationStream.ts
492
+ async function* textGenerationStream(args, options) {
493
+ yield* streamingRequest(args, options);
494
+ }
495
+
496
+ // src/utils/toArray.ts
497
+ function toArray(obj) {
498
+ if (Array.isArray(obj)) {
499
+ return obj;
398
500
  }
399
- /**
400
- * Helper that prepares request arguments
401
- */
402
- makeRequestOptions(args, options) {
403
- const mergedOptions = { ...this.defaultOptions, ...options };
404
- const { model, ...otherArgs } = args;
405
- const headers = {};
406
- if (this.apiKey) {
407
- headers["Authorization"] = `Bearer ${this.apiKey}`;
408
- }
409
- if (!options?.binary) {
410
- headers["Content-Type"] = "application/json";
411
- }
412
- if (options?.binary) {
413
- if (mergedOptions.wait_for_model) {
414
- headers["X-Wait-For-Model"] = "true";
415
- }
416
- if (mergedOptions.use_cache === false) {
417
- headers["X-Use-Cache"] = "false";
418
- }
419
- if (mergedOptions.dont_load_model) {
420
- headers["X-Load-Model"] = "0";
421
- }
422
- }
423
- const url = `${HF_INFERENCE_API_BASE_URL}${model}`;
424
- const info = {
425
- headers,
426
- method: "POST",
427
- body: options?.binary ? args.data : JSON.stringify({
428
- ...otherArgs,
429
- options: mergedOptions
430
- }),
431
- credentials: options?.includeCredentials ? "include" : "same-origin"
432
- };
433
- return { url, info, mergedOptions };
434
- }
435
- async request(args, options) {
436
- const { url, info, mergedOptions } = this.makeRequestOptions(args, options);
437
- const response = await fetch(url, info);
438
- if (mergedOptions.retry_on_error !== false && response.status === 503 && !mergedOptions.wait_for_model) {
439
- return this.request(args, {
440
- ...mergedOptions,
441
- wait_for_model: true
501
+ return [obj];
502
+ }
503
+
504
+ // src/tasks/nlp/tokenClassification.ts
505
+ async function tokenClassification(args, options) {
506
+ const res = toArray(await request(args, options));
507
+ const isValidOutput = Array.isArray(res) && res.every(
508
+ (x) => typeof x.end === "number" && typeof x.entity_group === "string" && typeof x.score === "number" && typeof x.start === "number" && typeof x.word === "string"
509
+ );
510
+ if (!isValidOutput) {
511
+ throw new InferenceOutputError(
512
+ "Expected Array<{end: number, entity_group: string, score: number, start: number, word: string}>"
513
+ );
514
+ }
515
+ return res;
516
+ }
517
+
518
+ // src/tasks/nlp/translation.ts
519
+ async function translation(args, options) {
520
+ const res = await request(args, options);
521
+ const isValidOutput = Array.isArray(res) && res.every((x) => typeof x?.translation_text === "string");
522
+ if (!isValidOutput) {
523
+ throw new InferenceOutputError("Expected type Array<{translation_text: string}>");
524
+ }
525
+ return res?.[0];
526
+ }
527
+
528
+ // src/tasks/nlp/zeroShotClassification.ts
529
+ async function zeroShotClassification(args, options) {
530
+ const res = toArray(
531
+ await request(args, options)
532
+ );
533
+ const isValidOutput = Array.isArray(res) && res.every(
534
+ (x) => Array.isArray(x.labels) && x.labels.every((_label) => typeof _label === "string") && Array.isArray(x.scores) && x.scores.every((_score) => typeof _score === "number") && typeof x.sequence === "string"
535
+ );
536
+ if (!isValidOutput) {
537
+ throw new InferenceOutputError("Expected Array<{labels: string[], scores: number[], sequence: string}>");
538
+ }
539
+ return res;
540
+ }
541
+
542
+ // src/HfInference.ts
543
+ var HfInference = class {
544
+ accessToken;
545
+ defaultOptions;
546
+ constructor(accessToken = "", defaultOptions = {}) {
547
+ this.accessToken = accessToken;
548
+ this.defaultOptions = defaultOptions;
549
+ for (const [name, fn] of Object.entries(tasks_exports)) {
550
+ Object.defineProperty(this, name, {
551
+ enumerable: false,
552
+ value: (params, options) => (
553
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
554
+ fn({ ...params, accessToken }, { ...defaultOptions, ...options })
555
+ )
442
556
  });
443
557
  }
444
- if (options?.blob) {
445
- if (!response.ok) {
446
- throw new Error("An error occurred while fetching the blob");
447
- }
448
- return await response.blob();
449
- }
450
- const output = await response.json();
451
- if (output.error) {
452
- throw new Error(output.error);
453
- }
454
- return output;
455
558
  }
456
559
  /**
457
- * Make request that uses server-sent events and returns response as a generator
560
+ * Returns copy of HfInference tied to a specified endpoint.
458
561
  */
459
- async *streamingRequest(args, options) {
460
- const { url, info, mergedOptions } = this.makeRequestOptions({ ...args, stream: true }, options);
461
- const response = await fetch(url, info);
462
- if (mergedOptions.retry_on_error !== false && response.status === 503 && !mergedOptions.wait_for_model) {
463
- return this.streamingRequest(args, {
464
- ...mergedOptions,
465
- wait_for_model: true
562
+ endpoint(endpointUrl) {
563
+ return new HfInferenceEndpoint(endpointUrl, this.accessToken, this.defaultOptions);
564
+ }
565
+ };
566
+ var HfInferenceEndpoint = class {
567
+ constructor(endpointUrl, accessToken = "", defaultOptions = {}) {
568
+ accessToken;
569
+ defaultOptions;
570
+ for (const [name, fn] of Object.entries(tasks_exports)) {
571
+ Object.defineProperty(this, name, {
572
+ enumerable: false,
573
+ value: (params, options) => (
574
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
575
+ fn({ ...params, accessToken, model: endpointUrl }, { ...defaultOptions, ...options })
576
+ )
466
577
  });
467
578
  }
468
- if (!response.ok) {
469
- if (response.headers.get("Content-Type")?.startsWith("application/json")) {
470
- const output = await response.json();
471
- if (output.error) {
472
- throw new Error(output.error);
473
- }
474
- }
475
- throw new Error(`Server response contains error: ${response.status}`);
476
- }
477
- if (response.headers.get("content-type") !== "text/event-stream") {
478
- throw new Error(
479
- `Server does not support event stream content type, it returned ` + response.headers.get("content-type")
480
- );
481
- }
482
- if (!response.body) {
483
- return;
484
- }
485
- const reader = response.body.getReader();
486
- let events = [];
487
- const onEvent = (event) => {
488
- events.push(event);
489
- };
490
- const onChunk = getLines(
491
- getMessages(
492
- () => {
493
- },
494
- () => {
495
- },
496
- onEvent
497
- )
498
- );
499
- try {
500
- while (true) {
501
- const { done, value } = await reader.read();
502
- if (done)
503
- return;
504
- onChunk(value);
505
- for (const event of events) {
506
- if (event.data.length > 0) {
507
- yield JSON.parse(event.data);
508
- }
509
- }
510
- events = [];
511
- }
512
- } finally {
513
- reader.releaseLock();
514
- }
515
579
  }
516
580
  };
517
581
  // Annotate the CommonJS export names for ESM import in node:
518
582
  0 && (module.exports = {
519
583
  HfInference,
520
- TextGenerationStreamFinishReason
584
+ HfInferenceEndpoint,
585
+ audioClassification,
586
+ automaticSpeechRecognition,
587
+ conversational,
588
+ featureExtraction,
589
+ fillMask,
590
+ imageClassification,
591
+ imageSegmentation,
592
+ imageToText,
593
+ objectDetection,
594
+ questionAnswering,
595
+ request,
596
+ sentenceSimilarity,
597
+ streamingRequest,
598
+ summarization,
599
+ tableQuestionAnswering,
600
+ textClassification,
601
+ textGeneration,
602
+ textGenerationStream,
603
+ textToImage,
604
+ tokenClassification,
605
+ translation,
606
+ zeroShotClassification
521
607
  });