@huggingface/inference 1.6.2 → 1.6.3

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.
package/dist/index.js CHANGED
@@ -43,130 +43,235 @@ var HfInference = class {
43
43
  * Tries to fill in a hole with a missing word (token to be precise). That’s the base task for BERT models.
44
44
  */
45
45
  async fillMask(args, options) {
46
- return this.request(args, options);
46
+ const res = await this.request(args, options);
47
+ const isValidOutput = Array.isArray(res) && res.every(
48
+ (x) => typeof x.score === "number" && typeof x.sequence === "string" && typeof x.token === "number" && typeof x.token_str === "string"
49
+ );
50
+ if (!isValidOutput) {
51
+ throw new TypeError(
52
+ "Invalid inference output: output must be of type Array<score: number, sequence:string, token:number, token_str:string>"
53
+ );
54
+ }
55
+ return res;
47
56
  }
48
57
  /**
49
58
  * 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.
50
59
  */
51
60
  async summarization(args, options) {
52
- return (await this.request(args, options))?.[0];
61
+ const res = await this.request(args, options);
62
+ const isValidOutput = Array.isArray(res) && res.every((x) => typeof x.summary_text === "string");
63
+ if (!isValidOutput) {
64
+ throw new TypeError("Invalid inference output: output must be of type Array<summary_text: string>");
65
+ }
66
+ return res?.[0];
53
67
  }
54
68
  /**
55
69
  * Want to have a nice know-it-all bot that can answer any question?. Recommended model: deepset/roberta-base-squad2
56
70
  */
57
71
  async questionAnswer(args, options) {
58
- return await this.request(args, options);
72
+ const res = await this.request(args, options);
73
+ const isValidOutput = typeof res.answer === "string" && typeof res.end === "number" && typeof res.score === "number" && typeof res.start === "number";
74
+ if (!isValidOutput) {
75
+ throw new TypeError(
76
+ "Invalid inference output: output must be of type <answer: string, end: number, score: number, start: number>"
77
+ );
78
+ }
79
+ return res;
59
80
  }
60
81
  /**
61
82
  * 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.
62
83
  */
63
84
  async tableQuestionAnswer(args, options) {
64
- return await this.request(args, options);
85
+ const res = await this.request(args, options);
86
+ 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"));
87
+ if (!isValidOutput) {
88
+ throw new TypeError(
89
+ "Invalid inference output: output must be of type <aggregator: string, answer: string, cells: string[], coordinates: number[][]>"
90
+ );
91
+ }
92
+ return res;
65
93
  }
66
94
  /**
67
95
  * Usually used for sentiment-analysis this will output the likelihood of classes of an input. Recommended model: distilbert-base-uncased-finetuned-sst-2-english
68
96
  */
69
97
  async textClassification(args, options) {
70
- return (await this.request(args, options))?.[0];
98
+ const res = (await this.request(args, options))?.[0];
99
+ const isValidOutput = Array.isArray(res) && res.every((x) => typeof x.label === "string" && typeof x.score === "number");
100
+ if (!isValidOutput) {
101
+ throw new TypeError("Invalid inference output: output must be of type Array<label: string, score: number>");
102
+ }
103
+ return res;
71
104
  }
72
105
  /**
73
106
  * 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).
74
107
  */
75
108
  async textGeneration(args, options) {
76
- return (await this.request(args, options))?.[0];
109
+ const res = await this.request(args, options);
110
+ const isValidOutput = Array.isArray(res) && res.every((x) => typeof x.generated_text === "string");
111
+ if (!isValidOutput) {
112
+ throw new TypeError("Invalid inference output: output must be of type Array<generated_text: string>");
113
+ }
114
+ return res?.[0];
77
115
  }
78
116
  /**
79
117
  * 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
80
118
  */
81
119
  async tokenClassification(args, options) {
82
- return toArray(await this.request(args, options));
120
+ const res = toArray(await this.request(args, options));
121
+ const isValidOutput = Array.isArray(res) && res.every(
122
+ (x) => typeof x.end === "number" && typeof x.entity_group === "string" && typeof x.score === "number" && typeof x.start === "number" && typeof x.word === "string"
123
+ );
124
+ if (!isValidOutput) {
125
+ throw new TypeError(
126
+ "Invalid inference output: output must be of type Array<end: number, entity_group: string, score: number, start: number, word: string>"
127
+ );
128
+ }
129
+ return res;
83
130
  }
84
131
  /**
85
132
  * This task is well known to translate text from one language to another. Recommended model: Helsinki-NLP/opus-mt-ru-en.
86
133
  */
87
134
  async translation(args, options) {
88
- return (await this.request(args, options))?.[0];
135
+ const res = await this.request(args, options);
136
+ const isValidOutput = Array.isArray(res) && res.every((x) => typeof x.translation_text === "string");
137
+ if (!isValidOutput) {
138
+ throw new TypeError("Invalid inference output: output must be of type Array<translation_text: string>");
139
+ }
140
+ return res?.[0];
89
141
  }
90
142
  /**
91
143
  * 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.
92
144
  */
93
145
  async zeroShotClassification(args, options) {
94
- return toArray(
146
+ const res = toArray(
95
147
  await this.request(args, options)
96
148
  );
149
+ const isValidOutput = Array.isArray(res) && res.every(
150
+ (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"
151
+ );
152
+ if (!isValidOutput) {
153
+ throw new TypeError(
154
+ "Invalid inference output: output must be of type Array<labels: string[], scores: number[], sequence: string>"
155
+ );
156
+ }
157
+ return res;
97
158
  }
98
159
  /**
99
160
  * 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.
100
161
  *
101
162
  */
102
163
  async conversational(args, options) {
103
- return await this.request(args, options);
164
+ const res = await this.request(args, options);
165
+ 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");
166
+ if (!isValidOutput) {
167
+ throw new TypeError(
168
+ "Invalid inference output: output must be of type <conversation: {generated_responses: string[], past_user_inputs: string[]}, generated_text: string, warnings: string[]>"
169
+ );
170
+ }
171
+ return res;
104
172
  }
105
173
  /**
106
174
  * This task reads some text and outputs raw float values, that are usually consumed as part of a semantic database/semantic search.
107
175
  */
108
176
  async featureExtraction(args, options) {
109
- return await this.request(args, options);
177
+ const res = await this.request(args, options);
178
+ return res;
110
179
  }
111
180
  /**
112
181
  * This task reads some audio input and outputs the said words within the audio files.
113
182
  * Recommended model (english language): facebook/wav2vec2-large-960h-lv60-self
114
183
  */
115
184
  async automaticSpeechRecognition(args, options) {
116
- return await this.request(args, {
185
+ const res = await this.request(args, {
117
186
  ...options,
118
187
  binary: true
119
188
  });
189
+ const isValidOutput = typeof res.text === "string";
190
+ if (!isValidOutput) {
191
+ throw new TypeError("Invalid inference output: output must be of type <text: string>");
192
+ }
193
+ return res;
120
194
  }
121
195
  /**
122
196
  * This task reads some audio input and outputs the likelihood of classes.
123
197
  * Recommended model: superb/hubert-large-superb-er
124
198
  */
125
199
  async audioClassification(args, options) {
126
- return await this.request(args, {
200
+ const res = await this.request(args, {
127
201
  ...options,
128
202
  binary: true
129
203
  });
204
+ const isValidOutput = Array.isArray(res) && res.every((x) => typeof x.label === "string" && typeof x.score === "number");
205
+ if (!isValidOutput) {
206
+ throw new TypeError("Invalid inference output: output must be of type Array<label: string, score: number>");
207
+ }
208
+ return res;
130
209
  }
131
210
  /**
132
211
  * This task reads some image input and outputs the likelihood of classes.
133
212
  * Recommended model: google/vit-base-patch16-224
134
213
  */
135
214
  async imageClassification(args, options) {
136
- return await this.request(args, {
215
+ const res = await this.request(args, {
137
216
  ...options,
138
217
  binary: true
139
218
  });
219
+ const isValidOutput = Array.isArray(res) && res.every((x) => typeof x.label === "string" && typeof x.score === "number");
220
+ if (!isValidOutput) {
221
+ throw new TypeError("Invalid inference output: output must be of type Array<label: string, score: number>");
222
+ }
223
+ return res;
140
224
  }
141
225
  /**
142
226
  * This task reads some image input and outputs the likelihood of classes & bounding boxes of detected objects.
143
227
  * Recommended model: facebook/detr-resnet-50
144
228
  */
145
229
  async objectDetection(args, options) {
146
- return await this.request(args, {
230
+ const res = await this.request(args, {
147
231
  ...options,
148
232
  binary: true
149
233
  });
234
+ const isValidOutput = Array.isArray(res) && res.every(
235
+ (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"
236
+ );
237
+ if (!isValidOutput) {
238
+ throw new TypeError(
239
+ "Invalid inference output: output must be of type Array<{label:string; score:number; box:{xmin:number; ymin:number; xmax:number; ymax:number}}>"
240
+ );
241
+ }
242
+ return res;
150
243
  }
151
244
  /**
152
245
  * This task reads some image input and outputs the likelihood of classes & bounding boxes of detected objects.
153
246
  * Recommended model: facebook/detr-resnet-50-panoptic
154
247
  */
155
248
  async imageSegmentation(args, options) {
156
- return await this.request(args, {
249
+ const res = await this.request(args, {
157
250
  ...options,
158
251
  binary: true
159
252
  });
253
+ const isValidOutput = Array.isArray(res) && res.every((x) => typeof x.label === "string" && typeof x.mask === "string" && typeof x.score === "number");
254
+ if (!isValidOutput) {
255
+ throw new TypeError(
256
+ "Invalid inference output: output must be of type Array<label: string, mask: string, score: number>"
257
+ );
258
+ }
259
+ return res;
160
260
  }
161
261
  /**
162
262
  * This task reads some text input and outputs an image.
163
263
  * Recommended model: stabilityai/stable-diffusion-2
164
264
  */
165
265
  async textToImage(args, options) {
166
- return await this.request(args, {
266
+ const res = await this.request(args, {
167
267
  ...options,
168
268
  blob: true
169
269
  });
270
+ const isValidOutput = res && res instanceof Blob;
271
+ if (!isValidOutput) {
272
+ throw new TypeError("Invalid inference output: output must be of type object & of instance Blob");
273
+ }
274
+ return res;
170
275
  }
171
276
  async request(args, options) {
172
277
  const mergedOptions = { ...this.defaultOptions, ...options };
package/dist/index.mjs CHANGED
@@ -18,130 +18,235 @@ var HfInference = class {
18
18
  * Tries to fill in a hole with a missing word (token to be precise). That’s the base task for BERT models.
19
19
  */
20
20
  async fillMask(args, options) {
21
- return this.request(args, options);
21
+ const res = await this.request(args, options);
22
+ const isValidOutput = Array.isArray(res) && res.every(
23
+ (x) => typeof x.score === "number" && typeof x.sequence === "string" && typeof x.token === "number" && typeof x.token_str === "string"
24
+ );
25
+ if (!isValidOutput) {
26
+ throw new TypeError(
27
+ "Invalid inference output: output must be of type Array<score: number, sequence:string, token:number, token_str:string>"
28
+ );
29
+ }
30
+ return res;
22
31
  }
23
32
  /**
24
33
  * 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.
25
34
  */
26
35
  async summarization(args, options) {
27
- return (await this.request(args, options))?.[0];
36
+ const res = await this.request(args, options);
37
+ const isValidOutput = Array.isArray(res) && res.every((x) => typeof x.summary_text === "string");
38
+ if (!isValidOutput) {
39
+ throw new TypeError("Invalid inference output: output must be of type Array<summary_text: string>");
40
+ }
41
+ return res?.[0];
28
42
  }
29
43
  /**
30
44
  * Want to have a nice know-it-all bot that can answer any question?. Recommended model: deepset/roberta-base-squad2
31
45
  */
32
46
  async questionAnswer(args, options) {
33
- return await this.request(args, options);
47
+ const res = await this.request(args, options);
48
+ const isValidOutput = typeof res.answer === "string" && typeof res.end === "number" && typeof res.score === "number" && typeof res.start === "number";
49
+ if (!isValidOutput) {
50
+ throw new TypeError(
51
+ "Invalid inference output: output must be of type <answer: string, end: number, score: number, start: number>"
52
+ );
53
+ }
54
+ return res;
34
55
  }
35
56
  /**
36
57
  * 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.
37
58
  */
38
59
  async tableQuestionAnswer(args, options) {
39
- return await this.request(args, options);
60
+ const res = await this.request(args, options);
61
+ 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"));
62
+ if (!isValidOutput) {
63
+ throw new TypeError(
64
+ "Invalid inference output: output must be of type <aggregator: string, answer: string, cells: string[], coordinates: number[][]>"
65
+ );
66
+ }
67
+ return res;
40
68
  }
41
69
  /**
42
70
  * Usually used for sentiment-analysis this will output the likelihood of classes of an input. Recommended model: distilbert-base-uncased-finetuned-sst-2-english
43
71
  */
44
72
  async textClassification(args, options) {
45
- return (await this.request(args, options))?.[0];
73
+ const res = (await this.request(args, options))?.[0];
74
+ const isValidOutput = Array.isArray(res) && res.every((x) => typeof x.label === "string" && typeof x.score === "number");
75
+ if (!isValidOutput) {
76
+ throw new TypeError("Invalid inference output: output must be of type Array<label: string, score: number>");
77
+ }
78
+ return res;
46
79
  }
47
80
  /**
48
81
  * 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).
49
82
  */
50
83
  async textGeneration(args, options) {
51
- return (await this.request(args, options))?.[0];
84
+ const res = await this.request(args, options);
85
+ const isValidOutput = Array.isArray(res) && res.every((x) => typeof x.generated_text === "string");
86
+ if (!isValidOutput) {
87
+ throw new TypeError("Invalid inference output: output must be of type Array<generated_text: string>");
88
+ }
89
+ return res?.[0];
52
90
  }
53
91
  /**
54
92
  * 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
55
93
  */
56
94
  async tokenClassification(args, options) {
57
- return toArray(await this.request(args, options));
95
+ const res = toArray(await this.request(args, options));
96
+ const isValidOutput = Array.isArray(res) && res.every(
97
+ (x) => typeof x.end === "number" && typeof x.entity_group === "string" && typeof x.score === "number" && typeof x.start === "number" && typeof x.word === "string"
98
+ );
99
+ if (!isValidOutput) {
100
+ throw new TypeError(
101
+ "Invalid inference output: output must be of type Array<end: number, entity_group: string, score: number, start: number, word: string>"
102
+ );
103
+ }
104
+ return res;
58
105
  }
59
106
  /**
60
107
  * This task is well known to translate text from one language to another. Recommended model: Helsinki-NLP/opus-mt-ru-en.
61
108
  */
62
109
  async translation(args, options) {
63
- return (await this.request(args, options))?.[0];
110
+ const res = await this.request(args, options);
111
+ const isValidOutput = Array.isArray(res) && res.every((x) => typeof x.translation_text === "string");
112
+ if (!isValidOutput) {
113
+ throw new TypeError("Invalid inference output: output must be of type Array<translation_text: string>");
114
+ }
115
+ return res?.[0];
64
116
  }
65
117
  /**
66
118
  * 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.
67
119
  */
68
120
  async zeroShotClassification(args, options) {
69
- return toArray(
121
+ const res = toArray(
70
122
  await this.request(args, options)
71
123
  );
124
+ const isValidOutput = Array.isArray(res) && res.every(
125
+ (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"
126
+ );
127
+ if (!isValidOutput) {
128
+ throw new TypeError(
129
+ "Invalid inference output: output must be of type Array<labels: string[], scores: number[], sequence: string>"
130
+ );
131
+ }
132
+ return res;
72
133
  }
73
134
  /**
74
135
  * 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.
75
136
  *
76
137
  */
77
138
  async conversational(args, options) {
78
- return await this.request(args, options);
139
+ const res = await this.request(args, options);
140
+ 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");
141
+ if (!isValidOutput) {
142
+ throw new TypeError(
143
+ "Invalid inference output: output must be of type <conversation: {generated_responses: string[], past_user_inputs: string[]}, generated_text: string, warnings: string[]>"
144
+ );
145
+ }
146
+ return res;
79
147
  }
80
148
  /**
81
149
  * This task reads some text and outputs raw float values, that are usually consumed as part of a semantic database/semantic search.
82
150
  */
83
151
  async featureExtraction(args, options) {
84
- return await this.request(args, options);
152
+ const res = await this.request(args, options);
153
+ return res;
85
154
  }
86
155
  /**
87
156
  * This task reads some audio input and outputs the said words within the audio files.
88
157
  * Recommended model (english language): facebook/wav2vec2-large-960h-lv60-self
89
158
  */
90
159
  async automaticSpeechRecognition(args, options) {
91
- return await this.request(args, {
160
+ const res = await this.request(args, {
92
161
  ...options,
93
162
  binary: true
94
163
  });
164
+ const isValidOutput = typeof res.text === "string";
165
+ if (!isValidOutput) {
166
+ throw new TypeError("Invalid inference output: output must be of type <text: string>");
167
+ }
168
+ return res;
95
169
  }
96
170
  /**
97
171
  * This task reads some audio input and outputs the likelihood of classes.
98
172
  * Recommended model: superb/hubert-large-superb-er
99
173
  */
100
174
  async audioClassification(args, options) {
101
- return await this.request(args, {
175
+ const res = await this.request(args, {
102
176
  ...options,
103
177
  binary: true
104
178
  });
179
+ const isValidOutput = Array.isArray(res) && res.every((x) => typeof x.label === "string" && typeof x.score === "number");
180
+ if (!isValidOutput) {
181
+ throw new TypeError("Invalid inference output: output must be of type Array<label: string, score: number>");
182
+ }
183
+ return res;
105
184
  }
106
185
  /**
107
186
  * This task reads some image input and outputs the likelihood of classes.
108
187
  * Recommended model: google/vit-base-patch16-224
109
188
  */
110
189
  async imageClassification(args, options) {
111
- return await this.request(args, {
190
+ const res = await this.request(args, {
112
191
  ...options,
113
192
  binary: true
114
193
  });
194
+ const isValidOutput = Array.isArray(res) && res.every((x) => typeof x.label === "string" && typeof x.score === "number");
195
+ if (!isValidOutput) {
196
+ throw new TypeError("Invalid inference output: output must be of type Array<label: string, score: number>");
197
+ }
198
+ return res;
115
199
  }
116
200
  /**
117
201
  * This task reads some image input and outputs the likelihood of classes & bounding boxes of detected objects.
118
202
  * Recommended model: facebook/detr-resnet-50
119
203
  */
120
204
  async objectDetection(args, options) {
121
- return await this.request(args, {
205
+ const res = await this.request(args, {
122
206
  ...options,
123
207
  binary: true
124
208
  });
209
+ const isValidOutput = Array.isArray(res) && res.every(
210
+ (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"
211
+ );
212
+ if (!isValidOutput) {
213
+ throw new TypeError(
214
+ "Invalid inference output: output must be of type Array<{label:string; score:number; box:{xmin:number; ymin:number; xmax:number; ymax:number}}>"
215
+ );
216
+ }
217
+ return res;
125
218
  }
126
219
  /**
127
220
  * This task reads some image input and outputs the likelihood of classes & bounding boxes of detected objects.
128
221
  * Recommended model: facebook/detr-resnet-50-panoptic
129
222
  */
130
223
  async imageSegmentation(args, options) {
131
- return await this.request(args, {
224
+ const res = await this.request(args, {
132
225
  ...options,
133
226
  binary: true
134
227
  });
228
+ const isValidOutput = Array.isArray(res) && res.every((x) => typeof x.label === "string" && typeof x.mask === "string" && typeof x.score === "number");
229
+ if (!isValidOutput) {
230
+ throw new TypeError(
231
+ "Invalid inference output: output must be of type Array<label: string, mask: string, score: number>"
232
+ );
233
+ }
234
+ return res;
135
235
  }
136
236
  /**
137
237
  * This task reads some text input and outputs an image.
138
238
  * Recommended model: stabilityai/stable-diffusion-2
139
239
  */
140
240
  async textToImage(args, options) {
141
- return await this.request(args, {
241
+ const res = await this.request(args, {
142
242
  ...options,
143
243
  blob: true
144
244
  });
245
+ const isValidOutput = res && res instanceof Blob;
246
+ if (!isValidOutput) {
247
+ throw new TypeError("Invalid inference output: output must be of type object & of instance Blob");
248
+ }
249
+ return res;
145
250
  }
146
251
  async request(args, options) {
147
252
  const mergedOptions = { ...this.defaultOptions, ...options };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@huggingface/inference",
3
- "version": "1.6.2",
3
+ "version": "1.6.3",
4
4
  "license": "MIT",
5
5
  "author": "Tim Mikeladze <tim.mikeladze@gmail.com>",
6
6
  "description": "Typescript wrapper for the Hugging Face Inference API",
@@ -519,21 +519,52 @@ export class HfInference {
519
519
  * Tries to fill in a hole with a missing word (token to be precise). That’s the base task for BERT models.
520
520
  */
521
521
  public async fillMask(args: FillMaskArgs, options?: Options): Promise<FillMaskReturn> {
522
- return this.request(args, options);
522
+ const res = await this.request<FillMaskReturn>(args, options);
523
+ const isValidOutput =
524
+ Array.isArray(res) &&
525
+ res.every(
526
+ (x) =>
527
+ typeof x.score === "number" &&
528
+ typeof x.sequence === "string" &&
529
+ typeof x.token === "number" &&
530
+ typeof x.token_str === "string"
531
+ );
532
+ if (!isValidOutput) {
533
+ throw new TypeError(
534
+ "Invalid inference output: output must be of type Array<score: number, sequence:string, token:number, token_str:string>"
535
+ );
536
+ }
537
+ return res;
523
538
  }
524
539
 
525
540
  /**
526
541
  * 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.
527
542
  */
528
543
  public async summarization(args: SummarizationArgs, options?: Options): Promise<SummarizationReturn> {
529
- return (await this.request<SummarizationReturn[]>(args, options))?.[0];
544
+ const res = await this.request<SummarizationReturn[]>(args, options);
545
+ const isValidOutput = Array.isArray(res) && res.every((x) => typeof x.summary_text === "string");
546
+ if (!isValidOutput) {
547
+ throw new TypeError("Invalid inference output: output must be of type Array<summary_text: string>");
548
+ }
549
+ return res?.[0];
530
550
  }
531
551
 
532
552
  /**
533
553
  * Want to have a nice know-it-all bot that can answer any question?. Recommended model: deepset/roberta-base-squad2
534
554
  */
535
555
  public async questionAnswer(args: QuestionAnswerArgs, options?: Options): Promise<QuestionAnswerReturn> {
536
- return await this.request(args, options);
556
+ const res = await this.request<QuestionAnswerReturn>(args, options);
557
+ const isValidOutput =
558
+ typeof res.answer === "string" &&
559
+ typeof res.end === "number" &&
560
+ typeof res.score === "number" &&
561
+ typeof res.start === "number";
562
+ if (!isValidOutput) {
563
+ throw new TypeError(
564
+ "Invalid inference output: output must be of type <answer: string, end: number, score: number, start: number>"
565
+ );
566
+ }
567
+ return res;
537
568
  }
538
569
 
539
570
  /**
@@ -543,21 +574,45 @@ export class HfInference {
543
574
  args: TableQuestionAnswerArgs,
544
575
  options?: Options
545
576
  ): Promise<TableQuestionAnswerReturn> {
546
- return await this.request(args, options);
577
+ const res = await this.request<TableQuestionAnswerReturn>(args, options);
578
+ const isValidOutput =
579
+ typeof res.aggregator === "string" &&
580
+ typeof res.answer === "string" &&
581
+ Array.isArray(res.cells) &&
582
+ res.cells.every((x) => typeof x === "string") &&
583
+ Array.isArray(res.coordinates) &&
584
+ res.coordinates.every((coord) => Array.isArray(coord) && coord.every((x) => typeof x === "number"));
585
+ if (!isValidOutput) {
586
+ throw new TypeError(
587
+ "Invalid inference output: output must be of type <aggregator: string, answer: string, cells: string[], coordinates: number[][]>"
588
+ );
589
+ }
590
+ return res;
547
591
  }
548
592
 
549
593
  /**
550
594
  * Usually used for sentiment-analysis this will output the likelihood of classes of an input. Recommended model: distilbert-base-uncased-finetuned-sst-2-english
551
595
  */
552
596
  public async textClassification(args: TextClassificationArgs, options?: Options): Promise<TextClassificationReturn> {
553
- return (await this.request<TextClassificationReturn[]>(args, options))?.[0];
597
+ const res = (await this.request<TextClassificationReturn[]>(args, options))?.[0];
598
+ const isValidOutput =
599
+ Array.isArray(res) && res.every((x) => typeof x.label === "string" && typeof x.score === "number");
600
+ if (!isValidOutput) {
601
+ throw new TypeError("Invalid inference output: output must be of type Array<label: string, score: number>");
602
+ }
603
+ return res;
554
604
  }
555
605
 
556
606
  /**
557
607
  * 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).
558
608
  */
559
609
  public async textGeneration(args: TextGenerationArgs, options?: Options): Promise<TextGenerationReturn> {
560
- return (await this.request<TextGenerationReturn[]>(args, options))?.[0];
610
+ const res = await this.request<TextGenerationReturn[]>(args, options);
611
+ const isValidOutput = Array.isArray(res) && res.every((x) => typeof x.generated_text === "string");
612
+ if (!isValidOutput) {
613
+ throw new TypeError("Invalid inference output: output must be of type Array<generated_text: string>");
614
+ }
615
+ return res?.[0];
561
616
  }
562
617
 
563
618
  /**
@@ -567,14 +622,35 @@ export class HfInference {
567
622
  args: TokenClassificationArgs,
568
623
  options?: Options
569
624
  ): Promise<TokenClassificationReturn> {
570
- return toArray(await this.request(args, options));
625
+ const res = toArray(await this.request<TokenClassificationReturnValue | TokenClassificationReturn>(args, options));
626
+ const isValidOutput =
627
+ Array.isArray(res) &&
628
+ res.every(
629
+ (x) =>
630
+ typeof x.end === "number" &&
631
+ typeof x.entity_group === "string" &&
632
+ typeof x.score === "number" &&
633
+ typeof x.start === "number" &&
634
+ typeof x.word === "string"
635
+ );
636
+ if (!isValidOutput) {
637
+ throw new TypeError(
638
+ "Invalid inference output: output must be of type Array<end: number, entity_group: string, score: number, start: number, word: string>"
639
+ );
640
+ }
641
+ return res;
571
642
  }
572
643
 
573
644
  /**
574
645
  * This task is well known to translate text from one language to another. Recommended model: Helsinki-NLP/opus-mt-ru-en.
575
646
  */
576
647
  public async translation(args: TranslationArgs, options?: Options): Promise<TranslationReturn> {
577
- return (await this.request<TranslationReturn[]>(args, options))?.[0];
648
+ const res = await this.request<TranslationReturn[]>(args, options);
649
+ const isValidOutput = Array.isArray(res) && res.every((x) => typeof x.translation_text === "string");
650
+ if (!isValidOutput) {
651
+ throw new TypeError("Invalid inference output: output must be of type Array<translation_text: string>");
652
+ }
653
+ return res?.[0];
578
654
  }
579
655
 
580
656
  /**
@@ -584,9 +660,25 @@ export class HfInference {
584
660
  args: ZeroShotClassificationArgs,
585
661
  options?: Options
586
662
  ): Promise<ZeroShotClassificationReturn> {
587
- return toArray(
588
- await this.request<ZeroShotClassificationReturnValue | ZeroShotClassificationReturnValue[]>(args, options)
663
+ const res = toArray(
664
+ await this.request<ZeroShotClassificationReturnValue | ZeroShotClassificationReturn>(args, options)
589
665
  );
666
+ const isValidOutput =
667
+ Array.isArray(res) &&
668
+ res.every(
669
+ (x) =>
670
+ Array.isArray(x.labels) &&
671
+ x.labels.every((_label) => typeof _label === "string") &&
672
+ Array.isArray(x.scores) &&
673
+ x.scores.every((_score) => typeof _score === "number") &&
674
+ typeof x.sequence === "string"
675
+ );
676
+ if (!isValidOutput) {
677
+ throw new TypeError(
678
+ "Invalid inference output: output must be of type Array<labels: string[], scores: number[], sequence: string>"
679
+ );
680
+ }
681
+ return res;
590
682
  }
591
683
 
592
684
  /**
@@ -594,14 +686,29 @@ export class HfInference {
594
686
  *
595
687
  */
596
688
  public async conversational(args: ConversationalArgs, options?: Options): Promise<ConversationalReturn> {
597
- return await this.request(args, options);
689
+ const res = await this.request<ConversationalReturn>(args, options);
690
+ const isValidOutput =
691
+ Array.isArray(res.conversation.generated_responses) &&
692
+ res.conversation.generated_responses.every((x) => typeof x === "string") &&
693
+ Array.isArray(res.conversation.past_user_inputs) &&
694
+ res.conversation.past_user_inputs.every((x) => typeof x === "string") &&
695
+ typeof res.generated_text === "string" &&
696
+ Array.isArray(res.warnings) &&
697
+ res.warnings.every((x) => typeof x === "string");
698
+ if (!isValidOutput) {
699
+ throw new TypeError(
700
+ "Invalid inference output: output must be of type <conversation: {generated_responses: string[], past_user_inputs: string[]}, generated_text: string, warnings: string[]>"
701
+ );
702
+ }
703
+ return res;
598
704
  }
599
705
 
600
706
  /**
601
707
  * This task reads some text and outputs raw float values, that are usually consumed as part of a semantic database/semantic search.
602
708
  */
603
709
  public async featureExtraction(args: FeatureExtractionArgs, options?: Options): Promise<FeatureExtractionReturn> {
604
- return await this.request(args, options);
710
+ const res = await this.request<FeatureExtractionReturn>(args, options);
711
+ return res;
605
712
  }
606
713
 
607
714
  /**
@@ -612,10 +719,15 @@ export class HfInference {
612
719
  args: AutomaticSpeechRecognitionArgs,
613
720
  options?: Options
614
721
  ): Promise<AutomaticSpeechRecognitionReturn> {
615
- return await this.request(args, {
722
+ const res = await this.request<AutomaticSpeechRecognitionReturn>(args, {
616
723
  ...options,
617
724
  binary: true,
618
725
  });
726
+ const isValidOutput = typeof res.text === "string";
727
+ if (!isValidOutput) {
728
+ throw new TypeError("Invalid inference output: output must be of type <text: string>");
729
+ }
730
+ return res;
619
731
  }
620
732
 
621
733
  /**
@@ -626,10 +738,16 @@ export class HfInference {
626
738
  args: AudioClassificationArgs,
627
739
  options?: Options
628
740
  ): Promise<AudioClassificationReturn> {
629
- return await this.request(args, {
741
+ const res = await this.request<AudioClassificationReturn>(args, {
630
742
  ...options,
631
743
  binary: true,
632
744
  });
745
+ const isValidOutput =
746
+ Array.isArray(res) && res.every((x) => typeof x.label === "string" && typeof x.score === "number");
747
+ if (!isValidOutput) {
748
+ throw new TypeError("Invalid inference output: output must be of type Array<label: string, score: number>");
749
+ }
750
+ return res;
633
751
  }
634
752
 
635
753
  /**
@@ -640,10 +758,16 @@ export class HfInference {
640
758
  args: ImageClassificationArgs,
641
759
  options?: Options
642
760
  ): Promise<ImageClassificationReturn> {
643
- return await this.request(args, {
761
+ const res = await this.request<ImageClassificationReturn>(args, {
644
762
  ...options,
645
763
  binary: true,
646
764
  });
765
+ const isValidOutput =
766
+ Array.isArray(res) && res.every((x) => typeof x.label === "string" && typeof x.score === "number");
767
+ if (!isValidOutput) {
768
+ throw new TypeError("Invalid inference output: output must be of type Array<label: string, score: number>");
769
+ }
770
+ return res;
647
771
  }
648
772
 
649
773
  /**
@@ -651,10 +775,27 @@ export class HfInference {
651
775
  * Recommended model: facebook/detr-resnet-50
652
776
  */
653
777
  public async objectDetection(args: ObjectDetectionArgs, options?: Options): Promise<ObjectDetectionReturn> {
654
- return await this.request(args, {
778
+ const res = await this.request<ObjectDetectionReturn>(args, {
655
779
  ...options,
656
780
  binary: true,
657
781
  });
782
+ const isValidOutput =
783
+ Array.isArray(res) &&
784
+ res.every(
785
+ (x) =>
786
+ typeof x.label === "string" &&
787
+ typeof x.score === "number" &&
788
+ typeof x.box.xmin === "number" &&
789
+ typeof x.box.ymin === "number" &&
790
+ typeof x.box.xmax === "number" &&
791
+ typeof x.box.ymax === "number"
792
+ );
793
+ if (!isValidOutput) {
794
+ throw new TypeError(
795
+ "Invalid inference output: output must be of type Array<{label:string; score:number; box:{xmin:number; ymin:number; xmax:number; ymax:number}}>"
796
+ );
797
+ }
798
+ return res;
658
799
  }
659
800
 
660
801
  /**
@@ -662,10 +803,19 @@ export class HfInference {
662
803
  * Recommended model: facebook/detr-resnet-50-panoptic
663
804
  */
664
805
  public async imageSegmentation(args: ImageSegmentationArgs, options?: Options): Promise<ImageSegmentationReturn> {
665
- return await this.request(args, {
806
+ const res = await this.request<ImageSegmentationReturn>(args, {
666
807
  ...options,
667
808
  binary: true,
668
809
  });
810
+ const isValidOutput =
811
+ Array.isArray(res) &&
812
+ res.every((x) => typeof x.label === "string" && typeof x.mask === "string" && typeof x.score === "number");
813
+ if (!isValidOutput) {
814
+ throw new TypeError(
815
+ "Invalid inference output: output must be of type Array<label: string, mask: string, score: number>"
816
+ );
817
+ }
818
+ return res;
669
819
  }
670
820
 
671
821
  /**
@@ -673,10 +823,15 @@ export class HfInference {
673
823
  * Recommended model: stabilityai/stable-diffusion-2
674
824
  */
675
825
  public async textToImage(args: TextToImageArgs, options?: Options): Promise<TextToImageReturn> {
676
- return await this.request(args, {
826
+ const res = await this.request<TextToImageReturn>(args, {
677
827
  ...options,
678
828
  blob: true,
679
829
  });
830
+ const isValidOutput = res && res instanceof Blob;
831
+ if (!isValidOutput) {
832
+ throw new TypeError("Invalid inference output: output must be of type object & of instance Blob");
833
+ }
834
+ return res;
680
835
  }
681
836
 
682
837
  public async request<T>(