0

I try to use onnx runtime in a custom ipywidget but i have a problem with the *wasm files needed by the wasm backend.

I start from the template made by cookie cutter ts and then add the onnx example code provided by onnx :

So here my widget.ts code :

import {
  DOMWidgetModel,
  DOMWidgetView,
  ISerializers,
} from '@jupyter-widgets/base';

import { MODULE_NAME, MODULE_VERSION } from './version';

// Import the CSS
import '../css/widget.css';

import {InferenceSession,Tensor} from "onnxruntime-web";

// use an async context to call onnxruntime functions.
async function create() {
    try {
        // create a new session and load the specific model.
        //
        // the model in this example contains a single MatMul node
        // it has 2 inputs: 'a'(float32, 3x4) and 'b'(float32, 4x3)
        // it has 1 output: 'c'(float32, 3x3)
        const session = await InferenceSession.create('./model.onnx'{ executionProviders: ['wasm']});
        console.log("session",session) 
        // prepare inputs. a tensor need its corresponding TypedArray as data
        const dataA = Float32Array.from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);
        const dataB = Float32Array.from([10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120]);
        const tensorA = new Tensor('float32', dataA, [3, 4]);
        const tensorB = new Tensor('float32', dataB, [4, 3]);

        // prepare feeds. use model input names as keys.
        const feeds = { a: tensorA, b: tensorB };

        // feed inputs and run
        const results = await session.run(feeds);

        // read from results
        const dataC = results.c.data;
        console.log("result",dataC)

    } catch (e) {
        document.write(`failed to inference ONNX model: ${e}.`);
    }
}


export class ExampleModel extends DOMWidgetModel {
  defaults() {
    return {
      ...super.defaults(),
      _model_name: ExampleModel.model_name,
      _model_module: ExampleModel.model_module,
      _model_module_version: ExampleModel.model_module_version,
      _view_name: ExampleModel.view_name,
      _view_module: ExampleModel.view_module,
      _view_module_version: ExampleModel.view_module_version,
      value: 'Hello World',
    };
  }

  static serializers: ISerializers = {
    ...DOMWidgetModel.serializers,
    // Add any extra serializers here
  };

  static model_name = 'ExampleModel';
  static model_module = MODULE_NAME;
  static model_module_version = MODULE_VERSION;
  static view_name = 'ExampleView'; // Set to null if no view
  static view_module = MODULE_NAME; // Set to null if no view
  static view_module_version = MODULE_VERSION;
}

export class ExampleView extends DOMWidgetView {
  render() {
    this.el.classList.add('custom-widget');

    this.value_changed();
    this.model.on('change:value', this.value_changed, this);
    create()
  }

  value_changed() {
    this.el.textContent = this.model.get('value');
  }
}

then i add onnxruntime-web to depencies in package.json

"dependencies": {
    "@jupyter-widgets/base": "^1.1.10 || ^2 || ^3 || ^4 || ^5 || ^6",
    "onnxruntime-web": "^1.8.0"
  },

and "copy-webpack-plugin": "^8.1.1", to devDependencies in order to copy the *.wasm file to dist and nbextension directory

I have also modified webpack.config.js in order to copy the file wasm file.

module.exports = [
  /**
   * Notebook extension
   *
   * This bundle only contains the part of the JavaScript that is run on load of
   * the notebook.
   */
  {
    entry: './src/extension.ts',
    output: {
      filename: 'index.js',
      path: path.resolve(__dirname, 'custom_onnx', 'nbextension'),
      libraryTarget: 'amd',
      publicPath: '',
    },
    module: {
      rules: rules
    },
    devtool: 'source-map',
    externals,
    resolve,
    plugins: [new CopyPlugin({
            // Use copy plugin to copy *.wasm to output folder.
            patterns: [{ from: 'node_modules/onnxruntime-web/dist/*.wasm', to: '[name][ext]' }]
        })]
  },
...

then i do :

yarn run build

jupyter nbextension install --sys-prefix --symlink --overwrite --py custom_onnx

jupyter nbextension enable --sys-prefix --py custom_onnx

I got the following files in the nbextension folder of my environnement:

anaconda3/envs/custom_widget/share/jupyter/nbextensions/custom_onnx/extension.js

anaconda3/envs/custom_widget/share/jupyter/nbextensions/custom_onnx/index.js

anaconda3/envs/custom_widget/share/jupyter/nbextensions/custom_onnx/index.js.map

anaconda3/envs/custom_widget/share/jupyter/nbextensions/custom_onnx/ort-wasm.wasm

anaconda3/envs/custom_widget/share/jupyter/nbextensions/custom_onnx/ort-wasm-simd.wasm

anaconda3/envs/custom_widget/share/jupyter/nbextensions/custom_onnx/ort-wasm-simd-threaded.wasm

anaconda3/envs/custom_widget/share/jupyter/nbextensions/custom_onnx/ort-wasm-threaded.wasm

As you can see the wasm files are here.

But when i run the introduction.ipynb notebook with jupyter notebook i got this in the console :

XHRGEThttp://localhost:8888/ort-wasm-simd.wasm
[HTTP/1.1 404 Not Found 9ms]

    
GET
    http://localhost:8888/ort-wasm-simd.wasm
État
404
Not Found
VersionHTTP/1.1
Transfert7,92 Ko (taille 7,66 Ko)
Politique de référentstrict-origin-when-cross-origin

wasm streaming compile failed: TypeError: WebAssembly: Response has unsupported MIME type 'text/html' expected 'application/wasm' ort-wasm.js:39:340
falling back to ArrayBuffer instantiation ort-wasm.js:39:377
XHRGEThttp://localhost:8888/ort-wasm-simd.wasm
[HTTP/1.1 404 Not Found 4ms]

Aborted(both async and sync fetching of the wasm failed) ort-wasm.js:18:81
failed to asynchronously prepare wasm: RuntimeError: Aborted(both async and sync fetching of the wasm failed). Build with -sASSERTIONS for more info. ort-wasm.js:38:357
Aborted(RuntimeError: Aborted(both async and sync fetching of the wasm failed). Build with -sASSERTIONS for more info.) ort-wasm.js:18:81
Cette page est en mode de compatibilité (quirks). La mise en page peut en être affectée. Pour le mode standard, utilisez « <!DOCTYPE html> ». widget.ts:45:17
Error: Promised response from onMessage listener went out of scope 32 background.js:841:170

it's look like the wasm file is to found on http://localhost:8888/

I try many things to get it work and the only thing which work it's to add :

import { env } from "onnxruntime-web";
env.wasm.wasmPaths='./wasm/' 

before calling InferenceSession

and put the wasm file 'ort-wasm-simd.wasm" in a wasm directory in the example directory

But i wandering if there is another way to use wasm files in a custom widget without having to ship it with the notebook but in the widget package.

I'm on ubuntu 16.04 and these is my pip list :

anyio 3.6.2

argon2-cffi 21.3.0

argon2-cffi-bindings 21.2.0

asttokens 2.1.0

attrs 22.1.0

Babel 2.11.0

backcall 0.2.0

backports.functools-lru-cache 1.6.4

beautifulsoup4 4.11.1

bleach 5.0.1

brotlipy 0.7.0

certifi 2022.9.24

cffi 1.15.1

charset-normalizer 2.1.1

coverage 6.5.0

cryptography 38.0.3

custom_onnx 0.1.0.dev0 /home/nallezard/dev/custom_onnx

debugpy 1.6.3

decorator 5.1.1

defusedxml 0.7.1

entrypoints 0.4

exceptiongroup 1.0.1

executing 1.2.0

fastjsonschema 2.16.2

flit_core 3.8.0

idna 3.4

importlib-metadata 5.0.0

importlib-resources 5.10.0

iniconfig 1.1.1

ipykernel 6.14.0

ipython 8.4.0

ipython-genutils 0.2.0

ipywidgets 8.0.2

jedi 0.18.1

Jinja2 3.1.2

json5 0.9.5

jsonschema 4.17.0

jupyter_client 7.4.1

jupyter-contrib-core 0.4.0

jupyter_core 5.0.0

jupyter-nbextensions-configurator 0.5.0

jupyter-server 1.23.1

jupyterlab 3.5.0

jupyterlab-pygments 0.2.2

jupyterlab_server 2.16.2

jupyterlab-widgets 3.0.3

MarkupSafe 2.1.1

matplotlib-inline 0.1.6

mistune 2.0.4

nbclassic 0.4.8

nbclient 0.7.0

nbconvert 7.2.4

nbformat 5.7.0

nbval 0.9.6

nest-asyncio 1.5.6

notebook 6.5.2

notebook_shim 0.2.2

packaging 21.3

pandocfilters 1.5.0

parso 0.8.3

pexpect 4.8.0

pickleshare 0.7.5

pip 22.3.1

pkgutil_resolve_name 1.3.10

platformdirs 2.5.2

pluggy 1.0.0

prometheus-client 0.15.0

prompt-toolkit 3.0.32

psutil 5.9.4

ptyprocess 0.7.0

pure-eval 0.2.2

pycparser 2.21

Pygments 2.13.0

pyOpenSSL 22.1.0

pyparsing 3.0.9

pyrsistent 0.19.2

PySocks 1.7.1

pytest 7.2.0

pytest-cov 4.0.0

python-dateutil 2.8.2

pytz 2022.6

PyYAML 6.0

pyzmq 24.0.1

requests 2.28.1

Send2Trash 1.8.0

setuptools 65.5.1

six 1.16.0

sniffio 1.3.0

soupsieve 2.3.2.post1

stack-data 0.6.0

terminado 0.15.0

tinycss2 1.2.1

tomli 2.0.1

tornado 6.2

traitlets 5.5.0

typing_extensions 4.4.0

urllib3 1.26.11

voila 0.4.0

wcwidth 0.2.5

webencodings 0.5.1

websocket-client 1.4.2

websockets 10.4

wheel 0.38.4

widgetsnbextension 4.0.3

zipp 3.10.0

0 Answers0