2024年11月13日水曜日

ONNX Runtime WebのQuick StartをOracle APEXに組み込んでみる

ONNX Runtime WebQuick StartをOracle APEXのアプリケーションに組み込んでみます。ONNX Runtime WebはONNX Runtimeによる機械学習モデルをブラウザのJavaScriptで実行するという、Microsoftさんによるプロジェクトです。

ONNX Runtime WebのQuick Startは、画面に一行表示するだけの簡単なスクリプトです。


本記事は、ONNX Runtime WebをOracle APEXに組み込むための作法の紹介になります。

GitHubの以下のページより、Quick Startのコードやモデルを取得します。


参照するコードが記述されたファイルは、ESモジュールを使ったサンプルであるindex_esm.htmlです。model.onnxは、Oracle APEXの静的アプリケーション・ファイルとして保存するため、あらかじめGitHubよりダウンロードしておきます。


空のAPEXアプリケーションを作成し、ホーム・ページにQuick Startを組み込みます。

ONNX Runtime Webを組み込むページのページ・プロパティHTMLヘッダーに、以下のimportmapを定義します。主にWasmを使うことを想定しており、WebGLやWebGPUの設定は含めていません。それらは必要に応じて追記するとよいでしょう。
<script type="importmap">
    {
        "imports": {
            "onnxruntime-web": "https://cdn.jsdelivr.net/npm/onnxruntime-web/dist/esm/ort.min.js",
            "onnxruntime-web/wasm": "https://cdn.jsdelivr.net/npm/onnxruntime-web/dist/esm/ort.wasm.min.js"
        }
    }
</script>

共有コンポーネント静的アプリケーション・ファイルとして、先ほどGitHubのリポジトリよりダウンロードしたmodel.onnxをアップロードします。参照#APP_FILES#model.onnxになります。


静的コンテンツのリージョンを作成し、index_esm.htmlの内容をほぼそのまま転記します。index_esm.html内では、document.bodyに結果を出力していますが、APEXのアプリケーションでは静的コンテンツのリージョンに含まれるDIV要素に出力するように変更しています。

<div id="output"></div>
<script type="module" defer>
// see also advanced usage of importing ONNX Runtime Web:
// https://github.com/microsoft/onnxruntime-inference-examples/tree/main/js/importing_onnxruntime-web
// import ONNXRuntime Web from CDN
import * as ort from "onnxruntime-web";
// set wasm path override
ort.env.wasm.wasmPaths = "https://cdn.jsdelivr.net/npm/onnxruntime-web/dist/";
// use an async context to call onnxruntime functions.
async function main() {
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 ort.InferenceSession.create('#APP_FILES#model.onnx');
// 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 ort.Tensor('float32', dataA, [3, 4]);
const tensorB = new ort.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;
// document.write(`data of result tensor 'c': ${dataC}`);
document.getElementById("output").textContent = `data of result tensor 'c': ${dataC}`;
} catch (e) {
// document.write(`failed to inference ONNX model: ${e}.`);
document.getElementById("output").textContent = `failed to inference ONNX model: ${e}.`;
}
}
main();
</script>


以上でONNX Runtime WebのQuick Startが動作するようになりました。

簡単なアプリケーションですが、アプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/onnx-runtime-web-quick-start.zip

Oracle APEXのアプリケーション作成の参考になれば幸いです。