Home 論文解説: SWE-RL — オープンソースコード進化データによる強化学習でLLMコーディングエージェントを強化する
投稿
キャンセル

📄 論文解説: SWE-RL — オープンソースコード進化データによる強化学習でLLMコーディングエージェントを強化する

論文概要(Abstract)

本記事は arXiv:2502.18449 SWE-RL の解説記事です。

SWE-RLは、オープンソースソフトウェアのコード変更履歴を活用して、LLMの実世界ソフトウェアエンジニアリング能力を強化学習(RL)で向上させる手法である。著者らは、変更後バージョンのテストスイートをバイナリ報酬の検証器として利用し、Llama 3 70BをGRPO(Group Relative Policy Optimization)でファインチューニングすることで、SWE-bench Verifiedにおいてオープンソースモデル中最高の41.0%を達成したと報告している。

この記事は Zenn記事: Claude API×LangGraphで自律コーディングエージェントを構築する実装ガイド の深掘りです。

情報源

背景と動機(Background & Motivation)

LLMベースのコーディングエージェント(OpenHands、Agentless等)は、GitHubのissue解決において成果を上げている。しかし、これらのエージェントの多くはプロンプトエンジニアリングや教師ありファインチューニング(SFT)に依存しており、数学やコーディング分野で成果を上げている強化学習(RL)ベースの推論を十分に活用できていなかった。

著者らは、RL適用の主な障壁が自動報酬信号の構築の困難さにあると指摘している。実世界のソフトウェアエンジニアリングでは、コード品質の評価が多面的であり、数学問題のように正解・不正解を自動判定することが容易ではない。この課題に対し、OSSプロジェクトのテストスイートを検証器として活用するという洞察が、SWE-RLの核心となっている。

Zenn記事で紹介したLangGraphベースの自律エージェントにおいても、テスト実行結果をフィードバックとした自己修正ループが核心であり、SWE-RLはこのフィードバック機構をRL訓練レベルにまで拡張した研究として位置づけられる。

主要な貢献(Key Contributions)

  • 貢献1: OSSのコード変更履歴(25K件)を用いたRL訓練用報酬信号の自動構築手法を提案。テストスイートをバイナリ検証器として使用する設計は、追加のアノテーションコストなしでスケーラブルな報酬を実現している
  • 貢献2: GRPOアルゴリズムとChain-of-Thought形式の推論ステップを組み合わせたRL訓練フレームワークを構築。LLMがパッチ生成前にコード変更について推論することを許可する設計が性能向上に寄与
  • 貢献3: SWE-bench Verified(41.0%)、SWE-bench Lite(37.0%)、SWE-bench Multilingual(18.7%)でオープンソースモデル中のSOTA(論文報告時点)を達成

技術的詳細(Technical Details)

データ構築: Open Software Evolution

著者らはGitHubのOSSリポジトリから、機械学習・Web開発・データサイエンス・科学計算など多領域にわたる25K件のコード進化タスクを収集している。各タスクは以下の3つ組で構成される:

  1. Issue記述: バグ報告や機能要求のテキスト
  2. コードベース: 変更前のリポジトリスナップショット
  3. テストスイート: 変更後バージョンのテスト群(報酬計算に使用)

報酬関数の設計

SWE-RLの報酬関数はバイナリで定義される:

\[R(a, s) = \begin{cases} 1 & \text{if } \text{TestSuite}(s \oplus a) = \text{PASS} \\ 0 & \text{otherwise} \end{cases}\]

ここで、

  • $s$: 変更前のリポジトリ状態
  • $a$: エージェントが生成したパッチ(コード変更)
  • $s \oplus a$: パッチ適用後のリポジトリ状態
  • $\text{TestSuite}(\cdot)$: 変更後バージョンのテストスイートによる検証

著者らは、この単純なバイナリ報酬が大規模かつ多様なデータセットと組み合わせることで十分に有効であると報告している。

GRPOによる訓練

GRPO(Group Relative Policy Optimization)はPPOの変種であり、グループ相対アドバンテージを使用して訓練の安定性と効率を向上させる。具体的には、同一タスクに対して複数の応答をサンプリングし、グループ内での相対的な報酬差をアドバンテージとして使用する。

\[J_{\text{GRPO}}(\theta) = \mathbb{E}_{s \sim \mathcal{D}} \left[ \mathbb{E}_{a_i \sim \pi_{\theta_{\text{old}}}(\cdot|s)} \left[ \min\left( \frac{\pi_\theta(a_i|s)}{\pi_{\theta_{\text{old}}}(a_i|s)} \hat{A}_i, \text{clip}\left(\frac{\pi_\theta(a_i|s)}{\pi_{\theta_{\text{old}}}(a_i|s)}, 1-\epsilon, 1+\epsilon\right) \hat{A}_i \right) \right] \right]\]

ここで、

  • $\pi_\theta$: 現在の方策
  • $\pi_{\theta_{\text{old}}}$: 前ステップの方策
  • $\hat{A}_i$: グループ相対アドバンテージ(同一タスクからサンプリングされた応答群内での正規化報酬)
  • $\epsilon$: クリッピング係数
  • $\mathcal{D}$: 訓練データセット

PPOとの主な違いは、Critic(価値関数)ネットワークを必要とせず、サンプリングされたグループ内の報酬分布から直接アドバンテージを推定する点にある。これにより、大規模LLMの訓練においてメモリ効率と計算効率が向上する。

推論フォーマット: Chain-of-Thought + パッチ生成

SWE-RLの重要な設計要素は、LLMがパッチ生成前にChain-of-Thought形式の推論ステップを実行する点である。

1
2
3
4
5
6
7
8
9
10
11
12
[推論]: このissueはファイルX.pyのclassYにおけるエッジケース処理の欠落が原因と考えられる。
テストケースから、空リスト入力時にIndexErrorが発生していることがわかる。
修正方針: 関数Zの先頭に空リストチェックを追加する。

[パッチ]:
--- a/X.py
+++ b/X.py
@@ -42,6 +42,8 @@
 def Z(self, items):
+    if not items:
+        return []
     result = items[0]

この推論ステップにより、LLMはコード変更の意図と根拠を明示化してからパッチを生成するため、単純なパッチ生成と比較して成功率が向上する。

実装のポイント(Implementation)

ベースモデルと訓練環境

  • ベースモデル: Llama 3 70B
  • 訓練環境: 64 × A100 GPU
  • データ規模: 25K件のコード進化タスク

訓練の実践的な注意点

著者らの報告に基づく実装上のポイント:

  1. データ品質フィルタリング: テストスイートが不十分なリポジトリ(テストカバレッジが低い、テスト件数が少ない等)は報酬信号のノイズ源となるため除外
  2. 複数ラウンドのRL訓練: 各ラウンドで更新されたモデルから新しいトラジェクトリを生成し、データの多様性を維持
  3. 推論フォーマットの強制: RL訓練中もCoT形式を維持するため、フォーマット報酬(推論→パッチの構造に従っているか)を補助的に使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 訓練パイプラインの概念的な実装
from transformers import AutoModelForCausalLM
from trl import GRPOTrainer, GRPOConfig

config = GRPOConfig(
    model_name="meta-llama/Llama-3-70b",
    num_sample_per_prompt=8,      # グループサイズ
    learning_rate=1e-6,
    clip_range=0.2,
    kl_coeff=0.01,
    max_new_tokens=4096,
)

def reward_fn(prompt: str, response: str) -> float:
    """テストスイートによるバイナリ報酬"""
    patch = extract_patch(response)
    repo = setup_repo(prompt)
    applied = apply_patch(repo, patch)
    if not applied:
        return 0.0
    test_result = run_tests(repo)
    return 1.0 if test_result.all_passed else 0.0

trainer = GRPOTrainer(
    model=model,
    config=config,
    reward_fn=reward_fn,
    train_dataset=swe_dataset,
)
trainer.train()

実験結果(Results)

SWE-benchベンチマーク比較

著者らが報告したSWE-bench各ベンチマークでの結果は以下の通りである(論文Table 1, Table 2より):

ベンチマークLiveCodeBench Pro (SWE-RL)最高オープンソース(従来)最高プロプライエタリ
SWE-bench Verified41.0%38.0%65.4%
SWE-bench Lite37.0%34.2%49.0%
SWE-bench Multilingual18.7%--

分析

  • RL訓練により、SFTのみのモデルと比較してSWE-bench Verifiedで+3.0ポイントの改善を達成(著者らの報告に基づく)
  • バイナリ報酬関数は単純だが、大規模かつ多様なデータセットとの組み合わせで有効に機能
  • 推論ステップ(CoT形式)の導入が、パッチ生成の精度向上に寄与していると著者らは分析

制約と限界

著者らは以下の制約を明記している:

  • バイナリ報酬はコード品質の全側面(可読性、保守性、パフォーマンス等)を捉えていない
  • 最高性能のプロプライエタリモデル(GPT-4系、Claude系)にはVerifiedで24ポイント以上の差がある
  • 訓練に64 × A100 GPUが必要であり、計算資源のコストが高い

実運用への応用(Practical Applications)

Zenn記事で紹介したLangGraph + Claude APIの自律コーディングエージェントとの関連で、SWE-RLの知見は以下の実務応用が考えられる:

  1. テスト駆動フィードバックループの強化: Zenn記事のtestノード→fixノード→generateノードのサイクルは、SWE-RLのテストスイート報酬と同じ設計思想に基づいている。テストの品質がエージェント全体の品質を決定するという知見は両者に共通
  2. 推論ステップの明示化: SWE-RLのCoT→パッチ形式は、Zenn記事のplanノード→generateノードの分離と対応。修正ループ時に「なぜ修正するか」を明示することで再発を防止できる
  3. 報酬設計のシンプルさ: 複雑なスコアリングよりもバイナリ(テスト通過/不通過)が実用的。本番エージェントでも同様に、テスト結果をベースとした判定が最も信頼性が高い

関連研究(Related Work)

  • Agentless (Xia et al., 2024): エージェントループなしの2段階手法(局所化→修正)。SWE-RLはこのシンプルな設計をRLで強化するアプローチと位置づけられる
  • SWE-Fixer (Xie et al., 2025): オープンソースLLMのSFTによるissue解決。SWE-RLはSFTの先にRLを適用することで追加の性能向上を実現
  • Agent-R (Yuan et al., 2025): MCTSベースの自己反省訓練。外部フィードバック不要という点でSWE-RLと共通するが、報酬源が異なる(MCTS探索 vs テストスイート)

まとめと今後の展望

SWE-RLは、OSSのコード変更履歴という豊富なデータソースをRL訓練に活用し、コーディングエージェントの推論能力を向上させる手法である。テストスイートを検証器としたバイナリ報酬設計のシンプルさと有効性は、実務でのエージェント設計においても参考になる。

今後の研究方向として、著者らはコード品質の多面的評価(可読性、保守性等)を報酬に組み込むこと、多言語対応の拡張、および計算コストの削減を挙げている。

参考文献

この投稿は CC BY 4.0 でライセンスされています。

論文解説: From Local to Global — GraphRAGによるクエリ指向要約の知識グラフアプローチ

論文解説: LightRAG — グラフ×ベクトルのデュアルレベル検索で軽量かつ高精度なRAGを実現