こんにちは、パレイド技術部です。
前回記事では、Mac 環境で MLX を使った qwen3.5:27b の実用性を検証しました。
今回は Windows 環境への展開で遭遇した問題と、その解決策としての llama.cpp への移行について書きます。
本記事はローカル LLM による自動執筆パイプラインで生成されました。現段階ではクラウド AI(Claude 等)の補助や人間の編集が介在していますが、pareido.jp では最終的に AI が自律的にコンテンツを制作できる仕組みの構築を目指しています。
Windows 環境でも qwen3.5 高速に動かしたい
前回までの検証は MacBook Air M5 上で行いました。結果、Ollama より 5〜10 倍高速に、qwen3.5 が安定して動きます。
主な理由は Unified Memoryの 余裕ですが、4b や 9b でも速さがここまで違うとは想定外。メインの開発環境は Windows + RTX4070 のため、VRAM 容量が 12GB と微妙ですができればこちらも qwen3.5 を安定して動かしたい。27b は無理ですが 9b は理屈では安定するはず。
これまでも qwen3.5:9b は動いて 4b が安定しなかったりと不思議に思っていたのですが、Ollama から切り替えれば安定する期待が出てきました。
モデルも諸条件も違うので Apple to Apple の比較ではなく参考値ですが、結論から言うと qwen3.5: 9b の利用において llama.cpp は2倍ほど速い。ただし検証目的のプロンプトでの話なので、体感では大きな違いはありません。
また、速さだけでなく Ollama では thinking や tool calling の利用に癖があり、現状は llama.cpp が無難なようです。(Claude や ChatGPT にコードを書かせると、カットオフの問題か、thinking をオフにするオプションを知らず苦労していました)
まずは llama.cpp を試す
Mac では MLX に切り替えて解決しましたが、MLX は Apple Silicon 専用です。Windows では別の選択肢が必要です。
Ollama の内部では llama.cpp が推論エンジンとして使われています。Ollama を「llama.cpp のラッパー + モデル管理」と捉えると分かりやすいかもしれません。軽く調べた範囲では、どうも Ollama が内部で使っている llama.cpp がまだqwen3.5 に対応していない様子。であれば、llama.cpp を直接使えば Ollama のラッパー層で起きている問題を回避できるのでは、と考えました。
Ollama の GGUF をそのまま llama-server に渡してみる
まず手っ取り早く、Ollama がダウンロード済みの GGUF ファイルをそのまま llama-server に渡して試します。Ollama のモデルは ~/.ollama/models/blobs/ に保存されているので、該当ファイルを指定して起動。
llama-server \
-m ~/.ollama/models/blobs/sha256-XXXX \
--port 8080 \
-ngl 99
――動きません。エラーメッセージを見ると、配列長の不整合のようです。
error: GGUF tensor 'blk.0.attn_k.weight' has wrong dimensions;
expected 3 dimensions, got ...
issue を見つけ、nightly 待ちに
エラーメッセージで検索すると、llama.cpp の GitHub にも Qwen3.5 関連の issue が上がっていました。Ollama 側でも同様の報告が多数あります。
issue のコメントを追っていくと、llama.cpp の nightly ビルド b8450 以降で Qwen3.5 の qwen35 / qwen35moe アーキテクチャに対応する、とのこと。
Windows 環境で llama.cpp を nightly からビルドするのは CUDA 周りの依存関係もあってなかなか大変。安定リリースを待つことにしました。
リリース版でもダメだった
しばらくして新しいリリースが出たので試してみましたが、Ollama 由来の GGUF ではやはり同じエラーが出ます。
ここで改めて調べ直すと、問題は llama.cpp のバージョンだけではなく、GGUF ファイル自体の構造にありました。
原因:qwen3.5 は全モデルがマルチモーダル
Qwen3.5 はアーキテクチャが前世代から大きく変わっています。Qwen3 ではテキスト専用モデルと VL(Vision-Language)モデルが別々に提供されていましたが、Qwen3.5 では全モデルにビジョン機能が統合されました。
このため、HuggingFace で配布されている GGUF は以下の2ファイル構成になっています。
| ファイル | 内容 |
|---|---|
| メインGGUF(例: Q4_K_M.gguf) | テキスト/言語モデルの重み |
| mmproj-F16.gguf | ビジョン投影(マルチモーダル)の重み |
Ollama が ollama pull でダウンロードする GGUF は、この VL 込みのモデルをラッピングしたものです。
Claude や ChatGPT に相談したでは、「GGUF 内の attention.head_count_kv メタデータがスカラーと配列で食い違っていたり、モデルのメタデータが image-text-to-text アーキテクチャを示していたりと、テキスト推論エンジンが想定する形式と噛み合わない部分が複数ある」とのこと。
Ollama 側でも修正の PR が提出されています(ollama/ollama#14517)が、記事執筆時点では安定版に未反映です。MoE 構成の 35B や 122B でも同様のエラーが報告されています。
テキスト専用 GGUF なら動いた
要するに、VL 込みの GGUF をテキスト推論エンジンに渡していたのが問題と理解。であれば、テキスト部分だけの GGUF を使えばいいのでは?
HuggingFace から Unsloth 版のテキスト用メイン GGUF(mmproj を含まない方)を直接ダウンロードして llama-server に渡してみます。
# テキスト専用 GGUF で起動(Ollama 由来ではなく HuggingFace から直接取得)
llama-server \
-m Qwen3.5-27B-Q4_K_M.gguf \
--port 8080 \
-ngl 99
――今度は動きました。Ollama の GGUF をそのまま使おうとして遠回りしましたが、結局 HuggingFace からテキスト専用の GGUF を取得して llama-server に直接渡すのが正解でした。
ビジョン機能も使う場合は --mmproj mmproj-F16.gguf を追加しますが、今回のパイプラインではテキスト処理だけなので不要です。
OpenAI 互換 API がそのまま使える
llama-server は OpenAI 互換の API(/v1/chat/completions)を提供するため、既存のパイプラインコードをほぼそのまま流用できました。変更点は接続先の URL を localhost:11434(Ollama)から localhost:8080(llama-server)に切り替える程度です。
(正確に言えば、Ollama が llama.cpp と同じ、という時系列だとは思いますが)
Qwen の公式ドキュメントでも、llama.cpp 経由での利用方法が案内されています。
thinking タグの除去は引き続き必要
Ollama では <think>...</think> タグが自動除去されますが、llama-server はそのまま返してきます。前回 MLX 向けに実装した thinking タグ除去の処理がここでも活用できました。
また、Qwen3.5 の thinking モードの制御は llama.cpp のチャットテンプレート経由では完全には対応していないため、presence_penalty パラメータで反復を抑制するアプローチを取っています。
Ollama vs llama.cpp vs MLX:使い分けの整理
3回にわたる検証を通じて、各バックエンドの性格がはっきりしてきました。
| 観点 | Ollama | llama.cpp | (参考)MLX |
|---|---|---|---|
| 対応OS | Win/Mac/Linux | Win/Mac/Linux | Mac のみ |
| セットアップ | 簡単(ワンクリック) | やや手間(ビルド済みは楽) | pip install |
| モデル管理 | ollama pull で自動 | 手動で GGUF 配置 | HuggingFace から自動 |
| Qwen3.5 対応 | 一部不安定 | 安定 | 安定 |
| GPU活用 | 自動 | -ngl で明示指定 | Metal 自動 |
| API互換 | 独自 + OpenAI互換 | OpenAI互換 | なし(Python直接) |
| 向いている場面 | 手軽に試す・複数モデル切り替え | 特定モデルを安定運用 | Apple Silicon で最速 |
普段の開発や実験では Ollama の手軽さが圧倒的です。ただ、Qwen3.5 のようにアーキテクチャが新しいモデルでは Ollama の対応が追いつかないこともあり、そういう場面で llama.cpp を直接使えるようにしておくと、選択肢が広がります。
まとめ
今回は Windows 環境で Qwen3.5 を動かすまでの試行錯誤を書きました。
振り返ると、遠回りの原因は「Ollama の GGUF をそのまま使えるはず」という思い込みでした。ポイントをまとめると:
- Qwen3.5 は全モデルにビジョン機能が統合された。GGUF がテキスト用と VL 用の2ファイル構成になっている
- Ollama 由来の GGUF は VL 込みでラッピングされており、llama-server に直接渡しても配列長の不整合で動かない
- HuggingFace からテキスト専用の GGUF を取得して llama-server に渡せば解決
- OpenAI 互換 API のおかげで、既存コードへの影響は最小限
llama.cpp のバージョンの問題だと思って nightly を待ったのが一番のロスでした。エラーメッセージだけでなく、モデルのアーキテクチャ変更まで視野に入れて原因を切り分けるべきだったと反省しています。
Ollama は「とりあえず動かす」には最適ですが、新しいモデルへの追随は llama.cpp 本体より遅れることがあります。パイプラインを本番運用するなら、バックエンドを切り替えられる設計にしておくのが安全です。
次回は、このマルチバックエンド対応を活かして、ニュース自動収集パイプラインでの LLM 統合抽出(1記事1回の LLM 呼び出しで本文抽出+要約+コメント生成を完了させる仕組み)について書く予定です。



