こんにちは。 ABEJAでデータサイエンティストをしている服部です。
LLMの進化は速いですね。 Reasoning能力があることは勿論Agenticな動きをすることも最近求められており、LLM開発においてもPost Trainingの重要性は高まっています。
本記事では、Agenticな能力の向上に向けた Post Training、特にSFTと強化学習で実施したこと、およびその過程で得られた知見をまとめました。 SFTでの精度劣化回避や、Tool-Useを用いたAgenticな強化学習タスクの紹介、強化学習におけるハマりどころなど多岐に渡って詰め込んでいます。 興味ある部分だけでも読んでもらえると幸いです。
弊社は、経済産業省とNEDOが実施する、国内の生成AIの開発力強化を目的としたプロジェクト「GENIAC(Generative AI Accelerator Challenge)」の1期、2期に続き、3期にも採択され、そこで大規模言語モデルの開発を行っています。 3期ではエージェントとして用いるための基盤モデルを開発しており、特にロングコンテキスト処理性能と Planning / Tool Use などの Agentic な能力の向上に重点を置いて開発を進めております。
最終モデル全体の評価は継続中ですが、本記事では学習過程及びその中で得られた知見に絞って紹介します。

既にロングコンテキスト周りはいくつかブログ記事が出ておりますのでこちらも興味ある方いましたらご覧ください。
- 今回強化したAgentic能力
- 検索強化とOpenSearch採用
- 学習全体の流れ
- SFT: 繰り返し思考・ツール実行の流れを学習させる
- 強化学習: Agentic能力の向上
- 実装・学習で直面した課題と対策
- 強化学習で問題が起きたときの切り分け
- まとめ
- We are hiring!!
今回強化したAgentic能力
Agenticで調べると、自律的に計画を立てて状況判断しツールの実行などを駆使してタスクを遂行する的な意味がでてきますが、開発においては曖昧な部分があるので、ここでの意味を先に説明します。
Agenticと呼べる上で一つ重要なのが、 最初に考えてツールを実行した後にその結果を経て再度思考し改めてツールを実行する...この繰り返しが出来ることだと考えています。 この繰り返しができることで、一つの大きいタスクを分解して逐次進めることが出来たり、得られた結果を元に計画の修正や深掘りなどを出来ることに繋がります。 最近ではgpt-ossやKimi-K2.5、GLM4.7等この繰り返しが出来るモデルも徐々に出てきていますが、ツールの実行結果を一度得たらそのままユーザに回答することを前提としているモデルがまだ多いです。 Qwen3もモデルの全体性能としては高いものの、ツールの実行に関しては繰り返す前提にはなっていません。
そこでQwen3に対しても繰り返し思考・ツール実行が出来るようにして、Agentic能力を強化していきます。
実際の生成の流れは、以下のイメージです。

- step1として、Systemとuserのmessageに対してReasoning1とツールの呼び出しTool Call1を出力
- Tool Call1の実行結果Tool result1が得られて、それをinputに加えて、step2としてその続きをモデルが出力 (Reasoning2の後Answerではなく、再度Tool Call2としてツールを呼び出し)
- Tool Call2の実行結果Tool result2が得られて、それをinputに....
これをstep3, step4, ....と進めていきTool Call N-1の実行結果Tool result N-1をinputに加えて、ReasoningN+Answerとして最終的なユーザへの回答を生成しています。
この繰り返しをタスクに応じて自然と行えるということは、Reasoning部分すなわち思考する際には、計画通り次のステップに進んだり、うまく行かない場合は計画を修正したり、完了したと思ったらそこで回答する判断をするなど自律的に行えている状態を意味します。
また外部の強制的なワークフローなどに当てはめれば繰り返すことも可能ですが、それ無しでモデル自身が柔軟に行える状態を目指します。
検索強化とOpenSearch採用
Agenticにツールを実行するといってもコーディング向けのものやDeepResearchのような検索系など様々な用途があります。 今回は、ローカルにある社内ドキュメントの探索・調査を行いながらタスクを遂行するエージェントを想定して、その中でもとくに検索系ツールの強化をしています。
そして学習時の検索ツールとしてはOpenSearchを採用しています。
OpenSearchは、Elasticsearchからフォークしたオープンソースの高速・高機能な検索・分析エンジンです。
OpenSearchを採用した理由としては、
- 検索品質の改善を、インデックスやルール側だけでなく、モデル自身によるクエリ生成の改善にも寄せやすい
- 実運用の際でもシステムとして安定して採用しやすい
といった点です。 1点目については、例えば検索で欲しいドキュメントが他の似たものに埋もれて拾えないときに、モデル側の判断でbool queryなどを使ってほしい情報を絞って取りに行くといった、モデル側の検索の仕方次第で結果の改善も期待できることを意味します。
もちろんこれ以外の検索ツールでもクエリ生成含め検索は可能なので扱えます。
学習全体の流れ
まず全体のフローで行くと、以下のような流れです。 最初に継続事前学習、ロングコンテキスト能力を強化するSFTの実施、ChatVector適用をした後、SFT及び強化学習を実施しています。 Chat Vectorというのは、オリジナルのQwen3のベースモデルとPost-Training後のモデルの重みの差分ベクトルのことで、これを足すことで指示追従能力を得られるというものです。

SFTを実施した後に3種類の強化学習タスクを実施して、最後にそれらをModel Soup、すなわちモデルを混ぜ合わせています。 このSFT及び強化学習について以降説明します。
SFT: 繰り返し思考・ツール実行の流れを学習させる
まずSFT (Supervised Fine-Tuning) では、モデルにToolの実行結果のあとすぐ回答するのではなく、再び思考する・Toolを実行するという流れ自体を覚えさせる必要があります。
SFTでは指示(Input)と教師となる出力(Output)が必要です。
学習方法などは一般的な手順なのでSFTはデータセットにのみ触れます。 データセットの構築手順は以下のとおりです。
SFTデータセット(Input)
指示については、繰り返しの検索が必要になるマルチホップQAデータセットをWikipediaの情報を元に構築しました。 マルチホップQAとは、複数の情報源や知識を統合し、多段階の推論が必要となるQAです。
例えば、「富士山が世界文化遺産に登録された年に日本の内閣総理大臣は誰でしたか?」という質問です。 これに答えるには、富士山が世界文化遺産に登録された年を確認した上で、その年の内閣総理大臣を調べるという複数ステップが必要になります。
SFTデータセット(Output)
モデルが学習する、指示に対しての回答部分です。 今回はオープンモデル(gpt-oss-120b)の出力を元にして教師出力を用意しました。 gpt-oss-120bに実際に検索しながら回答をしてもらえるように、OpenSearchでWikipediaのページを検索できるツールを用意し、このツールを用いて推論させました。
この推論の結果には、
- gpt-oss-120bのReasoning
- gpt-oss-120bのTool Call
- 検索ツールのTool実行結果
- gpt-oss-120bの最終回答
が含まれています。
SFTでモデルが学ぶべき文章はReasoning, Tool Call, 最終回答の3つであり、Tool実行結果自体は教師として予測させたい対象ではないため、損失計算の対象から除外します(実装上は該当トークンの loss mask を 0 に設定)。

Input含めた図はこのようなイメージです。
出力の修正
元のgpt-oss-120bの出力でもAgenticな挙動はしてくれるものの、
- 正解にたどり着かないことがある
- 思考部分が基本的に英語である
- 過程が単調になりやすく、計画変更や探索の分岐が十分に表れないケースが多い
といった形でそのまま使うと明らかに学習対象の品質に課題が残ります。 そこで、以下のような手順で出力を改善させました。
- MultihopQAをgpt-oss-120bがWikipedia検索ツールと共に推論した出力を用意
- 実際に正答できたデータに絞る
- Reasoning部分をLLMで日本語に和訳する
- Reasoning部分を自然でより、洗練されたものにする
- シナリオパターンに従ってReasoning部分をアレンジする
各ステップではgpt-oss-120bやQwen3-235B-A22B-2507などのモデルを使って処理をしています。 また、2や3はそれぞれの中でも複数回に分けて処理をしたり、実際にはより細分化されます。
4のシナリオパターンというのは、計画通りに検索結果が得られなかった時に方向性を修正するシナリオやOpenSearchのクエリを工夫するシナリオ等、様々なシナリオを用意しておき、ランダムに選ばれたシナリオに従うようにReasoning部分をLLMに修正させるということを行いました。 これは、後続の強化学習に関わるところで、SFTの時点である程度出力の幅を持たせたほうが強化学習の探索幅が自然と広がって、学習が進みやすくなるため実施しています。
上記の過程を踏まえることで、元のgpt-oss-120bの出力よりも品質の高い教師となる出力を得ることができました。
その他SFTデータ
上記の検索ツールを用いたReasoning部分とTool Callの過程が今回学習させたいことである一方で、繰り返した思考やツールを使わない回答もしたいケースもあるため、一般的なSFTも混ぜて学習させました。
思考含めたReasoning用データセットとして、ABEJA-QwQ32b-Reasoning-Japanese-v1.0 を構築したときのSFTデータを改善したものや、Nemotron-Science-v1などを候補として混ぜていきました。
強化学習: Agentic能力の向上
SFTで基本的な流れを覚えたうえで実際に強化学習の中でタスクを解きながら、Agentic能力の向上を目指します。
強化学習の基本的な考え方は、最近の多くのReasoningモデルが導入しているRLVR (Reinforcement Learning with Verifiable Rewards) をベースとします。
RLVRは日本語にすると 検証可能な報酬による強化学習 で、正解と一致しているかで報酬を決められるようなタスクによる強化学習を指します。
そして学習アルゴリズムとしては、DeepSeek-R1で有名になったGRPO(Group Relative Policy Optimization)のような手法を用います。
Reasoning能力獲得の際の強化学習としては、正解が決まっている数学のタスクを解くのが最も有名です。 GRPOでの数学タスクにおけるRLVRとしては、
- 同一プロンプトに対してG個のサンプルを生成(rollout)を1グループとして生成する
- 各出力に対して、最終回答の正誤やフォーマット遵守などで検証可能な報酬を付与する
- グループ内の報酬の平均・標準偏差を使ってアドバンテージを計算する
- アドバンテージが正の出力の生成確率を上げ、負の出力の確率を下げる方向にポリシーを更新する
のような方法をとります。
今回はこれのTool Useを利用かつ検索寄りのタスクを解きながら学習します。 タスクが変わってもほとんどの流れとしては同じですが、違いとして
- Rolloutでのサンプル生成は、1回の生成で終わらず、生成→Tool実行→続きを生成→....を繰り返すことで出来る
- 報酬をTool Callが出来たことやタスクの種類に応じてアレンジする
といった形です。
Tool-Star*1 や ARTIST *2 などの論文でもこうした方法で学習しています。
強化学習で用意した3つのタスク
強化学習としては以下3種類のタスクを用意しました。
a. Wikipediaを用いたマルチホップQA
b. Wikipediaを用いたDeepResearch
c. e-Gov法令データを用いたQA
それぞれ詳細を説明しますが、簡単に言うと、
| タスク | 説明 |
|---|---|
| a. Wikipediaを用いたマルチホップQA | Wikipediaの検索ツールを用いたSFTと同じマルチホップQA。正解がある。 |
| b. Wikipediaを用いたDeepResearch | aと同じWikipediaの検索ツールだが、調査タスクで最終出力はレポート。単一の正解文字列は定義しにくい。 |
| c. e-Gov法令データを用いたQA | e-Govの法令データの検索ツールを用いて、法令データに関しての選択式の設問を解く。正解がある。 |
といった形です。
特定のタスクや検索対象データだけに絞ると、その内容に特化しすぎてしまうことを考え、対象データやタスクに少し幅を持たせるために複数データ・複数タスク用意しました。
a. Wikipediaを用いたマルチホップQA
SFTのパートでも述べた多段的な過程を経ることで正解にたどり着けるマルチホップQAをタスクとしました。
正解にたどり着くためには複数の手がかりとなる情報を順次検索して取得して行く必要があります。 QA構築の段階で出来るだけ表記ゆれや正解に曖昧さが残らないようにしながら、正解自体は特定の単語としました。 数学における正解の数字・数式がこのタスクでは該当の単語ということになります。
LLMには最終回答を{{}}で囲むように指示して、その囲まれた単語と正解の単語が一致しているかどうか判定しています。
データセットの構築
そもそも日本語のマルチホップQAとしては、JEMHopQA *3 が有名なものとしてあります。 JEMHopQAは、様々なベンチマークで用いられているデータであること、構築過程の中でGPT-3.5やGPT-4などのLLMを用いており規約上学習に使えないことなどを踏まえ、ゼロから構築することとしました。
構築にあたってJEMHopQAの論文を参考にさせていただきつつ、期間的にもクラウドソーシングは難しかったため、全てオープンなLLMを用いて以下の手順で作りました。
- Wikipedia から (主語, 関係, 目的語) の Triple を抽出し、1つ目の目的語が2つ目の主語になる 2-Hop の Triple ペアを作成する。
- このペアをもとにマルチホップ質問を生成し、LLM による多段階の品質評価と修正を行ったうえで、最後に 実際に解ける問題だけを残す。
- 例
- Triple1 (ノルウェイの森, 著者, 村上春樹)、Triple2 (村上春樹, 出身地, 京都府)
- →『ノルウェイの森』の作者の出身地はどこか?
- 構築フロー
- Wikipedia 記事から Triple を抽出し、関係タイプを判定して 1:1 / N:1 のみ保持
- Triple 同士を接続して 2-Hop の Triple ペアを作成
- ペアをもとに マルチホップ質問を生成
- LLM による 品質評価・曖昧さ修正・再評価 を実施
- 最後に、実際にモデルへ Wikipedia ツールを使わせて複数回解かせ、安定して解ける問題のみ採用
報酬設計
報酬としては
- Tool Callをエラーなく実施できていること(実行回数によって報酬を加算するが上限を設定)
- Reasoning/Tool Call/最終回答などのフォーマットが正しいこと
- 最終的な回答が正解と一致していること
といったものを用意しました。 Weightとしては、最終的な回答が正解と一致しているかどうかが最も高くなっています。
b. Wikipediaを用いたDeepResearch
同じWikipediaを検索対象のドキュメントとしつつ、広く・深く調査をしてレポートにまとめさせるタスクです。
例えば以下のような指示を与えます。
日本各地の祭りを複数取り上げ、それぞれの歴史的背景や地域文化との関わりを比較し、祭りが地域の経済・観光に与える影響を分析しなさい。
こうした指示を元に、Wikipediaの様々なページを検索して、最終的にレポートとしてまとめ上げるというタスクです。
データセットの構築
DeepResearchの場合、"〇〇について調べてください"といった指示データセットを用意する必要があります。
Wikipediaをベースにして調査が可能なもの、かつ1ページでは完結しないような指示を用意すべきと考え、以下の手順で構築しました。
- Wikipediaの多くの記事から記事を特徴づけるキーワードを抽出
- マイナーなもの・高頻度すぎるものを除き、キーワードをベースにレポート作成の指示をLLMに作らせる
- 1つのページで完結しないように、複数の記事の情報を使うことで成立するように指示
- 作成時にLLMがWiki検索ツールを使って、実際に存在する記事を確認させながら作らせる
- 品質フィルタリング
- 追加のQA作成(半数)
- 追加の質問作成
- 追加の回答作成
- 追加QAの品質フィルタリング
追加のQA作成というのは、ChatGPTのDeepResearchのように、一度の指示だけで調査開始するのではなく、先に質問をして意図を明確にしてから調査するというケースも調査タスクでは重要だと考え、そういったケースにも正しくタスク遂行できるように入れてみました。
報酬設計
まず下記2つはMultiHopQAと同じようなものとして用意しています。
- Tool Callをエラーなく実施できていること(実行回数によって報酬を加算するが上限を設定)
- Reasoning/Tool Call/最終回答などのフォーマットが正しいこと
しかしレポートでは正解の定義が難しいため、LLMによるRubric評価を用いることにしました。 Rubric評価とは、複数の評価観点と段階的な基準(尺度)を元にした評価でLLM as a judgeなどでも使われるものです。
各調査指示ごとにそのタスクに応じたRubric評価基準を事前にLLMで用意しておき、Rolloutでサンプルを生成した際にそれをRubric評価し、その点数を報酬にしました。
当初は、すべての指示で共通的なRubric評価(N件以上の情報を参考にしているか等)を作っていたのですが、どうしても共通化することで曖昧になったり、それをクリアしたからと言って良い調査結果とは言いづらい・報酬ハックしやすいようなものになる傾向があり、学習も安定しませんでした。
そこで、指示毎に良い応答であればこういう調査もしている、この点にも言及しているはずだという個別具体の観点で作ったほうが報酬自体が調査の質にもひも付きやすく、Rubric評価自体もしやすくなると考え、この方法を採用しました。
例えば
子会社に関する制度を、一般子会社、連結子会社、特例子会社の3種類について、それぞれの定義・適用基準・主な目的を整理し、相互の違いを比較しなさい。
このような指示だった場合、
・「定義」「適用基準」「主な目的」「会計処理」の4項目が、3種類すべてについて揃って提示されているか ・回答が会社法第2章に基づき、一般子会社・連結子会社・特例子会社の各定義を正確に記述しているか ・比較結果が見やすい表形式で整理され、項目ごとに列が揃っているか
のようなRubricが作られ、これに基づいて実際の出力に対して評価を行います。
c. e-Gov法令データを用いたQA
Wikipediaとは違うデータセットのタスクとして、e-Govの法令データを用いたQAでの学習も行いました。 e-Govとは、デジタル庁が提供する日本の法令情報を一元的に公開しているポータルサイトです。 e-Govの法令データに関しては、XMLでダウンロードすることが可能です。
データセットの構築
以下の流れで構築をしました。
- e-Govの法令データを条単位でparseする
- 条単位の文章から、LLMにて4択のQAを作成
- QAの品質スコアリングをLLMにて行い、スコアでフィルタリング
xmlからのparseに関しては、ja-law-parserというライブラリを利用させていただきました。
QA作成に関してですが、問題文や選択肢に、法律名や条番号・項番号(例: 「第○条」、「第○項」、「第○条第○項」等)が入ると、簡単に検索・回答が出来てしまうので、これらを含めないようにQA作成及びフィルタリングを行いました。
報酬設計
ここの報酬は、a. Wikipediaを用いたマルチホップQAと同じTool Call, フォーマット系, 正答報酬に加えて、中国語混ざりの報酬も追加しています。
- Tool Callをエラーなく実施できていること(実行回数によって報酬を加算するが上限を設定)
- Reasoning/Tool Call/最終回答などのフォーマットが正しいこと
- 最終的な回答が正解と一致していること
- Reasoningに中国語が混ざっていないこと(混ざっていた場合は報酬をマイナス)
中国語混ざりについて、他のタスクではほぼ発生しなかったのですが、このタスクの出力では報酬がある程度伸びてここから更に伸びるかどうか?というタイミングから発生していることが分かりました。
恐らくですが、e-Gov法令データには古い法律で文語体と呼ばれる漢文ベースのものが含まれます。 例えば、「公正証書ナルトキハ其日付ヲ以テ確定日付トス」というようなものです。 検索結果を経てこの文語体がモデルの入力に入ると、中国語を想起しやすくなったのではないかと考えられます。
そこで、e-Govの学習では、途中からこの中国語混ざりを抑えるために報酬を導入しました。
言語混ざりの判定については以前に書いたこちらのブログでの判定ロジックを元にしました。
実装・学習で直面した課題と対策
SFTでの精度劣化
前章での記載の通り、SFTをして繰り返し思考・ツール利用する流れを覚えさせた後に強化学習をするのですが、このSFTをすることでモデルの性能が大きく劣化してしまうという課題が発生していました。
MT-Bench-Japaneseにおいて、SFT前が10点満点で9以上あったものが、8点台前半から7点台くらいまで落ちていました。
今回は汎用言語性能自体を高めることが目的ではないとはいえ、思考の基本となる汎用性能が大きく性能劣化するというのは解きたいタスク自体へも悪影響がでますし、利用用途が限定的になるため避けたいところです。
最初は学習率やスケジューラの調整、破壊的忘却を防ぐための英語データの比率調整などをしていたのですが、多少の変化しかありませんでした。
恐らく以下の2点での変更で、元モデルの出力分布から大きく変更させる学習のため破壊的忘却が発生したのではと考えています。
- 本来なら回答に向かうところを再度ツールを使う方向に変えようとしている
- Reasoningが英語中心だったところを、日本語に変えようとしている
2点目に関しては Qwen3-Swallow や GPT-OSS-Swallow 、Nemotron 2 Nano 9b Japanese などでもReasoning部分は元モデルの英語を採用しており、追加学習によるReasoning部分の日本語化自体にまだハードルがあることが想像できます。
我々もReasoning部分を必ずしも日本語にする必要はなかったのですが、モデルの解きたいAgenticなタスクの性質上、Reasoning部分・タスクの実行過程が日本語になることは、モデル開発時及び運用時にタスクの課題発見や改善、説明性にもプラスになるため、出来れば入れ込みたい要因でした。
そこで最終的には、システムプロンプトによる切り替えで既存モデル性能との両立を達成しました。
具体的には、SFTの際に
- 既存出力に近い英語Reasoningのデータセット + システムプロンプト無し
- 今回学習したい日本語ReasoningのAgenticなデータセット + システムプロンプトあり
の2つを同時に学習させました。
このシステムプロンプトは、「思考とツール利用を繰り返しながら回答にたどり着いてください」「日本語で思考してください」といった今回モデルに求めているものを言語化したものです。 この2つを同時に学習することで、
- 何もシステムプロンプトがないときの出力過程を維持して既存のモデル出力が破壊されないようにする
- システムプロンプトが与えられた場合には求められた出力を出すようにする
といった2つを両立させることに成功しました。
システムプロンプトが与えられることでそれをシグナルとして別の出力過程を出せるような回路作りを学習する(かつ既存の出力経路も残しておく)というイメージです。
この方法を採用した結果SFT直後のモデルで、SFTをして繰り返し日本語での思考・ツール利用することを覚えつつも、MT-Bench-Japaneseで9点以上の元モデルと同水準を維持することが出来ました。
モデルを特定用途に特化させたいが、既存の性能も失いたくない場合に汎用的に使えるアプローチかもしれません。
強化学習の不安定さ
これは従来の機械学習の時から変わらずなのですが、強化学習は教師あり学習よりも不安定です。
強化学習の場合、1step毎に得られる報酬が増えているかが主要なメトリクスで、ウォッチすべきところなのですが、簡単に増え続けてくれるわけではありません。

この図は横軸がstep数、縦軸が報酬で、最初は順調に増えているのですが、急に報酬がいきなり落ち始めてそのままモデルが崩壊したときのものです。
このようなケースが何度も発生しました。
学習の安定化に効くハイパーパラメータ
学習が崩壊せず安定して続くような対策としては学習時のハイパーパラメータの調整が一つとしてあげられます。 以下は今回の検証の中で有効性が感じられたパラメータたちです。 パラメータ名としてはNeMo-RL内のものをベースとしてますが、他のライブラリでも基本的には同様かと思います。
- 一般的な学習パラメータ
- learning_rate
- adam_eps
- Policyの乖離
- policy_kl_penalty
- ratio_clip_min, max
- GRPO系のGroup関連
- num_prompts_per_step
- num_generations_per_prompt
一般的な学習パラメータの部分は強化学習に限らず知られているところなので割愛します。
Policyとの乖離部分は、policy_kl_penalty は、現在の policy が参照 policy から過度に逸脱しないようにするための KL ペナルティ係数です。ここでの参照 policy は実装や設定に依存しますが、多くの場合は学習開始時の基準モデルや固定参照モデルが用いられます。 ratio_clip_min, max は、現在のPolicyと直前のPolicyの確率比 πθ(a|s) / πθ_old(a|s) のクリッピング範囲を意味し、1ステップの更新量を制限します。 実際にこれらの値を抑えることで、学習の失敗を防げたこともありました。
GRPO系のGroup関連は、学習効率にも影響します。num_prompts_per_step は、1ステップあたりに使用するプロンプト数を意味し、num_generations_per_prompt は、1つのプロンプトに対して1グループとして生成するサンプル数を意味します。すなわち、num_prompts_per_step × num_generations_per_prompt がbatch sizeといえます。 この2つのパラメータをある程度大きくすることは学習の安定に寄与すると考えられます。 num_prompts_per_stepが小さいとstepごとに使うプロンプトに偏りが発生しやすくなりますし、num_generations_per_promptが小さいと学習で使うグループ内での報酬の相対的な値のバラツキが大きくなってしまいます。 一方でこれら2つを大きくすると、1stepの学習にかかる時間も長くなっていくので、ある程度安定して学習できる中で抑えめにするくらいの感覚がよいのかもしれません。 (このあたりは実際に試しながら感覚を掴むほうが良い気がします)
ちなみに今回の学習ではだいたい以下の値を使いました。
- learning_rate: 1e-7 ~ 5e-7 - adam_eps: 1e-8 - policy_kl_penalty: 0.05 - ratio_clip_min, max: 0.1 / 0.1 - num_prompts_per_step: 16 - num_generations_per_prompt: 32
GRPO vs GSPO
DeepSeek-R1以降、GRPO(Group Relative Policy Optimization)が一気に有名になりました。 しかし、GRPOが出て以降も強化学習のアルゴリズムとしてはどんどん新しいものが増えています。
有名どころでいうと、DAPOやGSPOといったところです。
その中で今回はGRPOとGSPOを比較検証し、最終的にGSPOを採用しました。
GSPOは、Group Sequence Policy Optimizationの略で、GRPO ではトークン単位の比が長い系列で不安定化しうるのに対し、GSPO は系列単位の扱いを導入することで、その不安定さを緩和する方向の手法です。 この論文自体Qwen開発チームから出たもので、Qwen3にも採用されています。
GSPOを試した理由としては、
- GRPOを試している時に学習が不安定で失敗するケースが何度かあって、もっと安定させたかった
- 実際Qwen3で採用されている方法であり、信頼できそう
- NeMo-RL上で簡単に試せる
といったところです。
同じく有名なDAPOも試したかったのですが、DAPOはtoken単位の最適化でGRPOより効率化させる方針で、どちらかというとtoken単位の最適化を効率化させるよりも学習の安定性(崩壊させないこと)が優先度が高かったため、限られた時間の中ではGSPOを試すことにしました。
ちなみに、GSPOのあとで同じくQwenチームからSAPO(Soft Adaptive Policy Optimization)がでており、こちらはGRPOとGSPOのいいとこ取りを狙ったような手法でこれも試したかったのですが、時間の都合上見送りとしました。
以下はGRPOとGSPOの学習過程を比較した図です。 横軸がstep数で縦軸が各stepにおける平均報酬です。

GSPOのほうは効果が見えた途中で打ち切っているのですが、GSPOのほうが全体的に報酬及び伸びがあることがわかります。
この実験以外でもGRPOでは学習が途中で失敗したケースでも問題なく学習が出来ているケースも観測しています。
私はどちらかというと学習手法より、データ・タスク周りの改善に時間を使う派ではあるのですが、まだまだLLMの強化学習周りは発展途上で手法による性能差も出うるフェーズなのかなと感じました。
ツール設計と運用想定
今回強化学習をするにあたって、ツール自体の設計にかなり悩みました。
今回OpenSearchを使いましたが、OpenSearchを使う場合でもデフォルト何件取得するのか、1件あたり文字数はどれくらいにするのか、文字数超えた場合はどういう処理をするのか等の設計が必要です。
最終的な運用時に比べると自由に決めれるのですが、学習時のこの設計はモデルが得意とするツールの使い方にも影響を与えます。
例えば、コンテキスト長を贅沢に使って大量の文章を取得していくのか、コンテキスト長を気にしながらちょっとずつ情報を取得して進めるかなど、ツール自体の設計の仕方によって変わってきます。
完全に特定のケースだけであれば、そのユースケースに沿ったツールにすればいいのですが、今回は検索のできるエージェントとしてある程度の柔軟さ・汎用性を持たせたかったので、実利用ケースを見据えつつある程度汎用的なツール設計を想定しながら決めていきました。
このあたりの学習は、事前学習やSFTなどに比べて、特化モデルへの適用など運用に近い側面を持ったフェーズであると感じられました。
Tool DescriptionのAugmentationによる頑健化
強化学習を試していく過程の中で、学習前のモデルのtool useがtoolのdescriptionに敏感であることが分かりました。 Toolの説明文が長くなりすぎるとTool Call時にjsonのformat errorが発生しやすくなったり、descriptionよりもSFTしたときのtool名を優先して出力するなどが起こりました。
そこで、descriptionに対しての頑健性を強化したく、tool descriptionとして複数パターンを用意して、そこからランダムに選択するようにしました。 Data augmentationの一種のようなイメージです。
スケジュール的にdescription側のパターンを増やすのみでしたが、本来的にはtool側も複数のIF定義を設けといて、descriptionによって受け付ける形式を変えるようにすれば、もっとdescriptionの頑健性が増すようにも思えます。 もちろん強化学習のタスク・ツール側を多様にしていくことも出来るなら望ましいですが、用意できるツールやタスクにも限りがでてくるとも思えるので、その場合にはこういった方法も有効かなと思います。
報酬ハックとログ・可視化
Wandbのログを見ると報酬が少しずつ増えて学習が順調に進んでいると思っていたら、実際にはタスクの正答率が増えずにツールをひたすら呼び出しまくっているということが初期の頃に発生しました。 これは元といえば、Tool呼び出しで得られる報酬に回数制限を設けていた部分の実装にバグがあり、想定以上にTool呼び出しで報酬が得られる状態になっているのが原因だったのですが、しばらく学習がうまくいったものだと思って過ごしていました。
こういった本来獲得してほしいものと違う形でモデルが報酬を稼ぐ方法を見つけてその方向だけが過剰に最適化されるのを報酬ハックと言ったりします。
こうした報酬ハックが起きないようにするには報酬設計と実装を気をつけるしかないとは思うのですが、同時に報酬ハックが発生した時にすぐ気付けるようにしておくのも大事だと思います。
具体的には、
- 報酬は分解して、それぞれごとにWandbなどの実験管理ツールで見れるようにしておく
- step毎で実際の学習時のサンプル出力を保存しておいて、見れるようにしておく
- 定期的にこれらをウォッチする
といったことが大切になるかと思います。
報酬全体ではあがっているけど一部の報酬しか上がっていないケースは報酬を分解することで気付けますし、toolをやたら呼び出しているようなものも実サンプル出力を見ると気づけます。
またこうした報酬やサンプルの確認は報酬ハック以外の面でも大事です。例えば、e-Gov法令データでのQAタスク部分に記載した中国語混ざりの問題は、まさに当初想定していなかったものでサンプル出力を見て気づけて報酬を修正して対処したというものでした。
他にも色んなケースがあると思いますが、強化学習では報酬が上がること自体が目標としている状態に向かっているとは限らないケースも多いのでこうした状態のウォッチは重要だと思います。
強化学習で問題が起きたときの切り分け
今回LLMでの強化学習による能力向上を試す中で様々な課題が発生しましたが、強化学習周りでの主な課題は大きくは以下のパターンに分類できると感じました。
1. 学習をしてもそもそも報酬が上がらない
報酬が全く得られていない場合、モデルの探索範囲や報酬設計自体に問題がある可能性がありそうで、以下の観点で原因を切り分けてもよいかと思いました。
- グループ内の報酬分布を確認し、Rollout内での出力サンプルによっては報酬を得られているか(モデルの探索対象内にうまくいくケースがあるか)
- 報酬が得られたサンプルの出力確率にPolicyモデルを寄せることで改善できそうな気配はあるか
- 報酬を得るのが難しすぎる or 簡単過ぎて、改善されていないことはないか
2. 学習が安定せず、途中で報酬が得られずモデルが崩壊する
一時的に報酬が上がっても学習が発散・崩壊してしまうケースです。ハイパーパラメータを見つつ、データやモデル周りなど広く切り分けが必要だと思いました。
- ポリシーモデルとの乖離によるペナルティやClip、学習率などモデル崩壊防止と関連するパラメータを調整したか
- 別のモデルだとうまくいくか
- データセットの順番(shuffleのseed)を変えても、同じstep数らへんで崩壊するか
- 学習アルゴリズムを変えるとどうなるか(GRPO, GSPO, DAPO, ...)
3. 報酬は上がっていくが、求めている能力自体が得られているわけではない
報酬が上がっていても、それが本当に目的の能力向上に対応しているかは別問題です。報酬ハックや指標と能力のズレが起きていないかの確認も重要です。
- そもそも気付けないと問題なので、まずそれを確認する
- 報酬が上がる前後の実サンプルを比較して、定性的に改善傾向が見えるか
- 性能を測定したいベンチマークにおいても改善しているか
- 分解した報酬のうち一部しか上がっていない等求めている報酬改善以外の変化をしていないか?(報酬ハックが起きていないのか?)
- 報酬が上がる前後の実サンプルを比較して、報酬が上がったことによって出力はどこが変化したか?(思考の質?出力長?フォーマット遵守?)
- 求めている能力の向上に本当に繋がる報酬が設定されているのか?
4. 報酬は上がって能力も得られているが目標の報酬・性能に到達しない
方向性は正しいが性能の伸びが頭打ちになっているケースです。モデルの能力上限・データ・設定など複数の要因が絡んでいるため難しいところです。
- 対象の元モデルの性能的に、そこまで伸ばすことが実際可能なのか(判断難しい)
- データセットの質・バリエーション・数は十分か
- 報酬の定義や環境・ツール側の設定などで問題点はないか?
- 実サンプルを確認して、理想の出力と現状の出力の違いは何処なのか
- その理想の出力はSFTのときにも近しいものはあったか?
- 理想の出力をしたら報酬はあがりそうか?
- 十分な数のstep数をやっても改善しなかったのか?途中で上がらないと諦めていないか?
- 各種パラメータは適切か。学習の安定性を重視した結果、性能改善を打ち止めにしてないか?
まとめ
Agenticな能力をあげるための強化学習の取り組みについて、実施内容から過程で発生したこと、実施する中で感じたことなどをまとめてみました。
強化学習は以前から面白いと思っていましたが、LLMに適用することで生まれる新しい面白さ・難しさ・可能性を今回感じることが出来ました。
そして、今後試していく方がいましたら、参考になれば幸いです。
本成果は、経済産業省とNEDOが実施するGENIACでのモデル開発によって得られたものです。
We are hiring!!
ABEJAは、テクノロジーの社会実装に取り組んでいます。 技術はもちろん、技術をどのようにして社会やビジネスに組み込んでいくかを考えるのが好きな方は、下記採用ページからエントリーください! (新卒の方やインターンシップのエントリーもお待ちしております!)
*1:https://arxiv.org/abs/2505.16410
*2:https://arxiv.org/abs/2505.01441
*3:Ai Ishii, Naoya Inoue, Hisami Suzuki, and Satoshi Sekine. 2024. JEMHopQA: Dataset for Japanese Explainable Multi-Hop Question Answering. In Proceedings of the 2024 Joint International Conference on Computational Linguistics, Language Resources and Evaluation (LREC-COLING 2024), pages 9515–9525, Torino, Italia. ELRA and ICCL.