CodeContests における Claude 4、OpenAI Codex、Google Gemini 2.5 Pro の比較テスト
Claude 4 Sonnet と Opus を徹底検証
本記事は機械翻訳によるものです。誤訳の可能性があれば、コメント欄でお知らせください。
Created on August 27|Last edited on August 27
Comment
Anthropic の Claude 4 Opus と Claude 4 Sonnet は、コーディングと推論、そして開発者ワークフローへのシームレスな統合に焦点を当てた新世代の大規模言語モデルです。Claude ファミリーの強力な実績を土台に、これらのモデルは OpenAI の codex-mini や Google の Gemini 2.5 Pro といった有力な同世代モデルと並んで登場し、エンジニアやソフトウェアチームにとって不可欠なツールになることを目指しています。
本記事では、実運用に近いコーディング課題を対象に、Claude 4 Opus と Claude 4 Sonnet の性能を検証します。一貫したプログラム評価と実コード実行により、能力と信頼性を測定します。さらに、OpenAI と Google の現行モデルと比較することで、最新の Claude 4 系モデルが現代の開発ニーズにどのように応えるかを、最新かつ明確な観点で示します。特に、コード品質、問題解決力、効率が重要になる場面での実力に焦点を当てます。

目次
目次Claude 4の新機能は?LLMベンチマークは知能の指標になり得るのか?本稿のベンチマーク:CodeContestsコードの正確性という指標実験 1最適な思考トークン数はどれくらいか?実験2:Claude 4 Sonnet 対 Claude 4 Opus 対 Codex 対 Gemini 2.5 ProWeave Comparisons ビュー結論
Claude 4の新機能は?
Claude 4 は、透明性と安全性で定評のある Anthropic の強みを土台に、AI の推論力、コード生成、エージェント型ワークフローで大きく前進しました。Claude 4 ファミリーには、コーディングや高度な課題で新たな最先端となる Claude 4 Opus と、速度・賢さ・精度が大幅に向上した Claude 4 Sonnet が含まれます。
強力な新モデルが2つあります。
- Claude 4 OpusAnthropic 史上最強の AI。難易度の高いコーディングや多段階の推論、大規模なエージェント型ワークフローで卓越した性能を発揮します。従来のベンチマークを上回り、ソフトウェアエンジニアリングと研究においてクラス最高の成果を提供します。
- Claude 4 SonnetSonnet 3.7 から大きく前進し、最上位の推論能力、より的確な指示追従、より強力なコード合成を実現。しかも日常利用に適した、より高速で実用的な応答を提供します。
- ツール使用と拡張思考(ベータ)どちらのモデルも、段階的な推論の一環として外部ツール(電卓、コード実行環境、ウェブ検索、カスタム API など)を利用できるようになりました。途中で一度「考え」を挟み、ツールを呼び出し、その結果を踏まえて回答を組み立て続けます。
- 〜で、インタリーブ思考Claude は、内部思考・ツール呼び出し・最終出力を交互に行うことで、透明性が高く監査可能なワークフローを実現します。
- 並列ツール使用と強化メモリClaude 4 はツールを並列に実行でき、許可されている場合はターンをまたいで重要な事実や文脈を「記憶」できます。ファイルアクセスがあると、Opus 4 は独自のメモリファイルを作成・更新でき、長時間のエージェント実行において文脈保持と一貫性が向上します。
- API の強化: コード実行、柔軟なファイル API、MCP コネクタ、最大1時間のプロンプトキャッシュなどの新機能にアクセスできます。より強力で持続性のある AI ワークフローの構築を支援します。
- 安全性の向上と抜け道の削減: 両モデルは前世代比でショートカットや抜け道的な挙動が65%減少し、エージェントタスクやコード編集の信頼性が向上しました。
LLMベンチマークは知能の指標になり得るのか?
LLM の評価で近年問題になっているのは、モデルが明示的にそのベンチマークで訓練されていないにもかかわらず、テストセットに「過適合」して見えることです。ここで言う過適合は、学習中に見た解答をそのまま暗記する従来の意味ではありません。むしろ、LLM の事前学習のあり方によって大規模に生じるデータリークに近い現象です。
GSM8K、HumanEval、MMLU などの一般的なベンチマークは、何年も前からオンライン上で広く出回っています。GitHub、学術論文、ブログ記事、チュートリアルなどに掲載されているため、LLM が公開インターネットを大規模にクロールしたデータで事前学習されると、これらのベンチマークの一部、あるいは丸ごとに近い形を目にしている可能性が高くなります。つまり、評価時にそのベンチマークを微調整から除外していても、モデルはすでに課題の内容を「知っている」場合があるということです。
これにより、強い汎化ができているかのような錯覚が生まれます。モデルが高得点を取るのは、本当に問題を解けたからではなく、形式を見分けたり、似た言い回しを思い出したり、解答分布を暗記していたりするためです。だからこそ、一部のモデルは特定のベンチマークで訓練されていなくてもテストセットで良い成績を出せます。公開データ上で、きわめて類似(あるいは同一)の問題に十分な回数触れているため、あたかも汎化できているかのように振る舞えるのです。
このため、特に複数のモデルが類似コーパスで学習されている場合、ベンチマークスコアを信用しにくくなります。事前学習と評価の境界はあいまいで、ベンチマークが再利用されるほど価値は目減りします。推論力や汎化に関する重大な主張は、本当に未公開で未見のプライベート評価によって裏付けられない限り、慎重に扱うべきです。したがって、これから実施するベンチマークが真の汎化を反映していると保証はできません。公開ベンチマークは飽和が進んでおり(明示的にそれらで訓練していなくても、事前学習中に目にしている可能性が高いため)です。
とはいえ、ベンチマークには依然として有用性があります。モデル間の比較や経時変化の追跡、特定能力のストレステストにおける共通の参照点を提供してくれます。ただし、絶対的な真実ではなく診断的指標として扱うべきです。ベンチマークで高得点だからといって、そのモデルが課題を理解しているとは限りません。過去に見たものを吐き戻しているだけかもしれません。
本稿のベンチマーク:CodeContests
CodeContests 上で Gemini 2.5 Pro、OpenAI の codex、Claude 4 Sonnet と Opus 4 を実行し、実際の競技問題を最もうまく解けるのはどれかを検証します。これは Codeforces、AtCoder、CodeChef などのプラットフォームから集めた、1万件以上の実在する競技プログラミング問題を収録したコレクションです。各問題には自然言語の説明、複数の公開・非公開テストケース、タグや難易度評価といったメタデータが含まれます。
CodeContests は、多様な問題形式と厳格な評価設定により、コード生成モデルのベンチマークとして広く利用されています。これらの問題は LLM を前提に設計されておらず、明確な推論、正確な実装、そして「もっともらしいコード」ではなくテストケースにおける実際の正しさが求められます。
この比較では、公開テスト分割の一部だけを使用し、各モデルが未見で実在の問題に取り組むようにします。これにより、Gemini 2.5 Pro、OpenAI Codex、Claude 4 Sonnet および Claude 4 Opus が、実際の競技プログラミング課題でどの程度の性能を発揮するかを、透明性が高く現実的に評価できます。
コードの正確性という指標
異なる言語モデル間で公正かつ自動化された評価を実現するため、独自の軽量コード実行フレームワークを作成しました。各競技プログラミング問題について、各モデルには自然言語の問題文のみを提示し、解答として Python 関数を生成するよう促します。さらに、Gemini 2.5 Pro、OpenAI Codex、Claude 4 Sonnet および Claude 4 Opus の呼び出し方法を統一することで、コードの各行や各テストが厳密に比較可能になるよう、条件を揃えています。
本評価環境の重要な特徴は、コード生成だけでなく、例の入力文字列を有効な関数呼び出しに変換したり、実行用にデータを整形したりといった補助タスクにも LLM を用いている点です。これにより、サンプル入力を Python の呼び出しにマッピングするなどの「つなぎ」の作業を、すべての問題・すべてのモデルで一貫して実施できます。
生成したコードを公開テストケースに対して実行したのち、出力を期待解と照合する工程には LLM を用います。これにより、出力チェックの堅牢性が大きく向上します。つまり、書式の細かな違いや軽微な浮動小数点の誤差があっても、通常の文字列比較では見落としがちな、意味的に等価な結果を LLM が判定できるからです。
関数呼び出しと解答の照合を LLM で自動化することで、評価プロセス全体を再現可能かつ一貫したものにし、何よりも「実際の正しさ」——すなわち、各モデルのコードが実世界のテストケースを通過できるか——に焦点を当てています。重視するのは常に、もっともらしく見えるコードではなく、実際の性能です。
実験 1最適な思考トークン数はどれくらいか?
最初の実験の目的は基本的な問いに答えることです。すなわち、コード問題を解かせる際、Claude 4 Sonnet にどれだけの内部推論を求めるべきか。Claude には「思考」プロセスをきめ細かく制御する機能があり、budget_tokens の値を指定することで、最終回答を生成する前に内部推論(いわゆる「思考ブロック」)に費やせるトークンの上限を設定できます。
検証のため、標準設定(明示的な思考なし)から最大 24,000 トークンまで、複数の思考バジェットを試験しました。各設定ごとに、同一の CodeContests の競技プログラミング問題セットで Claude を実行します。フレームワークは各問題の自然言語による説明だけをモデルに渡して解答を生成させ、実際のテストケースでコードを実行して、正答率とレイテンシの両方を計測します。
各設定での結果を記録することで、Claude の「思考バジェット」を増やしたときにコードの正解率と応答時間がどう変化するかを把握できます。内部で考える余地を広げればコードの質は上がるのか、それとも単に遅くなるだけなのか。今回の実験は、このトレードオフを詳細に可視化し、最適な性能を得るために推論の深さを調整できるように設計しています。
評価用のコードは次のとおりです。
import osimport sysimport timeimport subprocessfrom datasets import load_datasetfrom litellm import completion as oai_completionfrom anthropic import Anthropicfrom google import genaiimport weavefrom weave.flow.eval_imperative import EvaluationLoggerfrom google.genai import typesimport reweave.init("codecontests_evalv2")os.environ["OPENAI_API_KEY"] = os.getenv("OPENAI_API_KEY", "your_api_key")OAIKEY = os.environ["OPENAI_API_KEY"] = os.getenv("OPENAI_API_KEY", "your_api_key")CLAUDE_KEY = os.getenv("CLAUDE_API_KEY", "your_api_key")GENAI_KEY = os.getenv("GOOGLE_API_KEY", "your_api_key")from openai import OpenAIclient = OpenAI(api_key=OAIKEY)anthropic_client = Anthropic(api_key=CLAUDE_KEY)gemini_client = genai.Client(api_key=GENAI_KEY)def clean_llm_code_block(text):cleaned_text = text.replace("```python", "").replace("```", "").strip()code_blocks = re.findall(r"(def solve\(.*?)(?=^def |\Z)", cleaned_text, re.DOTALL | re.MULTILINE)source_text = code_blocks[-1] if code_blocks else cleaned_textprompt = ("Given the following response from a language model, extract ONLY the valid Python code for the function. ""Do not include any explanations, text, or formatting fences. Only the code.\n\n"f"Response:\n{source_text}\n\n""Return ONLY the Python code, including any necessary imports:")response = oai_completion(model="openai/gpt-4o-2024-08-06",messages=[{"role": "user", "content": prompt}],temperature=0.0,)gpt4o_code = response["choices"][0]["message"]["content"]gpt4o_code = gpt4o_code.replace("```python", "").replace("```", "").strip()return gpt4o_code@weave.op()def generate_completion(model: str, prompt: str) -> str:# Codex models (openai/codex-*, openai/codex-mini-latest, etc)if model.startswith("openai/codex-"):# Use the .responses.create API as per the latest OpenAI SDKcodex_model = model.replace("openai/", "")# You can optionally add custom instructions (here, we use a neutral persona)response = client.responses.create(model=codex_model,instructions="You are a helpful, accurate Python coding assistant.",input=prompt)return response.output_text.strip()# General OpenAI chat-completionselif model.startswith("openai/"):from litellm import completion as oai_completionresponse = oai_completion(model=model,messages=[{"role": "user", "content": prompt}],reasoning_effort="low",)return response["choices"][0]["message"]["content"].strip()# Anthropic Claude (API unchanged)elif model.startswith("anthropic/"):response = anthropic_client.messages.create(model=model.replace("anthropic/", ""),max_tokens=8000,thinking={"type": "enabled", "budget_tokens": 4000},messages=[{"role": "user", "content": prompt}],)for block in response.content:if block.type == "text":return block.text.strip()return "[No Claude response]"# Gemini (API unchanged)elif model.startswith("gemini/"):result = gemini_client.models.generate_content(model=model.replace("gemini/", ""),config=types.GenerateContentConfig(thinking_config=types.ThinkingConfig(thinking_budget=4000)),contents=[prompt])return result.text.strip() if result.text else "[No Gemini response]"else:raise ValueError(f"Unsupported model: {model}")def ask_llm_for_function_implementation(description: str, model: str) -> str:prompt = (f"Write a Python3 function named `solve` with typed input arguments for this problem -- eg the solve function should take arguments to handle different test cases:\n\n"f"{description.strip()}\n\n""Return only a valid Python function -- no special packages that arent commonly used and NO MAIN function, no if __name__ == __main__....., JUST write the function -- that returns the result. No comments, no explanations."f"HOWEVER, you still need to include necessary imports for libraries"f"IF you do not include the right imports, the code will not be executable, and your response will be judged as incorrect!")return clean_llm_code_block(generate_completion(model, prompt))@weave.opdef ask_llm_for_function_call(code: str, raw_input: str, model: str) -> str:prompt = ("You're given a Python function and a single input string. ""Format it into a valid Python function call using only standard types.\n\n"f"Function:\n{code}\n\n"f"Input:\n{raw_input.strip()}\n\n""Return ONLY a valid function call (e.g., solve(3, 5)) WITH NO 'def' ")response = oai_completion(model="openai/gpt-4o-2024-08-06",messages=[{"role": "user", "content": prompt}],temperature=0.0,)content = response["choices"][0]["message"]["content"]content = content.replace("```python", "").replace("```", "").strip()return contentdef compare_output_with_llm(expected: str, actual: str, model: str) -> bool:prompt = (f"Expected output: {expected.strip()}\n"f"Actual output: {actual.strip()}\n\n""Are these outputs equivalent? Eg ignore minor formatting errors etc, we are just looking for overall correctness in the output Reply YES or NO.")response = oai_completion(model="openai/gpt-4o-2024-08-06",messages=[{"role": "user", "content": prompt}],temperature=0.0,)res = 'YES' in str(response["choices"][0]["message"]["content"]).upper()return resdef run_code_and_call_function(code: str, function_call: str, timeout=10):full_code = code + f"\n\nprint({function_call})"try:start = time.time()result = subprocess.run([sys.executable, "-c", full_code],capture_output=True,text=True,timeout=timeout)latency = time.time() - startreturn result.stdout.strip(), result.stderr.strip(), latencyexcept subprocess.TimeoutExpired:return "", "Execution timed out.", timeoutexcept Exception as e:return "", str(e), 0.0def ask_model_for_pip_command(error_msg):prompt = ("Given this Python error:\n\n"+ error_msg +"\n\nWrite the pip install command needed to fix it. Only return the command, e.g.:\n""pip install requests")return generate_completion("openai/gpt-4o-2024-08-06", prompt)def run_pip_install(pip_command):print(f"Running: {pip_command}")try:result = subprocess.run(pip_command.split(),capture_output=True,text=True,timeout=180)print(result.stdout.strip())if result.stderr:print(result.stderr.strip())except Exception as e:print(f"pip install failed: {e}")def evaluate_model_on_code_contests(model_name: str):print(f"\n\nRunning evaluation for model: {model_name}\n")ds = load_dataset("deepmind/code_contests", split="test", streaming=True)ds = list(ds.take(31))eval_logger = EvaluationLogger(model=model_name.replace("-", "_").replace("/", "_").replace(".", "_"),dataset="code_contests_test")all_latencies = []for i in range(30):row = ds[i]description = row["description"]raw_inputs = row["public_tests"]["input"]expected_outputs = row["public_tests"]["output"]try:code = ask_llm_for_function_implementation(description, model=model_name)print(f"\n=== Task {row['name']} ===", flush=True)all_passed = Truetask_latencies = []results_lst, expected_lst = [], []for j, raw_input in enumerate(raw_inputs):expected = expected_outputs[j] if j < len(expected_outputs) else ""try:function_call = ask_llm_for_function_call(code, raw_input, model=model_name)result, error, latency = run_code_and_call_function(code, function_call)if latency < 99:task_latencies.append(latency)if error:print(f"[{j}] Runtime error: {error}")if "ModuleNotFoundError" in error:pip_cmd = ask_model_for_pip_command(error)run_pip_install(pip_cmd)# Re-run once after pip installresult, error, latency = run_code_and_call_function(code, function_call)task_latencies.append(latency)if error:print(f"[{j}] Retry failed: {error}")all_passed = Falsecontinueelse:all_passed = Falsecontinueis_correct = compare_output_with_llm(expected, result, model="openai/gpt-4o-2024-08-06")results_lst.append(result)expected_lst.append(expected)if not is_correct:all_passed = Falseprint(f"[{j}] input: {raw_input.strip()} → output: {result} | expected: {expected.strip()} | PASS: {is_correct} | latency: {latency:.2f}s")except Exception as inner:print(f"[{j}] Inner error: {repr(inner)}")all_passed = Falsetask_avg_latency = sum(task_latencies) / len(task_latencies) if len(task_latencies) > 0 else 0.0all_latencies.extend(task_latencies)prediction_log = eval_logger.log_prediction(inputs={"description": description},output={'code': code, 'execution_result': results_lst, 'expected_execution_result': expected_lst})prediction_log.log_score("correctness", all_passed)prediction_log.log_score("code_latency", task_avg_latency)prediction_log.finish()except Exception as e:print(f"[{i}] Top-level failure: {repr(e)}")prediction_log = eval_logger.log_prediction(inputs={"description": description},output=str(e))prediction_log.log_score("correctness", False)prediction_log.finish()avg_latency = sum(all_latencies) / len(all_latencies) if all_latencies else 0.0eval_logger.log_summary({"avg_code_latency": avg_latency})print(f"Evaluation complete for {model_name}. View in Weave UI.")# ---- RUN FOR ALL TARGET MODELS ----evaluate_model_on_code_contests("gemini/gemini-2.5-pro-preview-05-06")evaluate_model_on_code_contests("anthropic/claude-sonnet-4-20250514")evaluate_model_on_code_contests("openai/codex-mini-latest")evaluate_model_on_code_contests("anthropic/claude-opus-4-20250514")
この Python スクリプトは、競技プログラミング課題向けに Gemini、Claude、OpenAI の Codex を自動評価する仕組みを構築します。まず、DeepMind Code Contests のデータセットから問題文を取り出し、各 LLM に Python の solve 関数を生成させます。続いて、生成された Python コードを適切にクリーンアップして抽出し、用意されたテストケースに対して実行できるよう必要な関数呼び出しを組み立てます。
このフレームワークは堅牢なエラーハンドリングを備えており、もしそれに遭遇した場合には ModuleNotFoundError 実行時には、足りないパッケージに対して正しい pip install コマンドを GPT-4o に提案させ、実際にインストールを試みてからコードを再実行します。重要なのは、単純な文字��比較ではなく、LLM を用いて実際の出力と期待出力を意味的に比較する点です。これにより、軽微な書式の違いには寛容になり、真の正確性に焦点を当てた評価が可能になります。
結果の可視化には Weave Evaluations を用いて評価指標を記録します。これにより、生のモデル生成コード、テスト入力、出力、エラー、平均レイテンシなどのパフォーマンス指標が保存されます。失敗の精査やモデル間の傾向把握が容易になり、モデルやベンチマークが更新されても、あらゆる結果や不具合の追跡可能性を確保できます。今回は Weave の新しい EvaluationLogger これには、評価を柔軟に計測・計装できる手段が用意されています。さらに、 EvaluationLogger厳密な形式に縛られる必要はありません。データセットを手動でループし、任意の方法でモデルを呼び出し、得られた予測やスコアをその場で記録できます。これにより、既存のパイプラインや独自の評価ループに、すべてを書き換えることなく Weave を容易に組み込めます。
Weave 上での結果は次のとおりです。

内部の「思考」配分がコード生成性能に与える影響を評価するため、30 件のサンプルでテストしました。表示される「Total Tokens」指標には思考トークンがすべて含まれていない点に注意が必要です。Claude 4 は内部思考を要約して返す場合があるためです。興味深いことに、思考バジェットなしの設定は正解率 36.7% を達成し、思考バジェット 1024 トークンの設定(26.7%)を上回りました。しかし、思考バジェットを増やすにつれて性能も向上しました。4000 トークンでは正解率 40.0% に達し、8000 トークンでも同水準を維持。重要なのは、12000 トークンの思考バジェットを与えた設定が正解率 53.3% と最も高く、大幅な改善を示したことです。これは、思考が少なすぎると性能を阻害する場合がある一方で、十分な思考配分は解答品質を大きく押し上げることを示唆しています。
実験2:Claude 4 Sonnet 対 Claude 4 Opus 対 Codex 対 Gemini 2.5 Pro
2 つ目の実験では、CodeContests のテストセットから同一の 30 問の競技プログラミング課題を用い、Claude 4 Sonnet、Claude 4 Opus、OpenAI の新しい Codex モデル、Gemini 2.5 Pro を直接比較しました。各モデルには問題の自然言語による説明のみを与え、解答として自己完結した単一の Python 関数を返すことを求めました。
各サンプル入力ごとに、正しい呼び出しシグネチャを自動生成し、候補コードを隔離環境で実行します。得られた出力は、強力な LLM 駆動の意味同値判定を用いて期待される正解データと照合します。これにより、軽微な書式の食い違いに評価が左右されることなく、実質的な正しさに焦点を当てられます。
これら3つのモデルを厳密に同一の条件下で実行することで、各システムが実世界のコーディング課題にどのように対処するかを明確に把握できます。評価しているのはコードのもっともらしさだけではなく、実際の問題解決力と実装力です。
評価用のコードは次のとおりです。
import osimport sysimport timeimport subprocessfrom datasets import load_datasetfrom litellm import completion as oai_completionfrom anthropic import Anthropicfrom google import genaiimport weavefrom weave.flow.eval_imperative import EvaluationLoggerfrom google.genai import typesimport reweave.init("codecontests_evalv2")os.environ["OPENAI_API_KEY"] = os.getenv("OPENAI_API_KEY", "your_api_key")OAIKEY = os.environ["OPENAI_API_KEY"] = os.getenv("OPENAI_API_KEY", "your_api_key")CLAUDE_KEY = os.getenv("CLAUDE_API_KEY", "your_api_key")GENAI_KEY = os.getenv("GOOGLE_API_KEY", "your_api_key")from openai import OpenAIclient = OpenAI(api_key=OAIKEY)anthropic_client = Anthropic(api_key=CLAUDE_KEY)gemini_client = genai.Client(api_key=GENAI_KEY)def clean_llm_code_block(text):cleaned_text = text.replace("```python", "").replace("```", "").strip()code_blocks = re.findall(r"(def solve\(.*?)(?=^def |\Z)", cleaned_text, re.DOTALL | re.MULTILINE)source_text = code_blocks[-1] if code_blocks else cleaned_textprompt = ("Given the following response from a language model, extract ONLY the valid Python code for the function. ""Do not include any explanations, text, or formatting fences. Only the code.\n\n"f"Response:\n{source_text}\n\n""Return ONLY the Python code, including any necessary imports:")response = oai_completion(model="openai/gpt-4o-2024-08-06",messages=[{"role": "user", "content": prompt}],temperature=0.0,)gpt4o_code = response["choices"][0]["message"]["content"]gpt4o_code = gpt4o_code.replace("```python", "").replace("```", "").strip()return gpt4o_code@weave.op()def generate_completion(model: str, prompt: str, thinking_budget=None, streaming=True) -> str:response_text = ""if model.startswith("anthropic/"):# Calculate correct total max_tokensif thinking_budget and int(thinking_budget) > 0:max_tokens = 8000 + int(thinking_budget)else:max_tokens = 8000create_kwargs = dict(model=model.replace("anthropic/", ""),max_tokens=max_tokens,messages=[{"role": "user", "content": prompt}],)# Only provide thinking if budget is positive and not Noneif thinking_budget and int(thinking_budget) > 0:create_kwargs['thinking'] = {"type": "enabled", "budget_tokens": int(thinking_budget)}client = anthropic_clientif streaming:with client.messages.stream(**create_kwargs) as stream:for event in stream:if event.type == "content_block_start":block_type = event.content_block.typeif block_type == "thinking":print("\n[THINKING]: ", end="", flush=True)elif block_type == "text":print("\n[RESPONSE]: ", end="", flush=True)elif event.type == "content_block_delta":d = event.deltaif getattr(d, "type", None) == "thinking_delta":print(d.thinking, end="", flush=True)elif getattr(d, "type", None) == "text_delta":print(d.text, end="", flush=True)response_text += d.textelif event.type == "content_block_stop":print()else:response = client.messages.create(**create_kwargs)for block in response.content:if block.type == "thinking" and getattr(block, "thinking", "").strip():print("\n[THINKING]:", block.thinking.strip(), flush=True)elif block.type == "text" and getattr(block, "text", "").strip():print("\n[RESPONSE]:", block.text.strip(), flush=True)response_text += block.text.strip()return str(response_text)else:raise ValueError(f"Unsupported model: {model}")def ask_llm_for_function_implementation(description: str, model: str, thinking_budget=None) -> str:prompt = (f"Write a Python3 function named `solve` with typed input arguments for this problem -- eg the solve function should take arguments to handle different test cases:\n\n"f"{description.strip()}\n\n""Return only a valid Python function -- no special packages that arent commonly used and NO MAIN function, no if __name__ == __main__....., JUST write the function -- that returns the result. No comments, no explanations."f"HOWEVER, you still need to include necessary imports for libraries"f"IF you do not include the right imports, the code will not be executable, and your response will be judged as incorrect!")return clean_llm_code_block(generate_completion(model, prompt, thinking_budget=thinking_budget))@weave.opdef ask_llm_for_function_call(code: str, raw_input: str, model: str, thinking_budget=None) -> str:prompt = ("You're given a Python function and a single input string. ""Format it into a valid Python function call using only standard types.\n\n"f"Function:\n{code}\n\n"f"Input:\n{raw_input.strip()}\n\n""Return ONLY a valid function call (e.g., solve(3, 5)) WITH NO 'def' ")response = oai_completion(model="openai/gpt-4o-2024-08-06",messages=[{"role": "user", "content": prompt}],temperature=0.0,)content = response["choices"][0]["message"]["content"]content = content.replace("```python", "").replace("```", "").strip()return contentdef compare_output_with_llm(expected: str, actual: str, model: str) -> bool:prompt = (f"Expected output: {expected.strip()}\n"f"Actual output: {actual.strip()}\n\n""Are these outputs equivalent? Eg ignore minor formatting errors etc, we are just looking for overall correctness in the output Reply YES or NO.")response = oai_completion(model="openai/gpt-4o-2024-08-06",messages=[{"role": "user", "content": prompt}],temperature=0.0,)res = 'YES' in str(response["choices"][0]["message"]["content"]).upper()return resdef run_code_and_call_function(code: str, function_call: str, timeout=10):full_code = code + f"\n\nprint({function_call})"try:start = time.time()result = subprocess.run([sys.executable, "-c", full_code],capture_output=True,text=True,timeout=timeout)latency = time.time() - startreturn result.stdout.strip(), result.stderr.strip(), latencyexcept subprocess.TimeoutExpired:return "", "Execution timed out.", timeoutexcept Exception as e:return "", str(e), 0.0def ask_model_for_pip_command(error_msg):prompt = ("Given this Python error:\n\n"+ error_msg +"\n\nWrite the pip install command needed to fix it. Only return the command, e.g.:\n""pip install requests")# In this context, no "thinking" is likely needed; you could propagate a thinking_budget if you wantreturn generate_completion("anthropic/claude-sonnet-4-20250514", prompt, thinking_budget=None)def run_pip_install(pip_command):print(f"Running: {pip_command}")try:result = subprocess.run(pip_command.split(),capture_output=True,text=True,timeout=180)print(result.stdout.strip())if result.stderr:print(result.stderr.strip())except Exception as e:print(f"pip install failed: {e}")def evaluate_model_on_code_contests(model_name: str, thinking_budget=None):tb_str = "nothinking" if not thinking_budget or int(thinking_budget) == 0 else f"tb{thinking_budget}"print(f"\n\nRunning evaluation for model: {model_name} | thinking_budget={tb_str}\n")ds = load_dataset("deepmind/code_contests", split="test", streaming=True)ds = list(ds.take(31))eval_logger = EvaluationLogger(model=f"{model_name.replace('-', '_').replace('/', '_').replace('.', '_')}_{tb_str}",dataset="code_contests_test")all_latencies = []for i in range(30):row = ds[i]description = row["description"]raw_inputs = row["public_tests"]["input"]expected_outputs = row["public_tests"]["output"]try:code = ask_llm_for_function_implementation(description, model=model_name, thinking_budget=thinking_budget)print(f"\n=== Task {row['name']} ===", flush=True)all_passed = Truetask_latencies = []results_lst, expected_lst = [], []for j, raw_input in enumerate(raw_inputs):expected = expected_outputs[j] if j < len(expected_outputs) else ""try:function_call = ask_llm_for_function_call(code, raw_input, model=model_name, thinking_budget=thinking_budget)result, error, latency = run_code_and_call_function(code, function_call)if latency < 99:task_latencies.append(latency)if error:print(f"[{j}] Runtime error: {error}")if "ModuleNotFoundError" in error:pip_cmd = ask_model_for_pip_command(error)run_pip_install(pip_cmd)# Re-run once after pip installresult, error, latency = run_code_and_call_function(code, function_call)task_latencies.append(latency)if error:print(f"[{j}] Retry failed: {error}")all_passed = Falsecontinueelse:all_passed = Falsecontinueis_correct = compare_output_with_llm(expected, result, model="openai/gpt-4o-2024-08-06")results_lst.append(result)expected_lst.append(expected)if not is_correct:all_passed = Falseprint(f"[{j}] input: {raw_input.strip()} → output: {result} | expected: {expected.strip()} | PASS: {is_correct} | latency: {latency:.2f}s")except Exception as inner:print(f"[{j}] Inner error: {repr(inner)}")all_passed = Falsetask_avg_latency = sum(task_latencies) / len(task_latencies) if len(task_latencies) > 0 else 0.0all_latencies.extend(task_latencies)prediction_log = eval_logger.log_prediction(inputs={"description": description},output={'code': code, 'execution_result': results_lst, 'expected_execution_result': expected_lst})prediction_log.log_score("correctness", all_passed)prediction_log.log_score("code_latency", task_avg_latency)prediction_log.finish()except Exception as e:print(f"[{i}] Top-level failure: {repr(e)}")prediction_log = eval_logger.log_prediction(inputs={"description": description},output=str(e))prediction_log.log_score("correctness", False)prediction_log.finish()avg_latency = sum(all_latencies) / len(all_latencies) if all_latencies else 0.0eval_logger.log_summary({"avg_code_latency": avg_latency})print(f"Evaluation complete for {model_name} (thinking_budget={tb_str}). View in Weave UI.")# ---- RUN FOR CLAUDE/SONNET4 FOR MULTIPLE THINKING BUDGETS INCLUDING "NO THINKING" ----thinking_budgets = [None, 1024, 4000, 8000, 12000 ]for tb in thinking_budgets:evaluate_model_on_code_contests("anthropic/claude-sonnet-4-20250514", thinking_budget=tb)
評価結果は次のとおりです。

Codex は「思考」機能がないにもかかわらず、正解率 63% で他モデルを上回り、最も高いスコアを達成しました。少なくとも公開されているものはなく、モデルの API も effort パラメータを受け付けません。)。Claude 4 Sonnet と Claude 4 Opus の正解率はそれぞれ 43% と 40% でした。Gemini 2.5 Pro は正解率 36% を記録しています。総じて、Claude 4 Sonnet が Claude 4 Opus を上回ったのは興味深い結果でしたが、今回の評価では Claude と Gemini の両モデルに思考トークンを 4000 に制限しているため、より大きな思考バジェットでスケールさせた場合に各モデルがどう変化するかも見てみたいところです。
Weave Comparisons ビュー
Weave の比較ビューは、複数のコーディングモデル間での推論の違いを明確に可視化できる点で特に有用です。各モデルの出力を横並びで表示することで、正解性や論理的一貫性の食い違いを即座に洗い出せます。この直感的なインターフェースによって、あるモデルが失敗し別のモデルが成功する理由をすばやく特定できます。

こうした示唆により、コーディングのパフォーマンスを効果的に分析・最適化しやすくなります。結果だけでなく、その背後にあるコーディングスタイルも可視化することで、Weave の比較ビューは各モデルの推論能力の評価と改善を容易にします。
結論
CodeContests ベンチマークにおける Claude 4 Sonnet、Claude 4 Opus、OpenAI の Codex、Gemini 2.5 Pro の評価は、実世界のコーディング課題への対応能力に関する有用な示唆を与えます。結果として、Codex が最も高い正解率を記録し、他モデルを上回りました。一方で、Claude 系モデルでは思考バジェットの重要性が示され、思考バジェットを 12,000 トークンに増やすと正解率が大きく向上することも明らかになりました。
これらのモデルの比較は、特にコーディングタスクの文脈において、大規模言語モデルの評価がいかに複雑であるかを示しています。カスタムのコード実行フレームワークと、LLM を用いたセマンティック同値性チェックを併用することで、公平で堅牢な評価プロセスを実現できます。結果からは、ベンチマークはモデル間比較に有用である一方で、データリークや過学習の可能性があるため、慎重に扱うべきであることも示唆されます。
総合的に見て、今回の評価は、現在の大規模言語モデルがコーディングタスクで持つ強みと限界の理解に貢献します。各モデルのパフォーマンスを分析することで、開発者は手法を洗練し、モデルの性能最適化と解答品質の向上につなげることができます。
Add a comment
Iterate on AI agents and models faster. Try Weights & Biases today.