vLLMとRDMAで構築するローカルLLMクラスタ (6):Claude Code をローカルLLMで動かす

執筆者:佐藤友昭

※ 「vLLMとRDMAで構築するローカルLLMクラスタ」連載記事一覧はこちら


実用での使用感

さて、前回まででほぼ完成したシステムの実用での使用感を見ていきたい。

予告では、「Open-WebUI の推論エンジンとして LM 分散実行環境を使用する(=Open-WebUI から OpenAI API で LM 分散実行環境の vLLM/Ray に接続する)ことでシステムとして「より大きなモデルでより高速にナレッジ(RAG)を使用」できるかを試してみたい。」と書いたが、何と何を比較すると役に立ちそうな情報が得られそうか、まだ良いアイディアが思いつかないでいる。
そこで、まずは趣向を変えてClaude Codeのバックエンドとして試すことにする。比較対象は M4 Max MacBookPro (128GB) である。

Claude Code が気になる

個人的に Cursor を使い始めて1年になる。Obsidianとの組み合わせで大変重宝している。
何か実験を始めるときに新規フォルダを作って新規ファイル(マークダウンファイル)に指示を書く。このファイルを指定して Cursor に「指示を書いた。確認し結果をログに追記してほしい」と言う。Cursor が書いたログを見て次の指示を書く、というのを繰り返す。結論に到達したら作業記録に清書してもらう。
最近、Cursor のソフトウェア更新頻度が高いような気がする。この感じは Obsidian を使い始める前の Evernote に似ている。Evernote の様子(=競争している感じ)から Obsidian の気配を感じ始め、そのうち Obsidian が気になって仕方なくなった。今度も同じように Claude Code が気になっていたところ、macOS 版の LM Studio が 0.4.1 以降で「Anthropic API 互換エンドポイント」を公式サポートしたというのを知り、ついに Claude サブスクリプションに契約してしまった。 Claude サブスクリプションは、"Pro" だと消費トークンが上限にすぐに到達してしまうようである。本格的に利用するには "Max" 以上が必須だろう。その場合 API コストはだいぶ高くなる。

Cursor を Claude Code + ローカルLLM で代替できる?

Cursor の使用感は大変気に入っており特に不満もないが、Claude Code + ローカルLLMでの使用感がどのようなものかは大変興味がある。
これまで M4 Max MacBookPro (128GB)上の Cursor (=クラウドLLM)で行っていた作業を、Claude Code + ローカルLLMで試すことにする。このときバックエンドを LM Studio (Mac上のアプリ)と vLLM (=前回までに構築した4ノードLM分散実行環境+共有ストレージ)とで使い比べてみたい。
「安さと早さが正義」と豪語して始めたプロジェクトであるが、eBay 等を駆使して構築した検証環境の購入金額は既にM4 Max MacBookPro (128GB)はおろかM3 Ultra MacStudio (512GB) をも上回ってしまっている。先日、DGX Spark 等 GB10 機8台による LM 分散実行環境の検証動画を YouTube で視聴したが、非常に安価な 400GbE スイッチを使用していた。是非ともAPI コスト不要の安価でスケーラビリティのある LM 分散実行環境が普及して欲しいところである。

Claude Code 側の準備(Mac)

Mac に Claude Code をインストールする。Cursor に「https://code.claude.com/docs/ja/setup をインストールして実行してほしい」と指示する。 (本稿では使用しないが、Cursor の拡張機能 "Claude Code for VS Code" もインストールした。)

LM Studio 側の準備(Mac)

今回、使用するモデルは上司がブログで取り上げている qwen3-coder-next のバリエーションの中から選択することにする。 (support.claude.com に "Claude’s context window size is 200K, meaning it can ingest 200K+ tokens (about 500 pages of text or more) when using a paid Claude plan." という記述がある。)

LM Studio (バージョン0.4.2+2) では qwen/qwen3-coder-next (4bit量子化) を使用する。コンテキストウインドウは最大の 256K を設定。

vLLM 側の準備(Linux)

vLLMはバージョン0.11.1からAnthropic APIの/v1/messagesエンドポイントをサポートしているようである。vLLM のバージョンを 0.11.0 から本稿執筆時点で最新の 0.16.0 に上げた。 モデルは cyankiwi/Qwen3-Coder-Next-AWQ-4bit を使用する。コンテキストウインドウは同じく 256K を設定。

Claude Code の起動(Mac)

claude --settings claude_local.json

claude_local.json の内容(バックエンドに LM Studio を使用する場合):

{
  "model": "qwen/qwen3-coder-next",
  "env": {
    "ANTHROPIC_BASE_URL": "http://localhost:1234",
    "ANTHROPIC_AUTH_TOKEN": "lmstudio"
  },
  "thinking": {
    "type": "disabled"
  }
}

claude_local.json の内容(バックエンドに vLLM を使用する場合):

{
  "model": "cyankiwi/Qwen3-Coder-Next-AWQ-4bit",
  "env": {
    "ANTHROPIC_BASE_URL": "http://192.168.0.3:8000",
    "ANTHROPIC_AUTH_TOKEN": "NA"
  },
  "thinking": {
    "type": "disabled"
  }
}

Claude Code の動作確認(Mac)

各バックエンドを使用して以下のプロンプトを実行し、動作を確認した。

次の仕様を満たす C プログラムを 1 つのソースファイルで実装してください。

【仕様】
- プログラムは標準入力、またはコマンドライン引数で指定したファイルからテキストを読み込む。
- 読み込んだテキストについて「行数」「単語数」「バイト数(文字数)」を集計し、1 行で出力する。
  - 出力形式: 行数 単語数 バイト数(空白区切り。例: 3 12 89)
- 単語は空白(スペース・タブ・改行)で区切られた連続した非空白文字の並びとする。
- 引数がない場合は標準入力から読み、引数が 1 つある場合はそのパスをファイルとして開いて読み込む。ファイルが開けない場合は標準エラーにエラーメッセージを出して終了コード 1 で終了する。

【制約】
- C11 または C99 の標準 C のみを使う。プラットフォーム固有の API(Windows 専用等)は使わない。
- Linux と macOS の両方で、次のコマンドで警告なくビルドできること:
  - gcc -std=c11 -Wall -Wextra -o wc_bench wc_bench.c
  - または clang -std=c11 -Wall -Wextra -o wc_bench wc_bench.c
- ソースファイル名は wc_bench.c とする。

【実施してほしいこと】
1. wc_bench.c を作成する。
2. 上記の gcc または clang コマンドでビルドを実行し、成功することを確認する。
3. ビルドが成功したら、適当なテスト用の短いテキスト(例: 2〜3 行)で実行し、行数・単語数・バイト数が期待どおりか確認する。

現在の作業ディレクトリに wc_bench.c を作成してください。

バックエンドに LM Studio を使用した時の様子:

⏺ Write(wc_bench.c)
  ⎿  Wrote 54 lines to wc_bench.c
       1 #include <stdio.h>
       2 #include <stdlib.h>
       3
       4 int main(int argc, char *argv[]) {
       5     FILE *fp = NULL;
       6     const char *filename = NULL;
       7
       8     if (argc > 2) {
       9         fprintf(stderr, "Usage: %s [file]\n", argv[0]);
      10         return 1;
     … +44 lines (ctrl+o to expand)

⏺ 次にビルドを実行します。

⏺ Bash(gcc -std=c11 -Wall -Wextra -o wc_bench wc_bench.c)
  ⎿  (No output)

⏺ ビルド成功しました。次にテストを行います。

⏺ Bash(cat << 'EOF' | ./wc_bench
      Hello world…)
  ⎿  3 8 38

⏺ Bash(cat << 'EOF' > test.txt
      Hello world…)
  ⎿  3 8 38

⏺ Bash(clang -std=c11 -Wall -Wextra -o wc_bench2 wc_bench.c && echo "Clang build succeeded")
  ⎿  Clang build succeeded

⏺ すべて完了しました。

  作成したファイル: wc_bench.c

  仕様の実装内容:
  - コマンドライン引数がなければ標準入力から、1 つの引数があればファイルから読み込み
  - 行数(改行文字のカウント)、単語数(空白区切りの連続非空白文字)、バイト数をカウント
  - ファイルオープン失敗時は標準エラーに出力して終了コード 1

  テスト結果:
  3 8 38
  - 行数: 3
  - 単語数: 8 (Hello, world, This, is, a, test, Line, three)
  - バイト数: 38 (改行文字を含む)

  gcc と clang の両方で警告なしにビルドできることを確認しました。

✻ Sautéed for 2m 30s

バックエンドに vLLM を使用した時の様子:

⏺ Write(wc_bench.c)
  ⎿  Wrote 78 lines to wc_bench.c
       1 #include <stdio.h>
       2 #include <stdlib.h>
       3 #include <string.h>
       4
       5 #define BUFFER_SIZE 4096
       6
       7 int main(int argc, char *argv[]) {
       8     FILE *fp = NULL;
       9     int from_stdin = 0;
      10     char buffer[BUFFER_SIZE];
     … +68 lines (ctrl+o to expand)

⏺ 次に、ビルドとテストを行います。

⏺ Bash(gcc -std=c11 -Wall -Wextra -o wc_bench wc_bench.c)
  ⎿  (No output)

⏺ ビルド成功。次にテストを行います。

⏺ Bash(printf "Hello world\nThis is a test\nLine three\n" > test.txt && cat test.txt && echo "---" && ./wc_bench test.txt)
  ⎿  Hello world
     This is a test
     Line three
     … +2 lines (ctrl+o to expand)

⏺ 結果を検証します:

  - 行数: 3行(正しい)
  - 単語数: 8語(Hello, world, This, is, a, test, Line, three → 正しい)
  - バイト数: 38バイト(Hello world\nThis is a test\nLine three\n = 12 + 17 + 9 = 38バイト → 正しい)

  念のため、標準入力からの入力もテストします。

⏺ Bash(printf "Test input\n123\n" | ./wc_bench)
  ⎿  2 3 15

⏺ 標準入力でも正常に動作します(2行、3語、15バイト)。

  エラーハンドリングも確認します。

⏺ Bash(./wc_bench nonexistent_file.txt; echo "Exit code: $?")
  ⎿  Error: cannot open file 'nonexistent_file.txt'
     Exit code: 1

⏺ すべての要件を満たしています:

  1. wc_bench.c を作成しました
  2. gcc -std=c11 -Wall -Wextra -o wc_bench wc_bench.c で警告なくビルド成功
  3. テストで行数・単語数・バイト数が正しくカウントされることを確認
  4. 標準入力とファイル読み込みの両方が動作
  5. ファイルオープン失敗時に標準エラーにエラーメッセージを出力し、終了コード 1 で終了

✻ Churned for 1m 55s

感想と今後

バックエンドを LM Studio (Mac上のアプリ)と vLLM (=前回までに構築した4ノードLM分散実行環境+共有ストレージ)とした場合とでの使用感の比較はできそうである。上記の動作確認ではvLLM 使用時の方が念入りな感じであるが完了までの時間は短い。たまたまかもしれないが逆でなくて良かったと思う。この後、本格的に色々試してみるつもりである。

Claude Code(=ソフトウェア開発環境)とLM 分散実行環境の組み合わせ以外としては、何かと話題の OpenClaw についても試してみる必要があるだろう。コモディティハードウェアと Linux カーネルをはじめとする OSS で実現可能な、PC の前での作業全般を行うロボット群を支えるLM分散実行環境についても考えてみよう。

Claude Code ってすごいね

Claude Code の使い方の勉強を兼ねて、ssh 経由で Linux PC に OpenClaw をインストールしてみた。
使用する PC は古くなって vLLMクラスタから外した Z390 機。GPUは RTX 4070 Ti Super (16GB) 。
Cursor の時と同じように、マークダウンファイルに指示を書いてから Claude Code に実行してもらってログを追記してもらうというのを繰り返す。
出来上がったら普段は手順書にしてもらうのだが、今回はメタプロンプトにしてもらった。将来、手順書を見て手作業することもないであろうし、仮にあったとしても古くて使えない可能性が高い。
以下が Claude Code が生成したメタプロンプト。

# OpenClaw セットアップ用プロンプト生成メタプロンプト

## Claude Code への指示

SSH でログインできる Linux ホスト <TARGET_HOST> に、ollama 上のローカルモデルを使った OpenClaw 環境を構築するためのセットアップ手順書をマークダウンで作成してください。

条件:
- 使用するソフトウェアはすべて最新バージョンとする
- OpenClaw のモデル選定には llmfit を使い、ターゲットホストの GPU VRAM に完全収容できるモデルを選ぶ
- WebChat へのアクセスは SSH ポートフォワード(localhost:18789)経由とする
- セットアップ手順は Claude Code が SSH 越しに実行できるコマンド形式で記載する

手順書に含めること:
1. ハードウェア・ソフトウェア構成の調査
2. apt / Ollama / Docker コンテナの更新
3. llmfit のインストールと `llmfit fit` によるモデル選定
4. Node.js 22・openclaw のインストールと Ollama プロバイダー設定
5. gateway の起動・セキュリティ設定・OLLAMA_API_KEY の永続化
6. SSH トンネルの設定(macOS: LaunchAgent、Linux: systemd user service)
7. contextWindow を GPU VRAM に合わせて調整する手順
8. 最終動作確認チェックリスト

手順書の末尾に、ホスト名・ユーザー名・認証トークンなど環境依存の置き換え箇所を一覧で示すこと。

次に、登録 YouTube チャンネルの新規コンテンツの中から実際に視聴するコンテンツを選ぶための YouTube チャネルの巡回と音声ダウンロードおよび(parakeetとfast_whisperによる)文字起こしのスクリプトをこの PC で動作するようにしてもらう。
毎日、午前0時に処理が走るように設定してもらう。生成された文字起こしテキスト群は git に push される。

次に、ピックアップした YouTube タイトルについて、文字起こしテキストの誤植を修正したり、パラグラフを整えて見出しを付けたり、用語集を作成したり、英文の場合は和訳するスクリプト(process_title.sh に連なるスクリプト群)を移植してもらう。
今までは Gemini を利用していたが、トークン上限のないローカル LLM を利用するように改修してもらう。
生成されたドキュメントの品質や処理速度を改善するために ollama 以外のエンジンやその上で動作する複数のモデルを比較してもらう。その結果、vLLMとqwen2.5-14b-gptqの組み合わせを使うことにした。
構築済みの OpenClaw もバックエンドを ollama から vLLM に変更してもらう。

ここまででは OpenClaw の出番はない。Claude Code にこの状況での OpenClaw ユースケースを提案してもらった。
以下が Claude Code が提案したユースケースのサマリ。

# ユースケース 難易度 即効性 既存資産活用
UC-3 議事録・アクションアイテム抽出
UC-6 process_title.sh 並列バッチ処理
UC-1 YouTube トレンドレポート
UC-2 コードレビュー支援
UC-5 llama4 マルチモーダル図解
UC-4 RAG ナレッジQ&A
UC-7 qwen3.5 thinking 技術調査

やりたかったことは YouTube の文字起こしをナレッジとする UC-4 だが、文字起こしテキストをフラットなまま与えるよりも、一手間かけて構造化したものを与えた方が回答品質が高い感じなので、先に UC-6 をやってもらうことにする。
以下は Claude Code 出力の引用。

### UC-6: process_title.sh の並列バッチ処理

**概要:** `YouTube_Monitoring.dir/` の未処理テキスト(翻訳未済ファイル)を OpenClaw の subagent 並列処理(maxConcurrent: 8)で一括処理する。

**構成:**
- openclaw subagent 最大8並列で `process_title.sh` を並列実行
- vLLM が同時リクエストを `--max-num-seqs 8` でキュー処理
- 翻訳・用語集生成・glossary を並列生成

**メリット:** 現在は逐次処理だが、並列化で処理速度を大幅向上できる。vLLMのバッチ推論を活用。

UC-6 を選択して実行してもらっている。以下は、実行中の進捗確認の様子。

❯ batch_process.log の進捗をまた確認してほしい

⏺ Bash(ssh cl1 'grep "OK:" ~/openclaw/batch_process.log | wc -l && tail -5 ~/openclaw/batch_process.log')
  ⎿  169
     [2026-03-12 10:01:29]   Launching (3/4 running): 128_gigs_of_RAM_in_this_ROG_Flow_Z13_Tablet
     [2026-03-12 10:06:21]   [164/14504] OK: 10x_AI_Engineers_with_1m_Salaries_—_Alex_Lieberman_&_Arman_Hezarkhani,_Tenex
     … +3 lines (ctrl+o to expand)

⏺ 現在の進捗(10:06時点):
  - 完了: 169件 / 14,504件
  - 経過: 約1時間48分で169件 → 約1件/38秒(ペース低下)
  - 直近: アルファベット順で 1xx タイトルを処理中
  全件完了まで約152時間(約6.3日) の見込みです。前回より処理が遅くなっています。一部の長いコンテンツで時間がかかっている可能性があります。

終わったら UC-4 を実行してもらおう。
以下は Claude Code 出力の引用。「112,000本超」は誤りで正しくは 14,504本。

### UC-4: RAG(検索拡張生成)による社内ナレッジQ&A

**概要:** 蓄積した文字起こし・翻訳テキスト群を embedding でベクトル化し、OpenClaw から自然言語で検索・質問応答できるナレッジベースを構築する。

**構成:**
- Embedding: `nomic-embed-text`(ollama、テキスト)または `embeddinggemma`
- Reranker: `BAAI/bge-reranker-v2-m3`(精度向上)
- VectorDB: chromadb または qdrant(ローカル)
- LLM: vllm/qwen2.5-14b-gptq で回答生成

**メリット:** 112,000本超の動画文字起こしが検索可能なナレッジベースになる。

Cursor もすごいけど、Claude Code もすごいな。
どんな強力なインフラが登場してきてもどうせ瞬く間に使い切ってしまうんだろうな。> 人類