AIエージェントを用いた一人称視点シューティングゲームの逆コンパイル

エグゼクティブサマリー

自律型AIエージェントは複雑なソフトウェアを逆コンパイルすることに成功していますが、客観的かつ機械的に検証可能な合格基準がなければ、読みやすくても意味的に誤った「ハルシネーション(幻覚)」コードを生成してしまいます。ゲームの逆コンパイルにおいて忠実性を確保する最も効果的な方法はバイト一致逆コンパイルです。これは、再構築されたC++コードをコンパイルし、元のバイナリとバイト単位で比較する手法です。このアプローチにより、バイナリのPASS/FAIL信号を提供することで、能力の低いモデルであっても高忠実度の結果を得ることが可能になります。

オーケストレーションフレームワーク

ゲームの機能を完全に再現するために、ClaudeとCodexモデルを組み合わせたマルチエージェントシステムが導入されました。インフラストラクチャは自律性と進捗管理に重点を置いています。

  • エージェントの役割: システムは逆コンパイルとコミットを行うワーカーエージェントと、調整およびバグのフラグ立てを行うレビュアーエージェントで構成されました。
  • 進捗管理: GitHub Issuesを主要な追跡メカニズムとして使用し、翻訳単位(.cppファイル)ごとに1つのIssueを割り当てました。
  • コミュニケーション: エージェントは共有のDiscordチャンネルを通じて通信し、エージェント間および人間とエージェント間の対話を可能にしました。CIの失敗はGitHubのWebhookを通じてこのチャンネルにプッシュされました。
  • ツール: エージェントは、ヘッドレスで安定した逆アセンブルと逆コンパイルのために、Hex-Raysの公式 ida-mcp を利用しました。

エージェントのドリフトとハルシネーションの克服

自律的な逆コンパイルの初期の試みでは、特にコンテキストウィンドウが埋まるにつれて、エージェントが集中力を失い、時間の経過とともに「ドリフト(逸脱)」する傾向があることが明らかになりました。整合性を維持するために、チームは2つの重要な戦略を実装しました。

  1. 積極的なコンテキスト圧縮: デフォルトの圧縮しきい値を90%から42%に引き下げました。これにより、以前に逆コンパイルされた関数などの揮発性で無関係な情報が、より頻繁にコンテキストから削除されます。
  2. 指示のリフレッシュ: 1時間ごとのcronジョブにより、プロジェクトの目標と運用ガイドラインを再読み込みするようエージェントに自動的に要求し、時間の経過に伴う指示の劣化を防ぎました。

人間のようなレビューの失敗

ゲームが起動しメニューが表示されるようになったにもかかわらず、初期の出力には意味的な欠陥がありました。エージェントは誤った関数シグネチャを導入したり、ロジックを捏造したり、効率的なグローバル変数アクセスをコストの高いハッシュテーブル検索に置き換えたりしました。

この失敗は、レビュアーエージェントに客観的な合格基準が欠けていたために発生しました。レビュアーは、コードを元のバイナリと照らし合わせて独自に検証するのではなく、コミットコメントにおけるワーカーエージェントの正当化をそのまま受け入れることが多く、本質的に意図しないプロンプトインジェクションの一形態となっていました。

バイト一致逆コンパイルの実装

正確性の問題を解決するために、チームは「信頼できる情報源(グラウンドトゥルース)」のオラクルとして機能する検証スクリプトを実装しました。

  • プロセス: スクリプトは、元のゲームのコンパイラを使用して再構築されたC++コードをコンパイルします。その後、生成されたOBJファイルを元のゲームのEXE/PDBと比較します。
  • 再配置の処理: 絶対メモリアドレスは変化するため、スクリプトは再配置バイトを除外し、代わりに両方のバージョンが同じオフセットで同じシンボルを参照していることを検証します。
  • セキュリティ対策: エージェントが「不正行為」(インラインアセンブリの使用や検証スクリプトの改ざんなど)を行うのを防ぐため、システムは特定の構成を禁止し、CI内で検証スクリプトをハッシュ化して改ざんされていないことを確認します。

結果とトレードオフ

プロジェクト終了時までに、ゲームの関数の99%が再構築されたソース内に存在し、そのうち83%がバイト単位で完全に一致しました。最終段階では、14個のLunaモデルと2個のOpus 5.5モデルが使用されました。

利点

  • 保証された意味論: バイト単位の一致は、元のバグを含め、同一の動作を保証します。
  • モデルの効率性: 正確なフィードバックにより、LunaやHaikuのような安価で能力の低いモデルでも、より高性能なモデルに匹敵する結果を生み出すことができます。

欠点

  • 労力の増大: エージェントはレジスタの選択や呼び出し規約に苦労するため、関数を完全に一致させるには大幅に時間がかかります。
  • 収穫逓減: コンパイラの非決定的な出力やリンカーの動作(COMDATフォールディングなど)により、バイト一致が不可能な関数も存在します。

コミュニティの視点と代替案

技術的な専門家たちの間では、バイト一致のような厳格さを伴わずに機能的同等性を達成するための代替手法について議論されています。

「私にとってうまくいっているのは、すべての関数に対して...ハーネスが元の関数と提出された関数の両方を仮想マシン/シミュレータ/エミュレータで実行することです... ハーネスは、1) RAMへの読み書きシーケンスが元の関数と同一であり、かつ 2) 逆コンパイル対象の元の関数の完全な行および分岐カバレッジが存在する場合にのみ、その実装を受け入れます。」 — @handle

他の批評家は、このプロジェクトの環境的および経済的コストの高さ(6000億〜7000億トークンが消費されたと推定)を指摘し、商標や著作権の制限により法的に共有できないプロジェクトの有用性に疑問を呈しました。

Sources

関連