UNPKG

34 kBJavaScriptView Raw
1"use strict";
2/**
3 * @license
4 * Copyright 2019 Google LLC. All Rights Reserved.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 * =============================================================================
17 */
18var __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};
26var __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};
53var _this = this;
54Object.defineProperty(exports, "__esModule", { value: true });
55var tfjs_1 = require("@tensorflow/tfjs");
56var tf = require("./index");
57var nodejs_kernel_backend_1 = require("./nodejs_kernel_backend");
58var saved_model_1 = require("./saved_model");
59// tslint:disable-next-line:no-require-imports
60var messages = require('./proto/api_pb');
61describe('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 /*yield*/, saved_model_1.readSavedModelProto('./test_objects/saved_model/times_three_float')];
67 case 1:
68 modelMessage = _a.sent();
69 // This SavedModel has one MetaGraph with tag serve
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 /*return*/];
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 /*yield*/, saved_model_1.readSavedModelProto('/not-exist')];
120 case 1:
121 _a.sent();
122 done.fail();
123 return [3 /*break*/, 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 /*break*/, 3];
130 case 3: return [2 /*return*/];
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 /*yield*/, tf.node.getMetaGraphsFromSavedModel('./test_objects/saved_model/times_three_float')];
139 case 1:
140 modelInfo = _a.sent();
141 /**
142 * The inspection output should be
143 * [{
144 * 'tags': ['serve'],
145 * 'signatureDefs': {
146 * '__saved_model_init_op': {
147 * 'inputs': {},
148 * 'outputs': {
149 * '__saved_model_init_op': {
150 * 'dtype': 'DT_INVALID',
151 * 'name': 'NoOp',
152 * 'shape': []
153 * }
154 * }
155 * },
156 * 'serving_default': {
157 * 'inputs': {
158 * 'x': {
159 * 'dtype': 'DT_FLOAT',
160 * 'name': 'serving_default_x:0',
161 * 'shape':[]
162 * }
163 * },
164 * 'outputs': {
165 * 'output_0': {
166 * 'dtype': 'DT_FLOAT',
167 * 'name': 'StatefulPartitionedCall:0',
168 * 'shape': []
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 /*return*/];
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 /*yield*/, 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 /*return*/];
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 /*yield*/, 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 /*return*/];
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 /*yield*/, 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 /*break*/, 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 /*break*/, 3];
247 case 3: return [2 /*return*/];
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 /*yield*/, 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 /*break*/, 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 /*break*/, 3];
268 case 3: return [2 /*return*/];
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 /*yield*/, 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 /*return*/];
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 /*yield*/, 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 /*return*/];
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 /*yield*/, 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 /*yield*/, 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 /*return*/];
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 /*yield*/, 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 /*yield*/, 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 /*return*/];
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 /*yield*/, 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 /*return*/];
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 /*yield*/, 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 /*yield*/, output.data()];
412 case 2:
413 _c = [_d.sent()];
414 return [4 /*yield*/, input.mul(3).data()];
415 case 3:
416 _b.apply(_a, _c.concat([_d.sent()]));
417 model.dispose();
418 return [2 /*return*/];
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 /*yield*/, 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 /*yield*/, output.data()];
438 case 2:
439 _b.apply(_a, [_c.sent(), [3.0, 6.0, 9.0]]);
440 model.dispose();
441 return [2 /*return*/];
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 /*yield*/, 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 /*yield*/, output.data()];
460 case 2:
461 _b.apply(_a, [_c.sent(), [3.0, 6.0, 9.0]]);
462 model.dispose();
463 return [2 /*return*/];
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 /*yield*/, 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 /*return*/];
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 /*yield*/, 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 /*yield*/, output.data()];
503 case 2:
504 _b.apply(_a, [_c.sent(), [2, 4, 6]]);
505 model.dispose();
506 return [2 /*return*/];
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 /*yield*/, 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 /*yield*/, 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 /*yield*/, 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 /*yield*/, 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 /*return*/];
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 /*yield*/, 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 /*yield*/, 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 /*yield*/, output2.data()];
571 case 3:
572 _d.apply(_c, [_e.sent(), [1, 2, 3]]);
573 model.dispose();
574 return [2 /*return*/];
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 /*yield*/, 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 /*yield*/, 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 /*yield*/, output2.data()];
600 case 3:
601 _d.apply(_c, [_e.sent(), [1, 2, 3]]);
602 model.dispose();
603 return [2 /*return*/];
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 /*yield*/, 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 /*yield*/, 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 /*return*/];
626 }
627 });
628 }); });
629});