初めに #
近年、AI 分野では大規模言語モデル(LLM)をはじめとした技術発展が急速に進んでいます。
これらの技術は、単なる文章生成にとどまらず、画像や動画の生成、さらには表形式データの解析や要約といった分野にも活用されるようになってきました。
その結果、これまでエンジニアの専門知識が必要とされてきた作業の一部についても、一般の利用者が扱える技術として提供されつつある、という意見も見られるようになっています。
そのような背景からエンジニアに求められる役割も変化しつつあります。
AI を「使う」だけでなく、「どのように動いているのか」「どこに制約があるのか」を理解することが、より重要になってきているといえます。
本記事では、そうした理解への第一歩として、AlmaLinux 10 環境上で LLM を実際に動かす方法を初心者向けにご紹介します。
GPU不要・CPUのみの構成 #
本記事では、高価な GPU(グラフィックスプロセッサ)を必要とせず、一般的なCPU環境のみで LLM を動かす構成を採用します。
通常、LLM の実行には高い推論能力を持つ GPU が推奨されますが、近年は「量子化」などの技術発展や軽量モデルの登場によりCPUのみの環境でも動作させることが可能になっています。
今回利用する検証環境のメモリ(RAM)は 4GB となっています。
そのため、標準的なクラウドサーバーの低スペックプランや少し古めのPCでも、手軽に構築を行うことが可能です。
また、今回動かすモデルは、Googleが開発し、オープンモデルとして公開している Gemma 2 2B となります。
このモデルは軽量ながらも日本語に対応しており一部のベンチマークでは GPT-3.5 を上回るパフォーマンスを示すなど、その実用性が高く評価されています。
LLMを動かす方法 #
LLM を利用する方法はいくつかありますが、大きく分けると クラウドサービスを利用する方法 と ローカル環境で実行する方法 の二つに分けられます。
またローカル環境で利用する場合にも、いくつかの方法が考えられます。
例えば、専用のランタイムや管理ツールを利用して手軽に実行する方法や、推論エンジンを直接ビルドし、モデルを指定して実行する方法などがあります。
| 方法 | 概要 | メリット | デメリット |
|---|---|---|---|
| 管理ツール・ランタイムを利用 | 専用ツールを用いてモデルの取得から実行までを管理 | 導入が容易で手順が少ない 初学者でも扱いやすい |
内部動作が見えにくい 設定や挙動の自由度が低い |
| 推論エンジンを直接利用 | 推論エンジンをビルドしモデルを指定して実行 | 実行方法やリソース使用を詳細に把握できる 構成の自由度が高い |
初期構築に手間がかかる ある程度の環境理解が必要 |
本記事では推論エンジン(llama.cpp)を直接利用し LLM モデルを実行する構成を採用します。
以下は llama.cpp の公式リポジトリとなっております。
LLM inference in C/C++
ビルドツールの導入 #
初めに llama.cpp のビルドを行うために利用するビルドツールを導入します。
次のコマンドを実行してください。
dnf install git make gcc-c++
実行すると、以下のようにインストールパッケージの確認画面が表示されます。
Total download size: 100 M
Is this ok [y/N]:
内容を確認し問題なければ y を入力してインストールを進めてください。
インストールが完了すると、次のメッセージが表示されます。
Complete!
依存関係パッケージの導入 #
llama.cpp のビルドには、いくつかのライブラリ依存関係パッケージとして必要になります。
libcurl は推論エンジン内のモデルファイルの取得や一部の機能でネットワーク通信を行う際に利用されます。
AlmaLinux 10 環境では libcurl-devel パッケージをインストールすることで、ビルド時に必要な環境が整えることができます。
dnf install libcurl-devel
なお、Curl の使用はデフォルトで有効になっていますが、ビルド時に以下を指定することで無効化する事ができます。
-DLLAMA_CURL=OFF
このオプションを指定した場合、libcurl-devel の導入は不要となります。
ソースコードのダウンロード #
次に llama.cpp のソースコードをダウンロードします。
本記事では、アプリケーションとして扱いやすいよう /opt ディレクトリ配下に配置します。
以下のコマンドを実行し /opt へ移動してください。
cd /opt
次に以下のコマンドを実行し llama.cpp リポジトリをローカル環境にクローンしてください。
git clone https://github.com/ggml-org/llama.cpp.git
クローンを実施すると以下のように llama.cpp ディレクトリが作成されます。
$ ls
llama.cpp
次のコマンドでディレクトリを移動してください。
cd llama.cpp
ビルドの実施 #
初めに CMake を用いてビルド設定を生成します。
この工程は、いわゆる事前確認にあたり、コンパイラやライブラリの検出、ビルド構成の確認などが行われます。
cmake -B build
問題がない場合は、以下のように各種コンポーネントが検出され最後に Build files have been written to と表示されます。
-- The C compiler identification is GNU 14.3.1
-- The CXX compiler identification is GNU 14.3.1
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
CMAKE_BUILD_TYPE=Release
-- Found Git: /usr/bin/git (found version "2.47.3")
-- The ASM compiler identification is GNU
-- Found assembler: /usr/bin/cc
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Success
-- Found Threads: TRUE
-- Warning: ccache not found - consider installing it for faster compilation or disable this warning with GGML_CCACHE=OFF
-- CMAKE_SYSTEM_PROCESSOR: x86_64
-- GGML_SYSTEM_ARCH: x86
-- Including CPU backend
-- Found OpenMP_C: -fopenmp (found version "4.5")
-- Found OpenMP_CXX: -fopenmp (found version "4.5")
-- Found OpenMP: TRUE (found version "4.5")
-- x86 detected
-- Adding CPU backend variant ggml-cpu: -march=native
-- ggml version: 0.9.4
-- ggml commit: 2aa45ef9e
-- Found CURL: /usr/lib64/libcurl.so (found version "8.12.1")
-- Configuring done (2.2s)
-- Generating done (0.5s)
-- Build files have been written to: /opt/llama.cpp/build
一方で依存関係が不足している場合などは、以下のようなエラーメッセージが表示されます。
以下は、libcurl-devel が環境にインストールされていないため、Curl 関連のライブラリが検出できずエラーとなった場合の出力となります。
このような場合は依存関係の見直しを実施してください。
-- Could NOT find CURL (missing: CURL_LIBRARY CURL_INCLUDE_DIR)
CMake Error at common/CMakeLists.txt:99 (message):
Could NOT find CURL. Hint: to disable this feature, set -DLLAMA_CURL=OFF
ビルド設定の生成が完了したら、次に実際のビルドを実行してください。
cmake --build build
コマンドを実行すると、以下のようにソースコードのコンパイルが順次進んでいきます。
cmake --build build
[ 0%] Building C object ggml/src/CMakeFiles/ggml-base.dir/ggml.c.o
[ 0%] Building CXX object ggml/src/CMakeFiles/ggml-base.dir/ggml.cpp.o
[ 0%] Building C object ggml/src/CMakeFiles/ggml-base.dir/ggml-alloc.c.o
[ 1%] Building CXX object ggml/src/CMakeFiles/ggml-base.dir/ggml-backend.cpp.o
[ 1%] Building CXX object ggml/src/CMakeFiles/ggml-base.dir/ggml-opt.cpp.o
[ 1%] Building CXX object ggml/src/CMakeFiles/ggml-base.dir/ggml-threading.cpp.o
[ 1%] Building C object ggml/src/CMakeFiles/ggml-base.dir/ggml-quants.c.o
ビルドが最後まで進むと、以下のように 100% と表示され、各ツールの実行ファイルが生成されます。
[ 99%] Linking CXX executable ../../bin/llama-export-lora
[ 99%] Built target llama-export-lora
[100%] Building CXX object tools/fit-params/CMakeFiles/llama-fit-params.dir/fit-params.cpp.o
[100%] Linking CXX executable ../../bin/llama-fit-params
[100%] Built target llama-fit-params
ビルドによって生成された実行ファイルおよびライブラリは、以下のディレクトリに配置されます。
/opt/llama.cpp/build/bin
以上で llama.cpp のビルドは完了となります。
モデルファイル(LLM)の配置 #
では実際に llama.cpp で利用する LLM モデルを配置します。
以下のコマンドを実行しディレクトリの移動を行ってください。
cd /opt/llama.cpp/models
次に以下のコマンドを実行し「Gemma 2 2B」をダウンロードしてください。
curl -L -o gemma-2-2b-it-Q4_K_M.gguf "https://huggingface.co/bartowski/gemma-2-2b-it-GGUF/resolve/main/gemma-2-2b-it-Q4_K_M.gguf?download=true"
ダウンロードが完了すると、models ディレクトリ配下に以下のようなモデルファイルが配置されます。
-rw-r--r-- 1 root root 1.5G gemma-2-2b-it-Q4_K_M.gguf
以上でモデルファイルの配置は完了となります。
CLIで実行する方法 #
モデルの配置が完了したら、llama-cli を利用し実際に LLM を実行する事ができます。
以下のコマンドを実行し移動を行ってください。
cd /opt/llama.cpp/build/bin
次に以下のコマンドを実行し LLM を実行してください。
./llama-cli \
-m /opt/llama.cpp/models/gemma-2-2b-it-Q4_K_M.gguf \
-p "Linuxとは何ですか?" \
-n 100
今回指定した設定は以下の通りとなります。
| オプション | 内容 |
|---|---|
-m |
使用する LLM モデルファイル(GGUF 形式)のパスを指定 |
-p |
モデルに与えるプロンプト(入力文)を指定 |
-n |
生成するトークン数を指定(出力される文章量の目安) |
コマンドを実行すると初めに以下のようなメッセージが表示されます。
▄▄ ▄▄
██ ██
██ ██ ▀▀█▄ ███▄███▄ ▀▀█▄ ▄████ ████▄ ████▄
██ ██ ▄█▀██ ██ ██ ██ ▄█▀██ ██ ██ ██ ██ ██
██ ██ ▀█▄██ ██ ██ ██ ▀█▄██ ██ ▀████ ████▀ ████▀
██ ██
▀▀ ▀▀
build : b7433-7b1db3d3b
model : gemma-2-2b-it-Q4_K_M.gguf
modalities : text
available commands:
/exit or Ctrl+C stop or exit
/regen regenerate the last response
/clear clear the chat history
/read add a text file
ここでは使用しているモデルやビルド情報が表示されます。
その後、LLM による応答が返ってきます。
> Linuxとは何ですか?
Linuxとは、**オープンソースの作業システム**です。
**簡単に説明すると、パソコンやサーバーを動かせるソフトウェアの基礎を構成するOSです。**
**具体的な説明:**
* **オープンソース:** 誰でも自由に利用、修正、配布することができるソフトウェアです。
* **作業システム:** パソコンやサーバーの動作を制御し、ユーザーがアプリケーションを実行できるようにします。
* **OSは「Operating System」:** コンピュータのソフトウェアの基礎
最後に生成時のパフォーマンスを示されます。
Prompt は入力文を解析する速度となっており Generation は回答を出力する速度となっております。
[ Prompt: 22.7 t/s | Generation: 9.7 t/s ]
llama-cli の対話モードを終了するには、以下の様に入力してください。
> /exit
また、ショートカットキーの Ctrl + C を押すことでも即座に終了する事ができます。
llama-server を用いた常駐実行(API サーバー方式) #
以下のような場合は llama-cli による単発実行ではなく llama-server の利用が適しています。
- Web API として利用したい
- 複数のアプリケーションから継続的に呼び出したい
- 複数回実行する場合のモデルファイルを読み込むオーバーヘッドを削減したい
llama-server は llama.cpp に含まれる常駐型の推論サーバー機能となっており、モデルをメモリに保持したまま HTTP 経由でリクエストを受ける事ができます。
今回は、より実践的な運用を想定し systemd に登録して常駐させる構成について解説します。
1.systemd サービスファイルの作成 #
以下のコマンドを実行しサービスファイルを作成してください。
vi /etc/systemd/system/llama-server.service
続いて、作成したファイルに以下の内容を記述してください。
[Unit]
Description=llama.cpp LLM API Server
After=network.target
[Service]
Type=simple
ExecStart=/opt/llama.cpp/build/bin/llama-server \
-m /opt/llama.cpp/models/gemma-2-2b-it-Q4_K_M.gguf \
-c 4096 \
--host 127.0.0.1 \
--port 8080
Restart=always
RestartSec=5
User=llama
Group=llama
[Install]
WantedBy=multi-user.target
2.実行ユーザーの作成 #
llama-server を systemd で常駐運用する場合、セキュリティの観点から専用の実行ユーザーを作成しておくのがベストプラクティスとなっております。
今回はログイン不可のシステムユーザー llama を作成しこのユーザーで llama-server を実行する構成とします。
以下のコマンドを実行しユーザーを作成してください。
useradd -r -s /usr/sbin/nologin -d /opt/llama llama
続いて、llama-server 本体プログラムおよびモデルファイルの所有者を実行ユーザーに変更します。
以下のコマンドを実行してください。
chown -R llama:llama /opt/llama.cpp
3.サービスの起動 #
サービスファイルを作成したら、systemd に認識させたうえで llama-server サービスを有効化・起動します。
初めに以下のコマンドを実行し systemd の設定を再読み込みしてください。
systemctl daemon-reload
続いて以下のコマンドを実行しサービスの起動と自動起動を有効化してください。
systemctl enable --now llama-server
起動後は以下のコマンドを実行し、サービスの起動確認を行ってください。
systemctl is-active llama-server
以下のように表示されれば、サービスが正常に稼働しています。
active
4.LLM を HTTP 経由で利用する #
llama-server が起動すると、LLM を HTTP API として利用できるようになります。
初めに以下のコマンドを実行しステータス確認を行ってください。
curl http://127.0.0.1:8080/health
以下のようにメッセージが表示されていれば API サーバーとして正常に動作しています。
{"status":"ok"}
続いて、llama-server が提供する OpenAI API 互換エンドポイントを利用し HTTP 経由で LLM にリクエストを送信します。
curl http://127.0.0.1:8080/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "gemma",
"messages": [
{"role": "user", "content": "Linuxとは何ですか?"}
]
}'
実行が完了すると以下のように JSON 形式でレスポンスが返却されます。
{
"id": "chatcmpl-O21YIMpV4rXi5wOWfdDlq0uiygQMW42v",
"object": "chat.completion",
"created": 1765969879,
"model": "gemma-2-2b-it-Q4_K_M.gguf",
"choices": [
{
"index": 0,
"finish_reason": "stop",
"message": {
"role": "assistant",
"content": "Linuxは、オープンソースのオペレーティングシステムです。\n\n簡単に説明すると、Linuxはコンピュータの動作を制御するOSであり、誰でも自由に利用・改変・再配布できます。サーバー、デスクトップ、組み込み機器など幅広い用途で利用されています。"
}
}
],
"usage": {
"prompt_tokens": 14,
"completion_tokens": 436,
"total_tokens": 450
},
"timings": {
"prompt_ms": 583.31,
"predicted_ms": 43884.05,
"prompt_per_second": 24.0,
"predicted_per_second": 9.93
}
}
今回の実行結果について、主要な項目とその値は以下の通りとなっております。
| 項目 | 今回の値 | 説明 |
|---|---|---|
| id | chatcmpl-O21YIMpV4rXi5wOWfdDlq0uiygQMW42v | リクエスト識別子 |
| object | chat.completion | チャット補完レスポンス |
| created | 1765969879 | レスポンス生成時刻(Unix time) |
| model | gemma-2-2b-it-Q4_K_M.gguf | 使用したLLMモデル |
| choices[0].message.role | assistant | 応答の発話者 |
| choices[0].message.content | Linuxの説明文 | LLM が生成した回答本文 |
| finish_reason | stop | 正常終了 |
| usage.prompt_tokens | 14 | 入力トークン数 |
| usage.completion_tokens | 436 | 生成トークン数 |
| usage.total_tokens | 450 | 合計トークン数 |
| timings.prompt_ms | 583.31 ms | 入力処理時間 |
| timings.predicted_ms | 43884.05 ms | 推論処理時間 |
| timings.predicted_per_second | 9.93 tokens/sec | 生成速度 |
Web アプリケーションや別ホストから 外部 API として利用する場合は、ファイアウォールで該当ポートを許可する必要があります。
必要に応じてIPの設定や通信許可の設定を行ってください。