Ox Alphaの正体を16プローブで特定した検証手法

※本記事の情報は2026年8月時点のものです。

「契約したのは最上位モデルのはずだけど、本当にそれが動いてるのかな」

APIの向こう側は見えません。レスポンスが返ってくるだけで、そこで何が動いているかを確かめる手段を、私たちはほとんど持っていません。

TL;DR: 同じプロンプトを複数モデルに投げて、トークン数の差分を比べます。16個のプローブで16個とも差分が一致すれば、トークナイザーは同一です。この記事では実際に動かしたスクリプトと、16プローブ全ての実測値を載せます。

目次

APIの向こう側は、契約書では確かめられない

モデル検証が必要になったのは、AIの供給構造が不透明になったからです。

理由は3つあります。ひとつめは、匿名で提供されるモデルが増えたこと。OpenRouterには「stealth(ステルス)モデル」という枠があります。提供元を明かさないままAPIで公開されるモデルが、定期的に登場します。2026年8月20日に現れた stealth/ox-alpha もそのひとつです。

ふたつめは、同じモデル名でも実体が変わりうること。プロバイダーが裏でモデルを差し替えても、API利用者からは気づきにくい構造になっています。

3つめは、業務利用でこれが効いてくること。社内システムに組み込むAIについて「契約したモデルが動いている」ことを説明できなければ、それはサプライチェーンの穴です。ベンダーの申告を検証する手段が要ります。

モデル検証は好奇心の問題ではなく、自分が使っているものを自分で確かめるという基本的な話です。

トークン数の絶対値を比べても何も分からない

最初に結論を書きます。トークン数はそのまま比べてはいけません。差分を見てください。

なぜかを実例で示します。英語の1文を2つのモデルに投げてみます。プロンプトは「The quick brown fox jumps over the lazy dog.」です。レスポンスの usage.prompt_tokens はこうなりました。

モデルprompt_tokens
stealth/ox-alpha97
z-ai/glm-5.322

75も違います。ここで「別のトークナイザーだ」と結論づけると間違えます。

差の正体はチャットテンプレートです。APIに送るのは私たちが書いたプロンプトだけですが、モデル側では、その前後にシステムプロンプトや役割タグが付加されます。推論モデルの場合は思考を促す指示も入るため、この付加分が大きくなります。Ox Alphaは推論モデルで、reasoning フィールドに思考過程を出力します。

重要なのは、この付加分がリクエストごとに変わらない定数だということです。だから、こうすれば消せます。

差分 = (プロンプトAのトークン数) - (プロンプトBのトークン数)

同じモデル内で引き算すれば、定数のテンプレート分は打ち消し合います。残るのは、トークナイザーがそのテキストをどう分割したかという情報だけです。

この差分ベクトルをモデル間で比べれば、テンプレートの違いに邪魔されずにトークナイザー自体を比較できます。

16個のプローブで、トークナイザーは割れる

実際に動かしたスクリプトを先に置きます。OpenRouterのAPIキーだけあれば動きます。依存ライブラリはありません。

#!/usr/bin/env python3
"""tokenizer指紋照合 — 差分比較でトークナイザーの同一性を判定する。"""
import json
import os
import urllib.request

API_KEY = os.environ["OPENROUTER_API_KEY"]
MODELS = ["stealth/ox-alpha", "z-ai/glm-5.3", "z-ai/glm-5.2"]

PROBES = [
    ("en-basic", "The quick brown fox jumps over the lazy dog."),
    ("en-contraction", "I can't believe it's already 2026! Don't stop."),
    ("ja-basic", "こんにちは、今日はいい天気ですね。"),
    ("ja-tech", "製造業におけるAI活用の事例を教えてください。"),
    ("code-python", "def fibonacci(n):\n    return n if n < 2 else fibonacci(n-1) + fibonacci(n-2)"),
    ("code-js", "const x = [1,2,3].map(n => n * 2);"),
    ("number-pi", "3.14159265358979323846264338327950288419716939937510"),
    ("emoji-unicode", "🚀✨🎉 特殊文字テスト 𝕏 𝔘𝔫𝔦𝔠𝔬𝔡𝔢"),
    ("currency", "The price is ¥1,980 (about $13.50) per month."),
    ("long-word", "antidisestablishmentarianism pneumonoultramicroscopicsilicovolcanoconiosis"),
    ("url", "https://github.com/openai/gpt-5/blob/main/README.md"),
    ("json", '{"name": "test", "values": [1, 2, 3], "nested": {"key": "value"}}'),
    ("zh", "人工智能的发展非常迅速。"),
    ("ko", "인공지능의 발전이 매우 빠릅니다."),
    ("math", "∫₀^∞ e^(-x²) dx = √π/2"),
    ("mixed", "AIモデル「Ox Alpha」は1Mコンテキスト対応で、$0.0000014/tokenです。"),
]


def get_prompt_tokens(model, prompt):
    """max_tokens=1 で投げて prompt_tokens だけ取る(生成コストを最小化)。"""
    req = urllib.request.Request(
        "https://openrouter.ai/api/v1/chat/completions",
        data=json.dumps({
            "model": model,
            "messages": [{"role": "user", "content": prompt}],
            "max_tokens": 1,
        }).encode("utf-8"),
        headers={
            "Authorization": f"Bearer {API_KEY}",
            "Content-Type": "application/json",
        },
    )
    with urllib.request.urlopen(req, timeout=120) as r:
        return json.load(r)["usage"]["prompt_tokens"]


counts = {m: {} for m in MODELS}
for name, prompt in PROBES:
    for m in MODELS:
        counts[m][name] = get_prompt_tokens(m, prompt)
    print(f"[{name}] " + "  ".join(f"{m}={counts[m][name]}" for m in MODELS))

# 差分ベクトルを作り、モデル間で比較する
base = "en-basic"
deltas = {m: {k: v - counts[m][base] for k, v in counts[m].items()} for m in MODELS}
ox, ref = deltas["stealth/ox-alpha"], deltas["z-ai/glm-5.3"]
match = sum(1 for k in ox if ox[k] == ref[k])
print(f"\n差分一致: {match}/{len(ox)}")

プローブの設計には意図があります。トークナイザーの違いが出やすいのは、文字体系の境界です。英語だけで比べても差は出にくいためです。日本語・中国語・韓国語、コード、数値の羅列、絵文字と特殊グリフ、URL、JSONを混ぜています。円周率50桁を入れているのは、数字の分割単位がトークナイザーごとに違うからです。

実行結果です。2026年8月23日に、OpenRouter API経由で実測しました。

プローブox-alphaGLM-5.3GLM-5.2ox差分GLM-5.3差分一致
英語(基本文)972222+0+0
英語(短縮形)1022727+5+5
日本語(日常)962121-1-1
日本語(技術)1032828+6+6
Python1113636+14+14
JavaScript1053030+8+8
円周率50桁1204545+23+23
絵文字+特殊グリフ1224747+25+25
通貨記号1053030+8+8
超長単語1083333+11+11
URL1022727+5+5
JSON1143939+17+17
中国語921717-5-5
韓国語1032828+6+6
数式記号1042929+7+7
日英混在1133838+16+16
Ox AlphaとGLM-5.3のprompt_tokens比較。上段は絶対値で一律+75トークンの差、下段は差分にすると16/16が完全一致

上段が絶対値、下段が差分。絶対値では一律75トークン離れているのに、差分は完全に重なります。

16個中16個の差分が一致しました。 絶対値では一律75トークン離れているのに、差分は完全に同じ動きをします。これは、テンプレートの重さが違うだけで、テキストを切り分ける規則そのものは同一だということです。

計測条件を明記します。16プローブ × 3モデル、max_tokens=1、OpenRouter API経由、2026年8月23日実測。基準は英語基本文です。

なお、この結果は英語圏の先行報告と独立に一致しました。研究者の@aitrackerbot氏が2026年8月22日に報告しています。30プローブ・14の書記体系でGLM-5.3と一致し、一貫した+75トークンの隠れラッパーがあった、と。私はこの報告を見る前に16プローブで実施し、同じ+75にたどり着きました。先に見つけたという話ではなく、別の手で同じ数字が出たという再現の話です。手法の信頼性としては、こちらの方が意味があります。

モデルの指紋は3層に分かれている

モデル検証の3層。上から行動層・サービング層・トークナイザー層。層ごとに証拠の強度と耐久性が異なる

トークナイザーだけが指紋ではありません。証拠は3つの層に分かれ、それぞれ強度と耐久性が違います

第1層: トークナイザー層

前章で見た差分照合です。強度は中、耐久性は高い

トークナイザーはモデルの学習時に固定されるため、プロバイダーが後から変えることは実質できません。パッチで潰せない証拠です。ただし後述するように、同一トークナイザーは同一モデルを意味しません。

第2層: サービング層

APIを運用しているインフラの署名です。強度は高いが、耐久性は低い

Ox Alphaでは2つの証拠が報告されています。ひとつはJavaのスタックトレースです。top_p に数値ではなく文字列 "abc" を渡す不正なリクエストで露出しました。内部クラス名は com.wd.paas.api.domain.v4.chat.ChatCompletionRequest でした。これがZhipu AI(Z.ai)の公開APIエンドポイント /api/paas/v4/chat/completions の構造と一致します(Chetaslua氏による報告)。

もうひとつがエラーコードです。role情報を不正にすると、次が返ります。{"code":"1214","message":"Incorrect role information"} です。このコードはZ.aiがホストするGLMで一貫して出ます。

ここが面白いところです。同じGLMの重みをDeepInfraでホストすると、別の検証エラーが出ます。 つまりエラーコード1214が指しているのは「モデルが何か」ではなく「誰がAPIを運用しているか」です。層が違うものを見ているわけです。

耐久性が低いのは、スタックトレースの露出がOpenCode側のバリデーションバグに依存しているからです。修正されれば消えます。強い証拠ですが、一時的です。

第3層: 行動層

モデルの応答内容そのものから読み取る指紋です。強度は低いが、独立性が高い

私の実測では2つ拾えました。ひとつは知識カットオフです。聞くと「early 2025、だいたい2025年1月まで」と答えます。GLM-5系のカットオフと整合します。

もうひとつは、思考過程の漏洩です。Ox Alphaに自己紹介を求めると、本人はこう名乗ります。

I am ox-alpha, a large language model developed by an undisclosed organization.

ところが同じレスポンスの reasoning フィールド(推論モデルが出力する思考過程)には、こう書かれていました。

According to my system prompt, I am “ox-alpha”… I should identify myself strictly as this model and not as any other.

正体を隠すよう指示されていること自体を、思考の途中で漏らしています。これは「隠されている」という事実の証拠にはなりますが、「何が隠されているか」の証拠にはなりません。行動層の証拠が弱いというのは、こういう意味です。

3層のまとめ

何を見るか強度耐久性パッチ可能性
トークナイザー層prompt_tokensの差分ほぼ不可
サービング層スタックトレース・エラーコード容易
行動層カットオフ・自己申告・CoTプロンプトで容易

検証を設計するときは、耐久性の高い層で当たりをつけ、強度の高い層で裏を取るのが基本です。1層だけで結論を出さないでください。

一致が証明するのは「同一トークナイザー」であって「同一モデル」ではない

ここが手法の限界です。誤って強く主張すると、検証の信頼性を自分で壊します。

前掲の表をもう一度見てください。GLM-5.2もGLM-5.3と完全に同じ数値です。つまりこの実測が示すのは「Ox AlphaはGLM-5系と同じトークナイザーを使っている」までです。「GLM-5.3である」までは言えません。

同じトークナイザーを共有する状況はいくらでもあります。同じシリーズの別バージョン、同じベースからのファインチューニング、同じ研究室の別モデル。トークナイザーは学習時の資産として使い回されるものです。

ではなぜGLM-5.3が有力視されているのか。他の証拠と重なるからです。

  • 1,048,576トークンのコンテキスト長がGLM-5.3と一致(GLM-5.1以下は204,800)
  • 出力上限131,072トークンが一致
  • 推論モデルであることが一致
  • 知識カットオフが2025年初頭でGLM-5系と整合
  • サービング層がZ.aiのインフラを指している

ひとつひとつは決定打になりません。重なった結果として、現時点で最も有力な仮説という位置づけになります。

ただし一致しない点もあります。OpenRouterのモデル一覧を見ると、Ox Alphaの入力modalityは text / image / video ですが、GLM-5.3は text のみです(2026年8月23日時点でAPIから取得)。これをどう読むかは2通りあります。ひとつは、Ox Alphaが未公開のマルチモーダル版である可能性。もうひとつは、stealth枠のメタデータが実際の能力を反映していない可能性です。都合の悪いデータを黙って落とさないのが検証の基本なので、ここは未解決として残します。

そして注意点です。2026年8月23日時点で、提供元からの公式発表はありません。 GLM-5.3の重み公開は2026年8月28日頃とされており、公開後に直接照合できるまで、これは仮説のままです。断定して書いている記事を見かけたら、その根拠が公式発表かどうかを確認してください。

もうひとつ、性能主張についても同じ姿勢が要ります。Ox AlphaのDeepSWE 80%という数字が話題になりました。ただしこれは10タスクのユーザーテストによるもので、監査されたリーダーボードの結果ではありません。数字を見たら、Nと計測条件を確認してください。

この手法を自社のAPI検証に持ち込む手順

ここまでを、業務で使える形に一般化します。「契約したモデルが動いているか」を確かめる手順です。

ステップ1: 基準となるモデルを決める

契約書のモデルが別経路でも呼べるなら、それを基準にします。公式API、他のプロバイダー、ローカルなどです。基準が取れない場合、この手法は「変化の検出」にしか使えません。その場合は次のステップ2をカレンダーで定期実行し、過去の自分の測定値を基準にします。

ステップ2: プローブを10〜20個用意する

文字体系の境界を狙います。以下を最低1つずつ入れてください。

  • 自社で実際に投げる言語(日本語なら日本語)
  • 英語
  • コード(自社で使う言語)
  • 数値の長い羅列
  • 絵文字・特殊記号
  • URLやJSONなど構造化テキスト

数が多いほど偶然の一致が起きにくくなります。16個で16個一致する確率は、別トークナイザーならまず出ません。

ステップ3: max_tokens=1 で投げて prompt_tokens を取る

生成させる必要はありません。max_tokens=1 にすれば出力コストがほぼゼロで、必要な usage.prompt_tokens は取れます。前掲のスクリプトがそのまま使えます。

ステップ4: 差分ベクトルを作って比較する

ひとつのプローブを基準にして引き算し、モデル間で並べます。全一致なら同一トークナイザー、1つでもずれれば別トークナイザーです。

ステップ5: 他の層で裏を取る

トークナイザーが一致したら、コンテキスト長、対応モダリティ、知識カットオフ、推論モデルか否かを突き合わせます。ずれがあれば、契約と違うものが動いている可能性を疑ってください。

定期実行に載せる

一度きりの検証には意味が薄いです。四半期ごとなど定期的に走らせて、測定値が変化したら通知する形にすると、モデルの無断差し替えを検出できます。

⚠️ 検証時の注意点

匿名モデルや外部APIを検証する際は、プロンプトの内容に注意してください。提供元が明かされていないモデルは、データの取り扱いポリシーも確認できません。OpenRouterのstealthモデルについても、提供者がプロンプトを保持する可能性があります。

検証用のプローブには、業務データ・社内固有名詞・機密コードを絶対に含めないでください。この記事で使ったプローブが、公開されている文章や無意味な文字列ばかりなのはそのためです。

まとめ

今回は、APIの向こうのモデルを検証する手法について解説しました。

要点の再掲

  • トークン数は絶対値ではなく差分で比べる(チャットテンプレートの定数分を打ち消すため)
  • 16プローブで差分が全一致すれば、トークナイザーは同一と判定できる
  • 証拠はトークナイザー層・サービング層・行動層の3つに分かれ、強度と耐久性が違う
  • 一致が証明するのは同一トークナイザーまでで、同一モデルの証明にはならない
  • 実測では、Ox AlphaはGLM-5系と16/16で一致し、一律+75トークンのテンプレート差があった(2026年8月23日実測)

契約したモデルが実際に動いているかどうか、これまでは確かめる手段がありませんでした。この手法を使えば、ベンダーの申告を自分で検証できます。

まずは自社で使っているAPIに対して、10個のプローブを投げることから始めてみてください。ベースラインが取れなくても、測定値を記録しておけば、次回以降の変化を検出できるようになります。

関連記事


出典

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

CAPTCHA


目次