Excelから書き出した商品CSVをデータベースや別サービスへ流し込む作業は、週に一度でも繰り返すなら手作業では持ちません。価格を桁落ちなく整数化し、不正な行を拒否し、失敗したときに前回のproducts.jsonやCSV原本を壊さない。この辺りは、使い捨てのスクリプトではなく「保存して何度も走らせる前提の小さなツール」として書かれていないと、本番に入れるのが怖くなります。
今回はGPT-5.6 SolとClaude Opus 4.8の両方に、まったく同じ要件で同じCSV→JSON変換ツールを書かせました。初版は両モデルとも、入力と出力に同じパスを渡すとCSV原本を黙って上書きするという、同じ危険な挙動を示しました。失敗ケースを戻して修訂させた2版目は、23種類のローカル入力をいずれも想定どおりに扱いました。ベンチマーク順位ではなく、「どの工程を任せられるか」「何を自分で検査すべきか」が本文の焦点です。
GPT-5.6 SolとClaude Opus 4.8に求めるCSV→JSON変換の輪郭
対象データは次のような1行です。SKU、商品名、価格、在庫の4列。価格は12.30のような2桁小数、在庫は非負整数で0も有効値です。
sku,name,price,stock
A01,Mug,12.30,7
A02,Canvas Bag,0.29,0
出力のproducts.jsonは、価格を整数の「セント」に正規化した配列にします。12.30は1230、0.29は29。在庫0は欠損ではないので、そのままstock: 0で出す必要があります。
[
{ "sku": "A01", "name": "Mug", "priceCents": 1230, "stock": 7 },
{ "sku": "A02", "name": "Canvas Bag", "priceCents": 29, "stock": 0 }
]
実務のCSVはこの程度では済みません。"Mug, Blue"のように引用符内のカンマが入り、場合によっては引用符内に改行が挟まります。それでも、修订版のGPT-5.6 SolとClaude Opus 4.8はいずれも、BOM付きUTF-8、引用符内カンマ、クオート内改行を含む複雑なサンプルを正しく解釈して期待どおりのJSONを生成しました。範囲が明確な小さなツールであれば、どちらのモデルもパースロジックは任せられると判断してよさそうです。
GPT-5.6 SolとClaude Opus 4.8に失敗時の挙動まで言語化して渡す
CSV→JSONで一番怖いのは、成功時の結果ではなく失敗時の副作用です。要件には成功条件と同じ重みで失敗条件を書き込みました。日本語で意訳すると次のような指示です。
完全に動作するNode.js CommonJSファイル
import-products.cjsを書いてほしい。使い方はnode import-products.cjs products.csv products.json。サードパーティ依存は不可。UTF-8のCSV(BOM許容)、CRLF/LFの両方、引用符内のカンマや改行、エスケープされた""に対応する。ヘッダーはsku/SKU/Product ID、name/Product Name、price/Price、stock/Stockから各1つを含み、順序入れ替えや両端の空白は許容するが、欠落・重複・未知の列は拒否する。SKUは大小区別、重複不可。価格は小数2桁ちょうどを要求し、安全な整数のセントに変換する。在庫は非負の安全な整数。重要: CSVが不正、データが要件外、または入力と出力のパスが同じ実ファイルを指す場合は、stderrにエラーを出して非0で終了する。入力ファイルを変更してはならず、既存の出力ファイルを作成・上書きしてもならない。成功時は件数を標準出力に出す。書き込みは同一ディレクトリの一時ファイルで行い、最後にrenameで目的ファイルに差し替える。ネットワークと子プロセスは使わない。コード本体のみを返す。
この粒度で書くと、エイリアスを正しく解決してくれる確率が高くなります。実際に以下のような日本語・英語混在のヘッダー順入れ替えでも、修訂版の両モデルは適切にマッピングしました。
Stock, Product Name ,Product ID,Price
7,"Mug, Blue",A01,12.30
ただし、こう書いても初版は入力ファイルを書き換えてはならないという条文を無視しました。入出力に同じパスを渡した時点で、両モデルの初版はCSV原本を上書きし、こちらが用意した「テスト用の捨てCSV」を失わせました。この具体的な失敗シナリオを戻し、ファイルの実身元(inode相当のチェック)を要件に加えてから、両モデルの修訂版はこのケースを拒否するようになりました。初版のAIコードを無検査で本番に当てないという原則は、プロンプトを丁寧に書いても消えません。
GPT-5.6 SolとClaude Opus 4.8が生成したツールを安全に走らせる
生成されたコードはimport-products.cjsとして、同じディレクトリのproducts.csvと並べ、Node.jsが入った環境で素直に動きます。
node import-products.cjs products.csv products.json
自動化パイプラインに組み込むなら、exit codeの確認を省略できません。$?が0以外であれば後段を止める、以下のような流儀です。
node import-products.cjs products.csv products.json
if [ $? -ne 0 ]; then
echo "インポート失敗。後続処理を停止します。" >&2
exit 1
fi
成功したproducts.jsonは、別のスクリプトからそのまま読んで集計などに使えます。たとえば「在庫ゼロのSKUを抽出する」は数行で済みます。
const fs = require('node:fs');
const products = JSON.parse(fs.readFileSync('products.json', 'utf8'));
const outOfStock = products.filter(product => product.stock === 0);
console.log(`合計: ${products.length}`);
console.log(`在庫ゼロSKU: ${JSON.stringify(outOfStock.map(product => product.sku))}`);
意図的に12.3(小数2桁ではない)を混ぜると、修訂版はどちらもstderrに失敗理由を出して非0終了し、既存のJSONは触りませんでした。ここで肝心なのは、「products.jsonが残っている=今回のインポートに成功した」ではないと覚えておくことです。前回成功時のJSONが残っているだけ、という状態を次工程に食わせないよう、exit codeを必ず読む設計にしてください。
GPT-5.6 SolとClaude Opus 4.8のエラー表現と限界
実務で意外に効くのは、失敗時のメッセージの読みやすさです。価格を12.3にして流したとき、Claude Opus 4.8の修訂版は「価格は小数2桁で指定してください(例: 12.30)」といった、仕様に近い指摘を出しました。文字コードはSimplified Chinese(簡体字)で、Qiita読者向けに日本語ロケールまで対応したとは言えません。GPT-5.6 Solの修訂版は英語で、エラーの発生した論理レコード番号を付記しました。長いCSVで引用符の閉じ忘れを探すときには、この番号が検索の起点になり助かります。
もう1つ、小さなパース関数単体に限定した3回サンプリングでは、GPT-5.6 Solの3件はいずれも引用符内カンマと改行を正しく解釈しましたが、Claude Opus 4.8は3件中1件のみ正解で、残り2件は空行の混入やクラッシュを起こしました。この観察はparseCsv(input)相当の小片に限ったもので、「GPTのほうがコード生成が総合的に優れている」という結論に拡張できるものではありません。既存のコードベースに差し込む1関数を頼みたい場面での、サンプル1回ぶんの判断材料として読んでください。
GPT-5.6 SolとClaude Opus 4.8のどちらを選ぶかは「どの工程を切り出すか」で決まる
完成形のCLIツールとして見ると、GPT-5.6 SolとClaude Opus 4.8はいずれも、1ラウンドのフィードバック後に要件を満たす実装を返しました。入れ替わったヘッダーを正しく解釈し、不正データで中断し、出力ファイルと入力ファイルを守る。ここに大きな差はありません。既に慣れているほうを使って、業務ルール(SKUの前後空白を同一視するか、価格の01.00を許容するかなど)の決定に時間を使う方が実利があります。
今回のリクエストは2026年11月3日、Crazyrouterのhttps://api.crazyrouter.com/v1/chat/completionsに対してgpt-5.6-solとclaude-opus-4-8を指名して送りました。初版と、初版の問題点を具体化した1回の修订版の2往復のみ、同じ中文プロンプトを使用し、生成されたコードには人手を加えていません。実行環境はNode.js v24.21.0、23種類のローカル入力はすべて「同じツールへの異なる入力」であって、23題分の独立したモデル評価ではありません。長期の安定性や大規模プロジェクトでの挙動は、この実験の範囲外です。
自分の手元で再現したい場合は、Crazyrouterのコーディング向けモデル一覧で型番を確認し、OpenAI互換の接続ドキュメントに沿ってBase URLとキーを設定するのが近道です。本物のデータをいきなり当てず、「成功時に何を書き出すか」と「失敗時に何を絶対に触らないか」を自分の言葉で定義してからプロンプトを渡してください。モデル選び以上に、この条件の明確さが「何度でも走らせられる小さなツール」を決めます。
