【M1以降対応】Apple謹製自然言語処理モデルをローカルで動かしてみる

# はじめに
2024年4月，Appleが自然言語モデル **OpenELM** を発表しました．
OpenELMは **Open** **E**fficient **L**anguage **M**odels の略で，要するにオープンソースな自然言語モデルということですね．
 ChatGPTやGeminiなどさまざまな自然言語処理モデルが群雄割拠するこの時代においては，自然言語処理モデルは珍しいものではなくなってきていますが，それでもローカルで無料で動くというのは魅力的なものです．
 今回はそんなOpenELMをローカルで動かしてみた記事になります．

 # 想定読者
 - M1以降のチップを積んでいるMacユーザー
 - プログラミングあんまりわからない
 - 黒い画面（ターミナル）あんまりわからない
 - 機械学習あんまりわからない

 全部わかる人にとっては冗長な部分もあると思うので，飛ばし飛ばし読んでみてください．
 Macユーザーではなくても動作可能ですが，Pythonの導入などが必要になると思います．
 エラーを解決しながら手順を踏めば，同様に動作可能です．

# 実践編
## LESSON1　ターミナルと仲良くなる
はじめに，環境を用意します．
Launchpadから「ターミナル」アプリを開いて，以下のコマンドを打ってください．

```bash
git clone https://huggingface.co/apple/OpenELM
```
これにより，OpenELMを使うための環境を整えることができます．

gitは標準でインストールされていると思うのですが，うまくいかない場合はgitのインストールをしてみてください．
解説記事は星の数ほどあるのでそちらに任せることにします．

次に，
```bash
cd OpenELM
```
を行い，OpenELMの環境に移動します．

これでひとまずの準備は整いました．

## LESSON2　Pythonと仲良くなる
兎にも角にもPythonと仲良くなりましょう．
PythonはMacにおいてはデフォルトでインストールされているはずですが，最初はライセンス関係のポップアップが出ることもあるようです．
「ターミナル」で，以下のコマンドを打ち込んでください．
```bash 
python3 -V
```
問題なく動作していればPythonのバージョン番号が出るはずです．
ポップアップが出た方はそのまま許可を押してください．
現在MacにおけるPythonの標準バージョンは3.9と認識していますが，それよりも後のバージョンであれば恐らく問題はないと思います．
もし，失敗した場合は，[過去の記事](https://qiita.com/navyracooon/items/4a6800d3377a12716cad)などを参考にしつつ，pyenvを用いてバージョンを3.9に固定していただければと思います．

次に，仮想環境を立ち上げたいので，以下のコマンドを打ちます．
```
python3 -m venv .venv
source .venv/bin/activate
```
これで，仮想環境が有効になりました．

次は，必要なライブラリをインストールします．
以下のコマンドを打ち込んでください．
```bash
pip install torch transformers
```
pipに関しては標準ではインストールされていないのですが， `sudo easy_install pip` でインストールできるはずです．
ただ，実際に私が試したことはないので，失敗した場合は他の解説記事に当たってください．こちらも星の数ほど解説記事があります．

## LESSON3　Hugging Faceと仲良くなる
[Hugging Face](https://huggingface.co/)はアメリカの機械学習のコミュニティです．Appleもこのサイトを活用しているようなので，私たちもHugging Faceと仲良くなる必要があります．

まずは右上のSign Upから会員登録をしてください．画面に沿って登録をすると1分ほどで終わると思います．
メールによる認証もあるので，そちらを確認したら会員登録終了です．メール認証を終えていないと次のステップに進めないので注意してください．

会員登録が終わったら次にアカウントトークンを発行します．このトークンはターミナルから自分のアカウントにログインするときに使うものなので、**絶対に**流出させないでください．
アカウントトークンは，右上のユーザーアイコン > Settings > Access Tokens > New tokenで発行できます．
Nameは(恐らく)適当で問題ありません．私はOpenELMにしました．RoleもREADで問題ないでしょう．

発行できたら，以下のようになっているはずです．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627957/810888f9-0b48-a904-2497-7eac286095fc.png)
コピーをすればアクセストークンの準備は完了です．

次に，以下のサイトにアクセスします．

https://huggingface.co/meta-llama/Llama-2-7b-hf

どうやら，こちらのサイトで個人情報を登録しないとうまくいかないようです．
Meta社に情報を握られてしまいますが，我慢しましょう．
ログインしている状態ではフォームが出てくると思うので，適当に回答しておきましょう．
Affiliation（所属）は何でも良いと思います．僕は所属の大学名を書いておきました．
フォームを送ったら，オーナーが認証をするのを待たなくては行けません．
気長に待ちましょう．僕の場合は1,2分で承認が通りました．

オーナーからの承認が通ればHugging Face側の準備は完了です．

## LESSON4　OpenELMに敬意を払う
ここまでくればあとは実際に走らせるだけです．
```bash
python generate_openelm.py --model apple/OpenELM-270M --hf_access_toke hf_ThisIsFakeHuggingFaceAccessToken --prompt 'Once upon a time there was' --generate_kwargs repetition_penalty=1.2
```
`hf_ThisIsFakeHuggingFaceAccessToken`の部分は先ほど入手したアクセストークンに置き換えてください．

うまく行けば以下のような結果を得られます．
```
=========================================================================================================
 Prompt + Generated Output
---------------------------------------------------------------------------------------------------------
Once upon a time there was a man named John. He was a farmer, and he had a wife named Mary. They were married for 20 years, and they had two children. One day, John's wife died, and the other died too.
John's wife was very sick, and she was dying. She was in pain, and she was not able to work. Her husband was very sad, and he wanted to help her. So he went to his brother-in-law, who was also a farmer, and he asked him if he could come over and help.
The brother-in-law said that he would be happy to do so, but he didn't want to go alone. So John went with his brother-in-law, and they went to the farm where John's wife was dying.
They found her body, and they buried her. Then they took her clothes, and they put them in a box. They put her shoes, and they put her purse, and they put her hair. They put her clothes on her, and they put her shoes on her, and they put her purse on her.
Then they put her hair in a p
---------------------------------------------------------------------------------------------------------

Generation took 7.94 seconds.
```
Johnという男性の昔話が出力されたようです．
お疲れ様でした．

これの`'Once upon a time there was'` 部分を変更すればプロンプトを変更できます．
また，`apple/OpenELM-270M` 部分を変更すれば，より別のモデルなどに変更できます．
ここでは，`apple/OpenELM-3B-Instruct` を使ってみます．

```bash
python generate_openelm.py --model apple/OpenELM-450M-Instruct --hf_access_toke hf_ThisIsFakeHuggingFaceAccessToken --prompt 'ジョジョの奇妙な冒険 第10部のプロットを説明して' --generate_kwargs repetition_penalty=1.2
```


結果
```
=========================================================================================================
 Prompt + Generated Output
---------------------------------------------------------------------------------------------------------
ジョジョの奇妙な冒険 第10部のプロットを説明しています。

**作者:** [ジョジョ](https://www.youtube.com/user/jojogames)

**公開日:** 2021/05/26

## 第10部「奇妙な冒険」

[![サイトリンク](https://img.youtube.com/vi/jojogames/mqdefault.jpg)](https://www.youtube.com/watch?v=jojogames&list=PL_qwQx-7gkJZuYbhX38zf4LcRy9HlWKrU)

# 概要

これは、奇妙な冒険です。

## 主人公

* **名前:** ジョジョ
* **性別:** 男性
* **出生地:
---------------------------------------------------------------------------------------------------------

Generation took 11.24 seconds.
```

# おわりに
やはり，軽量の言語モデルということもあってChatGPTなどに比べると弱いですね．
あまりいい結果が得られなかったように思います．
モデルの質を上げたり，下の補足資料で説明されているパラメータなどの調整をすればより良い結果を望めるかもしれません．コメントいただけると幸いです．
また，質問も受け付けています．エラーなどが出た際はエラーメッセージを添えていただければお力添えできるかと思います．では．

# 補足
こちらに，Appleによる詳細な情報があります．
興味があれば見てみると良いでしょう．
各モデルのスコアや，追加オプションの説明などがあります．

https://huggingface.co/apple/OpenELM