@huggingface/inference 1.6.1 → 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 +123 -18
- package/dist/index.mjs +123 -18
- package/package.json +1 -1
- package/src/HfInference.ts +174 -19
- package/src/utils/env-predicates.ts +7 -0
- /package/src/{utils.ts → utils/to-array.ts} +0 -0
package/dist/index.js
CHANGED
|
@@ -23,7 +23,7 @@ __export(src_exports, {
|
|
|
23
23
|
});
|
|
24
24
|
module.exports = __toCommonJS(src_exports);
|
|
25
25
|
|
|
26
|
-
// src/utils.ts
|
|
26
|
+
// src/utils/to-array.ts
|
|
27
27
|
function toArray(obj) {
|
|
28
28
|
if (Array.isArray(obj)) {
|
|
29
29
|
return obj;
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// src/utils.ts
|
|
1
|
+
// src/utils/to-array.ts
|
|
2
2
|
function toArray(obj) {
|
|
3
3
|
if (Array.isArray(obj)) {
|
|
4
4
|
return obj;
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
package/src/HfInference.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { toArray } from "./utils";
|
|
1
|
+
import { toArray } from "./utils/to-array";
|
|
2
2
|
|
|
3
3
|
export interface Options {
|
|
4
4
|
/**
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
588
|
-
await this.request<ZeroShotClassificationReturnValue |
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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>(
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
const isBrowser = typeof window !== "undefined" && typeof window.document !== "undefined";
|
|
2
|
+
|
|
3
|
+
const isWebWorker =
|
|
4
|
+
typeof self === "object" && self.constructor && self.constructor.name === "DedicatedWorkerGlobalScope";
|
|
5
|
+
|
|
6
|
+
export const isFrontend = isBrowser || isWebWorker;
|
|
7
|
+
export const isBackend = !isBrowser && !isWebWorker;
|
|
File without changes
|