名古屋出身ソフトウェアエンジニアのブログ

ELYZA Japanese LLaMA 2 のローカル実行を試す

公開:
更新:

仕事で使うかもしれないとなったので、GPU 搭載の Windows マシンで ELYZA Japanese LLaMa 2 をお試し動作させました。現時点での手順を簡潔にメモします。

ChatGPT のような使い方を想定して、7b-instruct モデルを選択しました。公式リポジトリはこちらです。

ELYZA Japanese LLaMA 2 Key Image

今回の環境

  • Ryzen 9 5950X
  • 64GB RAM
  • GeForce RTX 3090 24GB VRAM
  • Windows 11 Pro
  • CUDA 11.6
  • Python 3.10.8

仮想環境を切る

python -m venv venv
.\venv\Scripts\activate

Python パッケージのインストール

先に PyTorch を入れてから残りを入れるようにします。

pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118
pip install transformers accelerate

オリジナルの bitsandbytes は Windows 非対応なので他所1から入れます。

pip install https://github.com/jllllll/bitsandbytes-windows-webui/releases/download/wheels/bitsandbytes-0.41.1-py3-none-win_amd64.whl

即席 Python 関数の準備

Python の対話シェルを使って試していきます。ノートブックでも同じやり方になると思います。

まず、モデルとトークナイザーのダウンロードを行います。これらは Hugging Face のリポジトリからダウンロードされ、ホーム以下の .cache/huggingface にキャッシュされます。

from transformers import AutoModelForCausalLM, AutoTokenizer
import torch

tokenizer = AutoTokenizer.from_pretrained("elyza/ELYZA-japanese-Llama-2-7b-instruct")
model = AutoModelForCausalLM.from_pretrained(
    "elyza/ELYZA-japanese-Llama-2-7b-instruct",
    torch_dtype=torch.float16,
    device_map="auto",
)

つぎに、ELYZA 公式ドキュメントの例に従って、プロンプト用の関数を作成します。標準的な設定で引数文字列 text による質問を行い、回答文字列を返却するだけの関数です。

B_INST, E_INST = "[INST]", "[/INST]"
B_SYS, E_SYS = "<<SYS>>\n", "\n<</SYS>>\n\n"
DEFAULT_SYSTEM_PROMPT = "あなたは誠実で優秀な日本人のアシスタントです。"

def ask(text):
    prompt = "{bos_token}{b_inst} {system}{prompt} {e_inst} ".format(
        bos_token=tokenizer.bos_token,
        b_inst=B_INST,
        system=f"{B_SYS}{DEFAULT_SYSTEM_PROMPT}{E_SYS}",
        prompt=text,
        e_inst=E_INST,
    )
    with torch.no_grad():
        token_ids = tokenizer.encode(prompt, add_special_tokens=False, return_tensors="pt")
        output_ids = model.generate(
            token_ids.to(model.device),
            max_new_tokens=1024,
            pad_token_id=tokenizer.pad_token_id,
            eos_token_id=tokenizer.eos_token_id,
        )
        output = tokenizer.decode(output_ids.tolist()[0][token_ids.size(1):], skip_special_tokens=True)
        return output

これで準備完了です。

質問する

いくつか質問をしてみます。

今回作った関数は同期処理なので、全文が完成するまでしばらく待つ必要があります2

Java と C# はどちらが優れていますか?

>>> ask("Java と C# はどちらが優れていますか?")

Java と C# はともにオブジェクト指向のプログラミング言語であり、.NET Framework を採用している点でも共通点がありますが、異なる点も多くあります。一般的な違いとしては、Java は規約が明確であり、オープンソースである一方で、C# は Microsoft の製品であり、規約が明確でないという点が挙げられます。

プログラミング言語の選択は、開発するアプリケーションや、開発する環境によって異なります。そのため、あくまで一般的な違いに留まることを考えると、お答えするのが難しくなってしまいます。

GTA シリーズについて教えて

>>> ask("GTA シリーズについて教えて。")

GTA (グランド・ザンター・オープン・ワールド) は、ロックスター・ゲームスが開発しているオープンワールド型のアクションアドベンチャーゲームのシリーズです。

1997年に初代『グランド・ザンター・オープン・ワールド』が発売されて以降、現在までに『GTA III』『GTA IV』『GTA V』と、主に3Dグラフィックで展開されています。

また、『GTA Advance』『GTA Chinatown Wars』と いったスマートフォン用ゲームや、『GTA Online』といったオンラインモードもあります。

シリーズを通して特徴的なのは、オープンワールド型のマップに自由に動き回り、任務をこなしていくというゲームプレイです。

また、シリーズを通して描かれるストーリーは、一貫して高い評価を受けています。

名古屋市の観光プランを考えて

>>> ask("名古屋市の観光プランを考えて")

承知しました。名古屋市の観光スポットを中心にプランを考えます。

1日目:

  • 名古屋城
  • 名古屋駅

2日目:

  • 東山動植物園
  • 金山
  • 久屋大通公園

3日目:

  • 熱田神宮
  • 名古屋駅

以上が名古屋市の観光スポットを中心とした3 日間のプランです。ただし、これはあくまで一つの意見として参考になさってください。

所感

上記回答例のように、日本語として自然なテキストを生成できる一方、知識的な誤りは多分に含んでしまうようです。

知識を外部から注入できるタスクであれば、直ちに事業応用も可能かと思いました。

その他

サンプルでは from_pretrained を使って Hugging Face から実行時にモデルをダウンロードしています(キャッシュはされる)。デプロイ時にネットワーク上の依存物と完全に切り離したい場合は、transformers パッケージの save_pretrained を使いモデルを保存し、その上で読み込み時のパスを調整します。


  1. https://github.com/jllllll/bitsandbytes-windows-webui ↩︎

  2. 非同期ストリーム処理をする場合は transformers パッケージの TextIteratorStreamer を使用します。 ↩︎