PLaMo 2 1Bを動かしてみるまで

# はじめに

PFNが日本語用LLMをhuggingfaceに公開しました。

https://x.com/preferred_jp/status/1887734933143363671

https://huggingface.co/pfnet/plamo-2-1b

ライセンスがApache 2.0ということで、扱いやすいのが魅力的です。

今回、これを手元で動かしてみることを目標にします。

## TL; DR;

Google ColabのProに課金して、L4インスタンスを使うと動かすことができます。CPUやT4インスタンスで動かすことはできませんでした。

# 試行錯誤

## ローカル（Mac）で動かす

私の所有しているMac（M1 Pro)ではnvidiaのGPUを積んでいないので、CPUで動かすことを目標します。

### ライブラリのインストール

PLaMoのREADMEに書かれているもののうち、mamba_ssmとcausal_conv1dを除いてインストールします。

```bash
pip install numpy numba torch transfomers
```

公式の実行コードは公式だと以下ですが、これだとcausal_conv1dをつかう分岐でエラーになってしまったので、モデルの設定をいじって動かします。

```python
from transformers import AutoConfig, AutoModelForCausalLM, AutoTokenizer, pipeline

# 1. configを読み込む
config = AutoConfig.from_pretrained("pfnet/plamo-2-1b", trust_remote_code=True)

# 2. configの各パラメータをカスタマイズする
config.mamba_enabled = False

# 3. カスタマイズしたconfigを使ってモデルを読み込む
model = AutoModelForCausalLM.from_pretrained("pfnet/plamo-2-1b", config=config, trust_remote_code=True)

# 4. トークナイザーの読み込み
tokenizer = AutoTokenizer.from_pretrained("pfnet/plamo-2-1b", trust_remote_code=True)

# 5. pipelineにモデルとトークナイザーを渡して作成
gen_pipeline = pipeline("text-generation", model=model, tokenizer=tokenizer)

# 6. テキスト生成の実行
result = gen_pipeline("The future of artificial intelligence technology is ", max_new_tokens=32)
print(result)
```

実行結果

```console
/Users/autotaker/.local/share/virtualenvs/plamo-test-CdU1Gb5W/lib/python3.11/site-packages/transformers/dynamic_module_utils.py:212: UserWarning: mamba_ssm could not be imported
  module_spec.loader.exec_module(module)
/Users/autotaker/.local/share/virtualenvs/plamo-test-CdU1Gb5W/lib/python3.11/site-packages/transformers/dynamic_module_utils.py:212: UserWarning: causal_conv1d could not be imported
  module_spec.loader.exec_module(module)
Loading checkpoint shards: 100%|████████████████████████████████████████████| 6/6 [00:03<00:00,  1.69it/s]
Some weights of the model checkpoint at pfnet/plamo-2-1b were not used when initializing PlamoForCausalLM: ['model.layers.layers.0.mixer.A_log', 'model.layers.layers.0.mixer.B_norm_weight', 'model.layers.layers.0.mixer.C_norm_weight', 'model.layers.layers.0.mixer.D', 'model.layers.layers.0.mixer.bcdt_proj.weight', 'model.layers.layers.0.mixer.conv1d.weight', 'model.layers.layers.0.mixer.dt_bias', 'model.layers.layers.0.mixer.dt_norm_weight', 'model.layers.layers.0.mixer.dt_proj.weight', 'model.layers.layers.0.mixer.in_proj.weight', 'model.layers.layers.0.mixer.out_proj.weight', 'model.layers.layers.10.mixer.A_log', 'model.layers.layers.10.mixer.B_norm_weight', 'model.layers.layers.10.mixer.C_norm_weight', 'model.layers.layers.10.mixer.D', 'model.layers.layers.10.mixer.bcdt_proj.weight', 'model.layers.layers.10.mixer.conv1d.weight', 'model.layers.layers.10.mixer.dt_bias', 'model.layers.layers.10.mixer.dt_norm_weight', 'model.layers.layers.10.mixer.dt_proj.weight', 'model.layers.layers.10.mixer.in_proj.weight', 'model.layers.layers.10.mixer.out_proj.weight', 'model.layers.layers.12.mixer.A_log', 'model.layers.layers.12.mixer.B_norm_weight', 'model.layers.layers.12.mixer.C_norm_weight', 'model.layers.layers.12.mixer.D', 'model.layers.layers.12.mixer.bcdt_proj.weight', 'model.layers.layers.12.mixer.conv1d.weight', 'model.layers.layers.12.mixer.dt_bias', 'model.layers.layers.12.mixer.dt_norm_weight', 'model.layers.layers.12.mixer.dt_proj.weight', 'model.layers.layers.12.mixer.in_proj.weight', 'model.layers.layers.12.mixer.out_proj.weight', 'model.layers.layers.14.mixer.A_log', 'model.layers.layers.14.mixer.B_norm_weight', 'model.layers.layers.14.mixer.C_norm_weight', 'model.layers.layers.14.mixer.D', 'model.layers.layers.14.mixer.bcdt_proj.weight', 'model.layers.layers.14.mixer.conv1d.weight', 'model.layers.layers.14.mixer.dt_bias', 'model.layers.layers.14.mixer.dt_norm_weight', 'model.layers.layers.14.mixer.dt_proj.weight', 'model.layers.layers.14.mixer.in_proj.weight', 'model.layers.layers.14.mixer.out_proj.weight', 'model.layers.layers.2.mixer.A_log', 'model.layers.layers.2.mixer.B_norm_weight', 'model.layers.layers.2.mixer.C_norm_weight', 'model.layers.layers.2.mixer.D', 'model.layers.layers.2.mixer.bcdt_proj.weight', 'model.layers.layers.2.mixer.conv1d.weight', 'model.layers.layers.2.mixer.dt_bias', 'model.layers.layers.2.mixer.dt_norm_weight', 'model.layers.layers.2.mixer.dt_proj.weight', 'model.layers.layers.2.mixer.in_proj.weight', 'model.layers.layers.2.mixer.out_proj.weight', 'model.layers.layers.4.mixer.A_log', 'model.layers.layers.4.mixer.B_norm_weight', 'model.layers.layers.4.mixer.C_norm_weight', 'model.layers.layers.4.mixer.D', 'model.layers.layers.4.mixer.bcdt_proj.weight', 'model.layers.layers.4.mixer.conv1d.weight', 'model.layers.layers.4.mixer.dt_bias', 'model.layers.layers.4.mixer.dt_norm_weight', 'model.layers.layers.4.mixer.dt_proj.weight', 'model.layers.layers.4.mixer.in_proj.weight', 'model.layers.layers.4.mixer.out_proj.weight', 'model.layers.layers.6.mixer.A_log', 'model.layers.layers.6.mixer.B_norm_weight', 'model.layers.layers.6.mixer.C_norm_weight', 'model.layers.layers.6.mixer.D', 'model.layers.layers.6.mixer.bcdt_proj.weight', 'model.layers.layers.6.mixer.conv1d.weight', 'model.layers.layers.6.mixer.dt_bias', 'model.layers.layers.6.mixer.dt_norm_weight', 'model.layers.layers.6.mixer.dt_proj.weight', 'model.layers.layers.6.mixer.in_proj.weight', 'model.layers.layers.6.mixer.out_proj.weight', 'model.layers.layers.8.mixer.A_log', 'model.layers.layers.8.mixer.B_norm_weight', 'model.layers.layers.8.mixer.C_norm_weight', 'model.layers.layers.8.mixer.D', 'model.layers.layers.8.mixer.bcdt_proj.weight', 'model.layers.layers.8.mixer.conv1d.weight', 'model.layers.layers.8.mixer.dt_bias', 'model.layers.layers.8.mixer.dt_norm_weight', 'model.layers.layers.8.mixer.dt_proj.weight', 'model.layers.layers.8.mixer.in_proj.weight', 'model.layers.layers.8.mixer.out_proj.weight']
- This IS expected if you are initializing PlamoForCausalLM from the checkpoint of a model trained on another task or with another architecture (e.g. initializing a BertForSequenceClassification model from a BertForPreTraining model).
- This IS NOT expected if you are initializing PlamoForCausalLM from the checkpoint of a model that you expect to be exactly identical (initializing a BertForSequenceClassification model from a BertForSequenceClassification model).
Some weights of PlamoForCausalLM were not initialized from the model checkpoint at pfnet/plamo-2-1b and are newly initialized: ['model.layers.layers.0.mixer.k_weight', 'model.layers.layers.0.mixer.o_proj.weight', 'model.layers.layers.0.mixer.q_weight', 'model.layers.layers.0.mixer.qkv_proj.weight', 'model.layers.layers.10.mixer.k_weight', 'model.layers.layers.10.mixer.o_proj.weight', 'model.layers.layers.10.mixer.q_weight', 'model.layers.layers.10.mixer.qkv_proj.weight', 'model.layers.layers.12.mixer.k_weight', 'model.layers.layers.12.mixer.o_proj.weight', 'model.layers.layers.12.mixer.q_weight', 'model.layers.layers.12.mixer.qkv_proj.weight', 'model.layers.layers.14.mixer.k_weight', 'model.layers.layers.14.mixer.o_proj.weight', 'model.layers.layers.14.mixer.q_weight', 'model.layers.layers.14.mixer.qkv_proj.weight', 'model.layers.layers.2.mixer.k_weight', 'model.layers.layers.2.mixer.o_proj.weight', 'model.layers.layers.2.mixer.q_weight', 'model.layers.layers.2.mixer.qkv_proj.weight', 'model.layers.layers.4.mixer.k_weight', 'model.layers.layers.4.mixer.o_proj.weight', 'model.layers.layers.4.mixer.q_weight', 'model.layers.layers.4.mixer.qkv_proj.weight', 'model.layers.layers.6.mixer.k_weight', 'model.layers.layers.6.mixer.o_proj.weight', 'model.layers.layers.6.mixer.q_weight', 'model.layers.layers.6.mixer.qkv_proj.weight', 'model.layers.layers.8.mixer.k_weight', 'model.layers.layers.8.mixer.o_proj.weight', 'model.layers.layers.8.mixer.q_weight', 'model.layers.layers.8.mixer.qkv_proj.weight']
You should probably TRAIN this model on a down-stream task to be able to use it for predictions and inference.
Hardware accelerator e.g. GPU is available in the environment, but no `device` argument is passed to the `Pipeline` object. Model will be on CPU.
[{'generated_text': 'The future of artificial intelligence technology is ’leadingkidWORD’’’’’hurhurhurhurhurhurhurdonramawatwatwatwatwatwatwatwatwatwatwatwatwatcara'}]
```

モデルロード時にいくつかwarningが出ていて、結果もまともに動きませんでした。まだ設定が足りてないようです。

（追記）ソースコードを分析したところ、`config.mamba_enabled`はモデルのアーキテクチャを変更するオプションらしく、オプションを有効にした状態で学習した重みをオプションを無効にした状態で使用しても意味のある結果にならないようです。

依存しているmamba_ssmやcausal_conv1dというライブラリはCUDA前提のライブラリなのでApple Siliconで動かすのは一筋縄では行かなさそうでした。

## Google Colabで動かす


残念ながらローカルで動かすことは一旦諦めてGoogle Colabで動かすことを目指します。

### T4インスタンスでトライ

最初はT4インスタンスで試してみます。

```python
!pip install transformers torch numpy numba mamba_ssm causal_conv1d
```

これを実行すると

https://github.com/state-spaces/mamba/issues/607

のエラーに該当したのでその対処法を試みました。

```python
!pip install torch==2.4.0 torchvision==0.19.0 torchaudio==2.4.0 --index-url https://download.pytorch.org/whl/cu121
!pip install mamba_ssm==2.2.2 causal_conv1d==1.4.0
```

これでライブラリのインストールには成功しました。


```python
import transformers

# パイプラインを使ってモデルをロードし、テキスト生成を実施
pipeline = transformers.pipeline("text-generation", model="pfnet/plamo-2-1b", trust_remote_code=True)
result = pipeline("The future of artificial intelligence technology is ", max_new_tokens=32)
print(result)
```

残念ながら、エラーで動きませんでした。

```console
Loading checkpoint shards: 100%

 6/6 [00:23<00:00,  1.87s/it]
Device set to use cuda:0
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-6-6060c1603acc> in <cell line: 0>()
      3 # パイプラインを使ってモデルをロードし、テキスト生成を実施
      4 pipeline = transformers.pipeline("text-generation", model="pfnet/plamo-2-1b",trust_remote_code=True)
----> 5 result = pipeline("The future of artificial intelligence technology is ", max_new_tokens=32)
      6 print(result)

38 frames

/usr/local/lib/python3.11/dist-packages/triton/backends/nvidia/compiler.py in make_llir(src, metadata, options, capability)
    214         if os.environ.get("TRITON_DISABLE_LINE_INFO", "0") == "0":
    215             passes.llvmir.add_di_scope(pm)
--> 216         pm.run(mod)
    217         # LLVM-IR (MLIR) -> LLVM-IR (LLVM)
    218         llvm.init_targets()

IndexError: map::at
```

調べたところ以下のIssueの事象に該当しているようです。

https://github.com/triton-lang/triton/issues/4813

有効な解決策は見つからなかったのでGPUを変えて再チャレンジしました。

（2025/02/13追記) 以下の記事で無料枠のGPUで動かす方法が紹介されています！ぜひそちらもご確認ください。

https://www.mattari-benkyo-note.com/2025/02/12/plamo-2-1b-infernece/

### L4インスタンスでトライ

今度はColab Proに課金してL4インスタンスで試してみます。

```python
!pip install torch==2.4.0 torchvision==0.19.0 torchaudio==2.4.0 --index-url https://download.pytorch.org/whl/cu121
!pip install mamba_ssm==2.2.2 causal_conv1d==1.4.0
```

```python
import transformers
pipeline = transformers.pipeline("text-generation", model="pfnet/plamo-2-1b", trust_remote_code=True)
print(pipeline("The future of artificial intelligence technology is ", max_new_tokens=32))
```

```console
Device set to use cuda:0
[{'generated_text': 'The future of artificial intelligence technology is rife with possibilities, from self-driving cars to personalized medicine. But one area that has yet to fully embrace AI is agriculture.\nFarmers and agricultural professionals have long relied on'}]
```

ようやく動きました！

試しに日本語でも質問してみましょう。

```python
print(pipeline("美味しいカレーの作り方のレシピを紹介します。", max_new_tokens=300)[0]["generated_text"])
```

```console
美味しいカレーの作り方のレシピを紹介します。
## 美味しいカレーの作り方
### 材料
- 玉ねぎ １個
- にんじん １本
- じゃがいも １個
- 豚ひき肉 １００ｇ
- にんにく １かけ
- しょうが １かけ
- サラダ油 大さじ１
- カレー粉 大さじ１
- 塩 小さじ１
- こしょう 少々
- 水 １００ｃｃ
- トマト缶 １缶
- ケチャップ 大さじ１
- ウスターソース 大さじ１
- コンソメ 小さじ１
- 砂糖 小さじ１
- カレールー １個
- 水 １００ｃｃ
- バター 大さじ１
- パセリ 適量
### 作り方
- 玉ねぎ、にんじん、じゃがいもはみじん切りにします。
- フライパンにサラダ油を熱し、にんにく、しょうがを炒めます。
- 香りが出てきたら、ひき肉、玉ねぎ、にんじん、じゃがいも、トマト缶、ケチャップ、ウスターソース、コンソメ、砂糖、カレールー、水、バターを加え、中火で炒めます。
- 水とバターを加え、沸騰したら弱火で１０分ほど煮込みます。
- カレールーを溶かし、パセリを散らして完成です。
## まとめ
美味しいカレーの作り方のレシピを紹介しました。
ぜひ参考にしてみてください。Domain: www.s-housing.jp
**「住宅の性能」**。住宅の性能は、住宅
```

カレーの作り方を正しく教えてくれました！トマト缶とかも使っていてアレンジが効いてますね！

ということで無事Colab Proに課金すれば動かすことができました！