🏡 index : cold-air-networks/mirror-jetstream.git

"use strict";

var tf = _interopRequireWildcard(tfjsRequire("@tensorflow/tfjs"));
var use = _interopRequireWildcard(tfjsRequire("@tensorflow-models/universal-sentence-encoder"));
var cocoSsd = _interopRequireWildcard(tfjsRequire("@tensorflow-models/coco-ssd"));
var _tfjsBackendWasm = tfjsRequire("@tensorflow/tfjs-backend-wasm");
var _mobilenetInput = tfjsRequire("./mobilenet-input");

// FIXME: This is speculative fix for jetsams on iOS devices.
// It seems that loading model in each iteration increases
// memory usage on both Safari and Chrome.
globalThis.models = {
	use: null,
	cocoSsd: null,
	knn: null,
	mobilenet_v1: null,
	mobilenet_v3: null
};

function _getRequireWildcardCache(nodeInterop) {
    if (typeof WeakMap !== "function")
        return null;
    var cacheBabelInterop = new WeakMap();
    var cacheNodeInterop = new WeakMap();
    return (_getRequireWildcardCache = function (nodeInterop) {
        return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
    }
    )(nodeInterop);
}

function _interopRequireWildcard(obj, nodeInterop) {
    if (!nodeInterop && obj && obj.__esModule) {
        return obj;
    }
    if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
        return {
            default: obj
        };
    }
    var cache = _getRequireWildcardCache(nodeInterop);
    if (cache && cache.has(obj)) {
        return cache.get(obj);
    }
    var newObj = {};
    var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
    for (var key in obj) {
        if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
            var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
            if (desc && (desc.get || desc.set)) {
                Object.defineProperty(newObj, key, desc);
            } else {
                newObj[key] = obj[key];
            }
        }
    }
    newObj.default = obj;
    if (cache) {
        cache.set(obj, newObj);
    }
    return newObj;
}

const WASM_TFJS_DIR = './wasm/';
const loadAndPredict_mobilenet = async () => {
    // -------------- Load pre-trained mobilenet model --------------
    if (!models.mobilenet_v3) {
        // https://tfhub.dev/google/tfjs-model/imagenet/mobilenet_v2_100_224/classification/3/default/1
        models.mobilenet_v3 = await tf.loadGraphModel('wasm-tfjs-mobilenet', { fromTFHub: true });
        globalThis.MOBILENET_ARTIFACTS_V3 = null;
    }
    const model = models.mobilenet_v3;

    // -------------- Load image data --------------
    const imageSize = 224;
    const imageObject = {
        data: _mobilenetInput.mobilenetInputData,
        width: imageSize,
        height: imageSize
    };

    // -------------- Prediction --------------
    const startTime = performance.now();

    model.predict(tf.zeros([1, imageSize, imageSize, 3])).dispose();
    tf.tidy(() => {
        const img = tf.cast(tf.browser.fromPixels(imageObject), 'float32');
        const offset = tf.scalar(127.5);
        const normalized = img.sub(offset).div(offset);
        const batched = normalized.reshape([1, imageSize, imageSize, 3]);
        return model.predict(batched);
    }
    );

    const totalTime = Math.max(1, performance.now() - startTime);
    return totalTime;
};

const loadAndPredict_knn = async () => {
    // -------------- Load pre-trained KNN classifier model --------------
    if (!models.knn) {
		// https://www.npmjs.com/package/@tensorflow-models/mobilenet
		models.mobilenet_v1 = await tfjsRequire('@tensorflow-models/mobilenet').load();
		// https://www.npmjs.com/package/@tensorflow-models/knn-classifier
		models.knn = tfjsRequire('@tensorflow-models/knn-classifier').create();
        globalThis.MOBILENET_ARTIFACTS_V1 = null;
	}

	const classifier = models.knn;
	const mobilenet = models.mobilenet_v1;

    // -------------- Load image data --------------
    const imageSize = 224;
    const imageObject = {
        data: _mobilenetInput.mobilenetInputData,
        width: imageSize,
        height: imageSize
    };

    // -------------- Prediction --------------
    const startTime = performance.now();
    tf.cast(tf.browser.fromPixels(imageObject), 'float32');
    const logits0 = mobilenet.infer(tf.browser.fromPixels(imageObject), true);
    classifier.addExample(logits0, 0);
    const logits1 = mobilenet.infer(tf.browser.fromPixels(imageObject), true);
    classifier.addExample(logits1, 1);
    mobilenet.infer(tf.browser.fromPixels(imageObject), true);
    const totalTime = Math.max(1, performance.now() - startTime);
    return totalTime;
};

const loadAndPredict_cocoSsd = async () => {
    // -------------- Load pre-trained cocoSsd model --------------
    // https://www.npmjs.com/package/@tensorflow-models/coco-ssd
    if (!models.cocoSsd) {
		models.cocoSsd = await cocoSsd.load();
        globalThis.COCO_SSD_ARTIFACTS == null;
	}
	const model = models.cocoSsd;

    // -------------- Load image data --------------
    const imageSize = 224;
    const imageObject = {
        data: _mobilenetInput.mobilenetInputData,
        width: imageSize,
        height: imageSize
    };

    // -------------- Prediction --------------
    const startTime = performance.now();
    await model.detect(imageObject);
    const totalTime = Math.max(1, performance.now() - startTime);
    return totalTime;
};

const loadAndPredict_use = async () => {
    // -------------- Load pre-trained universal-sentence-encoder model --------------
    // https://www.npmjs.com/package/@tensorflow-models/universal-sentence-encoder
    if (!models.use) {
		models.use = await use.loadQnA();
        globalThis.USE_ARTIFACTS = null;
        globalThis.USE_VOCAB_JSON = null;
	}
	const model = models.use;

    // -------------- Load text data --------------
    const input = {
        queries: ['How are you feeling today?'],
        responses: ['I\'m not feeling very well.', 'Beijing is the capital of China.', 'You have five fingers on your hand.']
    };

    // -------------- Prediction --------------
    const startTime = performance.now();
    let result = model.embed(input);
    tf.matMul(result['queryEmbedding'], result['responseEmbedding'], false, true).dataSync();
    const totalTime = Math.max(1, performance.now() - startTime);
    return totalTime;
};

globalThis.setWasmBackend = async () => {
    // https://github.com/tensorflow/tfjs/tree/master/tfjs-backend-wasm
    // https://github.com/tensorflow/tfjs-models
    _tfjsBackendWasm.setWasmPaths(WASM_TFJS_DIR, (path) => {
        console.log("Fetching " + path)
    });
    let value = await tf.setBackend('wasm')
    if (!value)
        throw new Error("Should use wasm backend.");

    await loadAndPredict();
};

globalThis.loadAndPredict = async () => {
    let result = 0.0;
    result += await loadAndPredict_mobilenet();
    result += await loadAndPredict_knn();
    result += await loadAndPredict_cocoSsd();
    result += await loadAndPredict_use();
    return result;
};