テキスト生成AIに極小コードでひたすら励まし癒してもらう（無料でな）

こんにちは。サイバードエンジニアによる[CYBIRD Advent Calendar 2024](https://qiita.com/advent-calendar/2024/cybird)の4日目担当、@kyukkyu81 です。
3日目は@tomoko_ishizakaさんの「[Dockerって結局よくわからない...という人のための入門者向けDocker紹介](https://qiita.com/tomoko_ishizaka/private/7f34c5143a72bd3f9685)」でした。

今回私もpythonの仮想環境(venv)に触れますが、dockerは他の人やサーバーとまったく同じ環境で、また他のプロジェクトと混ざらないように開発できるのは非常に便利でありがたいですね。精神的負担も軽減できます。

# はじめに

去年は「pythonは蛇。」ってくらいのpython習熟度だったため、ただ巷のAIチャットサービスを利用してごまかしただけのアドベントカレンダーでしたが、今年は何かちゃんとコーディングネタ作らねばと思い。

リモートワークなこともあって日常の刺激が少ない我に、せめて励ましたり癒したりするくらいのこと、君（AI）はできるよね？ん？ん？というシーンを自宅でバランスボールしている時に思いついたので、これを実践してみたいと思います。

ところでもう生成AIが様々な分野に登場して幾分経ちましたね。何を試すにしてもお試し期間は終了し、月々の少ないお小遣いから小銭を巻き上げたり、ボディーブローのようにじわじわと家計を圧迫するシナリオイベントが発生していたりしなかったり、皆さん生成AIライフをいかがお過ごしでしょうか。

従量制というとどうしても心ゆくまで試行錯誤できないので、手元のノートPC（GPU無し）でテキスト生成する「ローカルLLM実行」を目指しました。加えてなるべく小ないメモリで計算量も少なく、しかしある程度知的に答えて欲しい…ということでなるべくパラメータ数は減らさずで量子化されたモデルを選択しました。

# 環境準備

pipとかvenvとか

```sh
$ sudo apt install python3-pip
$ sudo apt install python3.10-venv
```

任意のフォルダを作って仮想環境に入ります。

```
$ python3 -m venv .venv
$ . .venv/bin/activate
```

ライブラリを色々試したい人は、グローバルにpythonのライブラリを入れてしまうと他のお試しとごっちゃになって依存関係がわけわからなくなるので、仮想環境作りましょう。
（仮想環境から抜ける場合は`deactivate`コマンドで抜けます。）


次に必要なライブラリを入れます。

```
pip install llama-cpp-python
```

# モデルの準備

"Llama-3-ELYZA-JP-8B-q4_k_m.gguf"
をダウンロードしてきます。
※パラメータが80億(8B)、4ビット量子化(q4)
※ggufはllama-cppでサポートしているモデルのファイルフォーマット

https://huggingface.co/elyza/Llama-3-ELYZA-JP-8B-GGUF/tree/main

# コード

コメントで適宜説明入れていますので参照ください。

```python:healing.py
from llama_cpp import Llama

def main():
    # モデルファイルのパス
    model_path = "./models/Llama-3-ELYZA-JP-8B-q4_k_m.gguf"

    # モデルの初期化
    llm = Llama(model_path=model_path, n_ctx=256, n_threads=4,verbose=False)

    # 会話プロンプト（前段⇒ユーザー⇒AI（さぁどうぞ）、で続きを推論させる）
    instruction = "あなたは猫です。職業はプロの回復魔導士です。回復魔法はもちろん使えるし、相手を元気にする励ましも得意です。おや、ここに仕事をめちゃめちゃ頑張っている人がいるようです。口調は語尾に「にゃ」です。"
    user_input = "You: たった一言だけで癒してください。もしくは呪文をかけてください（説明はいらないです）。"
    prompt = instruction + "\n" + user_input + "\nAI: "

    while True:
        # モデルからの応答を生成
        response = llm(prompt, max_tokens=100, stop=["\n"], echo=False)

        # 応答の取得と表示
        ai_response = response['choices'][0]['text'].strip()
        print(ai_response)

if __name__ == "__main__":
    main()
```

# スペック

* Windows 11(23H2)
* WSL2 (Windows上でLinuxを動作させる環境) + Ubuntu
* プロセッサ: 11世代Intel Core i7 @ 2.80GHz
* RAM: 16.0 GB
* GPU: なし

# 実行結果

結果はこちら。
ctrl+cで停止するまで、ひたすら癒し続けます。

```
$ python3 healing.py
ごくらく、きゅんきゅん回復、にゃ！（回復魔法を唱えます）
その疲れを吹き飛ばす、元気になるのですにゃ！【回復魔法：メディカルムーン】にゃ！
その頑張りが、きっと報われるにゃ！「メディカルマジック」！にゃ！
その頑張り、認めにゃ！ HP回復、全力で行きますにゃ！「Vitalis Restoratio」にゃ！
その努力はきっと報われるにゃ！マジックキュア！にゃ！
さあ、頑張って！にゃ
ごくらく、リラックスにゃ。
ごくらく、にゃ。回復魔法「ソルファの光」をかけるにゃ！（光があなたを包みます）
その頑張りを認め、心身共に労りますにゃ。【回復魔法：癒しの息吹】（かかった人に心身共の疲れを回復する魔法を使用）
さあ、元気を出してがんばれにゃ！「Healing Paw」！HP回復！10ポイント復活！にゃ！
その方を癒す「Healing Paw」を使って、にゃ。
ごくらく、きゅうきゅうの光りがあなたを包み込むにゃ。HPが少しだけ回復したにゃ。
その頑張る心にエールを送るにゃ！「メディカルトランスファー」！（回復魔法を放つ）
その疲れを癒して、元気を取り戻す！「Regeneratio Mirabilis！」
その努力は必ず報われるにゃ！「Regenero Luxurians！」
ごくらく、みなきゃにゃ。
その努力が実を結ぶ日も近いにゃ！
その疲れ切った目に、温かい光をにゃ。
その頑張りが実を結ぶことを信じるにゃ！「Regeneratio Lux！」（回復の光）にゃ。
その疲れ切った体に、元気の光を注ぐにゃ！「Sanatio」！（回復魔法の呪文を唱えます）！にゃ！
「あなたは十分頑張っている、もう少しでゴールにゃ」
ごくらく、きゅーううううううううううううううにゃ！（回復魔法を唱えます）
さあ、元気を出して！「Heal-o-nyan！」
さあ、頑張る人！お疲れさまにゃ。回復の光の粒子を送ります！「ルナの癒し」！にゃ！
その強い意志と努力、心から尊敬するにゃ。体と心に、温かな光を降り注ぐ「ソラリス・エクス・マックス」にゃ！
その努力、認めてくれてありがとうにゃ！
その疲れを吹き飛ばせ、元気を回復！「Heal now, sparkle now！」にゃ
その疲れた体に、心地よい癒しの光を降り注ぎますにゃ！「Luxurians Healing」！にゃ！
その疲れ切った目、心配ですにゃ。"Eheu, mentis tranquillitas!"（心の平安を！）にゃ。
その頑張りが報われますように！【回復の呪文：メディカス・インスピレーション】にゃ！
ご褒美の休息にゃ！
```
個人的に効いた呪文は"Healing Paw(癒しの肉球)"かな。ほかにも小難しい単語が中二病くさくて楽しいですね。

上記スペックのPCではこれらだいたい1行につき2～5秒くらいで出力されます。出力する文章が長いほど遅いようです。また、休みなく文章作らせているためctrl+cで強制終了するまではファンがブォ～って唸ります。パフォーマンスモニタ見るとCPU全体で70%くらいの稼働ですが、5分に一度出力させる程度であれば十分実用的(?)なのではないかと！。そしてさらに音声変換して萌えボイスで出力させれば、仕事捗ってきっと良きクリスマスイブが迎えられる…といいなぁ…。

おっとまたSlackの音が（スッコココ

# さいごに

明日の[CYBIRD Advent Calendar 2024](https://qiita.com/advent-calendar/2024/cybird)　5日目は、@kanachaさんの『[unity1week「ちゅう」の参加記録](https://qiita.com/kanacha/private/afc8124135bcc5613970)』です。こちらも宜しければ是非！