AI

AI比較の実装手順|同じ入力を各社モデルへ流して品質とコストを測る

AI比較の実装手順|同じ入力を各社モデルへ流して品質とコストを測る

AIの比較を調べると、モデルの一覧表と料金表を並べた記事が並びます。読み終えても、自社の書類を投げたときにどれが当たるのかは分かりません。表に載っているのは各社が公表したスペックであり、手元のデータで測った結果ではないからです。

この記事で扱う比較は、表の閲覧ではなく、自社データを使った計測作業です。3社のAPIを1つの関数で呼び分け、同じ入力を流し、応答とトークン使用量を1行1レコードで残し、品質・コスト・遅延を数値で突き合わせるところまでをコードで示します。サービスとしての違いや料金プランの選び方はChatGPT・Gemini・Claude・Copilotを徹底比較|対話型AIの違い・料金・選び方で扱っているため、本記事はAPI越しの実測に絞ります。

まとめ:AI比較は公開スコアではなく自社データの実測で決める

  • 比較の前に測る軸を4つ(品質・コスト・遅延・運用)決め、それぞれの合格ラインを数値で書き出す
  • 3社のSDKを1つの関数で包み、同じプロンプトと同じ評価データを流して応答と使用量を記録する
  • コストは公表単価ではなく、実測した入力・出力トークン数に単価を掛けて月額に直す
  • 品質は正解が決まる項目を自動採点、決まらない項目をLLM審査に回し、両方を数値で残す
  • 遅延は初回トークン到達までの時間と、そこから先の生成速度を分けて測る
  • 公開ランキングと自社の採点が食い違ったら、自社の採点を採る。ただし採点差が小さいときは単価の安い側を選ぶ

以下、この手順を上から順に実装していきます。コードはPython 3.12系で動作を確認した形に整えており、そのまま貼って動かせます。

AI比較で見る4つの軸と、公開ランキングだけでは決まらない範囲

測る前に決めるのは、具体的に何を比べるのかという比較対象です。ここを曖昧にしたまま各社のAPIを叩くと、応答を眺めて「こちらのほうが良さそう」で終わります。比較の軸は品質・コスト・遅延・運用の4つに分けると、それぞれ別の計測方法に落とせます。

品質・コスト・遅延・運用の4軸を先に決めてから計測に入る理由

4軸は独立して動きます。単価の安いモデルが遅いとは限らず、採点の高いモデルが運用しやすいとも限りません。軸ごとに合格ラインを先に書いておくと、あとから結果を見て基準を作り直す誘惑を断てます。

軸 測る対象 記録する値
品質 応答の正しさ 正答率・審査スコア
コスト 入出力トークン 1件あたり単価・月額
遅延 応答時間 初回到達秒・生成速度
運用 失敗と制限 失敗率・レート制限

運用の軸は忘れられがちですが、本番で効いてきます。同時実行を上げたときに何件落ちるか、レート制限にどこで当たるか、モデルが廃止される時期がいつかは、採点表には出てきません。Anthropicはモデル一覧ページで各モデルの提供終了時期の下限を明記しており、2026年9月時点ではClaude Haiku 4.5が2026年10月15日より前には終了しないと書かれています。こうした期日は選定の段階で拾っておく値です。

LM Arenaのスコアが自社タスクの成績と一致しない構造的な理由

LM Arenaのような公開ランキングは、匿名の投票で2つの応答を比べた結果を集計したものです。集まっている質問は不特定多数が投げたもので、自社の業務書類でも社内規程でもありません。Artificial Analysisのような計測サイトも同じで、共通のベンチマークを共通の条件で走らせた結果です。

したがって公開スコアは候補を3つ程度に絞る道具として使い、順位そのものを採用根拠にはしません。順位の裏づけになる指標の設計はLLM評価とは?指標・データセット設計・評価ツールの選び方を実装視点で解説で整理しています。モデルそのものの仕組みから確認する場合はLLMとは?大規模言語モデルの仕組み・生成AIとの違いと企業導入の判断基準を先に読むと、本記事の計測対象が何を指すのかがつかめます。

検証環境をそろえる:3社のAPIを1つの関数で呼び分ける下準備

比較のコードは、モデルごとに別々のスクリプトを書くと途中で破綻します。呼び出し口を1つにして、モデル名を差し替えるだけで切り替わる形にします。

3社のSDKを入れてAPIキーを環境変数から読ませる初期設定

公式SDKを3つ入れます。キーはコードに書かず環境変数から読ませます。

python -m venv .venv
. .venv/bin/activate

pip install openai anthropic google-genai

export OPENAI_API_KEY="sk-..."
export ANTHROPIC_API_KEY="sk-ant-..."
export GEMINI_API_KEY="..."

各SDKの呼び出し形と引数名は公式ドキュメントに従います。OpenAIはAPI ドキュメント、Anthropicはモデル概要、Googleはモデル一覧が確認の起点です。ここを見ずに書くと、廃止済みのモデルIDや旧世代のパラメータ名を掴みます。

比較対象のモデルIDを一次情報で確認して設定ファイルに固定する

モデルIDは記事や記憶から書かず、公式のモデル一覧から写します。単価も同時に写し、モデルIDと同じファイルに置く形です。こうしておくと、あとでコスト計算のときに参照先が1か所で済みます。

# models.py — 比較対象と単価(USD / 100万トークン)
# 単価は2026年9月時点の各社公式料金ページの記載値

TARGETS = [
    {
        "key": "openai-terra",
        "vendor": "openai",
        "model": "gpt-5.6-terra",
        "price_in": 2.00,
        "price_out": 12.00,
    },
    {
        "key": "claude-sonnet",
        "vendor": "anthropic",
        "model": "claude-sonnet-5",
        "price_in": 2.00,
        "price_out": 10.00,
    },
    {
        "key": "gemini-flash",
        "vendor": "google",
        "model": "gemini-3.8-flash",
        "price_in": 0.75,
        "price_out": 3.75,
    },
]

この3つは単価帯を近づけて選んでいます。桁の違うモデルを混ぜると、品質差が単価差に埋もれて比較になりません。上位モデルを見たい場合は、同じ帯で組み直したうえで別回として走らせます。

同じプロンプトを各モデルへ流して応答と使用量を記録する実装手順

呼び出し関数は、応答テキストと入出力トークン数を同じ形で返すようにします。SDKごとに使用量の取り出し方が違うため、ここで吸収しておくと後段が楽になります。

評価用データセットをJSONL形式で20〜50件そろえる作り方

件数は20件から始めて、判断が割れるようなら50件まで増やします。1,000件は要りません。自社の実データから、typicalな案件・境界の案件・過去に失敗した案件を混ぜます。

{"id": "q001", "input": "見積書PDFの本文から合計金額を抜き出して", "expect": "1,485,000"}
{"id": "q002", "input": "この問い合わせを4分類のどれかに振り分けて", "expect": "解約"}
{"id": "q003", "input": "契約書の第12条に自動更新の定めがあるか判定して", "expect": "あり"}

expectは正解が一意に決まる項目にだけ入れます。要約や文案のように正解が定まらない項目は、expectを空にしておき、後述のLLM審査へ回します。

応答と使用量を1行1レコードでCSVへ落とす実行ループの組み方

3社のSDKを1関数で包み、結果をCSVに追記します。応答をその場で採点せず、まず生のまま残すのが要点です。採点方法を変えたくなったときに、再実行せずやり直せます。

import csv, json, os, time
from openai import OpenAI
from anthropic import Anthropic
from google import genai
from models import TARGETS

oa = OpenAI()
an = Anthropic()
gg = genai.Client(api_key=os.environ["GEMINI_API_KEY"])

def run_one(target, prompt):
    v = target["vendor"]
    t0 = time.perf_counter()
    if v == "openai":
        r = oa.responses.create(model=target["model"], input=prompt)
        text = r.output_text
        tin, tout = r.usage.input_tokens, r.usage.output_tokens
    elif v == "anthropic":
        r = an.messages.create(
            model=target["model"], max_tokens=1024,
            messages=[{"role": "user", "content": prompt}])
        text = r.content[0].text
        tin, tout = r.usage.input_tokens, r.usage.output_tokens
    else:
        r = gg.models.generate_content(model=target["model"], contents=prompt)
        text = r.text
        u = r.usage_metadata
        tin, tout = u.prompt_token_count, u.candidates_token_count
    return {
        "text": text, "in": tin, "out": tout,
        "sec": round(time.perf_counter() - t0, 3),
    }

rows = [json.loads(l) for l in open("dataset.jsonl", encoding="utf-8")]
with open("result.csv", "w", newline="", encoding="utf-8") as f:
    w = csv.writer(f)
    w.writerow(["id", "key", "in", "out", "sec", "text"])
    for target in TARGETS:
        for row in rows:
            res = run_one(target, row["input"])
            w.writerow([row["id"], target["key"], res["in"],
                        res["out"], res["sec"], res["text"]])
            time.sleep(0.5)

1件ごとに0.5秒空けているのは、無料枠や下位のレート上限に当てないためです。件数が増えて時間がかかるようなら、この段階では並列化せず、バッチ処理へ回します。OpenAI・Anthropic・Googleのいずれも、非同期のバッチは標準単価の50パーセント引きと各社の料金ページに記載があります。

100万トークン単価と実測トークン数から月額のコスト差を出す

ここからが、公開されている比較表では届かない部分です。単価の一覧は各社が出していますが、自社のプロンプトが何トークン消費するかは走らせないと分かりません。

入力と出力で単価が異なるため往復のトークン比で見積もりが変わる

各社とも出力単価は入力単価の5倍前後に設定されています。2026年9月時点のOpenAIの料金ページではgpt-5.6-terraが入力2.00ドル・出力12.00ドル、Anthropicの料金ページではClaude Sonnet 5が入力2ドル・出力10ドル、Geminiの料金ページではgemini-3.8-flashが入力0.75ドル・出力3.75ドルと記載されています(いずれも100万トークンあたり・USD)。

この構造のため、長い書類を読ませて短く答えさせる処理と、短い指示から長文を書かせる処理では、有利なモデルが入れ替わります。前者で効くのは入力単価、後者で効くのは出力単価です。実測値から計算します。

import csv
from collections import defaultdict
from models import TARGETS

price = {t["key"]: (t["price_in"], t["price_out"]) for t in TARGETS}
agg = defaultdict(lambda: [0, 0, 0])  # in, out, count

for r in csv.DictReader(open("result.csv", encoding="utf-8")):
    a = agg[r["key"]]
    a[0] += int(r["in"])
    a[1] += int(r["out"])
    a[2] += 1

MONTHLY_CALLS = 30_000
for key, (tin, tout, n) in agg.items():
    pin, pout = price[key]
    per_call = (tin / n * pin + tout / n * pout) / 1_000_000
    print(f"{key}: 1件 {per_call:.5f} USD "
          f"/ 月 {per_call * MONTHLY_CALLS:,.1f} USD "
          f"(平均 in {tin/n:.0f} / out {tout/n:.0f} tok)")

キャッシュとバッチの割引を織り込んで実運用に近い月額を算出する

素の単価で出した月額は、上振れした数字です。同じ社内規程やマニュアルを毎回前置きする処理では、プロンプトキャッシュが効きます。Anthropicの料金ページには、キャッシュ読み出しが基本入力単価の0.1倍、5分キャッシュの書き込みが1.25倍と書かれています。書き込みが1.25倍で読み出しが0.1倍なので、同じ前置きを2回以上使うなら差し引きで安くなる計算です。

OpenAIの料金表にもキャッシュ入力の単価が別列で載っており、gpt-5.6-terraは入力2.00ドルに対してキャッシュ入力0.20ドルです。前置きが全体の何割を占めるかを実測CSVから出し、その割合にキャッシュ単価を当てて計算し直すと、見積もりが実運用に寄ります。夜間にまとめて処理できる業務なら、さらにバッチの50パーセント引きが乗ります。

応答品質を採点する:正解データ照合とLLM審査の組み合わせ方

採点は2系統に分けます。混ぜると、自動でさばける部分まで人手やLLMに回すことになり、件数を増やせなくなります。

正解が決まる項目は文字列照合と数値一致による自動採点へまず回す

抽出・分類・判定は、expectとの一致で採点できます。金額や日付は表記ゆれを正規化してから比べます。

import re

def norm(s):
    s = s.strip().replace(",", "").replace("円", "")
    return re.sub(r"\s+", "", s)

def score_exact(pred, expect):
    if not expect:
        return None          # 正解なし。審査へ回す
    return 1 if norm(expect) in norm(pred) else 0

包含判定にしているのは、モデルが「合計金額は1,485,000円です」のように文を返すためです。厳密一致にしたい場合は、出力形式をJSONに固定してから比べます。形式を固定する手段は各社が構造化出力として用意しており、採点コードを短くできます。

LLM審査では採点基準を数値の定義まで書き下してぶれを抑える

要約や文案の採点を担当するのは、回答を作成したものとは別のモデルです。このとき「品質を5段階で評価して」とだけ書くと、走らせるたびに点が動きます。各点の条件を文章で定義します。

JUDGE = """あなたは採点者です。以下の回答を4観点で採点し、JSONだけを返してください。

観点と配点(各0〜5点):
- 正確性: 入力に無い事実を1つでも書いたら2点以下。数値の誤りは0点。
- 網羅性: 入力の要点を落とさず含むか。1つ欠けるごとに1点減。
- 形式: 指定した見出しと文字数の範囲を守っているか。
- 簡潔さ: 同じ内容の重複が無いか。重複1か所ごとに1点減。

出力: {"accuracy": n, "coverage": n, "format": n, "brevity": n, "reason": "40字以内"}

入力:
%s

回答:
%s
"""

審査役には、比較対象に入れていないモデルを使います。自分自身を採点させると自社の応答を高く付ける傾向が報告されているためです。採点結果は必ず一部を人が読み合わせて、審査役の点と人の判断がずれていないかを確認します。評価の設計をさらに詰める場合はLLM評価の記事にある指標の分類が、設計を整理する手がかりです。ツールを使う処理まで測るならAIエージェント評価とは?軌跡・ツール呼び出し・タスク達成を測る指標のほうが軸に合います。

公開ベンチマークを自分の環境で走らせたい場合は、lm-evaluation-harnessやOpenAI Evalsがそのまま使えます。ただしこれらが測るのは一般的なタスクなので、自社データの採点を置き換えるものではなく、候補を絞る段階で足す道具として扱います。

初回トークンまでの時間と生成速度を分けて測る計測コードの書き方

体感の速さは、応答が返り切るまでの秒数では説明できません。画面に1文字目が出るまでの時間と、そこから先の速度は別物で、対話型の画面では前者が効きます。

ストリーミングで初回トークン到達までの秒数だけを切り出して測る

ストリーミングで受け、最初のチャンクが来た時刻を記録します。

import time
from anthropic import Anthropic

an = Anthropic()

def measure_ttft(model, prompt):
    t0 = time.perf_counter()
    ttft = None
    n = 0
    with an.messages.stream(
        model=model, max_tokens=1024,
        messages=[{"role": "user", "content": prompt}]
    ) as stream:
        for _ in stream.text_stream:
            if ttft is None:
                ttft = time.perf_counter() - t0
            n += 1
    total = time.perf_counter() - t0
    return {
        "ttft": round(ttft, 3),
        "total": round(total, 3),
        "tps": round(n / max(total - ttft, 1e-6), 1),
    }

同じ入力を5回ずつ走らせて比較に使う値は、その中央値です。1回だけの計測は、そのときのネットワークと混雑を測っているだけになります。時間帯によっても動くため、日中と夜間の2回に分けて回すと差が見えます。

同時実行数を上げたときの失敗率とレート制限の挙動も記録に残す

本番のピークに近い同時実行数まで上げて、429や5xxが何パーセント出るかを数えます。ここで落ちる比率は、モデルの性能ではなく契約している利用階層で決まります。同じモデルでも階層が上がれば通るため、比較表には出てこない値です。リトライを入れたときの実効レイテンシまで含めて記録すると、遅延の軸の数字が本番寄りになります。

実測が公開ランキングと食い違ったときに採用可否を決める判断基準

ここまで測ると、公開ランキングの上位と自社の採点1位が一致しない場面が出てきます。そのときにどちらを採るかを、あらかじめ決めておきます。

採点差が5ポイント以内なら単価の安い側を採るという線の引き方

自社データでの採点を優先します。公開ランキングは自社の入力を含んでいないため、食い違いは想定内です。ただし採点差が小さいときは、差が本物かどうかが怪しくなります。20件の評価データで正答率が90パーセントと85パーセントに分かれても、1件の当たり外れで動く範囲です。

そこで、採点差が5ポイント以内なら単価の安い側、5ポイントを超えるなら採点の高い側、という線を先に引いておきます。5ポイントに根拠を持たせたいなら、評価データを50件に増やすか、同じ入力を3回走らせて採点のばらつき幅を先に測り、その幅より大きい差だけを差として扱います。

モデルを固定せず世代交代による切り替え前提で組んでおくべき場面と条件

今回の3社はいずれも、比較した世代の1つ前・2つ前を並行して提供しています。裏を返すと、選んだモデルの世代交代までの期間は1年程度です。Anthropicのモデル一覧には提供終了時期の下限が明記され、Geminiのモデル一覧には安定版とプレビュー版の区別が示されています。選定の時点で、次の乗り換え先が同じ社内から出てくることを前提に組みます。

具体的には、モデルIDを設定ファイルの1行に閉じ込め、プロンプトと評価データをコードから分離しておきます。この記事のmodels.pyとdataset.jsonlの分け方が、そのまま該当する構成です。運用に入ったあとのトレースやコスト監視の組み方はLLMOpsとは?MLOpsとの違いとトレース・評価・コスト管理の実装で扱っています。

一方で、切り替え前提にしないほうがよい場面もあります。出力の形式や語調を細かく詰め込んだプロンプトで運用している処理は、モデルを替えると調整をやり直すことになります。この場合は年1回の見直しに固定し、その間は世代交代を追いません。どちらに倒すかの判断や、評価データの設計から実装までを外部に預けたい場合は、生成AI導入支援で自社の業務データを使った検証から請けています。

比較のやり直しを避けるため評価データと結果を版管理に残しておく

dataset.jsonlとresult.csv、models.pyの3つをGitに入れます。半年後に新モデルが出たとき、前回との差分を出す作業は、同じデータを同じコードで流すだけです。ここを残していないと、そのたびに評価データの作成からやり直すことになり、比較の頻度が落ちます。

結果CSVには実行日と各社の単価も一緒に書き込んでおきます。単価は改定されるため、後から見返したときに「当時いくらで計算したか」が分からなくなるためです。実際、OpenAIの料金ページは2026年9月時点でplatform.openai.comからdevelopers.openai.comへ、Anthropicの料金ページはdocs.claude.comからplatform.claude.comへ移っており、参照先そのものが動きます。

よくある質問

評価データは何件そろえれば判断できますか?

20件から始め、モデル間の採点が僅差で割れるようなら50件へ増やします。20件で正答率に20ポイント以上の開きが出るなら、それ以上増やしても順位は動きません。増やすより、境界の案件と過去に失敗した案件を混ぜるほうが判別力が上がります。

無料枠だけで比較を済ませることはできますか?

一部は可能です。Geminiの料金ページには、いくつかのモデルに無料枠がある旨の記載があります。ただし無料枠はレート制限が低く、同時実行を上げたときの挙動が本番と変わります。品質の比較までは無料枠で進め、遅延と失敗率の計測は有料枠に切り替えてから行うのが現実的です。

社内データを外部APIに送ってよいか判断する際の確認事項は何ですか?

比較の前に、送るデータの区分を決めます。個人情報や取引先の秘密情報を含む書類をそのまま投げるのは避け、氏名や金額をダミーに差し替えた評価データを作ります。差し替えても文書の構造は変わらないため、抽出や分類の採点は可能です。データの所在地を指定できる機能を各社が用意しているので、契約前にその条件も確認します。

ローカルで動くモデルも比較対象に入れるべきですか?

入れる価値があるのは、送信できないデータを扱う場合と、月間の呼び出し回数が数十万件を超える場合です。それ以外では、GPUの調達と運用の手間が単価差を上回ります。判断は本記事のコスト計算に、サーバー費と運用工数を足して比べると付きます。

比較の結果はどのくらいの頻度で見直せばよいですか?

半年に1回を目安にします。各社とも数か月おきに新世代を出しており、単価も同時に動きます。評価データとコードを残しておけば、見直しの実作業にかかる時間は数時間です。障害や品質の苦情が出たときは、周期を待たずに同じセットを流します。

関連記事

お気に入りに入れた記事の一覧

この記事は以下の記事からリンクされています

資料請求

今日のトレンド記事 直近 24 時間で、いつもより多く読まれている記事

  1. 2026.10.23 テックブログ Renta!不正アクセスでサービス停止:再開未定の現状と運営側の停止判断・証拠保全・段階的再開
  2. 2025.01.09 コラム アドレサブルCM(Addressable CM)とは?フジテレビで出る表示の意味・仕組みと視聴データの扱い
  3. 2026.07.09 テックブログ Muse Imageとは?Metaの画像生成AIの使い方・API料金(1枚0.01ドル)と日本での提供状況【2026年10月】
  4. 2026.10.21 テックブログ ふるさとチョイス不正アクセスで445万件流出:対象確認・パスワード変更と再開時期
  5. 2025.12.10 コラム 今の50代は何世代?バブル世代・団塊ジュニア・氷河期の境目と特徴

RELATED POSTS 関連記事

目次