title: "DeepSeek-V4.1-Flash-1017を自分のタスクでA/B評価する:小さな評価ハーネスの作り方"
tags:
- AI
- LLM
- DeepSeek
- Python
- vLLM
private: false
---
TL;DR
- DeepSeek-V4.1-Flash-1017(MIT、総763B、1Mコンテキスト)が公開された。公式カードの数値は魅力的だが、すべて自社値である(※1)。
- 発表元が違う数字は並べて比べられない。たとえばTerminal-Bench 4.0のGLM-5.3は、DeepSeek表で37.9、Mistral発表で40%と、数字がずれている(※1、※2)。
- そこで本稿では、自分のタスクで旧モデルと新モデルをA/B比較する小さな評価ハーネスを作る。OpenAI互換エンドポイントなら何でも測れる。
- ハーネスの動作は、モックサーバーで確認した(Python 3.13、openai SDK 3.44.0、2026-11-04)。DeepSeek-V4.1-Flash-1017そのものは未検証である。
1. 前提:モデル側で分かっていること
モデルカードの記載から、評価に関係する点だけ整理する(※1)。
- サンプリングの推奨値は temperature 1.0、top_p 1.0。
- max_tokensは256K以上を推奨。1Mトークンのコンテキストを持つ。
- Jinja形式のチャットテンプレートがなく、プロンプトの組み立ては
encoding.py(Python参照実装)に頼る。 - サービングはvLLM、SGLang、Docker Model Runnerが記載されている。
つまり、サーバー側が正しくメッセージを組み立てているかどうかは、最初に確認すべき点である。ベンチマークの数字を見る前に、「普通の質問に普通に答えるか」を見るほうが先である。
2. なぜ自前のA/B評価が必要か
旧版との差は、モデルカード上ではTerminal-Bench 4.0が31.2→42.3(+11.1)、DeepSWE v1.1が74.2→77.0(+2.8)である(※1)。ただし、これが自分の仕事に効くかどうかは別の話である。理由は3つある。
- ベンチマークの課題と、自分のタスクは違う。
- 評価ハーネスや設定が変われば、数字は動く。
- 速度・トークン量・失敗の出方は、表に載らない。
APIのdeepseek-flashは、名前と価格を保ったまま中身が1017版に入れ替わったという情報もある(※3、第三者サイト)。気づかないうちに挙動が変わっていても、手元に評価セットがあれば検知できる。
3. 評価ハーネスを作る
3.1 評価ケースを用意する
1行1ケースのJSON Lines形式にする。expectには、応答に含まれるべき文字列を入れる。最初は単純な文字列一致で十分である。
{"id":"a","prompt":"2+2は?","expect":"4"}
{"id":"b","prompt":"3+3は?","expect":"6"}
実際のタスクでは、次のようなケースを20〜50件集めるとよい。
- 普段の依頼文(社内で実際に使っているもの)
- 過去にモデルが間違えた例
- 長い入力(コンテキストを使うもの)は別枠にする
3.2 ハーネス本体
次のコードは、OpenAI互換のエンドポイントに対して、同じケースを順に投げ、合否・所要時間・出力トークン数を集計する。
# ab_eval.py(Python 3.13、openai 3.44.0で動作確認:モックサーバー相手)
import json, time, statistics, sys
from openai import OpenAI
def run(base_url, model, cases, temperature=1.0, top_p=1.0, max_tokens=1024):
client = OpenAI(base_url=base_url, api_key="dummy")
rows = []
for c in cases:
t0 = time.perf_counter()
try:
r = client.chat.completions.create(model=model, temperature=temperature, top_p=top_p,
max_tokens=max_tokens, messages=[{"role": "user", "content": c["prompt"]}])
out = r.choices[0].message.content or ""
ok = c["expect"] in out
usage = r.usage.completion_tokens if r.usage else None
err = None
except Exception as e:
out, ok, usage, err = "", False, None, repr(e)
rows.append({"id": c["id"], "ok": ok, "sec": time.perf_counter() - t0, "tokens": usage, "err": err})
return rows
def summarize(name, rows):
n = len(rows); passed = sum(r["ok"] for r in rows)
lat = [r["sec"] for r in rows]
toks = [r["tokens"] for r in rows if r["tokens"] is not None]
print(f"{name}: pass {passed}/{n} ({passed/n:.0%}), median {statistics.median(lat):.2f}s, "
f"avg tokens {statistics.mean(toks) if toks else float('nan'):.0f}, errors {sum(1 for r in rows if r['err'])}")
if __name__ == "__main__":
cases = [json.loads(l) for l in open(sys.argv[1], encoding="utf-8")]
for spec in sys.argv[2:]:
name, url, model = spec.split(",")
summarize(name, run(url, model, cases))
ポイントは3つある。
-
temperatureとtop_pは、モデルカードの推奨値(1.0)を既定にした。モデルごとに変える場合は引数で渡す。 - 例外が出ても止めず、
errに記録する。タイムアウトや形式エラーは、それ自体が評価の材料になる。 - 比較対象は
名前,URL,モデル名の形で複数指定できる。
3.3 モックサーバーで動作確認
本物のモデルがなくても、ハーネスの配線を確かめられる。次のモックは、「2+2」にだけ正解を返す。
# mock.py:OpenAI互換のごく小さなモック
import json
from http.server import BaseHTTPRequestHandler, HTTPServer
class H(BaseHTTPRequestHandler):
def do_POST(self):
b = json.loads(self.rfile.read(int(self.headers["Content-Length"])))
p = b["messages"][0]["content"]
text = "答え: 4" if "2+2" in p else "不明"
out = json.dumps({"id":"x","object":"chat.completion","created":0,"model":b["model"],
"choices":[{"index":0,"message":{"role":"assistant","content":text},"finish_reason":"stop"}],
"usage":{"prompt_tokens":5,"completion_tokens":7,"total_tokens":12}}).encode()
self.send_response(200); self.send_header("Content-Type","application/json")
self.send_header("Content-Length", str(len(out))); self.end_headers(); self.wfile.write(out)
def log_message(self, *a): pass
HTTPServer(("127.0.0.1", 8765), H).serve_forever()
実行結果は次のとおりだった。2件中1件が正解で、期待どおりである(2026-11-04、筆者環境)。
$ python3 ab_eval.py cases.jsonl "mock,http://127.0.0.1:8765/v1,mock-model"
mock: pass 1/2 (50%), median 0.04s, avg tokens 7, errors 0
4. 本物のモデルを測るときの手順
ここからは未検証の手順である。モデルカードの記載と、vLLMの一般的な使い方に基づく。
4.1 サーバーを用意する
重みのサイズは、総763Bのうち、F8_E4M3が中心なら概算700GB台になる(筆者の単純計算、テンソル形式が混在するため正確ではない)。複数枚のハイエンドGPUが必要で、1枚のGPUでは動かない。手元にない場合は、推論プロバイダー経由を使う。モデルカードにはNovitaが載っている(※1)。
自前で立てる場合の形は次のとおりである(未検証)。
vllm serve deepseek-ai/DeepSeek-V4.1-Flash-1017 \
--tensor-parallel-size 8 \
--max-model-len 262144
このモデル固有のオプションが必要かどうかは、筆者は確認できていない。起動できなければ、モデルカードのinferenceフォルダと、vLLMのドキュメントを見てほしい。
4.2 比較の実行
python3 ab_eval.py cases.jsonl \
"old,https://YOUR-OLD-ENDPOINT/v1,YOUR-OLD-MODEL" \
"new,http://localhost:8000/v1,deepseek-ai/DeepSeek-V4.1-Flash-1017"
4.3 結果の見方
見るべきは次の4点である。数字は、必ず同じケース・同じ設定で比べる。
| 見る項目 | 見方 |
|---|---|
| 合格率 | 差が小さいときは、ケース数を増やすか、複数回実行する(temperature 1.0なので揺れる) |
| 中央値の所要時間 | 長い思考をするモデルは遅くなる。タスクの許容範囲に収まるか |
| 平均トークン数 | 単価が同じでも、トークンが増えればコストは増える |
| エラー数 | タイムアウトや形式エラーの有無。テンプレート関連の不具合の兆候になる |
temperatureが1.0の場合、同じ入力でも結果が揺れる。最低でも3回は回して、合格率の幅を見ておきたい。
5. ハマりやすい点
-
チャットテンプレートがない。 サーバーが
messagesを正しく組み立てているか、最初の数件で出力を目で見て確認する。文字化けや、会話の続きを勝手に書き続ける挙動があれば、プロンプト構成の問題を疑う。 - max_tokensの設定。 推奨は256K以上と書かれているが、評価では上限を決めないと、1件が極端に長くなる。ハーネスでは1,024に抑えている。長い思考が必要な課題では、引き上げる。
-
文字列一致の限界。 正解の表現が複数ある課題は、
expectを正規表現に変えるか、別のモデルに採点させる形に拡張する。ただし後者は、採点側のモデルのクセが入る点に注意する。 - ベンチマークの数字と比べない。 自分のケースの合格率と、モデルカードの表の数字は、別物である。
6. 筆者の評価
ハーネス自体は、数十行で作れる。モデルが変わるたびに作り直さず、ケースを貯めていけば、「今回の更新は自分のタスクに効いたのか」を数分で確認できる。特に、APIの中身が名前を変えずに入れ替わる状況では、定期的に同じケースを流す運用が、変化の検知にも役立つ。
一方で、DeepSeek-V4.1-Flash-1017の実力そのものは、本稿では確かめられていない。公式の数値は、MITライセンスの大型モデルとして期待できる内容だが、すべて自社値である。実際に測った結果を見るまでは、「期待できる候補」として扱うのが妥当だと考える。
まとめ
DeepSeek-V4.1-Flash-1017は、数値上は旧版から大きく伸びたとされるが、第三者による再現は見つかっていない。本稿では、自分のタスクで比較するための小さなA/B評価ハーネスを作り、モックサーバーで動作を確認した。本物のモデルを使った測定は未検証である。モデルカードの数字を信じる前に、自分の20件で測る。これが一番早い。
※本記事の記載内容は筆者個人の見解であり、所属する会社や組織の立場や方針とは一切関係ありません。
筆者情報
【Tomcat-zhou】|AI/AX/AIセキュリティ専門家
AI戦略洞察、AI駆動開発の方法論設計と現場で回る仕組みづくりをしています。
noteで戦略洞察 / Zenn・Qiitaで技術・方法論を書いています。
AIセキュリティ・AIコンサル・AIエージェント開発・AI活用・AI駆動開発教育、AI人材育成サービスを一体で提供。
X: @ZY20240528
LinkedIn: Tomcat-zhou
Facebook: zhou yi
note: Tomcat-zhou
Zenn: Tomcat-zhou
参考資料
- deepseek-ai/DeepSeek-V4.1-Flash-1017(Hugging Face)
- Mistral releases open weights for its 1 trillion-parameter Large 4 model(The Next Web)
- AI Changelog Week 44(neomanex)
タグ
AI LLM DeepSeek Python vLLM 評価