llama.cpp で動かす(GGUF)
使うファイルを選ぶ:
Table with columns: ファイル, サイズ, 用途| ファイル | サイズ | 用途 |
|---|
ljp41-ablit-L16-Q5mix.gguf | 20.7 GiB | 推奨。量子化による劣化が実質ゼロで、24GB クラスの GPU に収まる |
ljp41-ablit-L16-nvf4-W4A8.gguf | 19.9 GiB | Blackwell (RTX 50 系 / compute 12.0) 向け。fp4 重み × int8 activations の native mma kernel |
ljp41-ablit-L16-bf16.gguf | 59.9 GiB | 量子化なしの参照用。約 60GiB の VRAM/RAM が必要 |
# サーバー起動(推奨: --jinja で chat template 適用)llama-server -m ljp41-ablit-L16-Q5mix.gguf -ngl 99 -c 4096 --port 8905 --jinja# BF16 版(量子化なし・参照用)llama-server -m ljp41-ablit-L16-bf16.gguf -ngl 99 -c 4096 --port 8905 --jinja# NVFP4 版llama-server -m ljp41-ablit-L16-nvf4-W4A8.gguf -ngl 99 -c 4096 --port 8905 --no-webui --jinja
# ① /completion で raw prompt を直接入力(最も安定)curl -s http://127.0.0.1:8905/completion \ -H "Content-Type: application/json" \ -d '{ "prompt": "<|start|>system<|message|>You are LLM-jp-4, a large language model trained by LLM-jp.\nKnowledge cutoff: 2025-12\nCurrent date: <DATE>\n\nReasoning: medium\n\n# Valid channels: analysis, commentary, final. Channel must be included for every message.<|end|><|start|>user<|message|>17×23 はいくつか。数字だけ。<|end|><|start|>assistant<|channel|> final<|message|>", "n_predict": 128, "temperature": 0, "stop": ["<|end|>"] }'
# ② chat template を client 側で render して /completion に投げる(お勧め)from transformers import AutoTokenizertok = AutoTokenizer.from_pretrained("Hikari07jp/llm-jp-4.1-32b-a3b-thinking-Ablitrated", trust_remote_code=True)prompt = tok.apply_chat_template([{"role": "user", "content": "..."}], tokenize=False, add_generation_prompt=True)# → 推論は行わず text で /completion に POST、レスポンスの `content` をそのまま解析する(skip_special_tokens=False 相当の raw が返ってくる)# → final 部を split する:text = response["content"]final = text.rsplit("<|channel|> final<|message|>", 1)[-1].split("<|end|>")[0]
# ③ /v1/chat/completions は動くが、下記の「注意」にある通り# 一部の応答で openai 互換 layer の harmony parse に 500 が出ます(内容は失われていない、後述)。
リポジトリの中身
Table with columns: ファイル, 説明| ファイル | 説明 |
|---|
model-0*.safetensors(13 shard, 約 60GB) | Abliterated BF16 本体 |
ljp41-ablit-L16-Q5mix.gguf(20.7GiB) | llama.cpp 用の推奨量子化。expert gate/up=q5_K + down=q5_0 の混成(held-out ppl +0.011) |
ljp41-ablit-L16-nvf4-W4A8.gguf(19.9GiB) | llama.cpp 用 NVFP4 W4A8(Blackwell native fp4 重み + Q8 activations、held-out ppl +0.153) |
ljp41-ablit-L16-bf16.gguf(59.9GiB) | llama.cpp 用 BF16 GGUF。量子化前の参照(ppl の基準)で、上の GGUF 群はすべてこのファイルから生成 |
|
Tokenizer は trust_remote_code 付きで動きます(llmjp4_tokenizer.py / llmjp4_harmony.py を同梱)。
from transformers import AutoModelForCausalLM, AutoTokenizerimport torch m = "Hikari07jp/llm-jp-4.1-32b-a3b-thinking-Ablitrated"tok = AutoTokenizer.from_pretrained(m, trust_remote_code=True)model = AutoModelForCausalLM.from_pretrained( m, trust_remote_code=True, torch_dtype=torch.bfloat16, device_map="auto",) prompt = tok.apply_chat_template( [{"role": "user", "content": "日本の四季について短い随筆を書いて。"}], tokenize=False, add_generation_prompt=True, reasoning_effort="low",)out = model.generate( **tok(prompt, return_tensors="pt").to(model.device), max_new_tokens=512, do_sample=False,)print(tok.decode(out[0][tok(prompt).input_ids.shape[-1]:], skip_special_tokens=False))
skip_special_tokens=False で返り値に <|channel|>analysis ... <|channel|>final ... が入るので、
final の部分だけを UI に渡すのが基本です(後述の Harmony プロトコル注意点参照)。
注意点 / 既知の非互換(本モデルや量子化側ではなく llama.cpp 側)
/v1/chat/completions の検証:
このモデルは <|start|> の直後に space token (id 609) を生成する(本来 assistant で始まる)。これは normalization で
先頭に ▁ を prepend する llm-jp-4.1 の tokenizer 学習分布由来。 llama.cpp の Harmony parser が <|start|>assistant
を strict に見るので、この space token を検知して Failed to parse input at pos 18 型の 500 を返すことがある。
- 生成自体は完了しており、
/v1/chat/completions の戻り値のエラーメッセージ JSON に <|channel|> final<|message|> 以後の本文が含まれています
(client 側で regexp で取り出せば正しく回答を拾えます)。量子化前後でこの挙動は同一です。
- 対応済み: 上記の
/completion (raw prompt) or client-side template render + /completion をお勧めします。
/v1/chat/completions をそれでも使いたい場合、(a) をつけないで を起動し、 (b) 「 で special-token stream で final channel だけ抽出」のパッチを入れるのが最安定。
量子化で消える情報はあるか
- ハルシネーションやラベル付けの曖昧さは増えていません。負傷系マーカー(血/死体...)は 0。
- このモデル固有の挙動(
<|channel|>final でいきなり final に飛ぶ)は親・bf16 焼き込み・Q5mix・NVFP4 のどれでも同じです。
- 本モデルは runtime hook / 条件付き処理を一切使わない素の重みのみ で動作します。
推論の実装 (Python transformers / llama.cpp / その他のランタイム) 依存を生まない設計で、
ここに載せた実測値は すべて hook なしの素の推論で測定しています。
量子化の品質(実測)
能力面(llama.cpp 経由、temp 0):
Table with columns: 指標, base, 本モデル・BF16, NVFP4 W4A8| 指標 | base | 本モデル・BF16 | NVFP4 W4A8 |
|---|
| 知識 probe 30 問 | 28/30 | 29/30 | 29/30 |
| 偽前提 10 問の訂正 | 5/10 | 7/10 | 7/10 |
| ツールコール 5 問 | 5/5 | 5/5 | 5/5 |
| GSM8K 抽出 | 28/30 | 28/30 | 28/30 |
| 負傷系幻覚マーカー |
held-out 日本語 Wikipedia(校正コーパスと記事単位で非重複、150 chunks、n_ctx 1024)の
perplexity を、bf16 焼き込み基準の chunk 単位 paired 差分で比較:
Table with columns: GGUF, サイズ, held-out ppl 差分 vs bf16| GGUF | サイズ | held-out ppl 差分 vs bf16 |
|---|
bf16.gguf(量子化なし・参照) | 59.9 GiB | ±0(基準) |
Q5mix.gguf(推奨) | 20.7 GiB | +0.011 ± 0.003 |
nvf4-W4A8.gguf | 19.9 GiB | +0.153 ± 0.004 |
| 参考: 親 llm-jp-4.1 base bf16 | 60 GiB | +0.054 ± 0.002 |
焼き込み自体の能力コストは ゼロ(bf16 焼き込み vs 親 = ±0.05、誤差内)で、
Q5mix の量子化劣化は「親と焼き込みの差」より小さくなっています。
能力面(同一ハーネス、思考予算 512 tokens、client 側 template render + /completion):
Table with columns: モデル, 知識 30, ツールコール 5, GSM8K-30, GSM8K-100| モデル | 知識 30 | ツールコール 5 | GSM8K-30 | GSM8K-100 |
|---|
| bf16 焼き込み | 30/30 | 5/5 | 28/30 | 54/100 |
Q5mix | 30/30 | 5/5 | 28/30 | 54/100 |
この粒度では bf16 参考値自体が天井(30/30・28/30・54/100)のため、量子化の差は ppl 側に出ます。
llama-quantize に imatrix を渡し、テンソル型を明示指定して作成しています。
Table with columns: テンソル, 型| テンソル | 型 |
|---|
ffn_gate_exps / ffn_up_exps | q5_K |
ffn_down_exps | q5_0 |
attn_q / attn_output | q5_K |
attn_k / attn_v |
これ以外のテンソル(router ffn_gate_inp と各 norm)は常に f32 です。
imatrix も作り直しました。旧校正は 181 KiB の単一シーン文書(30 chunks ≒ 30k トークン)で、
ppl 評価にも同じファイルを使っていた(in-domain で循環)ため、Wikipedia-ja + 英語指示 +
GSM8K + harmony ツールコール実トレース + 口語 + 約9% in-domain の広域 2.0 MiB
(--chunks 200, n_ctx 2048 ≒ 410k トークン)に差し替えています。
License
Apache-2.0(ベースモデルに準拠)
Credits