Safetensors形式のモデルをLiteRT-LM形式に変換してみる

テクノロジー
この記事は約9分で読めます。

WSL2のセットアップ

 Windowsの機能の有効化または無効化で、「Linux用Windowsサブシステム」と「Windowsサンドボックス」を有効化し、再起動する。

 管理者権限でPowerShellを立ち上げ、以下のコマンドを実行する。Ubuntuがインストールされるので再度再起動する。

wsl --install

 スタートメニューに「Ubuntu」が追加されているので、これをクリックするとUbuntuが立ち上がるとともにターミナルが表示される。

WSL2の環境構築

必要なツールをインストール

 以下のコマンドを実行する。

sudo apt install git git-lfs python3-pip python3-venv

 python –versionと叩いてpythonが入っていることを確認する。入っていなければ以下のコマンドでインストールする。

sudo apt install python3.12

 Python環境構築用にuvをインストール

python3 -m pip install --user -U uv
uv --version

 uvのバージョンが表示されなければPATHが通っていないので、設定してあげる。

echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc

 作業ディレクトリを作成する。今回はユーザーフォルダ直下に「litert-conversion」という名前のディレクトリを作成。
 そして、作成したフォルダへ移動する。

mkdir -p ~/litert-conversion
cd ~/litert-conversion

 仮想環境を作成する。なお、Python3.14を使うとtorchaoでtyping.Unionエラーが出るそうなのでPython3.12を使うことを推奨(1敗)。

python3.12 -m venv litert-lm-20260719
fail to import torchao.quantization.pt2e ?? Issue #3619 ?? pytorch/ao
import torch,torchao import torchao.quantization.pt2e There is following issue: Traceback (most recent call last): File …

 仮想環境の立ち上げは以下のコマンドで行う。

source litert-lm-20260719/bin/activate

 立ち上がったら、以下のコマンドを実行してlitert-torch-nightlyをインストールする。

python -m pip install --upgrade pip
python -m pip install uv
uv tool install --python 3.12 litert-torch-nightly

 uv tool listと入力・実行した際に以下のようになっていればOK。

 litert-torchが立ち上がるか、以下のコマンドで確認する。

litert-torch --help
こんな感じで表示されればOK。「q」と入力することで元の画面に戻れる。

変換対象のモデルを配置

 変換するモデルが未ダウンロードであれば、huggingface-hubをpipしてダウンロードしてもよいが、今回はモデルは既にWindows側でダウンロード済みのため、それをLinux環境にコピーして使う。
 エクスプローラーで以下の赤枠を選択すると、Linux側のファイルを参照できる。

 今回は、作成した作業ディレクトリと同じ階層にモデルを配置した。使うモデルはQwen2.5 Coder-7B Instruct。

変換対象のモデルファイルを格納したディレクトリ

 作業ディレクトリに変換したモデルを出力するためのoutputフォルダを作成する。

mkdir -p ~/litert-conversion/output

モデルを変換

 –quantization_recipeで量子化の形式を選択できるとのこと。今回は「dynamic_wi4_afp32」を選択。

litert-torch export_hf --model="$HOME/Qwen2.5-Coder-7B-Instruct" --output_dir="$HOME/litert-conversion/output" --externalize_embedder --quantization_recipe=dynamic_wi4_afp32

 実行中のログは以下のとおり。変換には7分半ほどかかった。

 ちなみに、今回の変換に当たってメモリの割り当ては以下のようにした。RAM70GB、スワップ25GBでもメモリ不足になり、最終的にRAM70GB、スワップ50GBでようやく成功した…。

 生成されたモデルファイルは以下のとおり。元々は14GB強のモデルが4GB弱になった。

変換したモデルを実行してみる

 モデルをWindows側にコピーして、以下のコードで実行してみる。

import os
import psutil
import time
import litert_lm

process = psutil.Process(os.getpid())
mem_before = process.memory_info().rss / 1024**2  # MB

model_path = r"H:\LLM_Models\litert-lm\qwen2.5-coder-7b-it-dynamic_wi4_afp32\qwen2.5-coder-7b-it-dynamic_wi4_afp32.litertlm"

PROMPT = (
    "transformersとFAISSとstreamlitを使った、"
    "QAチャットボットをPythonで構築して。"
)


process = psutil.Process(os.getpid())
mem_before = process.memory_info().rss / 1024**2
start = time.perf_counter()

with litert_lm.Engine(
    str(model_path),
    backend=litert_lm.Backend.CPU(),
) as engine:

    with engine.create_conversation() as conversation:
        response = conversation.send_message(PROMPT)

        answer = response["content"][0]["text"]

        mem_during = process.memory_info().rss / 1024**2

end = time.perf_counter()

mem_after = process.memory_info().rss / 1024**2

print(answer)

print("=" * 60)
print(f"実行前メモリ使用量       : {mem_before:.2f} MB")
print(f"モデル使用中メモリ使用量 : {mem_during:.2f} MB")
print(f"解放後メモリ使用量       : {mem_after:.2f} MB")
print(f"モデル使用中の増加量     : {mem_during - mem_before:.2f} MB")
print(f"実行時間                 : {end - start:.3f} 秒")

 出力結果はいい感じ。

もちろんです。以下は、transformersとFAISSとstreamlitを使用して質問応答チャットボットを構築するためのPythonコードの基本的な例です。

まず、必要なライブラリをインストールします。

pip install transformers faiss-cpu streamlit

次に、以下のコードを実行します。

import streamlit as st
from transformers import pipeline
import faiss
import numpy as np

# transformersのpipelineを使用して、質問応答モデルをロードします。
qa = pipeline(“question-answering”)

# ここでは、事前に学習済みのモデルを使用しますが、必要に応じて独自のモデルを読み込むこともできます。
model_name = “bert-base-japanese”

# データセットをロードします。ここでは、事前に学習済みのモデルを使用しますが、必要に応じて独自のデータセットを使用することもできます。
# dataset = load_dataset(“squad_japanese”)

# データをベクトル化します。
# sentences = dataset[“train”][“context”] + dataset[“train”][“question”]
# inputs = qa.tokenizer(sentences, return_tensors=”pt”, truncation=True, padding=True)
# with torch.no_grad():
# embeddings = model(**inputs).last_hidden_state

# ベクトルを保存します。
# np.save(“embeddings.npy”, embeddings)

# 事前に学習済みのベクトルを読み込みます。
embeddings = np.load(“embeddings.npy”)

# FAISSでインデックスを作成します。
index = faiss.IndexFlatL2(embeddings.shape[1])
index.add(embeddings)

# Streamlitのアプリケーションを作成します。
st.title(“質問応答チャットボット”)

# ユーザーからの入力を取得します。
query = st.text_input(“質問を入力してください:”)

# 入力された質問をベクトル化します。
inputs = qa.tokenizer([query], return_tensors=”pt”, truncation=True, padding=True)
with torch.no_grad():
query_embedding = model(**inputs).last_hidden_state

# 最も近いベクトルを検索します。
D, I = index.search(query_embedding, 1)

# 最も近いベクトルに対応する回答を取得します。
answer = qa(question=query, context=dataset[“train”][“context”][I[0][0]])[“answer”]

# 回答を表示します。
st.write(answer)

このコードは、質問応答モデルを使用してユーザーからの質問を処理し、最も近いベクトルに対応する回答を返すシンプルなチャットボットを実装しています。ただし、このコードは非常に単純なものです。実際のアプリケーションでは、データの事前処理、モデルの調整、ユーザーインターフェースの改善など、多くの要素を考慮する必要があります。

実行前メモリ使用量 : 646.44 MB
モデル使用中メモリ使用量 : 4143.16 MB
解放後メモリ使用量 : 101.20 MB
モデル使用中の増加量 : 3496.73 MB
実行時間 : 87.121 秒

↓生成テストの実行結果をHTML出力したもの

今回作成したモデルのHuggingFaceリポジトリ

Uranos8685/qwen2.5-coder-7b-it-dynamic_wi4_afp32 · Hugging Face

コメント