CLIでLLMが使える"simonw/llm"を使ってGemma 2 2Bを動かしてみた

この記事は「LLM・LLM活用 Advent Calendar 2024」の3日目の記事になります！

https://qiita.com/advent-calendar/2024/large-language-model

## 概要
CLIでLLMを利用可能な[simonw/llm](https://github.com/simonw/llm)のプラグインである
[simonw/llm-gguf](https://github.com/simonw/llm-gguf)を導入し, コマンドラインで[google/gemma-2-2b-jpn-it](https://huggingface.co/google/gemma-2-2b-jpn-it)を動作させる. 

## [simonw/llm](https://github.com/simonw/llm)
* LLMと連携するためのCLI UtilityおよびPython Library
* API呼び出しだけでなく, ローカルLLMにも対応
* 埋め込みを生成し, その結果をSQLiteに保存することも可能

### プラグイン一覧(一部)
* [Plugin directory](https://llm.datasette.io/en/stable/plugins/directory.html#plugin-directory)に使用可能なプラグインが記述されている


| プラグイン名       | 説明                                                                                                                 |
|--------------------|--------------------------------------------------------------------------------------------------------------------|
| **[llm-gguf](https://github.com/simonw/llm-gguf)**       | llama.cpp を使用し, GGUF 形式で公開されたモデルを実行                                                       |
| **[llm-gpt4all](https://github.com/simonw/llm-gpt4all)**    | GPT4Allプロジェクトによってリリースされた, ローカルに実行可能なモデルをサポート. Vicuna、Orca、Falcon、MPT 等のバージョンが含まれる. [使用可能なモデルのリスト](https://observablehq.com/@simonw/gpt4all-models)|
| **[llm-ollama](https://github.com/taketwo/llm-ollama)**     | Ollama を使用しローカルで実行可能なモデルをサポート        |
| **[llm-gemini](https://github.com/simonw/llm-gemini)**             | GoogleのGeminiモデルをサポート  |
| **[llm-claude](https://github.com/tomviner/llm-claude)**             | AnthropicのClaude 2.1およびClaude Instant 2.1をサポート|
| **[llm-claude-3](https://github.com/simonw/llm-claude-3)**           | AnthropicのClaude 3モデルファミリーをサポート|


## [simonw/llm-gguf](https://github.com/simonw/llm-gguf)の使い方
### 実行環境
* Windows11 
* Ubuntu 20.04 LTS(WSL)
* CPU AMD Ryzen 7 5700X

### 導入
* Python 3.12が使える環境で`simonw/llm` をインストール
    ```bash
    pip install llm
    ```
* プラグイン`simonw/llm-gguf`のインストール
    ```bash 
    llm install llm-gguf
    ```
### GGUFモデル登録
* [alfredplpl/gemma-2-2b-jpn-it-gguf](https://huggingface.co/alfredplpl/gemma-2-2b-jpn-it-gguf)からGGUFモデルをダウンロード
* 以下のコマンドで使用したいモデルを登録
    ```bash
    llm gguf register-model gemma2-2b-iq4xs ./gemma-2-2b-jpn-it-IQ4_XS.gguf --alias gemma2 
    ```
* `llm gguf models`で現在登録されているモデルを確認可能
    ```bash
    > llm gguf models
    {
      "gemma2-2b-iq4xs": {
        "path": "path/to/gemma-2-2b-jpn-it-IQ4_XS.gguf",
        "aliases": [
          "gemma2"
        ],
        "size": "1.46 GB"
      }
    }
    ```
* 設定ファイルが`~/.config/io.datasette.llm/gguf`にあるので直接編集することも可能
    * [Setup - Configuration - Setting a custom directory location](https://llm.datasette.io/en/stable/setup.html)

### コマンドラインからの呼び出し
* `llm -m gemma2 "prompt"` で呼び出し
    ```bash 
    > llm -m gemma2 "日本で一番高い山は？"
    日本で一番高い山は富士山です。
    ``` 

## 使用例
### 他のコマンドの実行結果(標準出力)を受け取る
* `command | llm -m gemma2 -s "prompt"` でcommandの結果を受けてpromptの質問に答える
    * -s はシステムプロンプトを設定するオプション
        * [Usage - System prompts](https://llm.datasette.io/en/stable/usage.html)
    ```bash 
    > lscpu
    Architecture:            x86_64
      CPU op-mode(s):        32-bit, 64-bit
      Address sizes:         48 bits physical, 48 bits virtual
      Byte Order:            Little Endian
    CPU(s):                  16
      On-line CPU(s) list:   0-15
    Vendor ID:               AuthenticAMD
      Model name:            AMD Ryzen 7 5700X 8-Core Processor
    ... 省略
    
    > lscpu  | llm -m gguf/gemma2-2b-xq4xs  -s "このPCのCPUのモデルは？"
    CPUのモデルは、AMD Ryzen 7 5700X です。 
    ```

### エラー内容を`llm`に渡す
* 以下のようなコンパイルエラーになるCプログラムに対して質問したい場合
    ```c:compile_error.c
    #include <stdio.h>
    
    int main(void){
        int a = 1;
        printf("%d\n", a) // ; がないためコンパイルエラー
        return 0;
    }
    ```
    ````bash
    > gcc error_code.c 2>&1  | llm -m gemma2  -s "エラーの理由と解決方法を教えて"
     エラーメッセージ「expected ‘;’ before ‘return’」は、C言語のプログラムで、`return`コマンドの前にセミコロン（`;`)が必要であることを示しています。
    
    このエラーが発生する原因は、`return 0;`コマンドの後にセミコロンがないためです。
    
    **解決方法**
    
    1. **セミコロンを追加する:**  `return 0;`コマンドの前にセミコロンを追加します。
    
       ```c
       printf(&#34;%d\n&#34;, a);
       return 0; 
       ```
       
    ````
    * `2>&1`は標準エラー出力を標準出力にリダイレクトするコマンド
        * コンパイルエラーは標準エラー出力であるため `gcc error_code.c | ...` では 次のコマンドに渡せない
## 参考記事
* [コマンドラインでLLMが使える「llm」を試す(Zenn)](https://zenn.dev/kun432/scraps/1a9d701a28ecf4)

<!-- 
コマンドラインでLLMを利用することができる[simonw/llm](https://github.com/simonw/llm)のプラグインである
[simonw/llm-gguf](https://github.com/simonw/llm-gguf)を導入することでGGUFのモデルを使うことができる. 少ない計算資源で利用できる[google/gemma-2-2b-jpn-it](https://huggingface.co/google/gemma-2-2b-jpn-it)をGGUF化した[gemma-2-2b-jpn-it-IQ4_XS.gguf](https://huggingface.co/alfredplpl/gemma-2-2b-jpn-it-gguf)を用いてコマンドラインからLLMを使用してみる

使用モデル gemma-2-2b-jpn-it-IQ4_XS.gguf3
日本語版 Gemma 2 2B4をgguf化し4bit量子化を行ったもの

参考
コマンドラインでLLMが使える「llm」を試す
https://zenn.dev/kun432/scraps/1a9d701a28ecf4
-->