1 | "use strict";
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
19 | return new (P || (P = Promise))(function (resolve, reject) {
|
20 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
21 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
22 | function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
23 | step((generator = generator.apply(thisArg, _arguments || [])).next());
|
24 | });
|
25 | };
|
26 | var __generator = (this && this.__generator) || function (thisArg, body) {
|
27 | var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
28 | return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
29 | function verb(n) { return function (v) { return step([n, v]); }; }
|
30 | function step(op) {
|
31 | if (f) throw new TypeError("Generator is already executing.");
|
32 | while (_) try {
|
33 | if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
34 | if (y = 0, t) op = [op[0] & 2, t.value];
|
35 | switch (op[0]) {
|
36 | case 0: case 1: t = op; break;
|
37 | case 4: _.label++; return { value: op[1], done: false };
|
38 | case 5: _.label++; y = op[1]; op = [0]; continue;
|
39 | case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
40 | default:
|
41 | if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
42 | if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
43 | if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
44 | if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
45 | if (t[2]) _.ops.pop();
|
46 | _.trys.pop(); continue;
|
47 | }
|
48 | op = body.call(thisArg, _);
|
49 | } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
50 | if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
51 | }
|
52 | };
|
53 | var _this = this;
|
54 | Object.defineProperty(exports, "__esModule", { value: true });
|
55 | var tfjs_1 = require("@tensorflow/tfjs");
|
56 | var tf = require("./index");
|
57 | var nodejs_kernel_backend_1 = require("./nodejs_kernel_backend");
|
58 | var saved_model_1 = require("./saved_model");
|
59 |
|
60 | var messages = require('./proto/api_pb');
|
61 | describe('SavedModel', function () {
|
62 | it('deserialize SavedModel pb file', function () { return __awaiter(_this, void 0, void 0, function () {
|
63 | var modelMessage, signatureDefMapMessage, inputsMapMessage, inputsMapKeys, inputsMapKey1, inputTensorMessage, outputsMapMessage, outputsMapKeys, outputsMapKey1, outputTensorMessage;
|
64 | return __generator(this, function (_a) {
|
65 | switch (_a.label) {
|
66 | case 0: return [4 , saved_model_1.readSavedModelProto('./test_objects/saved_model/times_three_float')];
|
67 | case 1:
|
68 | modelMessage = _a.sent();
|
69 |
|
70 | expect(modelMessage.getMetaGraphsList().length).toBe(1);
|
71 | expect(modelMessage.getMetaGraphsList()[0]
|
72 | .getMetaInfoDef()
|
73 | .getTagsList()
|
74 | .length)
|
75 | .toBe(1);
|
76 | expect(modelMessage.getMetaGraphsList()[0].getMetaInfoDef().getTagsList()[0])
|
77 | .toBe('serve');
|
78 | signatureDefMapMessage = modelMessage.getMetaGraphsList()[0].getSignatureDefMap();
|
79 | expect(signatureDefMapMessage.has('serving_default'));
|
80 | inputsMapMessage = signatureDefMapMessage.get('serving_default').getInputsMap();
|
81 | expect(inputsMapMessage.getLength()).toBe(1);
|
82 | inputsMapKeys = inputsMapMessage.keys();
|
83 | inputsMapKey1 = inputsMapKeys.next();
|
84 | expect(inputsMapKey1.done).toBe(false);
|
85 | expect(inputsMapKey1.value).toBe('x');
|
86 | inputTensorMessage = inputsMapMessage.get(inputsMapKey1.value);
|
87 | expect(inputTensorMessage.getName()).toBe('serving_default_x:0');
|
88 | expect(saved_model_1.getEnumKeyFromValue(messages.DataType, inputTensorMessage.getDtype()))
|
89 | .toBe('DT_FLOAT');
|
90 | outputsMapMessage = signatureDefMapMessage.get('serving_default').getOutputsMap();
|
91 | expect(outputsMapMessage.getLength()).toBe(1);
|
92 | outputsMapKeys = outputsMapMessage.keys();
|
93 | outputsMapKey1 = outputsMapKeys.next();
|
94 | expect(outputsMapKey1.done).toBe(false);
|
95 | expect(outputsMapKey1.value).toBe('output_0');
|
96 | outputTensorMessage = outputsMapMessage.get(outputsMapKey1.value);
|
97 | expect(outputTensorMessage.getName()).toBe('StatefulPartitionedCall:0');
|
98 | expect(saved_model_1.getEnumKeyFromValue(messages.DataType, outputTensorMessage.getDtype()))
|
99 | .toBe('DT_FLOAT');
|
100 | return [2 ];
|
101 | }
|
102 | });
|
103 | }); });
|
104 | it('get enum key based on value', function () {
|
105 | var DataType = messages.DataType;
|
106 | var enumKey0 = saved_model_1.getEnumKeyFromValue(DataType, 0);
|
107 | expect(enumKey0).toBe('DT_INVALID');
|
108 | var enumKey1 = saved_model_1.getEnumKeyFromValue(DataType, 1);
|
109 | expect(enumKey1).toBe('DT_FLOAT');
|
110 | var enumKey2 = saved_model_1.getEnumKeyFromValue(DataType, 2);
|
111 | expect(enumKey2).toBe('DT_DOUBLE');
|
112 | });
|
113 | it('read non-exist file', function (done) { return __awaiter(_this, void 0, void 0, function () {
|
114 | var err_1;
|
115 | return __generator(this, function (_a) {
|
116 | switch (_a.label) {
|
117 | case 0:
|
118 | _a.trys.push([0, 2, , 3]);
|
119 | return [4 , saved_model_1.readSavedModelProto('/not-exist')];
|
120 | case 1:
|
121 | _a.sent();
|
122 | done.fail();
|
123 | return [3 , 3];
|
124 | case 2:
|
125 | err_1 = _a.sent();
|
126 | expect(err_1.message)
|
127 | .toBe("There is no saved_model.pb file in the directory: /not-exist");
|
128 | done();
|
129 | return [3 , 3];
|
130 | case 3: return [2 ];
|
131 | }
|
132 | });
|
133 | }); });
|
134 | it('inspect SavedModel metagraphs', function () { return __awaiter(_this, void 0, void 0, function () {
|
135 | var modelInfo;
|
136 | return __generator(this, function (_a) {
|
137 | switch (_a.label) {
|
138 | case 0: return [4 , tf.node.getMetaGraphsFromSavedModel('./test_objects/saved_model/times_three_float')];
|
139 | case 1:
|
140 | modelInfo = _a.sent();
|
141 | |
142 |
|
143 |
|
144 |
|
145 |
|
146 |
|
147 |
|
148 |
|
149 |
|
150 |
|
151 |
|
152 |
|
153 |
|
154 |
|
155 |
|
156 |
|
157 |
|
158 |
|
159 |
|
160 |
|
161 |
|
162 |
|
163 |
|
164 |
|
165 |
|
166 |
|
167 |
|
168 |
|
169 |
|
170 |
|
171 |
|
172 |
|
173 |
|
174 |
|
175 | expect(modelInfo.length).toBe(1);
|
176 | expect(modelInfo[0].tags.length).toBe(1);
|
177 | expect(modelInfo[0].tags[0]).toBe('serve');
|
178 | expect(Object.keys(modelInfo[0].signatureDefs).length).toBe(1);
|
179 | expect(Object.keys(modelInfo[0].signatureDefs)[0]).toBe('serving_default');
|
180 | expect(Object.keys(modelInfo[0].signatureDefs['serving_default'].inputs)
|
181 | .length)
|
182 | .toBe(1);
|
183 | expect(modelInfo[0].signatureDefs['serving_default'].inputs['x'].name)
|
184 | .toBe('serving_default_x:0');
|
185 | expect(modelInfo[0].signatureDefs['serving_default'].inputs['x'].dtype)
|
186 | .toBe('float32');
|
187 | expect(Object.keys(modelInfo[0].signatureDefs['serving_default'].outputs)
|
188 | .length)
|
189 | .toBe(1);
|
190 | expect(modelInfo[0].signatureDefs['serving_default'].outputs['output_0'].name)
|
191 | .toBe('StatefulPartitionedCall:0');
|
192 | expect(modelInfo[0].signatureDefs['serving_default'].outputs['output_0'].dtype)
|
193 | .toBe('float32');
|
194 | return [2 ];
|
195 | }
|
196 | });
|
197 | }); });
|
198 | it('get input and output node names from SavedModel metagraphs', function () { return __awaiter(_this, void 0, void 0, function () {
|
199 | var modelInfo, inputAndOutputNodeNames;
|
200 | return __generator(this, function (_a) {
|
201 | switch (_a.label) {
|
202 | case 0: return [4 , tf.node.getMetaGraphsFromSavedModel('./test_objects/saved_model/times_three_float')];
|
203 | case 1:
|
204 | modelInfo = _a.sent();
|
205 | inputAndOutputNodeNames = saved_model_1.getInputAndOutputNodeNameFromMetaGraphInfo(modelInfo, ['serve'], 'serving_default');
|
206 | expect(inputAndOutputNodeNames.length).toBe(2);
|
207 | expect(inputAndOutputNodeNames[0]['x']).toBe('serving_default_x:0');
|
208 | expect(inputAndOutputNodeNames[1]['output_0'])
|
209 | .toBe('StatefulPartitionedCall:0');
|
210 | return [2 ];
|
211 | }
|
212 | });
|
213 | }); });
|
214 | it('load TFSavedModel', function () { return __awaiter(_this, void 0, void 0, function () {
|
215 | var loadSavedModelMetaGraphSpy, model;
|
216 | return __generator(this, function (_a) {
|
217 | switch (_a.label) {
|
218 | case 0:
|
219 | loadSavedModelMetaGraphSpy = spyOn(nodejs_kernel_backend_1.nodeBackend(), 'loadSavedModelMetaGraph').and.callThrough();
|
220 | expect(loadSavedModelMetaGraphSpy).toHaveBeenCalledTimes(0);
|
221 | return [4 , tf.node.loadSavedModel('./test_objects/saved_model/times_three_float', ['serve'], 'serving_default')];
|
222 | case 1:
|
223 | model = _a.sent();
|
224 | expect(loadSavedModelMetaGraphSpy).toHaveBeenCalledTimes(1);
|
225 | model.dispose();
|
226 | return [2 ];
|
227 | }
|
228 | });
|
229 | }); });
|
230 | it('load TFSavedModel with wrong tags throw exception', function (done) { return __awaiter(_this, void 0, void 0, function () {
|
231 | var error_1;
|
232 | return __generator(this, function (_a) {
|
233 | switch (_a.label) {
|
234 | case 0:
|
235 | _a.trys.push([0, 2, , 3]);
|
236 | return [4 , tf.node.loadSavedModel('./test_objects/saved_model/times_three_float', ['serve', 'gpu'], 'serving_default')];
|
237 | case 1:
|
238 | _a.sent();
|
239 | done.fail();
|
240 | return [3 , 3];
|
241 | case 2:
|
242 | error_1 = _a.sent();
|
243 | expect(error_1.message)
|
244 | .toBe('The SavedModel does not have tags: serve,gpu');
|
245 | done();
|
246 | return [3 , 3];
|
247 | case 3: return [2 ];
|
248 | }
|
249 | });
|
250 | }); });
|
251 | it('load TFSavedModel with wrong signature throw exception', function (done) { return __awaiter(_this, void 0, void 0, function () {
|
252 | var error_2;
|
253 | return __generator(this, function (_a) {
|
254 | switch (_a.label) {
|
255 | case 0:
|
256 | _a.trys.push([0, 2, , 3]);
|
257 | return [4 , tf.node.loadSavedModel('./test_objects/saved_model/times_three_float', ['serve'], 'wrong_signature')];
|
258 | case 1:
|
259 | _a.sent();
|
260 | done.fail();
|
261 | return [3 , 3];
|
262 | case 2:
|
263 | error_2 = _a.sent();
|
264 | expect(error_2.message)
|
265 | .toBe('The SavedModel does not have signature: wrong_signature');
|
266 | done();
|
267 | return [3 , 3];
|
268 | case 3: return [2 ];
|
269 | }
|
270 | });
|
271 | }); });
|
272 | it('load TFSavedModel and delete', function () { return __awaiter(_this, void 0, void 0, function () {
|
273 | var loadSavedModelMetaGraphSpy, deleteSavedModelSpy, model;
|
274 | return __generator(this, function (_a) {
|
275 | switch (_a.label) {
|
276 | case 0:
|
277 | expect(tf.node.getNumOfSavedModels()).toBe(0);
|
278 | loadSavedModelMetaGraphSpy = spyOn(nodejs_kernel_backend_1.nodeBackend(), 'loadSavedModelMetaGraph').and.callThrough();
|
279 | deleteSavedModelSpy = spyOn(nodejs_kernel_backend_1.nodeBackend(), 'deleteSavedModel').and.callThrough();
|
280 | expect(loadSavedModelMetaGraphSpy).toHaveBeenCalledTimes(0);
|
281 | expect(deleteSavedModelSpy).toHaveBeenCalledTimes(0);
|
282 | return [4 , tf.node.loadSavedModel('./test_objects/saved_model/times_three_float', ['serve'], 'serving_default')];
|
283 | case 1:
|
284 | model = _a.sent();
|
285 | expect(loadSavedModelMetaGraphSpy).toHaveBeenCalledTimes(1);
|
286 | expect(deleteSavedModelSpy).toHaveBeenCalledTimes(0);
|
287 | expect(tf.node.getNumOfSavedModels()).toBe(1);
|
288 | model.dispose();
|
289 | expect(loadSavedModelMetaGraphSpy).toHaveBeenCalledTimes(1);
|
290 | expect(deleteSavedModelSpy).toHaveBeenCalledTimes(1);
|
291 | expect(tf.node.getNumOfSavedModels()).toBe(0);
|
292 | return [2 ];
|
293 | }
|
294 | });
|
295 | }); });
|
296 | it('delete TFSavedModel multiple times throw exception', function (done) { return __awaiter(_this, void 0, void 0, function () {
|
297 | var model;
|
298 | return __generator(this, function (_a) {
|
299 | switch (_a.label) {
|
300 | case 0: return [4 , tf.node.loadSavedModel('./test_objects/saved_model/times_three_float', ['serve'], 'serving_default')];
|
301 | case 1:
|
302 | model = _a.sent();
|
303 | model.dispose();
|
304 | try {
|
305 | model.dispose();
|
306 | done.fail();
|
307 | }
|
308 | catch (error) {
|
309 | expect(error.message).toBe('This SavedModel has already been deleted.');
|
310 | done();
|
311 | }
|
312 | return [2 ];
|
313 | }
|
314 | });
|
315 | }); });
|
316 | it('load multiple signatures from the same metagraph only call binding once', function () { return __awaiter(_this, void 0, void 0, function () {
|
317 | var backend, loadSavedModelMetaGraphSpy, model1, model2;
|
318 | return __generator(this, function (_a) {
|
319 | switch (_a.label) {
|
320 | case 0:
|
321 | expect(tf.node.getNumOfSavedModels()).toBe(0);
|
322 | backend = nodejs_kernel_backend_1.nodeBackend();
|
323 | loadSavedModelMetaGraphSpy = spyOn(backend, 'loadSavedModelMetaGraph').and.callThrough();
|
324 | expect(loadSavedModelMetaGraphSpy).toHaveBeenCalledTimes(0);
|
325 | return [4 , tf.node.loadSavedModel('./test_objects/saved_model/module_with_multiple_signatures', ['serve'], 'serving_default')];
|
326 | case 1:
|
327 | model1 = _a.sent();
|
328 | expect(loadSavedModelMetaGraphSpy).toHaveBeenCalledTimes(1);
|
329 | expect(tf.node.getNumOfSavedModels()).toBe(1);
|
330 | return [4 , tf.node.loadSavedModel('./test_objects/saved_model/module_with_multiple_signatures', ['serve'], 'timestwo')];
|
331 | case 2:
|
332 | model2 = _a.sent();
|
333 | expect(loadSavedModelMetaGraphSpy).toHaveBeenCalledTimes(1);
|
334 | expect(tf.node.getNumOfSavedModels()).toBe(1);
|
335 | model1.dispose();
|
336 | expect(tf.node.getNumOfSavedModels()).toBe(1);
|
337 | model2.dispose();
|
338 | expect(loadSavedModelMetaGraphSpy).toHaveBeenCalledTimes(1);
|
339 | expect(tf.node.getNumOfSavedModels()).toBe(0);
|
340 | return [2 ];
|
341 | }
|
342 | });
|
343 | }); });
|
344 | it('load signature after delete call binding', function () { return __awaiter(_this, void 0, void 0, function () {
|
345 | var backend, spyOnCallBindingLoad, spyOnNodeBackendDelete, model1, model2;
|
346 | return __generator(this, function (_a) {
|
347 | switch (_a.label) {
|
348 | case 0:
|
349 | backend = nodejs_kernel_backend_1.nodeBackend();
|
350 | spyOnCallBindingLoad = spyOn(backend, 'loadSavedModelMetaGraph').and.callThrough();
|
351 | spyOnNodeBackendDelete = spyOn(backend, 'deleteSavedModel').and.callThrough();
|
352 | expect(spyOnCallBindingLoad).toHaveBeenCalledTimes(0);
|
353 | expect(spyOnNodeBackendDelete).toHaveBeenCalledTimes(0);
|
354 | return [4 , tf.node.loadSavedModel('./test_objects/saved_model/module_with_multiple_signatures', ['serve'], 'serving_default')];
|
355 | case 1:
|
356 | model1 = _a.sent();
|
357 | expect(spyOnCallBindingLoad).toHaveBeenCalledTimes(1);
|
358 | expect(spyOnNodeBackendDelete).toHaveBeenCalledTimes(0);
|
359 | model1.dispose();
|
360 | expect(spyOnNodeBackendDelete).toHaveBeenCalledTimes(1);
|
361 | expect(spyOnCallBindingLoad).toHaveBeenCalledTimes(1);
|
362 | return [4 , tf.node.loadSavedModel('./test_objects/saved_model/module_with_multiple_signatures', ['serve'], 'timestwo')];
|
363 | case 2:
|
364 | model2 = _a.sent();
|
365 | expect(spyOnCallBindingLoad).toHaveBeenCalledTimes(2);
|
366 | expect(spyOnNodeBackendDelete).toHaveBeenCalledTimes(1);
|
367 | model2.dispose();
|
368 | expect(spyOnCallBindingLoad).toHaveBeenCalledTimes(2);
|
369 | expect(spyOnNodeBackendDelete).toHaveBeenCalledTimes(2);
|
370 | return [2 ];
|
371 | }
|
372 | });
|
373 | }); });
|
374 | it('throw error when input tensors do not match input ops', function (done) { return __awaiter(_this, void 0, void 0, function () {
|
375 | var model, input1, input2;
|
376 | return __generator(this, function (_a) {
|
377 | switch (_a.label) {
|
378 | case 0: return [4 , tf.node.loadSavedModel('./test_objects/saved_model/times_three_float', ['serve'], 'serving_default')];
|
379 | case 1:
|
380 | model = _a.sent();
|
381 | input1 = tf.tensor1d([1.0, 2, 3]);
|
382 | input2 = tf.tensor1d([1.0, 2, 3]);
|
383 | try {
|
384 | model.predict([input1, input2]);
|
385 | done.fail();
|
386 | }
|
387 | catch (error) {
|
388 | expect(error.message)
|
389 | .toBe('Length of input op names (1) does not match the ' +
|
390 | 'length of input tensors (2).');
|
391 | model.dispose();
|
392 | done();
|
393 | }
|
394 | return [2 ];
|
395 | }
|
396 | });
|
397 | }); });
|
398 | it('execute model float times three', function () { return __awaiter(_this, void 0, void 0, function () {
|
399 | var model, input, output, _a, _b, _c;
|
400 | return __generator(this, function (_d) {
|
401 | switch (_d.label) {
|
402 | case 0: return [4 , tf.node.loadSavedModel('./test_objects/saved_model/times_three_float', ['serve'], 'serving_default')];
|
403 | case 1:
|
404 | model = _d.sent();
|
405 | input = tf.tensor1d([1.0, 2, 3]);
|
406 | output = model.predict(input);
|
407 | expect(output.shape).toEqual(input.shape);
|
408 | expect(output.dtype).toBe(input.dtype);
|
409 | expect(output.dtype).toBe('float32');
|
410 | _b = (_a = tfjs_1.test_util).expectArraysClose;
|
411 | return [4 , output.data()];
|
412 | case 2:
|
413 | _c = [_d.sent()];
|
414 | return [4 , input.mul(3).data()];
|
415 | case 3:
|
416 | _b.apply(_a, _c.concat([_d.sent()]));
|
417 | model.dispose();
|
418 | return [2 ];
|
419 | }
|
420 | });
|
421 | }); });
|
422 | it('execute model with tensor array as input', function () { return __awaiter(_this, void 0, void 0, function () {
|
423 | var model, input, outputArray, output, _a, _b;
|
424 | return __generator(this, function (_c) {
|
425 | switch (_c.label) {
|
426 | case 0: return [4 , tf.node.loadSavedModel('./test_objects/saved_model/times_three_float', ['serve'], 'serving_default')];
|
427 | case 1:
|
428 | model = _c.sent();
|
429 | input = tf.tensor1d([1.0, 2, 3]);
|
430 | outputArray = model.predict([input]);
|
431 | expect(outputArray.length).toBe(1);
|
432 | output = outputArray[0];
|
433 | expect(output.shape).toEqual(input.shape);
|
434 | expect(output.dtype).toBe(input.dtype);
|
435 | expect(output.dtype).toBe('float32');
|
436 | _b = (_a = tfjs_1.test_util).expectArraysClose;
|
437 | return [4 , output.data()];
|
438 | case 2:
|
439 | _b.apply(_a, [_c.sent(), [3.0, 6.0, 9.0]]);
|
440 | model.dispose();
|
441 | return [2 ];
|
442 | }
|
443 | });
|
444 | }); });
|
445 | it('execute model with tensor map as input', function () { return __awaiter(_this, void 0, void 0, function () {
|
446 | var model, input, outputMap, output, _a, _b;
|
447 | return __generator(this, function (_c) {
|
448 | switch (_c.label) {
|
449 | case 0: return [4 , tf.node.loadSavedModel('./test_objects/saved_model/times_three_float', ['serve'], 'serving_default')];
|
450 | case 1:
|
451 | model = _c.sent();
|
452 | input = tf.tensor1d([1.0, 2, 3]);
|
453 | outputMap = model.predict({ 'x': input });
|
454 | output = outputMap['output_0'];
|
455 | expect(output.shape).toEqual(input.shape);
|
456 | expect(output.dtype).toBe(input.dtype);
|
457 | expect(output.dtype).toBe('float32');
|
458 | _b = (_a = tfjs_1.test_util).expectArraysClose;
|
459 | return [4 , output.data()];
|
460 | case 2:
|
461 | _b.apply(_a, [_c.sent(), [3.0, 6.0, 9.0]]);
|
462 | model.dispose();
|
463 | return [2 ];
|
464 | }
|
465 | });
|
466 | }); });
|
467 | it('execute model with wrong tensor name', function (done) { return __awaiter(_this, void 0, void 0, function () {
|
468 | var model, input;
|
469 | return __generator(this, function (_a) {
|
470 | switch (_a.label) {
|
471 | case 0: return [4 , tf.node.loadSavedModel('./test_objects/saved_model/times_three_float', ['serve'], 'serving_default')];
|
472 | case 1:
|
473 | model = _a.sent();
|
474 | input = tf.tensor1d([1.0, 2, 3]);
|
475 | try {
|
476 | model.predict({ 'xyz': input });
|
477 | done.fail();
|
478 | }
|
479 | catch (error) {
|
480 | expect(error.message)
|
481 | .toBe('The model signatureDef input names are x, however ' +
|
482 | 'the provided input names are xyz.');
|
483 | model.dispose();
|
484 | done();
|
485 | }
|
486 | return [2 ];
|
487 | }
|
488 | });
|
489 | }); });
|
490 | it('execute model int times two', function () { return __awaiter(_this, void 0, void 0, function () {
|
491 | var model, input, output, _a, _b;
|
492 | return __generator(this, function (_c) {
|
493 | switch (_c.label) {
|
494 | case 0: return [4 , tf.node.loadSavedModel('./test_objects/saved_model/times_two_int', ['serve'], 'serving_default')];
|
495 | case 1:
|
496 | model = _c.sent();
|
497 | input = tf.tensor1d([1, 2, 3], 'int32');
|
498 | output = model.predict(input);
|
499 | expect(output.shape).toEqual(input.shape);
|
500 | expect(output.dtype).toBe(input.dtype);
|
501 | _b = (_a = tfjs_1.test_util).expectArraysClose;
|
502 | return [4 , output.data()];
|
503 | case 2:
|
504 | _b.apply(_a, [_c.sent(), [2, 4, 6]]);
|
505 | model.dispose();
|
506 | return [2 ];
|
507 | }
|
508 | });
|
509 | }); });
|
510 | it('execute multiple signatures from the same model', function () { return __awaiter(_this, void 0, void 0, function () {
|
511 | var backend, loadSavedModelMetaGraphSpy, model1, input1, output1, _a, _b, model2, input2, output2, _c, _d;
|
512 | return __generator(this, function (_e) {
|
513 | switch (_e.label) {
|
514 | case 0:
|
515 | backend = nodejs_kernel_backend_1.nodeBackend();
|
516 | loadSavedModelMetaGraphSpy = spyOn(backend, 'loadSavedModelMetaGraph').and.callThrough();
|
517 | expect(loadSavedModelMetaGraphSpy).toHaveBeenCalledTimes(0);
|
518 | return [4 , tf.node.loadSavedModel('./test_objects/saved_model/module_with_multiple_signatures', ['serve'], 'serving_default')];
|
519 | case 1:
|
520 | model1 = _e.sent();
|
521 | expect(loadSavedModelMetaGraphSpy).toHaveBeenCalledTimes(1);
|
522 | input1 = tf.tensor1d([1, 2, 3]);
|
523 | output1 = model1.predict(input1);
|
524 | expect(output1.shape).toEqual(input1.shape);
|
525 | expect(output1.dtype).toBe(input1.dtype);
|
526 | _b = (_a = tfjs_1.test_util).expectArraysClose;
|
527 | return [4 , output1.data()];
|
528 | case 2:
|
529 | _b.apply(_a, [_e.sent(), [3.0, 6.0, 9.0]]);
|
530 | expect(loadSavedModelMetaGraphSpy).toHaveBeenCalledTimes(1);
|
531 | return [4 , tf.node.loadSavedModel('./test_objects/saved_model/module_with_multiple_signatures', ['serve'], 'timestwo')];
|
532 | case 3:
|
533 | model2 = _e.sent();
|
534 | expect(loadSavedModelMetaGraphSpy).toHaveBeenCalledTimes(1);
|
535 | input2 = tf.tensor1d([1, 2, 3]);
|
536 | output2 = model2.predict(input2);
|
537 | expect(output2.shape).toEqual(input2.shape);
|
538 | expect(output2.dtype).toBe(input2.dtype);
|
539 | _d = (_c = tfjs_1.test_util).expectArraysClose;
|
540 | return [4 , output2.data()];
|
541 | case 4:
|
542 | _d.apply(_c, [_e.sent(), [2.0, 4.0, 6.0]]);
|
543 | expect(loadSavedModelMetaGraphSpy).toHaveBeenCalledTimes(1);
|
544 | model1.dispose();
|
545 | model2.dispose();
|
546 | return [2 ];
|
547 | }
|
548 | });
|
549 | }); });
|
550 | it('execute model with single input and multiple outputs', function () { return __awaiter(_this, void 0, void 0, function () {
|
551 | var model, input, output, output1, output2, _a, _b, _c, _d;
|
552 | return __generator(this, function (_e) {
|
553 | switch (_e.label) {
|
554 | case 0: return [4 , tf.node.loadSavedModel('./test_objects/saved_model/model_single_input_multi_output', ['serve'], 'serving_default')];
|
555 | case 1:
|
556 | model = _e.sent();
|
557 | input = tf.tensor1d([1, 2, 3], 'int32');
|
558 | output = model.predict(input);
|
559 | output1 = output[0];
|
560 | output2 = output[1];
|
561 | expect(output1.shape).toEqual(input.shape);
|
562 | expect(output1.dtype).toBe(input.dtype);
|
563 | expect(output2.shape).toEqual(input.shape);
|
564 | expect(output2.dtype).toBe(input.dtype);
|
565 | _b = (_a = tfjs_1.test_util).expectArraysClose;
|
566 | return [4 , output1.data()];
|
567 | case 2:
|
568 | _b.apply(_a, [_e.sent(), [2, 4, 6]]);
|
569 | _d = (_c = tfjs_1.test_util).expectArraysClose;
|
570 | return [4 , output2.data()];
|
571 | case 3:
|
572 | _d.apply(_c, [_e.sent(), [1, 2, 3]]);
|
573 | model.dispose();
|
574 | return [2 ];
|
575 | }
|
576 | });
|
577 | }); });
|
578 | it('execute model with multiple inputs and multiple outputs', function () { return __awaiter(_this, void 0, void 0, function () {
|
579 | var model, input1, input2, output, output1, output2, _a, _b, _c, _d;
|
580 | return __generator(this, function (_e) {
|
581 | switch (_e.label) {
|
582 | case 0: return [4 , tf.node.loadSavedModel('./test_objects/saved_model/model_multi_output', ['serve'], 'serving_default')];
|
583 | case 1:
|
584 | model = _e.sent();
|
585 | input1 = tf.tensor1d([1, 2, 3], 'int32');
|
586 | input2 = tf.tensor1d([1, 2, 3], 'int32');
|
587 | output = model.predict({ 'x': input1, 'y': input2 });
|
588 | output1 = output['output_0'];
|
589 | output2 = output['output_1'];
|
590 | expect(output1.shape).toEqual(input1.shape);
|
591 | expect(output1.dtype).toBe(input1.dtype);
|
592 | expect(output2.shape).toEqual(input2.shape);
|
593 | expect(output2.dtype).toBe(input2.dtype);
|
594 | _b = (_a = tfjs_1.test_util).expectArraysClose;
|
595 | return [4 , output1.data()];
|
596 | case 2:
|
597 | _b.apply(_a, [_e.sent(), [2, 4, 6]]);
|
598 | _d = (_c = tfjs_1.test_util).expectArraysClose;
|
599 | return [4 , output2.data()];
|
600 | case 3:
|
601 | _d.apply(_c, [_e.sent(), [1, 2, 3]]);
|
602 | model.dispose();
|
603 | return [2 ];
|
604 | }
|
605 | });
|
606 | }); });
|
607 | it('load multiple models', function () { return __awaiter(_this, void 0, void 0, function () {
|
608 | var model1, model2;
|
609 | return __generator(this, function (_a) {
|
610 | switch (_a.label) {
|
611 | case 0:
|
612 | expect(tf.node.getNumOfSavedModels()).toBe(0);
|
613 | return [4 , tf.node.loadSavedModel('./test_objects/saved_model/module_with_multiple_signatures', ['serve'], 'serving_default')];
|
614 | case 1:
|
615 | model1 = _a.sent();
|
616 | expect(tf.node.getNumOfSavedModels()).toBe(1);
|
617 | return [4 , tf.node.loadSavedModel('./test_objects/saved_model/model_multi_output', ['serve'], 'serving_default')];
|
618 | case 2:
|
619 | model2 = _a.sent();
|
620 | expect(tf.node.getNumOfSavedModels()).toBe(2);
|
621 | model1.dispose();
|
622 | expect(tf.node.getNumOfSavedModels()).toBe(1);
|
623 | model2.dispose();
|
624 | expect(tf.node.getNumOfSavedModels()).toBe(0);
|
625 | return [2 ];
|
626 | }
|
627 | });
|
628 | }); });
|
629 | });
|