音声言語モデルを試したい、とふと思って、そしてLM StudioあるのでGGUFで動かしたいと思ったけど、LM Studioは音声モデルに対応してないしGGUFに対応したモデルも少なくてハマったのでまとめ。
GGUFのある音声言語モデル
結局、Voxtral 3BとQwen2.5 Omni 7Bだけ試せた。
音声が受け取れる言語モデルにはPhi-4-multimodalやGemma 3n E4B、Qwen3 Omni 30Bなんかがあるけど、GGUFがない、もしくはあっても音声に対応していないのであきらめ。
ggml-orgのものを使う。
Voxtral 3Bはこちら。モデルとmmprojの2つのGGUFファイルをダウンロードする。
https://huggingface.co/ggml-org/Voxtral-Mini-3B-2507-GGUF/tree/main
Qwen2.5-Omni-7Bは、モデルがQ4_K_M、Q8_0、f16と、mmprojがQ8_0とf16がある。どちらも小さいほうにしておく。
https://huggingface.co/ggml-org/Qwen2.5-Omni-7B-GGUF/tree/main
もしVoxtral 24Bが試したければ、bartowskiさんのところにある。量子化がたくさんあるので、手ごろなサイズのものを選ぶ。これもモデルとmmprojが必要。
https://huggingface.co/bartowski/mistralai_Voxtral-Small-24B-2507-GGUF/tree/main
起動
LM Studioがアテにならんので、llama.cppを直接使います。
ここから環境にあわせてダウンロードしてください。
https://github.com/ggml-org/llama.cpp/releases
で、llama-serverでサーバーを起動。APIサーバーとWebUI両方使えます。
Voxtral-Mini-3B-2507はこんな感じ。
>llama-server --model Voxtral-Mini-3B-2507-Q4_K_M.gguf \ -mm mmproj-Voxtral-Mini-3B-2507-Q8_0.gguf
Qwen2.5 Omni 7Bはこう。
>llama-server --model Qwen2.5-Omni-7B-Q4_K_M.gguf \ -mm mmproj-Qwen2.5-Omni-7B-f16.gguf
http://localhost:8080 にアクセスするとWeb UIがあるので、ファイル添付でAudio Fileが有効になっていることを確認。

要約してもらう
それでは5分の英語の対談を要約してもらう。
この、QwenにまとめてもらったEmacsとVimの話。
https://chat.qwen.ai/s/365de3d7-5aea-4a80-9d47-9db61dc94531
こちらQwen2.5 Omni。なんか、仕事をサボりがち。指示はちゃんと通じる。読み込みは速い。

こちらVoxtral。「話の」を追加してる。なかなか言うことを聞いてくれないけど、指示が通るとかなりちゃんと仕事する。
ただし、結構音声読込に時間がかかる。

ところで、Voxtralは3BでQ4_K_Mを使ってるのに読込んだときに16GBフルフル使ってしまう。たぶんめいっぱいまでメモリ確保するんだと思う。ちょっと使いにくい。

このあとのHuggingFaceモデルの読み込みがわかりやすいけど、一旦モデルを読み込んだあとでメモリ一杯まで確保してる。行儀悪い。

Voxtralで文字起こし
Voxtralは文字起こしが優秀ということで試してみました・・・が、どうやっても要約とかしてしまう。

どうやら特別なモードがあるらしく、llama.cppサーバーでは使えなさそう。
ということで、普通にTransformersモデルを使います。
from transformers import VoxtralForConditionalGeneration, AutoProcessor import torch device = "cuda" repo_id = "mistralai/Voxtral-Mini-3B-2507" processor = AutoProcessor.from_pretrained(repo_id) model = VoxtralForConditionalGeneration.from_pretrained(repo_id, load_in_4bit=True, device_map=device) inputs = processor.apply_transcription_request(language="ja", audio="sample.mp3", model_id=repo_id) inputs = inputs.to(device) outputs = model.generate(**inputs, max_new_tokens=2500) decoded_outputs = processor.batch_decode(outputs[:, inputs.input_ids.shape[1]:], skip_special_tokens=True) print("\nGenerated responses:") print("=" * 80) for decoded_output in decoded_outputs: print(decoded_output) print("=" * 80)
pip installしたのはこれだけ。bitsandbytesは量子化しないなら不要。
torch torchvision --index-url https://download.pytorch.org/whl/cu128 transformers accelerate librosa bitsandbytes
さっきも出したけど、メモリはこんな感じで消費。

このときの読み上げ音声を文字起こししてみる。
台湾のJavaイベント、JCConf 2025での登壇準備にローカルLLMを活用した話 - きしだのHatena
5分ほど待つとこんな感じで文字起こししてくれた。改行ナシで読みづらい。

load_in_4bitのところをload_in_8bitにすれば8bit量子化になる。精度はあがるけど、10分待った。
まあ、結構ちゃんと文字起こししてくれることがわかった。
結論
Whisper使おう。日本語の精度は変わらんし、使い勝手が全然違う。