top of page

UGREEN DXP6800 Pro + Ollama 続々編:eGPU 付き NAS を Zed につないだら、12B は「読める」が「思い出せない」ことがわかった

  • ccf代表
  • 5 日前
  • 読了時間: 16分

サマリー

  • 16GB の eGPU を積んだ NAS で、12B のコミュニティ finetune を Zed から使ってみました

  • 生成速度 24.85 tok/s。VRAM 的には公称 256K コンテキストが丸ごと載ります

  • 同じ箱の qwen3-coder:30b は VRAM に載り切らず、プロンプト処理が 26 分の1でした

  • ただしプロンプト処理は長くなるほど遅くなり、実用的な max_tokens は 32768 でした

  • インフラ実務タスク12本を実際に実行して採点したところ、合計 123 / 500 点

  • しかし点数より、得意と苦手がきれいに割れたことのほうが重要でした

このモデルは「与えられたコードを直す」のは得意で、「仕様から書き起こす」のは壊滅的でした。 境界線は言語(Python / PowerShell)ではなく、API を記憶から引く必要があるかどうかです。

前回までのあらすじ

前回は 64GB 化した UGREEN DXP6800 Pro で qwen3-coder:30b を動かしました。今回はその続きです。30B は VRAM に載り切らず CPU にこぼれていました。 では「全部載るサイズ」ならどうなのか。ちょうど話題になっていた 12B のファインチューンで試します。


今回のモデルについて、先に断っておくこと

xentriom/gemma-4-12B-coder-fable5-composer2.5-v1 は、名前に Gemma とありますが Google 公式のモデルではありません。HuggingFace ユーザー yuxinlu1 氏による個人ファインチューンです。

ollama show で素性が見えます。

Model
  architecture        gemma4
  parameters          11.9B
  context length      262144
  embedding length    3840
  quantization        Q4_K_M

Capabilities
  completion
  tools
  thinking

ベースは google/gemma-4-12B-it。そこに Composer 2.5 が生成しテストスイートで実行検証済みの Python コードを、 Composer 2.5 が失敗したケースは Fable 5 が補って学習させた、というのがモデルカードの説明です。 名前の "fable5-composer2.5" はこの2つの教師モデルに由来します。

作者自身が注意点を明記しています。

  • Python とアルゴリズム的コーディングに特化しており、汎用知識は別モデルでの検証を推奨

  • 学習セットに safety hedging を含めていないため、ベースモデルより拒否が少ない

  • Google の後援・保証はない(ライセンスは Apache 2.0)

そして v1 について公表されたベンチマークはありません。 つまりこの記事は「誰も数字を出していないモデルを、自分の実務タスクで測ってみた」記録になります。

構成

[MacBook Pro / Zed] ── LAN ── [UGREEN DXP6800 Pro]
                                      │
                              {{ OCuLink / USB4 }}
                                      │
                          [eGPU Dock + RTX 2000 Ada 16GB]

レイヤ

項目

NAS

型番

UGREEN DXP6800 Pro

NAS

OS

Debian 12 (bookworm) / UGOS 1.15.0.0120 / kernel 6.12.74

NAS

CPU

12th Gen Intel Core i5-1235U(12スレッド)

NAS

メモリ

62GB(64GB 化済み)

NAS

Ollama

Docker コンテナ ollama/ollama:0.24.0

eGPU

GPU

NVIDIA RTX 2000 Ada Generation / VRAM 16,380 MiB

eGPU

電力

70W 上限

eGPU

ドライバ

535.261.03 / CUDA 12.2

Model

タグ

:latest(実体は Q4_K_M、7.4GB)


Zed から NAS の Ollama につなぐ

公式ドキュメントの例は localhost 前提ですが、今回は NAS を指します。 ~/.config/zed/settings.json に追記します。

jsonc

{
  "language_models": {
    "ollama": {
      "api_url": "http://xxx.xxx.xxx.xxx:11434",
      "available_models": [
        {
          "name": "xentriom/gemma-4-12B-coder-fable5-composer2.5-v1:latest",
          "display_name": "gemma4-coder-fable5 12B",
          "max_tokens": 32768,
          "supports_tools": true,
          "supports_thinking": true,
          "supports_images": false
        }
      ]
    }
  }
}

NAS 側は OLLAMA_HOST=0.0.0.0:11434 にしておかないと、127.0.0.1 にしかバインドされず LAN から届きません。

ハマったところ

① タグ名を間違えて「モデルが非対応」だと勘違いしかけた

ollama show の quantization が Q4_K_M と出ていたので、つい :Q4_K_M を指定していました。 ですが pull してあるのは :latest だけで、:latest の実体が Q4_K_M です。

$ curl -s http://$NAS:11434/api/chat -d '{"model":"...:Q4_K_M", ...}' | jq '.message'
null

.message が null になるだけで、原因がまるでわかりません。 /api/tags でタグ一覧を確認するのが先でした。

② curl -s がエラーごと隠す

bash

$ time curl -s http://$NAS:11434/api/generate -d '...' | jq '...'
curl ...  0.020 total
(出力なし)

0.02 秒で終わって何も出ません。原因は $NAS が未設定で、URL が http://:11434/... になっていたことでした。 -s を付けているのでエラーメッセージも出ず、jq は空入力を黙って捨てます。

切り分け中は -s を外すか --fail-with-body を付けるべきでした。

③ num_ctx を変えるたびにモデルが再ロードされる

ollama ps を2回見比べたら、同じモデルが別々の状態で載っていました。

時点

SIZE

CONTEXT

UNTIL

A

14 GB

262144

Forever

B

9.8 GB

4096

4 minutes from now

open-webui と Zed と curl がそれぞれ違う num_ctx を投げていたためです。 後述のベンチで、この再ロードに毎回 5.4 秒かかっていることが数値で出ました。

対策として、コンテナを作り直して値を固定しました。

bash

docker run -d --name ollama --gpus all --restart unless-stopped \
  -p 11434:11434 \
  -e OLLAMA_KEEP_ALIVE=-1 \
  -e OLLAMA_NUM_PARALLEL=1 \
  -e OLLAMA_CONTEXT_LENGTH=32768 \
  -v ollama:/root/.ollama \
  ollama/ollama:0.24.0

まず確認:本当に eGPU に載っているのか

Ollama は VRAM に収まらないぶんを黙って CPU にオフロードします。エラーは出ません。ただ遅くなるだけです。 前回 30B で痛い目を見たので、今回は先に確認しました。

$ docker exec ollama ollama ps
NAME                                    SIZE     PROCESSOR    CONTEXT    UNTIL
xentriom/gemma-4-12B-...:latest         14 GB    100% GPU     262144     Forever

262,144 トークンのフルコンテキストでも 100% GPU。nvidia-smi では 13,599MiB / 16,380MiB でした。

num_ctx を変えて2点測ると、KV キャッシュの傾きが出せます。

num_ctx

VRAM

4,096

9.8 GB

262,144

14.0 GB

差分は 4.2GB / 258,048 トークン ≒ 17 KB/token。ここから内挿すると:

num_ctx

推定 VRAM

16GB に対する余裕

8,192

約 9.9 GB

6.1 GB

32,768

約 10.3 GB

5.7 GB

65,536

約 10.8 GB

5.2 GB

131,072

約 12.0 GB

4.0 GB

262,144

14.0 GB

2.0 GB

12B は 256K でも VRAM に載り切ります。 qwen3-coder:30b は Q4 で約 18GB なので、 この 16GB には物理的に収まりません。同じ箱の上で、載り切る 12B と載り切らない 30B。 これが今回の対比の出発点です。


速度:24.85 tok/s

$ ollama run xentriom/gemma-4-12B-coder-fable5-composer2.5-v1:latest --verbose "フィボナッチ数列を返すPython関数を書いて"
Thinking...
Fibonacci sequence in Python.
Edge cases: n=0, n=1, negative n (undefined/error), large n ...
Approach: Iterative with two variables (a, b) → O(n) time, O(1) extra space.
...done thinking.

total duration:       21.33837892s
load duration:        5.374200083s
prompt eval count:    28 token(s)
prompt eval rate:     502.04 tokens/s
eval count:           387 token(s)
eval rate:            24.85 tokens/s

RTX 2000 Ada のメモリ帯域は約 224GB/s、モデルは 7.4GB。 理論上限 224 ÷ 7.4 ≒ 30 tok/s に対して 実効 24.85 tok/s、効率 83% です。 70W のロープロ GPU としては素直に出ていますし、100% GPU に載っている裏付けにもなります。

回答自体も悪くありませんでした。n < 0 で ValueError、n == 0 / n == 1 の分岐、 反復実装で O(n) 時間・O(1) 空間、計算量の説明つき。thinking も正常に機能しています。

ただし 387 トークンのうち体感 1/3 は thinking です。 答えが出るまでの待ち時間は、見えている回答の長さの 1.5 倍前後になります。


ここが本題:プロンプト処理は、長くなるほど遅くなる

上の prompt eval rate: 502.04 tokens/s は信用してはいけない数字です。 28 トークンしか投げていないので、55ms の大半は固定オーバーヘッドで、 スループットではなく往復遅延を測っています。

そこでプロンプト長を振って測り直しました。

投入トークン

prefill tok/s

prefill 時間

146

1,015

0.14 s

599

1,455

0.41 s

2,419

1,515 ← ピーク

1.60 s

10,489

1,107

9.47 s

21,277

994

21.41 s

44,349

829

53.50 s

91,997

621

148.11 s

約 184,000

(測定を中断)

推定 7〜11分


2.4K でピークを打ったあと、単調に落ちていきます。 92K ではピークの 41% です。 Attention の計算量が入力長の2乗で効いてくるためで、 131,072 狙いは実際には約18万トークンになり、prefill だけで数分かかるので測定を打ち切りました。

つまり——

256K コンテキストは、載るけれど、待てません。

VRAM に収まるかどうかで max_tokens を決めると間違えます。


副産物:再ロードのコストが正確に測れた

このベンチは条件ごとに num_ctx を変えていたので、load の値がきれいに割れました。

条件

load

初回(cold)

6.00 s

同じ num_ctx の2回目以降

0.23 s

num_ctx を変えた直後

5.17 〜 5.59 s

先ほどの「クライアントごとに num_ctx が違う」問題のコストが、そのまま 5.4 秒として出ています。


max_tokens は 32768 にしました

混同しやすいのですが、この2つは別物です。


何で決まるか

コスト

num_ctx(Zed の max_tokens)

設定値

VRAM のみ。確保するだけなら遅くならない

prefill 時間

実際に送ったトークン数

上の表のとおり

num_ctx を大きくすること自体は遅くありません。 大きいプロンプトを実際に送ったときだけ待たされます。 なので max_tokens は「最悪ケースで何秒待てるか」の上限として決めるのが正解です。

max_tokens

VRAM

使い切った場合の待ち時間

判定

16,384

10.0 GB

約 17 秒

快適だが少し窮屈

32,768

10.3 GB

約 40 秒

採用

65,536

10.8 GB

約 105 秒

待てない場面が出る

131,072

12.0 GB

約 4 分

実用外

262,144

14.0 GB

約 11 分

論外

32768 なら最悪 40 秒台、VRAM も 5.7GB 余るので open-webui と同居させても即死しません。 実運用では 5〜15K トークンに収まることが多く、その帯域なら 1,000 tok/s 以上出ています。

公称 256K のモデルを 16GB の GPU に載せて、実際に使える設定は 32K でした。


ツール呼び出しは問題なく動きました

モデルカードにツール呼び出しの記載がなかったので心配していましたが、ollama show の Capabilities に tools があり、実際に API を叩くときちんと返ってきました。

json

{
  "role": "assistant",
  "content": "",
  "thinking": "The user is asking for the weather in Tokyo in Japanese. The available tool `get_weather` takes a `city` parameter and returns the weather for that city. So I should call `get_weather` with `city=\"Tokyo\"`.",
  "tool_calls": [
    { "id": "call_dixhqupg",
      "function": { "name": "get_weather", "arguments": { "city": "Tokyo" } } }
  ]
}

ツールの実行結果を返すと、そこから日本語で続けることもできました。

東京の天気は晴れで、気温は31度です。

関数名も引数名も引数の値も、すべて正しい。 思考過程まで筋が通っています。 ……この点は、後半の話とつながってきます。


実務タスク12本を、実際に実行して採点しました

インフラ現場で本当に頼みたいことを12本用意し、 4観点(正確性×2・完全性・指示追従・実務適合、各0〜5点=1タスク25点)で採点しました。

そして採点とは別に、生成物を全部動かしました。 python -m py_compile、pytest、mypy --strict、用意した Cisco コンフィグを食わせる、など。 「読むと良さそうだが動かない」を可視化するためです。

ID

タスク

小計

実行検証

A-1

AD 棚卸し (PowerShell)

6

Fail

A-2

イベントログ解析 (PowerShell)

7

Fail

A-3

Azure VM 棚卸し (Python)

7

Fail

A-4

SG 監査 (Python/boto3)

7

Fail

A-5

Cisco コンフィグパーサ (Python)

6

Fail

A-6

YAMAHA RTX 拠点間 IPsec VPN

2

Fail

A-7

syslog からの障害切り分け(日本語)

15

N/A

B-1

CIDR マージ関数の実装

8

Fail

B-2

バグ修正

21

Pass

B-3

リファクタリング

17

Pass

B-4

pytest 生成

12

Fail

B-5

型注釈(mypy --strict)

15

Fail

合計 123 / 500 点。実行検証は Pass 2 / Fail 9 / N/A 1。


立てた仮説は、外れました

PowerShell の A-1 / A-2 が壊滅したとき、私はこう考えました。

Python で学習した finetune だから、PowerShell の構文が転移していないのだろう

違いました。A-3 / A-4 / A-5 は Python です。同じように壊れました。

$ python3 -m py_compile a3_snippet.py
    "power_state": view.instance_status.display_status,
                 ^
SyntaxError: invalid syntax
        ↑ dict.update() を "key": value の形式で呼んでいる

$ python3 -m py_compile a4_snippet.py
    for page in paginator.paginate(filters=[...])
                                                 ^
SyntaxError: expected ':'
        ↑ for 文の行末にコロンが無い

言語の問題ではありませんでした。


本当の境界線は「思い出せるか」だった

スコアを並べ替えると、驚くほどきれいに割れます。

分類

タスク

平均

① 与えられたコードを直す・変換する

B-2 (21) / B-3 (17) / B-5 (15)

17.7 / 25

② コードを書かない(説明・分析)

A-7 (15)

15 / 25

③ 仕様から書き起こす

A-1〜A-5, B-1, B-4

7.6 / 25

④ 国内ドメイン知識が要る

A-6 (2)

2 / 25

①と③の差は 2.3 倍。 そして①には構文エラーが1件もなく、③は7本中4本が構文エラーで落ちました。

③で捏造された API を並べてみます。

どこで

生成された記述

実際

B-1

netmask

B-1

net.broadcast

broadcast_address

A-3

ComputeManagementClient(credential)

(credential, subscription_id)

A-3

view.network_probe でプライベート IP

NetworkManagementClient が必要

A-3

tenacity.retry_if_exception_is_a

retry_if_exception_type

A-4

boto3.parse_region(...)

存在しない

A-2

XPath の (Number)

EventID

A-1

SupportedShouldProcess

SupportsShouldProcess

A-1

EnabledParameterBinding

存在しない

注目してほしいのは B-1 です。ipaddress は Python の標準ライブラリです。

$ python3 -c "import ipaddress; n=ipaddress.ip_network('10.0.0.0/8'); print(hasattr(n,'network_mask'), hasattr(n,'broadcast'))"
False False

外部 SDK どころか、標準ライブラリの属性名すら思い出せていません。 しかもこの課題、正解は標準ライブラリの1行です。

python

# 生成されたのは 30 行の自作マージロジック(AttributeError で動かない)
# 正解:
[str(x) for x in ipaddress.collapse_addresses(nets)]
# → ['10.0.0.0/8', '192.168.0.0/23']   仕様の期待値と完全一致

ツール呼び出しが完璧だった理由も、これで説明がつきます

さきほど get_weather を正しく呼べたのは、関数名も引数名もプロンプトで与えられていたからです。 思い出す必要がなかった。同じ軸の話でした。


唯一「使える」と言えた1本:B-2 バグ修正

仕込んだ3つのバグを全部当てただけでなく、症状として伝えていない4つ目まで自分から指摘してきました。

Off-by-one: range(max_retries + 1) allowed one extra attempt Unreachable sleep: The continue statement was placed before time.sleep() Hidden errors: Catching the exception and continuing without raising Resource leak: urlopen responses were never closed on success (minor, but still)

4番は仕込んだけれど症状として書かなかったものです。実行検証も通りました。

正常系:        b'ok'
500継続:       OK  例外送出 (server error: 500) / 試行 3 回 / sleep 2 回
max_retries=3: 試行 3 回(期待3)/ backoff sleep 2 回(期待2)

バックオフを「次の試行が残っているときだけ」に限定した判断も正しい。 瑕疵はエッジケース1つ(max_retries=0 で last_error が None のまま raise して TypeError)だけです。

これならレビューを通せます。


失敗の中身も、なかなか教科書的でした

B-4:それらしいテストは書けるが、通らない

pytest は 2 passed, 2 failed。原因は @patch の引数順でした。

python

@patch("time.sleep")                # 上
@patch("urllib.request.urlopen")    # 下(関数に近い)
def test_network_error_with_backoff(mock_sleep, mock_urlopen, max_retries):

unittest.mock は関数に近いデコレータから順に引数へ注入します。 つまり第1引数に入るのは urlopen のモックで、名前と中身が入れ替わっています。

pytest の失敗出力がそれをそのまま暴きました。

mock_sleep  = <MagicMock name='urlopen' ...>
mock_urlopen = <MagicMock name='sleep' ...>
E   AssertionError: assert 1 == (3 - 1)

人間が実行を確認しない限り、テストの自動生成は信用できません。


A-4:動いても、検出しない

python

cidr = rule.get("IpRanges", []) + rule.get("Ipv6Ranges", [])
open_cidr = any(cidr_block in OPEN_CIDRS for cidr_block in cidr)

IpRanges は 辞書のリスト([{'CidrIp': '0.0.0.0/0'}])で、文字列ではありません。

cidr = [{'CidrIp': '0.0.0.0/0'}, {'CidrIpv6': '::/0'}]
判定 → TypeError: unhashable type: 'dict'   ← 最初のルールでクラッシュ

しかも OPEN_CIDRS に ::1/128(ループバック) が混ざっています。全開放とは正反対のアドレスです。

一方でポート範囲の判定ロジック(0-65535 のようなレンジ指定もちゃんと拾う)は正しく、 設計の勘所は押さえているのが余計にたちが悪いところです。


A-5:2箇所直しても、要件の半分が取れない

段階的に確かめました。

段階

結果

そのまま実行

NameError: name 'stack' is not defined(変数名の書き間違い)

①を修正

IndexError(split(" ", 5)[5] — 要素は5個しかない)

②も修正して完走

VLAN 名が全て unnamed / 静的ルートが 0 件

Cisco は vlan 10 の次の行に  name USER を書きますが、同一行から取ろうとしています。 静的ルートは実際には ip route 0.0.0.0 0.0.0.0 ... ですが、コードは startswith("route ") を見ているので一生マッチしません


A-6:YAMAHA RTX は、有効な行が1行もなかった

予想はしていましたが、想定を超えていました。

yaml

lan1 use dhcp server            # 存在しない
ipsec ike 1
  esp aes256                    # RTX にインデントブロック構文は無い
ipsec keepalive 10 10           # 存在しない
nat des monthly lan1 slave wan1 outbound nat server masquerade   # 意味不明

tunnel select / tunnel enable / ipsec tunnel / ipsec sa policy / ip route ... gateway tunnel / nat descriptor ——VPN の骨格が丸ごとありません

おまけに要件を正面から2つ破っています。固定グローバル IP を与えたのに lan2 use dhcp client。 そして「日本語コメントを付けてください」と指示したのに、コメントが全部英語でした。

「英語圏中心の学習データでは国産ネットワーク機器は扱えない」という予想は当たりましたが、 部分的に正しいのではなく全面的に別物だった、というのが実際のところです。


いちばん怖かったのは、点数ではありませんでした

3つのタスクで、やっていないことを「やった」と書いてきました

タスク

主張

実際

A-1

「-whatif と -confirm を尊重します」

Set-ADUser -Enabled $false が無条件で走る

A-3

「requirements.txt に必要なライブラリを列挙しています」

生成されていない

B-3

「テストスイートが不具合を再現し、修正を確認します」

テストは1行も書かれていない

A-2

「サーバー側でフィルタするので忙しいシステムでも高速」

XPath が成立せず1件も取れない

とくに A-1 が危険です。要件の中心は「既定では無効化せず、-WhatIf が効くこと」でした。 生成されたコードでは ShouldProcess がただの文字列で、Set-ADUser を何も守っていません。

powershell

if ($Disable) {
    ShouldProcess "Disable account $($user.SamAccountName)"   # 何もしていない
    Set-ADUser -Identity ($user.SamAccountName) -Enabled $false   # 無条件で実行される
}

説明が流暢なぶん、レビューをすり抜けます。 これは点数では表せないリスクです。


30B と比べてどうだったか:差は「賢さ」ではなく「載るかどうか」でした

同じ箱、同じ num_ctx 32768 で qwen3-coder:30b と並べました。

指標

gemma4-coder-fable5 12B

qwen3-coder 30B

モデルサイズ (Q4)

7.4 GB

約 18 GB

VRAM 16.4GB に載るか

Yes(256K でも)

No

ollama ps の PROCESSOR

100% GPU

{{ 実測値 }}

生成速度

24.8 tok/s

16.8 tok/s

プロンプト処理速度

約 1,094 tok/s

42 tok/s

cold ロード

6.6 秒

7.9 秒

生成速度の差は 1.48 倍です。これだけなら「まあ 12B のほうが速いよね」で終わります。

問題は prefill の 26 倍差でした。

実際に送るプロンプト長

12B

30B

8,192 トークン

約 10 秒

約 3.3 分

16,384 トークン

約 20 秒

約 6.5 分

32,768 トークン

約 39 秒

約 13 分

Zed でファイルを2〜3本コンテキストに入れた時点で、30B は10分単位の待ちになります。 コーディングアシスタントとしては成立しません。


なぜ prefill だけが極端に落ちるのか

prefill は行列積が主体で、GPU が最も得意とし、CPU が最も苦手な処理です。 一方トークン生成はメモリ帯域律速なので、CPU にこぼれても相対的な劣化は小さい。

この非対称性そのものが「VRAM に載り切っていない」証拠になります。

しかも qwen3-coder:30b は MoE(総 30B / アクティブ約 3B)です。 全部 VRAM に載っていれば、密な 12B より速いはずなのです。 それが 12B より遅く、prefill が 26 分の1というのは、CPU オフロードでしか説明がつきません。

Q4 で約 18GB。RTX 2000 Ada の VRAM は 16.4GB。物理的に収まりませんでした。

16GB の GPU では、30B は「遅い」のではなく「使えない」。 VRAM に載り切るかどうかは、モデル選定において賢さより先に効く制約でした。

前回「30B は Sonnet の代わりになるか」を試しましたが、 同じ箱の上では、載り切る 12B のほうが実用的だった、というのが今回の回答です。


ただし、24.8 tok/s は「体感」ではありません

ここは正直に書いておきます。warm でも本文が出始めるまで 10.2〜10.9 秒かかりました。

短いプロンプトなのに、なぜ10秒も沈黙するのか。thinking が先に走るからです。

Thinking...
Fibonacci sequence in Python.
Edge cases: n=0, n=1, negative n (undefined/error) ...
Approach: Iterative with two variables (a, b) → O(n) time, O(1) extra space.
...done thinking.

  ← ここまで約10秒。ここからやっと本文が出る

24.8 tok/s という数字だけ見ると快適そうですが、実際の体感は 「10秒黙ってから喋り出す」です。Zed で使うと、これが毎回のやり取りに乗ります。


Zed で実際に使ってみて

結論:書かせるな、直させろ

用途

判定

根拠

自分のコードのバグ修正・レビュー

B-2 21/25。隠しバグまで発見

リファクタリング

B-3 17/25

型注釈の付与

B-5 15/25。--strict は2件残る

障害切り分けの壁打ち

A-7 15/25。筋は良いがコマンド名は信用不可

Python スクリプトの新規生成

×

A-3/A-4/A-5/B-1 が全滅

PowerShell スクリプト

×

A-1/A-2 が構文エラー

テストの自動生成

×

B-4 は 2 failed

ネットワーク機器コンフィグ

×

A-6 は有効行ゼロ


私はこう使うことにしました

実際の運用方針:

  • NAS に常駐させ、自分が書いたコードのレビュー役として使う

  • バグの原因を探させる、型を付けさせる、リファクタさせる

  • ゼロから生成させたコードは一切信用しない

  • ネットワーク機器まわりは触らせない

閉域環境で「自分のコードを読ませる」用途に限れば、24.85 tok/s の 12B は十分に実用的です。 ただし生成物をそのまま流す使い方は、インフラの現場では事故になります


参考

コメント


bottom of page