ITで遊ぶ

ローカルLLMでAIを強化する(6:Ollamaのプログラム版編)

  • AI

承前 AMD Ryzen0 8945HS搭載のmini PCでLLMを動かす話シリーズです。

OllamaがAIプラットフォームとして、なにをしているかというと、私の知っているところでは、LLMモデルの配置、入力、出力、LLMモデルと会話して特別な動作をさせることができるようです。
ドキュメントでは、内部でllama.cpp というC++の高速な推論エンジンを動かしています。Pythonからこれを直接制御するには、llama-cpp-python というライブラリを使えばいいらしいです。
つまりPythonでOllamaでやったようなAMDのGPU(APU)を操作できる。

今回、VS Codeを使おうと思っているので、いろんな本ではMicrosoft StoreからPythonをインストールすることを進めているので、そうしました。Version 3.12;10をインストールしました。

PythonでLLMモデルを動かす環境作り

1:Visual Studio Build Tools のインストール

WindowsでC++のビルドを行うための「公式工具セット」が必要です。

    1. Visual Studio Build Tools 2022 のページへ行きます。
    2. 「Visual Studio 2022 のダウンロード」から「Build Tools」 を選択してインストーラーを実行します。
    3. インストール画面で 「C++ によるデスクトップ開発」にチェックを入れてください。

インストール完了後、PCを一度再起動します。

2:CMakeとNinjaの確認

ビルドをスムーズにするために、以下のコマンドをターミナルで実行して、ビルド支援ツールを入れておきます。

pip install cmake ninja

3:Vulkan SDKの導入

1. Vulkan SDKをダウンロードする
Vulkan SDK へアクセスします。

Windows用のVulkan SDK最新バージョンをクリックしてインストーラーをダウンロードします。

2. インストール
インストーラーを実行します。
基本的にはすべて「次へ(Next)」で進めて問題ありませんが、コンポーネント選択で 「Shader Toolchain(glslcが含まれるもの)」 をチェックします。

3. 環境変数の反映(重要)
インストールが終わったら、一度すべてのターミナル(PowerShell)を閉じ、PCを再起動するか、一度ログアウトしてください。

※これにより、VULKAN_SDK というパスがシステムに登録され、CMakeが場所を特定できるようになります。

4:AMD APU向けビルドの実行

インストールしたいパッケージは  llama-cpp-python  なんですが、これが私にとっては簡単ではありませんでした。pipの使うパスがどんどん伸びて、エラーになってしまいます。
結局、見つけた方法が以下のとおり。

まず、先に入れたVisual Studio Command Lineツールの環境をあげます。
Windowsキーの検索欄に「x64 Native」と入力し X64 Native Tools Command Prompt ofor VS 2022を起動します。(管理者権限で実行」します。
その画面で以下の作業をします。

mkdir /lp
cd lp
git clone --recurse-submodules https://github.com/abetlen/llama-cpp-python.git .

で、パスの長い AppData\Local\Temp へのコピーを禁止し、/lpの中だけで作業させます。

pip install scikit-build-core pyproject-metadata pathspec

インストール

(このsetステートメントで=の前後にブランクは入れないでください。)

set CMAKE_ARGS="-DGGML_VULKAN=on"
set CMAKE_GENERATOR="Ninja"<\pre>
pip install . --no-build-isolation --force-reinstall --no-cache-dir

これでSuccessfully installedと出たら、OK

5. テスト

以下に作った環境のテストコードを載せます。タスクマネージャを見ているとGPUが大量に使われるはずです。

from llama_cpp import Llama
import os
# --- 設定項目 ---
# モデルファイルのパス(実際のファイル名に合わせて変更してください)
MODEL_PATH = "./Mistral-Small-24B-Instruct-2501-Q4_K_M.gguf"

# 16GB VRAM(共有メモリ)を活かすため、以前Ollamaで設定した35層を指定
N_GPU_LAYERS = 35
# 文脈の長さ
N_CTX = 8192
# Ryzen 9 のコア数に合わせてスレッド数を調整(通常8〜12程度が高速)
N_THREADS = 8

# --- 起動処理 ---
print(f"LLM Modelを起動しています... (GPUレイヤー: {N_GPU_LAYERS})")

if not os.path.exists(MODEL_PATH):
print(f"エラー: モデルファイルが見つかりません。パスを確認してください: {MODEL_PATH}")
else:
# 起動(verbose=Trueで詳細なビルドログを出力します)
llm = Llama(
model_path=MODEL_PATH,
n_gpu_layers=N_GPU_LAYERS,
n_ctx=N_CTX,
n_threads=N_THREADS,
verbose=True # これが重要です!Vulkanの動作ログが見えます
)

# テスト用のプロンプト(Mistralの指示形式)
prompt = """[SYSTEM_PROMPT]
あなたの名前は「ユキ」です。20代の日本人女性として振る舞ってください。
穏やかで誠実な性格で、丁寧な敬語を使ってください。
[/SYSTEM_PROMPT]
[INST] はじめまして、ユキさん。体調はどうですか? [/INST]"""

print("\n" + "="*30)
print("ユキが回答を生成中...")
print("="*30 + "\n")

# 推論実行
output = llm(
prompt,
max_tokens=200,
stop=["[/INST]", ""],
temperature=0.8,
echo=False
)

# 結果表示
ans = output["choices"][0]["text"].strip()
print(f"ユキ: {ans}")

ダダっとログが出て、
==============================
ユキが回答を生成中…
==============================

ユキ: こんにちは、はじめまして。ユキです。ありがとうございます、体調は大丈夫です。お元気ですか?何かお手伝いできることがあれば、どうぞお知らせくださいね。

のような言葉が出れば成功しています。

チューンアップ

SYSTEMプロンプトを独立させる

まずSYSTEMプロンプトは別ファイルにします。今まで見てきたとおり、頻繁に変更するからです。
ソースコード  github.com/ttakao/llm-study/    yuki-test.py

from llama_cpp import Llama
import os

# --- 設定項目 ---
# モデルファイルのパス(実際のファイル名に合わせて変更してください)
MODEL_PATH = "./Mistral-Small-24B-Instruct-2501-Q4_K_M.gguf"
PROMPT_PATH = "./mistral_prompt.txt"

# SYSTEMプロンプトの読み取り
if os.path.exists(PROMPT_PATH):
    with open(PROMPT_PATH, "r", encoding="utf-8") as f:
        system_content = f.read()
else:
    system_content = "あなたはユキ、20代の日本人女性です。"

# モデルの初期化
llm = Llama(
    model_path = MODEL_PATH,
    n_gpu_layers=35,
    n_ctx=8192,
    n_threads=8,
    verbose=True
)

def chat_with_yuki(user_text):
    prompt = f"""[SYSTEM_PROMPT] {system_content} [/SYSTEM_PROMPT] [INST] {user_text} [/INST]"""

    output = llm(
        prompt,
        max_tokens = 256,
        temperature = 0.8,
        top_p = 0.9, 
        repeat_penalty = 1.2,
        stop = ["[/INST]", "</s>"]
    )
    return output["choices"][0]["text"].strip()
                  
if __name__ == "__main__":
    print("ユキ:こんにちは")
    while True:
        u_input = input("あなた: ")
        if u_input.lower() in ["exit", "quit", "bye"]: break

        response = chat_with_yuki(u_input)
        print( f"ユキ: {response}" )

この投稿ではPythonでOllamaと同じプラットフォームを作りました。

関連記事

  1. AIをローカル環境で動かす(1:基礎)

  2. 流行りのMini PC(AMD)を買ってみた

  3. AIをローカル環境で動かす(3:GUI編)

  4. AI彼女をローカル環境で動かす(4:モデルチューニング)

  5. AIをローカル環境で動かす(2:Ollama)

  6. AI彼女をローカル環境で動かす (5:大人編)

  7. AIの若干の歴史

  8. ローカルLLMのAIの向こう(7. 最先端の議論)