JavaScriptでLLMを弄ってみる【transformers.js】
ブラウザで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する。
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がオススメ。
推論(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