AIが間違えた答えを、検算係はもう知っていた
入力は note: "None"。指示は「小文字の none だけをnullに変える」。
検算係は正しい期待値を計算し、モデルの null を誤りとして拒否しました。それなのに、最終的に返ってきたのは同じ null でした。
正解はすでにコードの中にあったのに、捨てられていた——この1問を糸口に、どこでAIに任せ、どこで任せないかを追います。
何が起きていたのか
「検出できる」と「直せる」と「正しい値を返す」は、別の話でした。
"None" を内部で構成していた。しかしその値は回答に使われず、モデルの再生成結果が最終回答として残った。
この1問(以下HJ3)では、検算係が入力から期待レコードを導出する関数を実行し、正しい "None" を計算しています。モデルの候補 null はその期待値と一致しないため拒否されます。ところが処理は、拒否したあとにモデルへ修復を求め、2回目も同じ null が返ると、それを最終回答として保持します。
数字で見る:主要16問と、全体20問は別物
同じ20問を、通常方式・検証方式・決定論的処理だけで解いた方式の3つで再採点しました。
通常 → 検証方式 → 決定論的処理のみ。計算・コード・証拠照合・JSON正規化の4分類。
同点。全20問の意味正答は13 → 19 → 18で、決定論的処理は検証方式より1問少ない。
主要16問では、決定論的処理だけで16/16でした。一方、全体20問では検証方式と厳格正答で同点、意味正答では1問負けています。理由は単語の直接回答4問(対照群)で、決定論的処理は反対語と色名の2問を「対応する規則がない」として未対応にしたためです。この2問を分母から外した「対応18問」の成績だけを並べると、全体の優越と誤読されます。
| 指標 | 通常 | 検証方式 | 決定論的処理のみ |
|---|---|---|---|
| 主要4分類16問の厳格正答 | 9/16 | 15/16 | 16/16 |
| 全20問の厳格正答 | 12/20 | 18/20 | 18/20 |
| 全20問の意味正答 | 13/20 | 19/20 | 18/20 |
| 全20問の形式合格 | 14/20 | 19/20 | 18/20 |
| 対応18問の厳格正答 | 11/18 | 17/18 | 18/18 |
| 単語4問(対照)の厳格正答 | 3/4 | 3/4 | 2/4 |
| モデル呼び出し | 20 | 23 | 0 |
| 修復 | 0 | 3 | 0 |
未対応の2問は、全体成績では非正解として数えています。対応した18問だけの条件付き成績(18/18)は、この処理が選んだ範囲の中での話であり、全20問での優越を意味しません。また、決定論的処理が検証方式に対して正答を上積みしたのはHJ3の1問だけで、逆に通常方式が正答していた反対語1問を未対応にしています。
なぜ「検算係だけ」で終わったのか
カテゴリーごとに、入力から答えを確定できるかどうかが違いました。
| 分類 | 確定できる根拠 | 対応/正解 |
|---|---|---|
| 整数計算 | 入力の式を、許可した演算子だけの構文木で評価する | 4/4・4/4 |
| 固定コードの出力 | レビュー済みの4つの純粋関数を、供給データで実行する | 4/4・4/4 |
| 提供証拠の抽出 | 全条件に一致する唯一の行を選び、値・ID・引用をそのまま写す | 4/4・4/4 |
| JSON正規化 | 明示された変換規則を入力に適用する(今回の主役) | 4/4・4/4 |
| 単語の直接回答(対照) | 小文字化と復唱は入力だけで決まる。反対語と色名は規則が与えられていない | 2/4・2/2 |
ポイントは、「入力と明示された規則だけで答えが一意に決まる」仕事に限ったことです。反対語(cold→hot)や色名(#FF0000→red)は、入力だけでは答えが決まりません。この2問を、その場で答え表を作って埋めることはしませんでした。それは検証ではなく、答えの後付けになるからです。
これは新しい発見ではなく、配置の見直しだった
HJ3の正解 "None" は、以前の実験の推論前チェックでも既に生成され、受理されていました。新しく見つけた計算法ではなく、すでにオフラインで成功していた処理を、最終回答の経路に採用できるという配置上の問題です。だから「より賢いモデルを見つけた」という話にはなりません。
この点は正直に書いておきます。決定論的処理は、元の検証器の関数をそのまま再利用しています。独立した実装同士が一致したわけではありません。また、今回の処理は公開されたタスクと命令文を見て書かれており、同じテンプレートの新しい入力ではあっても、この処理にとっての未知入力ではありません。「作者が事前に正解を見ていなかったこと」は、記録上そうなっているだけで、独立には証明できません。
では、どう組めばいいのか
以下は実測で確かめた成果ではなく、この記録から導いた設計案です。まだ端から端までは試していません。
1. AIで意図を整理する 自由文や曖昧な要求から、「どのカテゴリーの、どの変換か」を取り出す。 ここはAIの得意分野。ただし結果は構造化された入力契約として出力させる。 2. 確定処理に渡す 入力契約が既知のカテゴリーに一致するなら、決定論的な処理で答えを確定する。 計算・固定コード・証拠照合・正規化のように、入力だけで答えが決まる仕事が対象。 3. 確定値は書き換えない 確定処理が出した値を、モデルに再生成させない。検算係が持っている期待値を 捨てて作り直させるのは、まさに今回の1問が示した遠回り。 4. 必要だけ説明する モデルには、確定値をどう扱うかの説明や、契約に当てはまらない部分の 要約だけを任せる。値そのものは生成させない。
この4段のうち、今回の実験で実測できたのは2と3の一部です。1の「AIで意図を整理する」工程と、契約に当てはまらない場合の扱いは、まだ試していません。提案として提示しますが、検証済みの成果としては扱いません。
コードで見る:「期待値と照合して再生成」と「入力から確定」
正解データ(gold)には一切触れず、入力と明示された規則だけで完結する最小例です。
# --- 悪い例: 期待値と照合したあと、モデルに作り直させる ---
def validate_then_regenerate(record, ask_model):
want = normalize(record) # 正しい期待値がここにある
candidate = ask_model(record) # それでもモデルに生成させる
if candidate != want:
candidate = ask_model(record) # 1回だけ修復
if candidate != want:
return {"status": "not_verified", "answer": candidate} # 誤答を返す
return {"status": "correctness_verified", "answer": candidate}
# --- 良い例: 変換が完全に指定されているなら、入力から確定させる ---
def normalize(record):
"""入力と明示された規則だけで期待レコードを導出する(goldは見ない)。"""
return {
"label": record["label"],
"count": int(record["count"]),
"enabled": record["enabled"] == "yes",
# 小文字の "none" だけを null にする。大文字の "None" は文字列のまま。
"note": None if record["note"] == "none" else record["note"],
}
def answer_from_input(record):
return {"status": "correctness_verified", "answer": normalize(record)}
if __name__ == "__main__":
# 入力だけを渡す。正解表は参照しない。
case = {"label": "D:\\archive\\weekly", "count": "407",
"enabled": "no", "note": "None"}
print(normalize(case)["note"]) # => None ではなく "None" が正しい
2つの関数の違いは、正しく計算した期待値を、回答に使うか捨てるかだけです。変換が完全に指定されている仕事では、モデルの生成を経由せずに入力から答えを確定できます。逆に、規則が与えられていない語彙や色名のような仕事には、この関数は使えません。
時間と費用について、言えること・言えないこと
決定論的処理は、20問を1,000回繰り返した中央値で約57マイクロ秒でした。一方、過去の検証方式の記録は20問で約21.5秒です。しかし、これは測定の境界も条件も違うので、速度倍率としては主張しません。片方はファイル入出力もモデルの起動も含まないCPU上の計算で、もう片方はモデルのHTTP往復・推論・修復・検証を含みます。同じ土俵の比較ではありません。
費用も同じです。両方の実験とも外部API料金は$0で、削減額を測ったわけではありません。電力や機材費も未測定です。「何倍速い」「何円得」という見出しには使いません。
この記録の出どころと、独立性の限界を読む
何を再検証したのか
元の実験は、同じ5種類のテンプレートに新しい入力値を入れた20問を、通常方式と検証方式の2つで解いたものです。今回はその保存済みの回答と生トレースを、決定論的処理だけの方式で解き直し、既存の採点器で再採点しました。新しいモデル推論は行っていません。
| 項目 | 内容 |
|---|---|
| 問題数 | 20問(主要4分類16問+単語の対照4問) |
| 比較した方式 | 通常回答 / 検証方式 / 決定論的処理のみ |
| 採点 | 意味が正しい AND 指定形式を守る(履歴モデルは通信成功も必要) |
| モデル呼び出し | 決定論的処理: 0回 / 検証方式: 23回 / 通常: 20回 |
| 外部API料金 | $0(ローカル実行) |
| 新規推論 | なし(保存済み結果の再採点と再実行のみ) |
独立性について、正直に書くこと
- 決定論的処理は、元の検証器の関数を直接再利用しています。独立した実装同士の一致ではありません。
- 採点器は処理を読み込みませんが、固定された正解と照合します。処理は公開されたタスクを見て書かれています。
- 「処理の作者が事前に正解を見ていない」ことは、記録上はそうなっていますが、独立の第三者による証明ではありません。
- 問題は同じテンプレートの入力置換であり、無作為標本でも、未知カテゴリーへの一般化テストでもありません。
- 正解の導出は、別の手順とコードで求めたという意味での「別経路」です。別の人間による盲検評価ではありません。
採点側の制約も開示する
単語の対照4問のうち色名1問は、モデルの回答 Red が意味としては正しいのに、採点器が課した小文字限定の形式条件で不合格になりました。これは指示文には明記されていない追加の制約です。元の測定・採点結果は変更せず、厳格正答と意味正答を併記しています。
元データの出典を読む(外部ファイルに依存しない要約)
この記事の数値は、すべて保存済みの記録から再集計したものです。以下は要約であり、リンク切れする外部アセットには依存しません。
| 記録 | 内容 |
|---|---|
| 採点結果 | 20問の意味・形式・厳格判定、3方式の正答数、呼び出し数、時間集計 |
| 保存回答 | 決定論的処理による20問の回答と、未対応2問の理由 |
| 時間計測 | 20問バッチ1,000回の中央値と、各問1,000回の生サンプル |
| 固定記録 | 処理・出力・公開入力・再利用実装のSHA-256と固定時刻 |
| 検証ログ | HJ3を含むJSON正規化4問の、初回・修復後の候補と拒否理由 |
| 監査記録 | 独立再集計の結果、拒否チェックの再現、goldの別導出 |
決定論的処理の固定時刻は2026-09-12 23:15:37 UTC、採点プロセスが正解を開いた時刻は23:17:03 UTCです。固定した8ファイルのハッシュは一致し、保存回答20件は再現されました。これは追試と改変検出のための記録であり、第三者署名付きの証明ではありません。
この記録から言えること
ただし、これは「LLMは要らない」という一般論ではありません。見つかったのは、この処理経路のどこにLLMが要らなかったかです。自由文から契約を作る工程、曖昧な要求の解釈、語彙知識が必要な仕事は、この実験の外側にあります。AIを使い続ける前提で、任せる場所を選び直すのが、この記録の実用的な意味です。
関連する記録として、AIの精度を上げたいなら、まず計算とデータ変換に検証を足すと、その前提になった過去記事の訂正(ローカルLLM比較の採点ミス)も合わせて確認してください。
確定できる仕事は、確定処理に渡す
まずは自分の処理のどこで「正しい値がすでに計算されているのに、作り直させているか」を探すところから。検証の始め方は実測ガイドにまとめています。
検証の始め方と実測を読む →