読者=APIやモデル出力を業務プログラムにつなぐ開発者;読後に持ち帰れるもの=JSON抽出結果を本番処理へ渡す前の検証コードと合否基準。
Grok 4.6とKimi K2.5をJSON抽出で比べるなら、見た目の整った出力だけでは判定できません。構文を解析できるか、値の型が契約どおりか、値を入力資料で裏づけられるかを分けて確認する必要があります。1つでも崩れれば、後続の更新処理で誤った担当者や期限が確定値として保存されるためです。
このメモでは、合成した備品貸出記録を題材に、比較条件と小さな検証器を整理します。サンプルは検証コードの動作例であり、どちらかのモデルが生成した結果ではありません。2026年10月26日に確認したKimiの公式モデル一覧では、kimi-k2.5 は8月31日付で提供終了と記載されています。したがって、現時点の公式APIで同じ条件の新規呼び出しを行えるとは扱いません。利用経路と実際のモデルIDは実験開始時に再確認してください。
先に入力資料と出力契約を固定する
比較対象の文章は、次のような短い記録にします。
管理票 R-184。貸出品は USB-C 測定器。返却予定は 2026-11-03。申請部署は検査チーム。担当者名は記録されていない。
この入力から取り出せるのは、管理票番号、品名、返却予定日、申請部署です。担当者名は不明であり、部署名から推測して埋めてはいけません。プロンプトには「JSONだけを返す」と書けますが、それだけでサーバー側の構造化出力スキーマが有効になるわけではありません。提供経路がJSON Schemaやstructured outputをサポートするか、対象モデルがその機能を受け付けるかは別々に調べます。
モデルとサービス経路も記録します。製品名が同じでも、APIのモデルID、提供者、推論設定、上限トークン、構造化出力オプションが違えば、同条件の比較ではありません。モデル仕様や提供状況の確認先として、Grok系モデルのCrazyrouter一覧とKimi公式モデル一覧を使い、実行時の応答に含まれるモデルIDを別途保存します。後者にはK2.5の提供終了情報があるため、過去のモデルカードだけを見て現行API利用を前提にしないことが重要です。
3段階で機械判定する
以下はPython 3.10以降、標準ライブラリのみで動く最小例です。input_text と candidate は作成した合成サンプルです。まずパース、次にスキーマ、最後に入力根拠を確認します。
import json
from datetime import date
input_text = """管理票 R-184。貸出品は USB-C 測定器。
返却予定は 2026-11-03。申請部署は検査チーム。担当者名は記録されていない。"""
candidate = '''{
"ticket": "R-184",
"item": "USB-C 測定器",
"due_date": "2026-11-03",
"department": "検査チーム",
"owner": null
}'''
def validate(raw: str, source: str) -> list[str]:
errors = []
try:
data = json.loads(raw)
except json.JSONDecodeError as exc:
return [f"invalid JSON at {exc.lineno}:{exc.colno}"]
expected = {"ticket", "item", "due_date", "department", "owner"}
if not isinstance(data, dict) or set(data) != expected:
return ["keys do not match the contract"]
for key in ("ticket", "item", "department"):
if not isinstance(data[key], str) or not data[key].strip():
errors.append(f"{key} must be a non-empty string")
if data["owner"] is not None and not isinstance(data["owner"], str):
errors.append("owner must be a string or null")
try:
date.fromisoformat(data["due_date"])
except (TypeError, ValueError):
errors.append("due_date must be an ISO calendar date")
evidence = {
"ticket": "R-184",
"item": "USB-C 測定器",
"due_date": "2026-11-03",
"department": "検査チーム",
}
for key, value in evidence.items():
if data.get(key) != value or value not in source:
errors.append(f"{key} is not grounded in the source")
if data["owner"] is not None:
errors.append("owner is unknown in the source and must stay null")
return errors
issues = validate(candidate, input_text)
print("PASS" if not issues else "FAIL: " + "; ".join(issues))
実行結果は PASS です。値を 2026-11-30 に変更すると入力にない日付として失敗し、担当者を 佐藤 にすると根拠のない補完として失敗します。これは検証器を合成例で実行した結果で、モデルAPIの応答や精度測定ではありません。実プロンプトで集めた出力を candidate に入れるなら、同じ評価コード、同じ項目定義、同じ入力集合を使い、モデルごとに生出力も保存します。
3段階の意味は異なります。構文検査は後続プログラムで開けること、型検査はフィールドの契約を守ること、根拠検査は値が元資料に結びついていることを示します。構文の成功率だけを比べると、もっとも危険な「きれいなJSONの中の誤情報」を見逃します。正規化が必要な日付や表記ゆれは、期待する変換規則を事前に用意し、原文との対応を別途保持してください。
null、空文字、unknownは同じではない
ここはタスク定義に含めておきたい点です。null は「このフィールドは存在するが、資料から値を確定できない」、空文字は「文字列はあるものの、意図的に空である」、unknown はAPI契約で列挙値として決めた状態を表す場合があります。三つを混ぜると、画面では未入力に見えても、後段の同期処理が「確認済みの空欄」と解釈することがあります。担当者が記録されていない状態を部署名から補完するより、未知の状態を保ち、必要なら別フィールドに根拠や確認タスクを残す方が安全です。比較時には欠損値の表現をモデル任せにせず、スキーマと評価器で固定します。製品側が未提供値をどう扱うかに合わせ、APIへ送る値と画面に表示する文言を分けるのも有効です。
どちらを採るかは失敗の重さから決める
まず、必須キー欠落、型違い、資料にない値の3種類を別々に数えます。次に、同じ入力集合で人が直した件数と時間を記録します。担当者や金額のように誤補完が重大な項目では、根拠不明の確定値が1件でも出た設定を候補から外す、といった停止条件を先に決められます。停止条件を満たす候補だけで、修正時間、価格、応答時間を比較します。実測値がなければ「優位」とは書かず、品質と費用は要検証のままにします。
現状、Kimi公式APIの kimi-k2.5 は提供終了と案内されているため、公式API同士の現在の直接対決という結論は出せません。過去の保存出力を比較する場合も、取得日や設定が異なるなら同条件実験とは呼べません。利用可能なKimiの経路が見つかった場合は、モデルIDと提供者を記録したうえで、同じ入力・契約・評価器を再実行するのが判断の入口です。
まとめ
JSON抽出では、パースできること、契約に合うこと、入力に裏づけられることを分けて採点します。未知の値を勝手に埋めない挙動は、見栄え以上に業務データの信頼性を左右します。実際の勝者はモデル名からは決まりません。Kimi K2.5を含む同一条件の現行出力が取得できる場合に限り、同じ評価器で比較し、根拠のない確定値を許さない運用基準を満たした候補から選びます。
ローカル検証の範囲
- Python:3.10以降を想定、追加パッケージなし
- コマンド:
python validate_json.py - 合成サンプル:パス、根拠のない日付、未記録の担当者
- 結果:基準例
PASS、不正な日付と担当者補完はFAIL - モデルAPI出力、レイテンシ、料金:要実測確認


