🛹

JavaScriptでLLMを弄ってみる【transformers.js】

2023/10/28に公開

ブラウザでtransformers動かせたら面白そうなので、一番最初の練習として、node.jsで動かす。
今回は「rinna/japanese-gpt2-xsmall」をnode.jsで動かすことを目標とする。

環境構築

まずはnode.jsで動かせるかを試す。transformers.jsというライブラリがあるらしい
yarn init
yarn add @xenova/transformers

モデルの変換

transformers.jsではonnxモデルでないと読み込めないらしく、onnx変換する必要がある。
onnxモデルの変換スクリプトは配布されているので、リポジトリをcloneする。
https://github.com/xenova/transformers.js/tree/main
cd scripts
venvの環境構築は省略。
pip install -r requirements.txt
python -m scripts.convert --quantize --model_id rinna/japanese-gpt2-xsmall
変換が終了するとmodelsディレクトリに変換されたモデルがあるので、modelsディレクトリごと先程のtransformers.jsをyarn addしたディレクトリに移す。

推論(ローカル)

main.js

import { pipeline,env } from '@xenova/transformers';
// Specify a custom location for models (defaults to '/models/').
env.localModelPath = 'models/';

// Disable the loading of remote models from the Hugging Face Hub:
env.allowRemoteModels = false;

let classifier = await pipeline('text-generation','rinna/japanese-gpt2-xsmall');
let result = await classifier('こんにちは!');
console.log(result);

node main.js

//前略//
2023-10-24 00:14:08.4576675 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] Removing initializer '/transformer/h.5/mlp/act/Constant_output_0'. It is not used by any node and should be removed from the model.
[ { generated_text: 'こんにちは! いつもブログを拝見しています。 いつもブログを拝見' } ]

モデルのアップロード

モデルのアップロードはhuggingfaceのブラウザから行った。firefoxだとうまくアップロードできなかったので、Chromeがオススメ。
https://huggingface.co/saldra/rinna-japanese-gpt2-xsmall-onnx

推論(huggingfaceからダウンロード)

import { pipeline,env } from '@xenova/transformers';

env.allowLocalModels = false;
let classifier = await pipeline('text-generation','saldra/rinna-japanese-gpt2-xsmall-onnx');
let result = await classifier('こんにちは!');
console.log(result[0].generated_text);

これで、Node.jsからonnxモデルで推論することができた。

うまくいかなかったこと

Node.jsでうまくいったのでhtml+javascriptで試すことにした。

<!DOCTYPE html>
<html lang="ja">
    <head>
        <script src="./index.js" type="module"></script>
    </head>
    <body>
        <h1>index.html</h1>
        <p>index.html</p>    
</html>
import { pipeline, env } from "https://cdn.jsdelivr.net/npm/@xenova/transformers@2.6.2";
// Specify a custom location for models (defaults to '/models/').
async function gen(text) {
    const classifier = await pipeline('text-generation','saldra/rinna-japanese-gpt2-xsmall-onnx');
    const result = await classifier(text)
    console.log("result: ", result)
    console.log(result[0].generated_text)
}
gen("こんにちは!")

モデルのダウンロードまではうまく回っているようにみえるものの、推論結果の部分がすべて空白になっている。

モデル指定をなくしてデフォルトの「Xenova/gpt2」で回すとうまく推論できているように見える。

他モデルが動くことを考えると自分のonnx変換にミスがあったのかと考えたが、Node.jsでは動く理由がわからない。もしご存じの方いたら教えてください。

Discussion