Mistral AI vs ChatGPT コーディング比較:実戦投入した第一人称の深掘りレポート
この2週間、私はMistral AI(具体的には mixtral-8x22b-instruct と mistral-large-2407 エンドポイント)とChatGPT(GPT-4oとGPT-4-turbo)を、実際のコーディングタスクの数々で徹底的にテストしました。おもちゃのサンプルコードではありません——本番レベルのPythonリファクタリング、Rustの非同期デバッグ、SQLクエリ最適化、そしてちょっとした組み込みCまでです。すべての出力、すべての幻覚(ハルシネーション)、すべての見落とされたエッジケースを追跡しました。以下がその結果です。
クイック比較表
| 項目 | Mistral AI (Large 2407) | ChatGPT (GPT-4o) |
|---|---|---|
| コンテキストウィンドウ | 32Kトークン(実効) | 128Kトークン(実効) |
| レイテンシ(最初のトークンまで) | 約1.2秒(API) | 約0.8秒(API) |
| コード正確性(私のテスト) | 76% 合格率 | 84% 合格率 |
| 幻覚発生率 | 18%(存在しないAPI、誤ったインポート) | 12%(より微妙なエラー) |
| デバッグの明瞭さ | 良好だが冗長 | 優れており簡潔 |
| 複数ファイルの理解 | 弱い(ファイル間でコンテキストを失う) | 強い(プロジェクト全体の視点を維持) |
| 100万トークンあたりのコスト | $2.50(入力)/ $8.00(出力) | $5.00(入力)/ $15.00(出力) |
| オフライン/自己ホスティング | 可能(オープンウェイト) | 不可 |
機能別比較
ラウンド1:レガシーPythonモノリスをリファクタリング
2,000行のPythonスクリプトを両方に投入しました——グローバル状態、ネストされたループ、型ヒントゼロの絡み合った混乱です。目標:モジュールに分割し、型ヒントを追加し、テスト可能にすること。
Mistral AI は好調なスタートを切りました。コアクラスを特定し、data_loader.py、processor.py、exporter.py へのクリーンな分割を提案しました。しかし、processor.py の実際のコードを生成するよう依頼したところ、存在しない cache_manager モジュールを参照する process_with_cache() メソッドを幻覚しました。指摘すると、Mistralは謝罪して書き直しました——今度は新たな幻覚 from utils.decorators import memoize(これも存在しません)を導入しました。3回の修正後、ようやく動作するバージョンができましたが、元の関数シグネチャは失われていました。最終出力には手動修正が必要でした。
ChatGPT は異なるアプローチを取りました。まず関数呼び出しグラフを尋ねました(私は提供しませんでしたが、コードから推測しました)。そしてリファクタリング版を一発で生成——インポート漏れも、幽霊メソッドもありません。適切な箇所に @dataclass デコレータまで追加しました。唯一の問題:あるモジュールで変数 data を raw_data にリネームし、不一致が生じて修正が必要でした。しかし、全体的な構造は堅牢で、生成されたテストは実際にパスしました。
勝者:ChatGPT – Mistralの幻覚により20分のデバッグ時間を浪費。ChatGPTの一発出力は95%正確でした。
ラウンド2:Rust非同期デッドロックのデバッグ
10~15接続後にハングするTokioベースのTCPサーバーがある小さなRustプロジェクトがありました。コードは3ファイル、約400行です。3ファイルすべてを各モデルのコンテキストに貼り付けました。
Mistral AI は問題を正確に特定しました:tokio::spawn 内の .await ポイントをまたいで保持された Mutex です。根本原因の説明は良好で——「ミューテックスガードはawait後にドロップされるが、futureは Send ではない」——そして tokio::sync::Mutex を使用した修正を提供しました。しかし、この修正により新しいバグが発生しました:Arc<Mutex<...>> を Arc<tokio::sync::Mutex<...>> に変更したものの、.lock() 呼び出しの1つを更新し忘れ、まだ std::sync::Mutex::lock を使用していました。これによりコンパイルエラーが発生しました。指摘すると、Mistralは修正しましたが、2回目の試行では Arc の不要な clone() が追加されました(無害ですが無駄です)。
ChatGPT は同じデッドロックパターンを発見しましたが、さらに踏み込みました:共有ミューテックスの代わりにチャネルベースのアーキテクチャを使用するようコードを再構築することを提案しました。tokio::sync::mpsc を使用したコネクションハンドラの完全な書き換えを提供しました。新しいコードは初回でコンパイルが通り、100以上の接続をハングせずに処理しました。さらに、Mistralが考慮していなかったチャネル送信のタイムアウトも追加しました。唯一の欠点:ChatGPTの解決策はアーキテクチャを大幅に変更しており、小規模プロジェクトには過剰かもしれません。
勝者:ChatGPT – Mistralの修正は精神としては正しかったが、実行にバグがあった。ChatGPTの解決策はより堅牢で本番対応であり、たとえより侵襲的であっても。
ラウンド3:SQLクエリ最適化
両モデルに、5つのテーブルをネストされたサブクエリで結合し、50GBのデータセットで12秒かかる、書き方の悪いPostgreSQLクエリを与えました。目標:1秒未満で実行できるように書き換えること。
Mistral AI はインデックスの追加とサブクエリのCTEへの書き換えを提案しました。私が提供していなかった EXPLAIN ANALYZE の出力を使用して、(user_id, created_at) に複合インデックスを推奨する書き換えクエリを提供しました。新しいクエリは2.3秒で実行——5倍の改善ですが、1秒未満ではありません。さらなる最適化を依頼すると、Mistralはマテリアライズドビューを提案しましたが、生成されたコードにはタイポがありました(CREATE MATERIALIZED VIEW の VIEW キーワードが欠落——CREATE MATERIALIZED と書いていました)。これは基本的な構文エラーです。
ChatGPT はまずテーブルのカーディナリティとインデックス構造を尋ねました(私は提供しました)。次に、ラテラルジョインとフィルタリングされた集計を使用してクエリを書き換え、実行時間を0.8秒に短縮しました。また、最大のテーブルを created_at でパーティショニングすることを提案しましたが、クエリ自体はすでに十分高速でした。出力は構文的に完璧で、SET enable_seqscan = off; ヒントまで含まれていました——ただし、これは真の修正というより応急処置ですが。それでも、機能しました。
勝者:ChatGPT – Mistralの最初のクエリは良好でしたが不完全で、2回目の試行には構文エラーがありました。ChatGPTの一発クエリは目標を達成しました。
ラウンド4:組み込みC(STM32)——I2Cプロトコルのビットバンギング
私は趣味でファームウェアを書いています。両モデルに、STM32F103上でGPIOレジスタのみを使用した(HALなしの)ビットバンギングI2Cマスターの実装を依頼しました。これは、正確なタイミングとレジスタレベルの知識を必要とするニッチなタスクです。
Mistral AI は、for ループ(移植性がありません)に基づく遅延を使用した妥当な実装を生成しました。SCLとSDAラインを正しく設定しましたが、スタート/ストップ条件が逆でした:スタート条件でSDAをSCLより先にLowにしていました(これは誤り——SDAが遷移するときSCLはHighであるべきです)。このコードはバスをロックしていたでしょう。エラーを指摘すると、Mistralは謝罪して修正しました——が、今度は初期化関数でSCLピンのGPIOモードを出力に設定するのを忘れるという新しいバグを導入しました。2回目の修正は機能しましたが、コードは肥大化していました(基本的なI2Cトランザクションに120行)。
ChatGPT の最初の試行はほぼ完璧でした。#define マクロを使用した遅延(CPU周波数依存であることをコメントで明記)、I2Cプロトコルの正しい処理(スタート/ストップ遷移中はSCL High)、クロックストレッチ用のタイムアウトを含んでいました。唯一の問題:ピンのセット/リセットに GPIO_BSRR を使用していました(STM32では正しい)が、F103のレジスタオフセットが誤っていました(リセットレジスタに 0x18 ではなく 0x10 を使用)。修正すると、ChatGPTはエラーを認めて正しいオフセットを提供しました。最終コードは80行でクリーンでした。
勝者:引き分け(わずかにChatGPTに分) – 両方にバグがありましたが、ChatGPTの方が小さく修正が容易でした。Mistralのプロトコルエラーはより根本的でした。
ラウンド5:フルスタックWebアプリの生成(FastAPI + React)
FastAPIバックエンド、SQLiteデータベース、Tailwind CSSを使用したReactフロントエンドを持つシンプルなToDoアプリを依頼しました。これは一般的なタスクですが、各モデルが1つのプロンプトでフルスタックをどのように処理するかを見たかったのです。
Mistral AI はまずバックエンドコードを提供しました:すべてのルート、モデル、データベース設定を含む単一の main.py です。機能はしましたが、関心事が混在していました——ORMクエリがルートハンドラにインラインで記述されていました。Reactフロントエンドは単一の App.jsx で、インラインスタイル(私の要求にもかかわらずTailwindではありません)でした。Tailwindを依頼すると、Tailwindクラスでフロントエンドを再生成しましたが、package.json の依存関係を含めるのを忘れました。バックエンドは動作しましたが、MistralがFastAPIアプリに CORSMiddleware を追加しなかったため、フロントエンドにCORS問題が発生しました。手動で追加する必要がありました。
ChatGPT は出力を3つのファイルに構造化しました:backend/main.py、backend/models.py、frontend/src/App.jsx。デフォルトで CORSMiddleware を含み、リクエスト検証にPydanticモデルを使用し、Reactコンポーネントは useEffect と fetch を正しく使用していました。Tailwindの統合は完璧で、requirements.txt と package.json まで提供しました。唯一の小さな問題:最初のバージョンで fetch の代わりに axios を使用していましたが、fetch を依頼するとすぐに書き換えました。アプリ全体は、pip install と npm install 後に初回実行で動作しました。
勝者:ChatGPT – Mistralの出力は不完全で手動修正が必要でした。ChatGPTの出力は最初から本番対応でした。
長所と短所
Mistral AI
長所:
- トークンあたりのコストが安い(ChatGPTの約半分)。
- オープンウェイトモデルにより、機密コードの自己ホスティングが可能。
- 高レベルのパターン特定に優れている(例:モジュール分割)。
- 複雑な概念の説明が得意(Rustデッドロックなど)。
短所:
- ニッチなAPIやライブラリに対する幻覚発生率が高い。
- 複数ファイル間でコンテキストを失う——各ファイルを独立して扱う。
- 生成コードの構文エラーが一般的(キーワード欠落、誤ったレジスタオフセット)。
- 冗長な出力で、複数回の修正ラウンドが必要になることが多い。
- ファイル間リファクタリングが弱く、不整合を導入する。
ChatGPT
長所:
- 幻覚発生率が低く、コードは通常初回で構文的に正しい。
- 複数ファイルにわたってプロジェクト全体のコンテキストを良好に維持。
- 簡潔で本番対応の出力、必要なイテレーションが少ない。
- アーキテクチャ改善の提案に優れている(例:チャネルベース設計)。
- デフォルトでエッジケース(タイムアウト、CORS、エラーハンドリング)を処理。
短所:
- より高価(トークンあたり2~3倍のコスト)。
- クローズドモデルで、機密コードの自己ホスティングが不可。
- 時々過剰エンジニアリング(例:ミューテックス修正で十分な場合にチャネルベースの書き換え)。
- 人気ライブラリに過度に依存することがある(fetchよりaxios)。
最終判定
コーディングにおいては、私のテストでは ChatGPT(GPT-4o)が明確な勝者 です。5つのタスクすべてにおいて、初回または2回目の試行で正確で本番品質のコードを生成しました。幻覚のデバッグと修正で節約した時間は、高いコストを十分に上回りました。Mistral AIは、予算重視のチームやIP保護のために自己ホスティングが必要な場合の有力な候補ですが、追加のイテレーションサイクルとバグ修正がそのコスト優位性を損なっています。
重要な本番コードを書いているなら、ChatGPTに料金を払ってください。プロトタイピングや、数回の追加デバッグを許容できるオープンソースプロジェクトに取り組んでいるなら、Mistral AIは実行可能な代替手段です——ただし、すべての行を再確認する覚悟はしておいてください。
