Tanzu Kubernetes Grid上でllama.cppをサクッと使う

[前回](https://qiita.com/ipppppei/items/371cd0eed13dd28f7c4f)はTanzu Kubernetes Grid（以下TKG）上でJupyter Notebookを立ち上げるところまで行った。
せっかくなので、ここではその環境をPythonの実行環境と見立ててNotebookを作成し、llama.cppを動かしてみる。
## llama.cppとは
[llama.cpp](https://github.com/ggerganov/llama.cpp)とは元々はMacBook上で[LLaMA](https://ai.meta.com/llama/)(Large Language Model Meta AI：Metaが公開した言語モデル)を動かすためのランタイムであり、Mac以外でもWindowsやLinuxでも動作可能である。
大きな特徴としては**GPUが不要**であり、ちょっとした検証目的とかにはうってつけである。
また現在はサポートしているモデルもLLaMA以外のモデルも複数対応し、サポート言語もPython、Go、Node.js、Java、etcと幅広く対応しており、ちょっとだけLLMやってみたい人にはありがたい。

## Jupyter Notebook環境の作成
前回作った環境がリッチかつjupyter-tensorflow-cuda-fullを使っていれば作成は不要だが、もしスペックが低い場合や、大きなモデルを持ち込みたい人は再作成する。
また、イメージについてはjupyter-tensorflow-fullだとpipのinstallに必要なパッケージが不足しているので注意が必要となる。
ここでは以下のスペックで作成する。
- CPU：2
- Memory：8
- Workspace Volume：10Gi
- Image：kubeflownotebookswg/jupyter-tensorflow-cuda-full:v1.6.0
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/716e3aa0-4d74-f7c0-35d3-9dfcfeeaadd4.png)

ここではWorkspace Volumeで作成したが、データを残したい人はData Volumesで作成した方がいい。
起動したら`CONNECT`をクリックしてJupyter Notebookに接続する。

## Notebookの作成
Notebookを作成していく。なお、作るのが面倒な人は[こちら](https://github.com/imurata/jupyter-mynotebook/blob/main/lla-cpp-python-sample.ipynb)に今回の検証で使ったものを置いているので、ダウンロードして使うとよい。

Jupyter Notebook環境に接続したらLauncherのNotebookの"Python 3(ipykernel)"をクリックするか、左サイドバーから"New Notebook"をクリックし、Notebookを作成する。
"Select Kernel"では`Python3(ipykernel)`を選択する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/e12b676d-037e-258a-ffd6-9e2d6aba1b72.png)

最初にpipでllama.cppのPython版であるllama-cpp-pythonをインストールする。
インストール方法は[本家](https://github.com/ggerganov/llama.cpp)より[LangChain](https://python.langchain.com/docs/integrations/llms/llamacpp)の記載の方が分かりやすいかも。ノードに合わせて環境変数を設定する。
ここではGPUがないインストール方法で進める。
```sh
! pip install llama-cpp-python
```
次にモデルをコンテナ内に取り込む処理を書く。
ここではHugging Faceで配布されている、GGUF形式で小さそうだった[TheBloke/Mistral-7B-Instruct-v0.1-GGUF](https://huggingface.co/TheBloke/Mistral-7B-Instruct-v0.1-GGUF)にした。
他のモデルを使いたい人は適宜書き換えること。
```sh
! wget -O model.gguf https://huggingface.co/TheBloke/Mistral-7B-Instruct-v0.1-GGUF/resolve/main/mistral-7b-instruct-v0.1.Q2_K.gguf?download=true
```
最後にモデルを使ってテキストを生成する。モデルにあなたは何者か、と聞いてみる。
```python
from llama_cpp import Llama
llm = Llama(
    model_path = "/home/jovyan/model.gguf",
)
Question = "Who are you?"

output = llm(Question)
print(output['choices'][0]['text'])
```
ここまで書いたNotebookは以下になる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/2e0c9305-aae4-06dc-69c2-5e2885e288e0.png)
記載が終わったら、カーソルをNotebookの先頭に持っていき、Notebook内の再生ボタン（▶）をクリックしてそれぞれを実行していく。
pipのインストールでは依存関係のエラーが出るが、最終的に以下が表示されればOK。
```
Successfully installed diskcache-5.6.3 llama-cpp-python-0.2.22 numpy-1.24.4 typing-extensions-4.9.0
```
モデルのダウンロードに関しては3G程度あるため、時間が掛かる点に注意。
Pythonのコード本体の実行が始まって少し待つと以下のような結果が得られる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/2a68a6ac-d886-8df8-97cc-8ebd29ffa1e7.png)
Mistralだそうだ。
せっかくなので、質問を変えて再実行してみる。
```python
from llama_cpp import Llama
llm = Llama(
    model_path = "/home/jovyan/model.gguf",
)
Question = "日本語分かりますか？"

output = llm(Question)
print(output['choices'][0]['text'])
```
実行結果はこちら。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/11ddf84a-dc8e-7113-d392-a000fb3f742d.png)
変な回答が返ってきた。
なお、もうちょっとサイズの大きいモデルに変えるともう少し良い回答が貰える。

ということで、TKG上でllama.cppをサクッと使うことが出来た。
llama.cpp、環境によってはインストールに手間取る話も聞いているので、構築トラブルを避けたい人や、会社の都合でローカルPCにソフトウェアが入れられない人などは今回の手順を試していただければ幸いである。