ローカル+CPU+Python で Large-Language Model（LLM）を動かしてみた

# ローカル+CPU+Python で Large-Language Model（LLM）を動かしてみた


## 🔗 目次
1. [はじめに](#はじめに)
1. [動作確認環境](#動作確認環境)
1. [環境構築](#環境構築)
1. [使用技術説明](#使用技術説明)
    1. [llama-cpp-python](#llama-cpp-python)
    1. [Phi-3-mini-4k-instruct-gguf](#phi-3-mini-4k-instruct-gguf)
1. [デモ](#デモ)
1. [4bit vs 16bit](#4bit-vs-16bit)
1. [まとめ](#まとめ)

## はじめに
本記事では，「ローカル環境で GPU も無いけど LLM を試してみたい」という方向けに軽量な LLM を動かす方法をご紹介します．
簡単に試すことができるように，基本的には **python があれば動く**最小構成になっています．

## 動作確認環境
|  | スペック |
|:-:|:-:|
| PC | MacBook Pro 2020モデル  |
| CPU  |  Intel Core i5 1.4 GHz クアッドコア|
| メモリ| 8 GB| 
|Python | 3.13.1 |
| llama-cpp-python | 0.3.9 |
| LLM モデル形式|gguf（phi-3-mini 4bit / 16bit） | 


## 環境構築
### フォルダ構成
```plaintext
./playground/　　　　　　　 # 作業フォルダ
    ┣━ .venv/            # Python 仮想環境
    ┣━ models/           # モデル格納用フォルダ
    ┃    ┗━ Phi-3-mini-4k-instruct-q4.gguf
    ┗━ sample.py         # 実行スクリプト
```


### 準備
terminal または コマンドプロンプトで下記を実行します．
1. 仮想環境構築
    ```bash
    $ python -m venv .venv
    ```
1. activate
    * Linux/Mac
        ```bash
        $ source .venv/bin/activate
        ```
    * Windows
        ```cmd
        .\.venv\Scripts\activate.exe
        ```
1. ライブラリインストール
    ```bash
    $ pip install -U pip
    $ pip install llama-cpp-python
    ```
1. モデルダウンロード
    今回のデモでは **[Phi-3-mini-4k-instruct-gguf](https://huggingface.co/microsoft/Phi-3-mini-4k-instruct-gguf)** という Microsoft のモデルを使用します．
    [リンク](https://huggingface.co/microsoft/Phi-3-mini-4k-instruct-gguf/tree/main)から **Phi-3-mini-4k-instruct-q4.gguf** というモデルをダウンロードし，**models/** フォルダに格納します．

これで動かす準備は完了です．
`sample.py` は後ほど出てきます．

## 使用技術説明
今回は手軽に動かすために llama-cpp-python というライブラリと phi という LLM モデルを使用しました．

### llama-cpp-python 
#### llama-cpp-python とは
`llama-cpp-python` は，`llama.cpp`（C/C++ で書かれた LLM 推論エンジン）を Python から扱うためのラッパーライブラリです．


主な特徴：
* `.gguf` 形式のモデルを手軽にロード・推論可能
* ローカルで動作
* CPU で動作可能

裏側では `llama.cpp` を呼び出す仕組みになっており，Python ユーザーでも高速・軽量な LLM 体験が可能になります．

#### gguf とは

`gguf` は、`ggml`（軽量推論用フォーマット）の後継であり，  
軽量化・量子化された LLM モデルを効率的に扱うためのファイル形式です．

主な特徴：
* モデルをさまざまな bit 精度で格納可能
* llama.cpp ライブラリから使用可能
* 多くのオープンモデルが対応

### Phi-3-mini-4k-instruct-gguf

#### Phi-3-mini-4k-instruct とは
`Phi-3-mini-4k-instruct` は，Microsoft によって開発された軽量 LLM です．

主な特徴：
* 約 3.8B パラメータと非常に軽量
* `.gguf` 形式に変換することで、`llama-cpp` 系ライブラリで高速・ローカル実行が可能（Phi-3-mini-4k-instruct-gguf）

#### プロンプトフォーマット
phi モデルでは，下記のようなフォーマットで入力を行います．
```text

\nQuestion 
\n

```
例えば，
```plaintext


あなたは何ができますか？



```
上記のようなプロンプトをモデルに入力すると，モデルが `
` 以降の続きを出力します．
Phi に関してはこのようなフォーマットでプロンプトを与えます．

## デモ
### 実行方法
下記のコードを `sample.py` にコピーして実行してください．
`query` の内容を変更すると，LLM からの回答もそれに沿った内容になります．
```python
from llama_cpp import Llama

llm = Llama(
    model_path="./models/Phi-3-mini-4k-instruct-q4.gguf",
    n_ctx=2048,          # コンテキスト長（質問＋回答）
    n_threads=4,         # CPUスレッド数（環境に合わせて調整）
)

query = "こんにちは！あなたは何が得意ですか？\n"
prompt = (
    "
\n"
    f"{query}"
    "
\n"
    "
\n"
)

output = llm(prompt, max_tokens=256, stop=["
", "
", "
"])
print(output["choices"][0]["text"].strip())
```

#### 実行例1
* 質問
    ```python
    query = "こんにちは！あなたは何が得意ですか？\n"
    ```
* 回答
    ```plaintext
    こんにちは！
    私の得意とするスキルには、多言語処理、大規模データベースの検索、
    精度の高い情報の提供、およびAIに基づく自然な会話があります。
    私はテキストベースのインタラクティブな対話での質の高い解答を提供することで知られており、
    さまざまな分野の質問に対して対応することができます。
    ```
#### 実行例2
* 質問
    ```python
    query = "ダイエットを続けられる一言ちょうだい\n"
    ```
* 回答
    ```plaintext
    "継続されるダイエットは、自己管理と意図を持って行動することが大切です。
    それぞれの目標に注意を払い、毎日の選択を見直してみてください。"
    ```
どちらもそれっぽい回答得られました！
ダイエットに関してはなかなか辛辣なお言葉をいただきました．


## 4bit vs 16bit
**[Phi-3-mini-4k-instruct-gguf](https://huggingface.co/microsoft/Phi-3-mini-4k-instruct-gguf/tree/main)** には，Phi-3-mini-4k-instruct-fp16.gguf と Phi-3-mini-4k-instruct-q4.gguf があります．これはモデルの bit 精度を表しています．fp16 は 16bit で，q4 は 4bitです．
一般的に，fp16 の方が精度は良いですが推論に時間がかかり，q4 の方が精度は劣る分，推論時間が短いです．

今回は同じプロンプトを入力して，推論時間と回答を比較してみようと思います．

### 質問1
```python
query = "あなた自身のことを説明してください．\n"
```
| | 4bit | 16bit |
| :-: |:-:|:-:|
| 処理時間 [s] |  36 |  5548 (=約92分) |

* 4bit モデルの回答
    ```text
    私はオープンAIアシスタントの言語モデルであり、
    大量のデータに基づいて機能しています。
    私の主な機能には、質問に答えたり、テキストを生成したり、
    言語を理解したりする能力が含まれます。
    私は大文字小文字を区別せず、情報を提供し、
    単語やパラグラフを細かく編集することができます。
    私は開発者が定義したガイドラインに基づいて操作されており、
    一人一人のユーザーにカスタマイズ可能な体験を提供するためのサポートを行っています。
    ただし、私は個人の意見や感情を
    ```


* 16bit モデルの回答
    ```text
    私はオープンAIの言語モデルです。
    私は大量のテキストデータを学習し、
    それを基にユーザーの質問や入力に対して適切な回答や情報を生成することができます。
    私のプログラミングはTensorFlowやPyTorchのような
    計算機のための機械学習フレームワークを使用して行われ、
    機械学習アルゴリズムとディープラーニングを駆使しています。
    私の目的は情報を提供し、ユーザーが問いの意図を理解し、
    それに応じた助言をすることにあります。
    ただし、私は個人的な意見や感情
    ```

どちらのモデルの回答も似たような要旨の内容ですが，16bit モデルの方がより具体的な内容を語っているように見えます．

### 質問2（論理クイズ）
```python
query = "この問題解ける？\n"
quiz = "【問題】\n\
A、B、Cの3人の中で1人だけが正直者です。残りの2人は嘘をついています。\n\
次の3人の言葉から正直者を見つけてください。 \n\
A「私は正直者です。」\n\
B「Aはうそつきです。私が正直者です。」\n\
C「Bはうそつきです。本当の正直者は私です。」\n\
A、B、C のいずれかで答えてください。\n"
```
| | 4bit | 16bit |
| :-: |:-:|:-:|
| 処理時間 [s] |  40 |  4338 (=約72分) |

* 4bit モデルの回答
    ```text
    正直者はBです。
    説明：
    Aが正直者であるという前提で考えると、Aが自己を正直者と表明しているため、
    Aが嘘をついている可能性が高いです。
    Bが正直者であるという前提で考えると、BがAが嘘をついていると結論づけることができますが、
    これによりBも嘘をついていることになります。
    Cが正直者であるという前提で考えると、
    CがBを嘘該当者としていると結論づけます。
    この場合、AとCが嘘をついていることになります。
    したがって、嘘をつく人は3人ということに
    ```


* 16bit モデルの回答
    ```text
    正直者はBです。
    説明：
    Aが正直者であるとすると、BとCが嘘をついていることになります。
    Bが正直者だった場合、Aは嘘をついていると言っているので嘘ではないのですが、
    Cの発言は不可解であり、矛盾してしまいます。
    Cが正直者であるとすると、Bはうそつきであるため、
    Bの発言は真実ではありません。
    したがって、Bが正直者であると判断します。
    ```

一応，どちらのモデルも回答は正解ですが，説明に大きな差が出ました．
4bit モデルは説明の論理が破綻しています．
16bit は言っていることは理解できるけれど，納得するにはあと少し必要，といった印象でした．
ちなみに，ちょっとプロンプトを変更すると回答もコロコロ変わるので，試してみても面白いです．

この比較から，**4bit モデルは高速に動作する一方で，推論の正確性や説明力にはやや難がある**ことがわかります．
また，**16bit モデルは非常に重いですが，より整った論理的回答が得られやすい**という結果になりました．

用途に応じてモデルの精度を選ぶ判断材料として，こういった比較は非常に重要です．


## まとめ
今回は、**ローカル環境 + CPU + Python** というシンプルな構成で，
軽量な LLM（Phi-3-mini）を実行する方法をご紹介しました．
また，bit 精度の異なるモデル（4bit vs 16bit）で推論速度と回答の質がどう異なるかも比較しました．
AI モデルを扱うにおいて，**速度と精度は常にトレードオフ**の関係です．
自分のマシンスペックや用途に合わせて，**最適なモデル構成を選ぶことが重要**だと実感できる内容だったのではないでしょうか．

## 📎 あわせて読みたい：RAG（Retrieval-Augmented Generation）

本記事のモチベーションは，Retrieval-Augmented Generation（RAG）を試す中で生まれました．

RAG は，**LLMを再学習せずに、外部データを検索・活用して回答を補強する技術**です．

興味がある方は，以下の記事で解説していますので，ぜひあわせてどうぞ👇

🔗 [RAGでブラック企業の社内規則チャットBotを作ってみた](https://qiita.com/k2-gc/items/2ce5ee092aadee9432ca)