この記事の対象読者
- LLM(大規模言語モデル)に興味があり、ローカルで動かしてみたい方
- llama.cppを使ったことがある、またはこれから使ってみたい方
- GPU(CUDA)を使った推論環境の構築に関心がある方
- 「1兆パラメータって本当にシングルGPUで動くの?」という疑問を持っている方
この記事で得られること
- Kimi K2.5の全体像: MoEアーキテクチャの仕組みと、なぜ1兆パラメータでも動かせるのかの理解
- 完全な環境構築手順: Windows + llama.cpp + CUDAでKimi K2.5を動かすまでのステップバイステップガイド
- 3つの壁と突破法: 筆者が実際にハマったトラブルとその解決策(GPU認識不可、メモリ不足、GPU使用率0%問題)
- 環境別の設定テンプレート: 開発・本番・ベンチマーク用の設定ファイル一式
この記事で扱わないこと
- マルチGPU(NVLink)構成での実行
- Linux / macOS 環境でのセットアップ
- モデルのファインチューニングや学習
- vLLM / SGLang 等の他の推論エンジンでの実行
1. Kimi K2.5との出会い
「96GBのVRAMがあれば、何でも動かせるだろう。」
RTX PRO 6000 Blackwell Workstation Editionを手に入れたとき、私はそう思っていました。VRAM 96GB。一般的なGPU(RTX 4090で24GB)の4倍です。これだけあれば、どんなモデルだって余裕で動くに決まっている。
そんな自信満々の私の前に現れたのが、Kimi K2.5でした。
「1兆パラメータ」という数字を見たとき、正直なところ実感が湧きませんでした。しかし、最も小さい量子化版でも223GBと知ったとき、96GBのVRAMが急に小さく見えました。引っ越しに例えるなら、「大きなトラックを借りたのに、荷物が3台分あった」ような状態です。
結論から言うと、動きはしましたが、期待通りにはいきませんでした。GPU使用率はほぼ0%。96GBのVRAMは「計算装置」ではなく「高速メモリ」として使われていたのです。
この記事では、その過程で遭遇した3つの壁と、そこから学んだことを共有します。失敗談も含めて赤裸々に書きますので、同じ沼にハマる方が一人でも減れば幸いです。
ここまでで、この記事がどんな内容か、なんとなくイメージできたでしょうか。次は、この記事で登場する用語を整理しておきましょう。
2. 前提知識の確認
本題に入る前に、この記事で頻繁に登場する用語を確認します。すでにご存知の方は読み飛ばしてください。
2.1 MoE(Mixture of Experts)とは
MoEは「Mixture of Experts(混合エキスパート)」の略です。
通常のLLMは、入力されたテキストに対して全てのパラメータを使って計算します。一方、MoEモデルは複数の「エキスパート(専門家)」を持ち、入力に応じて一部のエキスパートだけを選んで計算します。
料理で例えるなら、普通のLLMは「全員が全品担当するキッチン」です。MoEは「和食担当・洋食担当・デザート担当が分かれた分業制キッチン」。注文に応じて適切な担当者だけが動きます。結果として、パラメータの総数は巨大でも、実際に動くパラメータは少なく済むのです。
Kimi K2.5の場合、1兆パラメータのうち実際に動くのは320億(32B)パラメータだけです。
2.2 GGUF(GPT-Generated Unified Format)とは
GGUFは、llama.cppが使用するモデルファイルフォーマットです。
元のモデルファイル(PyTorchの.safetensorsなど)は非常に大きく、特定のフレームワークに依存します。GGUFはそれを単一のファイルにまとめ、CPUでもGPUでも効率よく読み込める形式に変換したものです。
2.3 llama.cppとは
llama.cppは、C/C++で書かれた軽量なLLM推論エンジンです。
Metaが公開したLLaMAモデルを動かすために開発されましたが、現在ではLLaMA以外のモデル(Kimi K2.5を含む)も幅広くサポートしています。最大の特徴は、PythonやPyTorchなしで動作すること。実行ファイル1つとモデルファイルがあれば推論できます。
2.4 量子化(Quantization)とは
量子化は、モデルのパラメータをより少ないビット数で表現する技術です。
通常、パラメータは16ビット(FP16)や32ビット(FP32)の浮動小数点数で保存されます。これを4ビットや2ビット、さらには1ビットまで圧縮するのが量子化です。ファイルサイズは劇的に縮小しますが、精度は多少犠牲になります。
| 量子化レベル | 1パラメータあたり | 特徴 |
|---|---|---|
| FP16(非量子化) | 16ビット | 最高精度だがサイズ大 |
| Q4_K_M | 約4.5ビット | バランス型、最も一般的 |
| IQ2_XXS | 約2ビット | かなり小さいが精度低下あり |
| IQ1_S / TQ1_0 | 約1ビット | 極限の圧縮、大幅な精度低下 |
Kimi K2.5は1兆パラメータあるため、最も強い量子化(TQ1_0)でも223GBになります。
これらの用語が押さえられたら、Kimi K2.5の背景を見ていきましょう。
3. Kimi K2.5が生まれた背景
3.1 Moonshot AI(月之暗面)について
Kimi K2.5を開発したのは、中国・北京に拠点を置く**Moonshot AI(月之暗面)**です。
2023年3月、清華大学の研究者であるYang Zhilin氏らによって設立されました。社名はPink Floydのアルバム「The Dark Side of the Moon」に由来しています。設立からわずか3年で、評価額は**43億ドル(約6,500億円)**に到達。中国AI業界の「AIタイガー」と呼ばれる企業の一角を占めています。
3.2 K2からK2.5への進化
Kimi K2.5の系譜を簡単に整理します。
| モデル | リリース | 特徴 |
|---|---|---|
| Kimi K1.5 | 2025年1月 | OpenAI o1に匹敵する推論性能 |
| Kimi K2 | 2025年7月 | 1兆パラメータMoE、テキスト特化 |
| Kimi K2 Thinking | 2025年11月 | 推論特化版、200-300回の連続ツール呼び出し |
| Kimi K2.5 | 2026年1月 | ネイティブマルチモーダル(視覚+言語)対応 |
K2.5の最大の進化点は、MoonViTと呼ばれる4億パラメータの視覚エンコーダが追加されたことです。画像や動画を「後付け」ではなく「生まれつき」理解できるモデルになりました。約15兆トークンの視覚+テキスト混合データで継続事前学習されています。
3.3 なぜ1兆パラメータなのか
「1兆パラメータ」と聞くと圧倒されますが、MoEアーキテクチャのおかげで実態はもう少しスリムです。
Kimi K2.5のMoE構造を表にまとめます。
| 項目 | 値 |
|---|---|
| 総パラメータ数 | 1兆(1T) |
| 推論時のアクティブパラメータ | 320億(32B) |
| レイヤー数 | 61(うちDenseレイヤー1) |
| エキスパート数 | 384 |
| 1トークンあたりの選択エキスパート数 | 8 |
| Attention Hidden Dimension | 7,168 |
| コンテキスト長 | 256K トークン |
384人のエキスパートから8人だけ選ぶ。つまり、推論時は**全体の約2%**しか使わない計算です。これがMoEの効率の良さです。
ベンチマークでは、GPT-5.2やClaude 4.5 Opusと同等以上のスコアを複数の評価項目で記録しています。オープンソース(Modified MITライセンス)でこの性能は注目に値します。
背景がわかったところで、基本的な仕組みを見ていきましょう。
4. 基本概念と仕組み
4.1 MoEアーキテクチャの動作原理
Kimi K2.5が推論リクエストを受け取ったときの処理の流れを整理します。
入力テキスト
↓
トークン化(テキストを数値に変換)
↓
各レイヤーで処理(61レイヤー)
↓ 各レイヤー内で...
├── Attention(全体の文脈を把握)
└── MoEブロック
├── ルーター: 384エキスパートから8つ選択
└── 選ばれた8エキスパートだけ計算
↓
出力トークンを生成
ポイントは「ルーター」の存在です。各トークンに対して、ルーターが「このトークンにはどのエキスパートが最適か」を判断し、8つを選びます。残りの376エキスパートは何もしません。これが計算コストを抑える仕組みです。
4.2 量子化によるサイズ削減
Kimi K2.5の各量子化版のサイズを比較します。
| 量子化 | サイズ | FP16比 | 精度への影響 |
|---|---|---|---|
| FP16(非量子化) | 約2TB | 100% | なし |
| IQ2_XXS | 327GB | 約16% | 中程度 |
| IQ1_S | 276GB | 約14% | 大きい |
| TQ1_0 | 223GB | 約11% | かなり大きい |
TQ1_0は元の約1/9のサイズですが、それでも223GBあります。96GBのVRAMに収まらないため、GPU/CPUハイブリッド実行が必要になります。
4.3 GPU/CPUハイブリッド実行の仕組み
llama.cppには -ngl(Number of GPU Layers)というパラメータがあります。これは「モデルの何レイヤーをGPUに配置するか」を指定します。
-ngl の仕組み(Kimi K2.5、61レイヤーの場合)
-ngl 61: 全レイヤーをGPUに配置(VRAM不足でエラー)
-ngl 26: 26レイヤーをGPU、35レイヤーをCPUに配置
-ngl 0: 全レイヤーをCPUに配置(GPUを使わない)
高速道路(GPU)と一般道(CPU)を走り分けるようなものです。高速道路に乗れる区間が多いほど速くなります。しかし、高速道路の長さ(VRAMサイズ)には限りがあります。
推奨nglの計算式:
推奨ngl = (VRAM容量 ÷ モデルサイズ) × レイヤー数
例: 96GB VRAM、223GBモデル、61レイヤー
ngl = (96 / 223) × 61 ≈ 26
ただし、推論時にはKVキャッシュ等の追加メモリも必要なため、実際には計算値より少し余裕を持たせます。
基本概念が理解できたところで、実際にコードを書いて動かしてみましょう。
5. 実践:実際に動かしてみよう
5.1 環境構築
今回の検証環境は以下の通りです。
| 項目 | スペック |
|---|---|
| OS | Windows 11 Pro |
| GPU | NVIDIA RTX PRO 6000 Blackwell Workstation Edition |
| VRAM | 96GB |
| RAM | 128GB DDR5 |
| CPU | Intel Core(Alder Lake) |
| ストレージ | NVMe SSD(空き500GB以上推奨) |
| CUDA | 13.0(ドライバー対応) |
| llama.cpp | b7898 |
Step 1: ディレクトリ作成
New-Item -ItemType Directory -Path "C:\Kimi" -Force
New-Item -ItemType Directory -Path "C:\Kimi\llama-cpp" -Force
New-Item -ItemType Directory -Path "C:\Kimi\models" -Force
New-Item -ItemType Directory -Path "C:\Kimi\configs" -Force
Step 2: llama.cppのダウンロード
ここが最初の落とし穴でした。llama.cppの本体とCUDA DLLsは別パッケージです。
# 本体のダウンロード
$llamaUrl = "https://github.com/ggml-org/llama.cpp/releases/download/b7898/llama-b7898-bin-win-cuda-13.1-x64.zip"
Invoke-WebRequest -Uri $llamaUrl -OutFile "C:\Kimi\llama-cpp.zip"
Expand-Archive -Path "C:\Kimi\llama-cpp.zip" -DestinationPath "C:\Kimi\llama-cpp" -Force
# CUDA DLLs(これを忘れるとGPUが認識されない!)
$cudaUrl = "https://github.com/ggml-org/llama.cpp/releases/download/b7898/cudart-llama-bin-win-cuda-13.1-x64.zip"
Invoke-WebRequest -Uri $cudaUrl -OutFile "C:\Kimi\cudart.zip"
Expand-Archive -Path "C:\Kimi\cudart.zip" -DestinationPath "C:\Kimi\cudart-temp" -Force
Copy-Item "C:\Kimi\cudart-temp\*.dll" -Destination "C:\Kimi\llama-cpp\" -Force
私はここでハマりました。 本体だけダウンロードして「GPUが認識されない!」と30分悩みました。公式リリースページをよく見ると、CUDA DLLsは別のzipファイルとして提供されています。ドキュメントにもっと目立つように書いてほしい…。
Step 3: GPU認識の確認
& "C:\Kimi\llama-cpp\llama-cli.exe" --list-devices
正常な場合の出力:
ggml_cuda_init: found 1 CUDA devices:
Device 0: NVIDIA RTX PRO 6000 Blackwell Workstation Edition, compute capability 12.0, VMM: yes
load_backend: loaded CUDA backend from C:\Kimi\llama-cpp\ggml-cuda.dll
Available devices:
CUDA0: NVIDIA RTX PRO 6000 Blackwell Workstation Edition (97886 MiB, 95288 MiB free)
CUDAデバイスが表示されない場合は、5.5節のトラブルシューティングを参照してください。
Step 4: モデルのダウンロード
Hugging Face CLIを使ってGGUF版をダウンロードします。TQ1_0(223GB)が最小の量子化版です。
"""
Kimi K2.5 モデルダウンローダー
実行方法: python download_model.py
所要時間: 回線速度により2-8時間程度
"""
from huggingface_hub import hf_hub_download
REPO_ID = "unsloth/Kimi-K2.5-GGUF"
LOCAL_DIR = r"C:\Kimi\models\UD-TQ1_0"
FILES = [
f"UD-TQ1_0/Kimi-K2.5-UD-TQ1_0-0000{i}-of-00005.gguf"
for i in range(1, 6)
]
def main():
for f in FILES:
print(f"Downloading {f}...")
hf_hub_download(
repo_id=REPO_ID,
filename=f,
local_dir=LOCAL_DIR,
)
print("Download complete!")
if __name__ == "__main__":
main()
事前に pip install huggingface_hub が必要です。
5.2 環境別の設定ファイル
用途に応じて3種類の設定ファイルを用意しました。そのままコピーして使えます。
開発環境用(config_dev.yaml)
デバッグや動作確認に最適化した設定です。GPUレイヤーを少なくして起動を速くしています。
# config_dev.yaml - 開発・動作確認用
# 最小限のリソースで素早く起動し、動作確認するための設定
server:
host: "127.0.0.1" # ローカルのみ
port: 8080
model:
path: "C:\\Kimi\\models\\UD-TQ1_0\\UD-TQ1_0\\Kimi-K2.5-UD-TQ1_0-00001-of-00005.gguf"
ngl: 10 # GPUレイヤー少なめ(起動が速い)
context_size: 2048 # コンテキスト小さめ(メモリ節約)
threads: 8 # CPUスレッド控えめ
batch_size: 512
logging:
level: "DEBUG"
本番環境用(config_prod.yaml)
VRAMとCPUリソースを最大限に活用する設定です。
# config_prod.yaml - 本番・最大性能用
# GPU/CPUリソースを最大活用し、最高のスループットを目指す設定
server:
host: "0.0.0.0" # 外部アクセス許可
port: 8080
model:
path: "C:\\Kimi\\models\\UD-TQ1_0\\UD-TQ1_0\\Kimi-K2.5-UD-TQ1_0-00001-of-00005.gguf"
ngl: 26 # 96GB VRAMの最大活用(計算式: 96/223*61≈26)
context_size: 8192 # 大きめのコンテキスト
threads: 16 # CPUスレッドも全開
batch_size: 2048
logging:
level: "INFO"
ベンチマーク環境用(config_bench.yaml)
性能測定に特化した設定です。変数を統制するため、最小限の構成にしています。
# config_bench.yaml - ベンチマーク・性能測定用
# 再現性のある測定のために、パラメータを固定した設定
server:
host: "127.0.0.1"
port: 8081 # 開発環境と衝突しないポート
model:
path: "C:\\Kimi\\models\\UD-TQ1_0\\UD-TQ1_0\\Kimi-K2.5-UD-TQ1_0-00001-of-00005.gguf"
ngl: 26 # 本番と同じGPUレイヤー
context_size: 4096 # 測定用の固定値
threads: 16
batch_size: 512
benchmark:
warmup_requests: 3 # ウォームアップ回数
test_requests: 10 # 測定回数
prompt: "Explain the concept of mixture of experts in neural networks."
logging:
level: "WARNING" # ログを最小限にして計測への影響を抑える
設定ファイルを読み込むランチャースクリプト
"""
Kimi K2.5 サーバーランチャー
実行方法: python launcher.py [dev|prod|bench]
"""
import yaml
import subprocess
import sys
import os
LLAMA_SERVER = r"C:\Kimi\llama-cpp\llama-server.exe"
CONFIG_DIR = r"C:\Kimi\configs"
def load_config(env: str) -> dict:
"""指定された環境の設定ファイルを読み込む"""
config_path = os.path.join(CONFIG_DIR, f"config_{env}.yaml")
if not os.path.exists(config_path):
print(f"Error: {config_path} が見つかりません")
sys.exit(1)
with open(config_path, encoding="utf-8") as f:
return yaml.safe_load(f)
def build_command(config: dict) -> list[str]:
"""設定からllama-serverの起動コマンドを組み立てる"""
model = config["model"]
server = config["server"]
return [
LLAMA_SERVER,
"-m", model["path"],
"-ngl", str(model["ngl"]),
"-c", str(model["context_size"]),
"-t", str(model["threads"]),
"--host", server["host"],
"--port", str(server["port"]),
]
def main():
env = sys.argv[1] if len(sys.argv) > 1 else "dev"
if env not in ("dev", "prod", "bench"):
print("Usage: python launcher.py [dev|prod|bench]")
sys.exit(1)
config = load_config(env)
cmd = build_command(config)
print(f"Starting Kimi K2.5 server ({env} mode)...")
print(f" GPU Layers: {config['model']['ngl']}")
print(f" Context: {config['model']['context_size']}")
print(f" Address: {config['server']['host']}:{config['server']['port']}")
print(f" Command: {' '.join(cmd)}")
print("-" * 60)
subprocess.run(cmd)
if __name__ == "__main__":
main()
5.3 基本的な使い方
サーバーの起動(設定ファイルなしの場合)
$model = "C:\Kimi\models\UD-TQ1_0\UD-TQ1_0\Kimi-K2.5-UD-TQ1_0-00001-of-00005.gguf"
& "C:\Kimi\llama-cpp\llama-server.exe" `
-m $model `
-ngl 26 `
-c 4096 `
-t 16 `
--host 0.0.0.0 `
--port 8080
ランチャー経由の起動
python launcher.py prod
APIの呼び出し(PowerShell)
$body = @{
prompt = "Hello! Please introduce yourself."
n_predict = 100
temperature = 0.7
} | ConvertTo-Json
$response = Invoke-RestMethod `
-Uri "http://localhost:8080/completion" `
-Method Post `
-Body $body `
-ContentType "application/json"
$response.content
APIの呼び出し(Python)
"""
Kimi K2.5 APIクライアント
実行方法: python client.py
前提条件: llama-serverが起動済みであること
"""
import requests
BASE_URL = "http://localhost:8080"
def chat(prompt: str, max_tokens: int = 200) -> str:
"""llama-serverにリクエストを送信し、レスポンスを返す"""
response = requests.post(
f"{BASE_URL}/completion",
json={
"prompt": prompt,
"n_predict": max_tokens,
"temperature": 0.7,
},
)
response.raise_for_status()
return response.json()["content"]
def main():
answer = chat("What is the Mixture of Experts architecture?")
print(answer)
if __name__ == "__main__":
main()
5.4 実行結果
サーバー起動時のログ(正常時):
load_tensors: offloading output layer to GPU
load_tensors: offloading 25 repeating layers to GPU
load_tensors: offloaded 26/62 layers to GPU
load_tensors: CPU_Mapped model buffer size = 170950.23 MiB
load_tensors: CUDA0 model buffer size = 92176.02 MiB
26レイヤーがGPUに、残りがCPUに配置されています。
推論のパフォーマンス:
| 項目 | 結果 |
|---|---|
| 動作 | 成功 |
| 推論速度 | 約1-2 tokens/sec |
| GPU VRAM使用 | 94-96GB(ほぼフル) |
| GPU計算使用率 | 0-6%(主にCPU処理) |
正直な感想: 動いたことは動きましたが、1-2 tokens/secは「待つ」レベルです。100トークンの生成に1分近くかかります。リアルタイムチャットには厳しい速度でした。
5.5 よくあるエラーと対処法
私が遭遇した3つの壁を含め、起こりうるエラーをまとめました。
| # | エラーメッセージ | 原因 | 対処法 |
|---|---|---|---|
| 1 | no devices with dedicated memory found |
CUDA DLLs未配置 |
cudart-llama-bin-win-cuda-*.zip を別途ダウンロードし、llama-cppフォルダに展開する |
| 2 | cudaMalloc failed: out of memory |
-ngl が大きすぎてVRAM不足 |
-ngl の値を下げる。計算式: (VRAM GB / モデルサイズ GB) × レイヤー数
|
| 3 | GPU-Util 0% だが VRAM は使用中 | モデルがVRAMに収まらず、計算の大部分がCPUで実行 | より小さい量子化版を使うか、-ngl を上げてGPU比率を増やす |
| 4 | ModuleNotFoundError: No module named 'huggingface_hub' |
パッケージ未インストール |
pip install huggingface_hub を実行 |
| 5 | サーバーが 0.0.0.0:8080 で応答しない |
ファイアウォールでブロック | Windows Defenderファイアウォールで8080番ポートを許可する |
| 6 |
failed to load model + ファイルパスエラー |
分割GGUFの1つ目以外を指定 |
-m には必ず 00001-of-00005.gguf を指定する(残りは自動読み込み) |
第1の壁(GPU認識不可)の詳細
これが最もハマりやすいポイントです。llama.cppの公式リリースページには2つのzipがあります。
| ファイル名 | 内容 |
|---|---|
llama-b7898-bin-win-cuda-13.1-x64.zip |
llama.cpp本体 + ggml-cuda.dll
|
cudart-llama-bin-win-cuda-13.1-x64.zip |
CUDA Runtime DLLs(cudart64_13.dll, cublas64_13.dll, cublasLt64_13.dll) |
両方をダウンロードし、同じフォルダに配置する必要があります。以下のDLLが揃っているか確認してください。
# 必要なDLLの存在確認
Get-ChildItem "C:\Kimi\llama-cpp" | Where-Object {
$_.Name -match "cuda|cublas"
} | Select-Object Name
期待される出力:
ggml-cuda.dll
cudart64_13.dll
cublas64_13.dll
cublasLt64_13.dll
第3の壁(GPU使用率0%問題)の詳細
nvidia-smiで確認すると、VRAMは96GB使用済みなのに、GPU-Utilはほぼ0%という不思議な状態でした。
+-----------------------------------------------------------------------------------------+
| GPU Name | Memory-Usage | GPU-Util |
|=========================================+============+==========|
| 0 NVIDIA RTX PRO 6000 Blac... | 96418MiB / 97887MiB | 1% |
+-----------------------------------------------------------------------------------------+
サーバーログの graph splits = 797 が原因を示していました。計算グラフが797回に分割され、GPU/CPU間でデータが行ったり来たりしている状態です。
根本原因: モデル(223GB)がVRAM(96GB)より大きいため、GPUは主に「高速メモリ」として使われ、計算の大部分はCPUが担当していました。これはハードウェアの問題ではなく、純粋なメモリ制約です。
5.6 環境診断スクリプト
問題が発生した場合は、以下のスクリプトで環境を一括診断できます。
#!/usr/bin/env python3
"""
Kimi K2.5 環境診断スクリプト
実行方法: python check_env.py
"""
import os
import sys
import shutil
import subprocess
def check_python():
"""Pythonバージョンを確認"""
ver = sys.version_info
ok = ver >= (3, 9)
status = "OK" if ok else "NG"
print(f" [{status}] Python: {sys.version}")
if not ok:
print(" -> Python 3.9以上が必要です")
return ok
def check_packages():
"""必須パッケージの確認"""
required = ["huggingface_hub", "requests", "yaml"]
pkg_map = {"yaml": "pyyaml"} # importとpip名が異なるもの
all_ok = True
for pkg in required:
try:
__import__(pkg)
print(f" [OK] {pkg}: インストール済み")
except ImportError:
pip_name = pkg_map.get(pkg, pkg)
print(f" [NG] {pkg}: 未インストール -> pip install {pip_name}")
all_ok = False
return all_ok
def check_nvidia_smi():
"""nvidia-smiの実行確認"""
try:
result = subprocess.run(
["nvidia-smi", "--query-gpu=name,memory.total,memory.free",
"--format=csv,noheader"],
capture_output=True, text=True, timeout=10,
)
if result.returncode == 0:
for line in result.stdout.strip().split("\n"):
print(f" [OK] GPU: {line.strip()}")
return True
else:
print(f" [NG] nvidia-smi エラー: {result.stderr.strip()}")
return False
except FileNotFoundError:
print(" [NG] nvidia-smi が見つかりません(NVIDIAドライバ未インストール?)")
return False
def check_llama_cpp():
"""llama.cppバイナリの確認"""
llama_dir = r"C:\Kimi\llama-cpp"
server_path = os.path.join(llama_dir, "llama-server.exe")
if not os.path.exists(server_path):
print(f" [NG] llama-server.exe が見つかりません: {server_path}")
return False
print(f" [OK] llama-server.exe: 存在確認済み")
# CUDA DLLsの確認
cuda_dlls = ["ggml-cuda.dll", "cudart64_13.dll",
"cublas64_13.dll", "cublasLt64_13.dll"]
all_found = True
for dll in cuda_dlls:
path = os.path.join(llama_dir, dll)
if os.path.exists(path):
print(f" [OK] {dll}: 存在確認済み")
else:
print(f" [NG] {dll}: 見つかりません!")
all_found = False
if not all_found:
print(" -> cudart-llama-bin-win-cuda-*.zip を別途ダウンロードしてください")
return all_found
def check_disk_space():
"""ディスク空き容量の確認"""
model_dir = r"C:\Kimi\models"
if os.path.exists(model_dir):
total, used, free = shutil.disk_usage(model_dir)
free_gb = free / (1024 ** 3)
ok = free_gb >= 250
status = "OK" if ok else "NG"
print(f" [{status}] ディスク空き: {free_gb:.1f} GB")
if not ok:
print(" -> TQ1_0モデル(223GB)のダウンロードには250GB以上推奨")
return ok
else:
print(f" [--] {model_dir} が存在しません")
return False
def check_model_files():
"""モデルファイルの存在確認"""
model_dir = r"C:\Kimi\models\UD-TQ1_0\UD-TQ1_0"
if not os.path.exists(model_dir):
print(f" [--] モデルディレクトリ未作成: {model_dir}")
return False
expected = [
f"Kimi-K2.5-UD-TQ1_0-0000{i}-of-00005.gguf"
for i in range(1, 6)
]
all_found = True
total_size = 0
for fname in expected:
path = os.path.join(model_dir, fname)
if os.path.exists(path):
size_gb = os.path.getsize(path) / (1024 ** 3)
total_size += size_gb
print(f" [OK] {fname}: {size_gb:.1f} GB")
else:
print(f" [NG] {fname}: 見つかりません")
all_found = False
if all_found:
print(f" 合計: {total_size:.1f} GB")
return all_found
def main():
print("=" * 60)
print("Kimi K2.5 環境診断")
print("=" * 60)
sections = [
("1. Python環境", check_python),
("2. 必須パッケージ", check_packages),
("3. NVIDIA GPU", check_nvidia_smi),
("4. llama.cpp + CUDA DLLs", check_llama_cpp),
("5. ディスク空き容量", check_disk_space),
("6. モデルファイル", check_model_files),
]
results = []
for title, check_fn in sections:
print(f"\n{title}")
print("-" * 40)
results.append(check_fn())
print("\n" + "=" * 60)
if all(results):
print("診断結果: すべてOKです!サーバーを起動できます。")
else:
ng_count = sum(1 for r in results if not r)
print(f"診断結果: {ng_count}件の問題が見つかりました。上記の指示に従って修正してください。")
print("=" * 60)
if __name__ == "__main__":
main()
実装方法がわかったので、次は具体的なユースケースを見ていきます。
6. ユースケース別ガイド
6.1 ユースケース1: 対話型チャット(Web UI経由)
想定読者: ブラウザからKimi K2.5と対話してみたい方
推奨構成: llama-serverの組み込みWeb UIを使用
llama-serverを起動すると、http://localhost:8080 にWeb UIが自動で提供されます。追加のインストールは不要です。
起動コマンド:
$model = "C:\Kimi\models\UD-TQ1_0\UD-TQ1_0\Kimi-K2.5-UD-TQ1_0-00001-of-00005.gguf"
& "C:\Kimi\llama-cpp\llama-server.exe" `
-m $model `
-ngl 26 `
-c 4096 `
-t 16 `
--host 127.0.0.1 `
--port 8080
ブラウザで http://localhost:8080 を開くと、チャットインターフェースが表示されます。推論速度が1-2 tokens/secのため、長文の回答には時間がかかる点に注意してください。
6.2 ユースケース2: PythonからのAPI呼び出し
想定読者: 自分のアプリケーションにKimi K2.5を組み込みたい方
推奨構成: llama-server + requests ライブラリ
サンプルコード:
"""
Kimi K2.5 バッチ推論クライアント
実行方法: python batch_inference.py
前提条件: llama-serverが起動済みであること
"""
import requests
import json
import time
BASE_URL = "http://localhost:8080"
def complete(prompt: str, max_tokens: int = 200,
temperature: float = 0.7) -> dict:
"""単一のプロンプトを推論する"""
response = requests.post(
f"{BASE_URL}/completion",
json={
"prompt": prompt,
"n_predict": max_tokens,
"temperature": temperature,
},
timeout=300, # 推論が遅いため長めに設定
)
response.raise_for_status()
return response.json()
def batch_inference(prompts: list[str]) -> list[str]:
"""複数のプロンプトを順次推論する"""
results = []
for i, prompt in enumerate(prompts, 1):
print(f"Processing {i}/{len(prompts)}: {prompt[:50]}...")
start = time.time()
result = complete(prompt)
elapsed = time.time() - start
content = result.get("content", "")
tokens = result.get("tokens_predicted", 0)
speed = tokens / elapsed if elapsed > 0 else 0
print(f" -> {tokens} tokens in {elapsed:.1f}s ({speed:.1f} t/s)")
results.append(content)
return results
def main():
prompts = [
"Explain quantum computing in simple terms.",
"What is the difference between TCP and UDP?",
"Write a Python function to calculate fibonacci numbers.",
]
results = batch_inference(prompts)
for prompt, result in zip(prompts, results):
print(f"\n{'='*60}")
print(f"Q: {prompt}")
print(f"A: {result[:200]}...")
if __name__ == "__main__":
main()
6.3 ユースケース3: OpenAI互換APIとして利用
想定読者: 既存のOpenAI APIベースのコードを流用したい方
推奨構成: llama-server + openai ライブラリ
llama-serverはOpenAI互換のAPIエンドポイントを提供しています。既存のコードの base_url を変更するだけで利用できます。
サンプルコード:
"""
Kimi K2.5 OpenAI互換クライアント
実行方法: python openai_compat.py
前提条件: pip install openai, llama-serverが起動済みであること
"""
from openai import OpenAI
# llama-serverをOpenAI互換エンドポイントとして使用
client = OpenAI(
base_url="http://localhost:8080/v1",
api_key="not-needed", # ローカルサーバーでは認証不要
)
def chat(user_message: str) -> str:
"""OpenAI互換APIでチャットする"""
response = client.chat.completions.create(
model="kimi-k2.5", # ローカルでは任意の文字列でOK
messages=[
{
"role": "system",
"content": "You are Kimi, an AI assistant. Answer concisely.",
},
{"role": "user", "content": user_message},
],
max_tokens=200,
temperature=0.7,
)
return response.choices[0].message.content
def main():
questions = [
"What is MoE in the context of LLMs?",
"How does quantization affect model quality?",
]
for q in questions:
print(f"Q: {q}")
print(f"A: {chat(q)}")
print()
if __name__ == "__main__":
main()
これにより、LangChainやLlamaIndex等のフレームワークからもそのまま利用できます。
ユースケースを把握できたところで、この先の学習パスを確認しましょう。
7. 学習ロードマップ
この記事を読んだ後、次のステップとして以下をおすすめします。
初級者向け(まずはここから)
- 小さいモデルで練習する: いきなり1兆パラメータは荷が重いです。まずは7Bや13Bのモデル(例: Llama 3.1 8B GGUF)でllama.cppの使い方に慣れましょう
- llama.cppの公式ドキュメントを読む: GitHub README にパラメータの詳細が記載されています
- 量子化の違いを体感する: 同じモデルのQ4_K_MとQ2_Kを比較して、品質と速度のトレードオフを実感してみましょう
中級者向け(実践に進む)
- nglパラメータの最適化: 自分のGPUに合わせてnglを1ずつ変えながら、速度とメモリ使用量の最適点を探る
-
llama.cppのサーバーオプションを深掘り:
--ctx-size,--batch-size,--parallel等のチューニング - OpenAI互換APIの活用: LangChainやLlamaIndex経由でRAGパイプラインを構築する
上級者向け(さらに深く)
- マルチGPU構成に挑戦: 2枚以上のGPUでKimi K2.5のGPU比率を上げる
- vLLM / SGLangでの実行: 公式デプロイメントガイド にvLLMとSGLangの設定例があります
- Kimi K2.5のAgent Swarm機能を試す: Kimi Code CLI で最大100のサブエージェントによる並列実行を体験する
8. まとめ
この記事では、Kimi K2.5について以下を解説しました。
- Kimi K2.5とは何か: Moonshot AI(月之暗面)が開発した1兆パラメータのMoEモデル。384エキスパートから8つを選択して推論する効率的なアーキテクチャ
- シングルGPUでの動かし方: Windows + llama.cpp + CUDA DLLsの環境構築から、環境別設定ファイル、API呼び出しまでの完全手順
- 3つの壁と教訓: GPU認識不可→CUDA DLLs別途配置、メモリ不足→ngl調整、GPU使用率0%→メモリ制約の理解
私の所感
96GBのVRAMは「巨大」ですが、1兆パラメータモデルの前では足りませんでした。
今回の検証で最も印象的だったのは、GPUが「計算装置」ではなく「高速メモリ」として使われていたことです。96GBのVRAMはほぼ満杯なのに、GPU使用率は0%。高性能なスポーツカーのエンジンではなく、トランクの広さだけが活用されている状態です。
しかし、ネガティブなことばかりではありません。この検証で以下が確認できました。
- Blackwell (sm_120) はllama.cpp b7898 + CUDA 13.1で動作する: 新アーキテクチャの互換性が確認できた
- GPU/CPUハイブリッドで超巨大モデルも「動く」: 速くはないが、動くことには価値がある
- 1兆パラメータの民主化が始まっている: API経由ではなくローカルで動かせる時代が近づいている
私の見解では、シングルGPUでの実用的な速度にはGPUメモリの進化(次世代の192GB+VRAMなど)が必要です。あるいは、より効率的な量子化技術で50-80GB級まで圧縮できれば、世界が変わるでしょう。
1兆パラメータの壁は高いですが、登れない壁ではありません。次回は複数GPU構成か、より小さいモデルでの検証に挑みたいと思います。