{
  "format": "writing-sources-v1",
  "article": "ppo-long-horizon",
  "files": {
    "en.html": "<section aria-labelledby=\"overview\"><h2 id=\"overview\">1 The complete training loop</h2><p>A coding agent reads files, calls tools, and edits code. Its actions and the tool responses form a <strong>trajectory</strong>. PPO uses the outcome of that execution to adjust the probabilities of actions generated along the way.</p><p>In <strong>reinforcement learning from human feedback (RLHF)</strong> with a reward model, the <strong>Actor generates actions, the RM scores the completed attempt, the Critic predicts future return from the current context, and the Reference supplies a fixed policy baseline</strong>. Rewards and value predictions enter advantage estimation, producing the targets used to train Actor and Critic. A—D in the overview correspond to the four modules below.</p><!-- FIGURE:training-overview --></section>\n<section aria-labelledby=\"reward-model\">\n<h2 id=\"reward-model\">2 A · Prepare the policy and reward model</h2><p>Training usually starts with an existing language model and <strong>supervised fine-tuning (SFT)</strong>: successful demonstrations teach it to produce appropriate actions in context. PPO then lets the policy network, the <strong>Actor</strong>, try new executions and learn from their outcomes. <a href=\"https://arxiv.org/html/2203.02155v1#S3.SS1\">[1]</a></p><p>After SFT, keep two copies of the policy: one becomes the Actor and continues learning; the other is frozen as the Reference. The Reference computes probabilities for generated tokens, helping constrain how far the Actor moves from its initial policy.</p><p>Our running example repairs an amount-summing script: add the strings <code>\"0.10\"</code> and <code>\"0.20\"</code> exactly and print <code>0.30</code>. The trajectory and scores are constructed for illustration.</p>\n<p>First, prepare two complete executions. A uses Decimal and passes the tests; B retains the floating-point output. An annotator selects A, providing the label <strong>“A is preferred to B.”</strong> To train a <strong>reward model (RM)</strong>, feed “task + execution A” and “task + execution B” separately into the same model, obtaining scores <var>r<sub>A</sub></var> and <var>r<sub>B</sub></var>.</p>\n<!-- FIGURE:reward-value-training --><div aria-label=\"Reward-model preference loss\" class=\"formula-scroll\" role=\"region\" tabindex=\"0\"><math display=\"block\" xmlns=\"http://www.w3.org/1998/Math/MathML\"><msub><mi>L</mi><mtext>RM</mtext></msub><mo>=</mo><mo>−</mo><mi>log</mi><mo>⁡</mo><mi>σ</mi><mo>(</mo><msub><mi>r</mi><mi>A</mi></msub><mo>−</mo><msub><mi>r</mi><mi>B</mi></msub><mo>)</mo></math></div>\n<p>The sigmoid function <var>σ</var> converts the score difference into a preference probability. Minimizing this loss encourages a higher relative score for A. Many such pairs teach the RM to evaluate new executions. Annotators supply the ordering; the RM learns its scoring scale. The RM commonly consists of a language-model backbone and a scalar head that outputs one score. <a href=\"https://arxiv.org/html/2203.02155v1#S3.SS5\">[1]</a></p>\n</section>\n<section aria-labelledby=\"rollout\">\n<h2 id=\"rollout\">3 B · Let the Actor make an attempt</h2><p>The input uses JSONL, one JSON object per line. The original script converts amounts to <code>float</code>, producing <code>0.30000000000000004</code>. The Actor needs to find the problem, parse amount strings with <code>Decimal</code>, and format the result to two decimal places.</p>\n<p>We use four roles in this reinforcement learning from human feedback (<strong>RLHF</strong>) setup. A <strong>rollout</strong> is an attempt made by the current Actor in its environment. It generates tokens—the encoded units of text—to form tool calls and a final response. File contents and test logs returned by the environment become context for subsequent generation.</p><!-- FIGURE:trajectory-models -->\n<p>The Actor generates actions. The RM reads the task and completed record to provide a final score. At each generation position, the Critic reads the prefix available at that moment and predicts the return ahead. A fixed <strong>Reference model</strong> computes the probability of the generated token in the same context, providing a reference for how far the policy has moved from its starting point.</p>\n<p>In this example, “tests passed” is a tool observation; the RM supplies the final reward. With a reliable automated verifier, its result can instead define the reward directly and replace the RM.</p>\n<p>A training <strong>mask</strong> identifies positions generated by the Actor. File contents and test logs remain in the input to inform its decisions; the policy loss applies only to generated tokens. The Critic's predictions can be computed in a batch after collection, with each prediction still restricted to its corresponding prefix.</p>\n</section>\n<section aria-labelledby=\"advantages\"><h2 id=\"advantages\">4 C · How the Critic learns from outcomes</h2><p><strong>The value network, or Critic, predicts the average future return when the current Actor continues from a given context.</strong> Suppose four outcomes for the same task are equally likely and receive scores of 2, 4, 6, and 8 from a fixed RM. Their mean is 5. The Critic learns that expectation from observed outcomes. These numbers use an illustrative scale.</p><p>A <strong>return</strong> accumulates rewards from a particular position onward. To train the Critic, finish an attempt and pair earlier history prefixes with their return targets. <strong>Generalized Advantage Estimation (GAE)</strong> constructs these targets from rewards and value predictions; the diagram traces that data flow.</p><!-- FIGURE:critic-training --><p>A Critic also commonly uses a language-model backbone with a scalar head. InstructGPT initialized its value function from the RM, then trained it on trajectory returns. It reused the initial parameters; subsequent supervision came from the return targets associated with each prefix. <a href=\"https://arxiv.org/html/2203.02155v1#S3.SS5\">[1]</a></p><p>The Critic pairs each prefix with its return target. A prediction of 5 against a target of 8 gives a squared error of 9. Backpropagation and an optimizer adjust its trainable parameters to reduce that error. Full fine-tuning updates both the backbone and the scalar head. Targets are fixed for this update, and this loss does not update the RM.</p><div aria-label=\"Value regression\" class=\"equation\" role=\"math\">L<sub>V</sub> = mean [V<sub>φ</sub>(h<sub>t</sub>) − Ĝ<sub>t</sub>]<sup>2</sup></div><p><var>φ</var> denotes the Critic's parameters. With repeated outcomes, regression learns an average return. Its context-dependent baseline helps reduce sampling noise in the policy gradient. Returns alone can also train a policy; a suitable value prediction makes updates from limited samples more stable. <a href=\"https://spinningup.openai.com/en/latest/spinningup/rl_intro3.html#baselines-in-policy-gradients\">[3]</a></p><p>The RM learns a scoring criterion from preferences; the Critic learns an expectation from returns. During PPO, the RM is usually fixed while the Critic continues learning. As the Actor produces high-scoring executions more often, the Critic's prediction should rise even though the scoring criterion stays the same.</p><p>A common RLHF-PPO setup combines the final RM score with a reference penalty. At generation position <var>t</var>, a commonly used sampled form is:</p><div aria-label=\"Reward at a generation position\" class=\"equation\" role=\"math\">r<sub>t</sub> = −β [log π<sub>old</sub>(a<sub>t</sub> | h<sub>t</sub>) − log π<sub>ref</sub>(a<sub>t</sub> | h<sub>t</sub>)] + 𝟙<sub>t=T</sub> R</div><p>Here <var>h<sub>t</sub></var> is the prefix, <var>a<sub>t</sub></var> the generated token, and <var>T</var> the final generation position. <var>R</var> is added only at the end; <var>β</var> sets the strength of the reference penalty. The expected log-probability difference over the action distribution is a KL divergence. <a href=\"https://arxiv.org/html/2203.02155v1#S3.SS5\">[1]</a></p><p><strong>Generalized Advantage Estimation (GAE)</strong> combines rewards and value predictions, working backward to estimate an advantage at each generation position:</p><div aria-label=\"GAE recursion\" class=\"equation\" role=\"math\">δ<sub>t</sub> = r<sub>t</sub> + γ(1 − d<sub>t</sub>)V<sub>t+1</sub> − V<sub>t</sub><br/>A<sub>t</sub> = δ<sub>t</sub> + γλ(1 − d<sub>t</sub>)A<sub>t+1</sub><br/>Ĝ<sub>t</sub> = A<sub>t</sub> + V<sub>t</sub></div><p><var>δ</var> is the one-step prediction error. <var>γ</var> discounts future rewards, and <var>λ</var> controls how much later advantage estimates contribute. <var>d=1</var> marks genuine task termination. <var>Ĝ</var> is the Critic's return target. Here <var>t</var> indexes generation decisions; tool observations enter the next decision's context. <a href=\"https://arxiv.org/abs/1506.02438\">[2]</a></p><p>Take the example's final score <strong>R=8</strong>, with β=0, γ=λ=1, and a reward only at genuine termination. A starting prediction of V=5 gives an advantage of <strong>+3</strong>. At a later position after the repair, a prediction of V=7 gives <strong>+1</strong>. Both return targets are 8; their differences from the local expectations are different.</p></section>\n<section aria-labelledby=\"optimization\">\n<h2 id=\"optimization\">5 D · How the Actor updates probabilities</h2>\n<p>The Actor uses advantages to adjust the probabilities of sampled actions. Call the policy that collected this batch <var>π<sub>old</sub></var>, and the policy being updated <var>π<sub>θ</sub></var>:</p>\n<!-- FIGURE:ppo-update --><div aria-label=\"PPO clipped objective\" class=\"equation\" role=\"math\">ρ<sub>t</sub> = π<sub>θ</sub>(a<sub>t</sub> | h<sub>t</sub>) / π<sub>old</sub>(a<sub>t</sub> | h<sub>t</sub>)<br/>L<sub>π</sub> = −mean min [ρ<sub>t</sub>A<sub>t</sub>, clip(ρ<sub>t</sub>, 1 − ε, 1 + ε)A<sub>t</sub>]</div>\n<p>A positive advantage encourages a higher probability; a negative advantage points in the opposite direction. <var>clip</var> bounds the probability ratio inside the objective, limiting the incentive to push an update further. The full batch also influences the actual parameter update. <a href=\"https://spinningup.openai.com/en/latest/algorithms/ppo.html\">[4]</a></p>\n<p><strong>The old policy and the Reference serve different purposes.</strong> The old policy anchors this batch's update and changes with later batches. The Reference usually stays fixed at the SFT starting point. Old log probabilities can be saved with trajectories, without keeping a fifth model resident in memory.</p>\n</section>\n<section aria-labelledby=\"long-horizon\">\n<h2 id=\"long-horizon\">6 What long trajectories make difficult</h2>\n<p>A successful execution can contain investigation, useful edits, and unnecessary actions. Advantage estimation passes terminal feedback back through those positions, but the feedback remains noisy. Errors in value predictions also enter the advantages. As the Actor changes, the Critic needs to keep up.</p>\n<p>Tool logs add another concern: trajectory length. An implementation must specify which positions participate in advantage recursion and how often discounting applies. Masking the logs out of the policy loss does not establish those rules. Computational chunks must carry the next value and advantage across their boundaries; genuine termination and truncation require different treatment.</p>\n<p>The scoring criterion must track the intended outcome. An RM that favors polished completion claims may reward an execution that never fixes the program. Tests, preference data, and held-out evaluations should cover the actual deliverable. Large policy updates can also make collected trajectories stale, while an excessive KL penalty limits exploration. Learning rates, clipping, scoring quality, and sampling cost need to be considered together. <a href=\"https://arxiv.org/abs/2210.10760\">[5]</a></p>\n</section>\n<section aria-labelledby=\"alternatives\">\n<h2 id=\"alternatives\">7 What GRPO and DPO change</h2>\n<p><strong>GRPO</strong> generates a group of answers for each task and uses the group's mean and standard deviation to compute relative advantages, removing the Critic. The original method retains an RM and a reference model; verifiable rewards can also replace the RM. Multiple executions per task cost more to sample, and equal scores throughout a group provide no relative reward differences. <a href=\"https://arxiv.org/html/2402.03300v3#S4.SS1\">[6]</a></p>\n<p><strong>Standard offline DPO</strong> trains directly on existing “A is preferred to B” data. It retains an Actor and a reference model while removing the separate RM, Critic, and online sampling-and-scoring loop. It rewrites KL-regularized reward optimization as an objective over policy probabilities: reward can be expressed using a policy-to-reference log-probability ratio, and the shared normalization term cancels when comparing two answers to the same prompt. Preference-data quality and coverage become central. <a href=\"https://arxiv.org/html/2305.18290v3#S4\">[7]</a></p>\n<p>For coding tasks, the choice also depends on execution cost, the reliability of automated verification, and the availability of paired preferences. <a href=\"/writing/terminal-rsi/?lang=en\">Terminal-RSI</a> uses verifier rewards with PPO and studies long-trajectory advantage estimation and Critic handoff. It has no separate preference RM.</p>\n</section>\n\n",
    "figures/build_figures.py": "from pathlib import Path\nimport runpy\nrunpy.run_path(str(Path(__file__).with_name('build_workflows.py')), run_name='__main__')\n",
    "figures/build_workflows.py": "\"\"\"Deterministic PPO workflow figures. See ../WORKFLOW-EVIDENCE.md.\"\"\"\nfrom pathlib import Path\nimport html,json,math,re\nfrom bs4 import BeautifulSoup\nROOT=Path(__file__).resolve().parent\nLANGS=('zh','en','ja')\nWORDS={}\ndef tr(key,zh,en,ja): WORDS[key]=dict(zip(LANGS,(zh,en,ja)))\n\ntr('overview-title','训练全流程','The complete training loop','学習の全体像')\ntr('overview-caption','图 1 · A 准备模型，B 收集轨迹，C 计算奖励与优势，D 更新 Actor 与 Critic。RM 与 Reference 在 PPO 中固定。节点可跳转至对应章节。','Figure 1 · A prepares models; B collects trajectories; C computes rewards and advantages; D updates Actor and Critic. RM and Reference stay fixed during PPO. Nodes link to the corresponding sections.','図 1 · A はモデル準備、B は軌跡収集、C は報酬とアドバンテージ計算、D は Actor と Critic の更新。PPO 中の RM と Reference は固定。各ノードから対応する節へ移動できる。')\ntr('prep','A · 学习开始前','A · Before PPO','A · PPO の前')\ntr('demos','操作示范','Examples','操作の実演')\ntr('sft','监督微调 SFT','Supervised fine-tuning','教師あり学習 SFT')\ntr('copies','Actor + Reference','Actor + Reference','Actor + Reference')\ntr('copies-sub','同一初始策略的两份参数','Two copies of the initial policy','同じ初期方策の二つのコピー')\ntr('prefs','成对偏好','Preference pairs','選好ペア')\ntr('rm-training','训练 RM','Train RM','RM を学習')\ntr('collect','B · 执行任务','B · Collect trajectories','B · タスクを実行')\ntr('targets','C · 奖励与优势','C · Rewards and advantages','C · 報酬とアドバンテージ')\ntr('update','D · 参数更新','D · Parameter updates','D · パラメータを更新')\ntr('actor-sub','当前策略 πold','Current policy πold','現在の方策 πold')\ntr('env','工具环境','Tool environment','ツール環境')\ntr('env-sub','文件 · Shell · 测试','Files · shell · tests','ファイル・Shell・テスト')\ntr('trajectory','轨迹记录','Trajectory record','軌跡の記録')\ntr('trajectory-sub','任务 + 动作 + 观察','Task + actions + observations','タスク＋行動＋観測')\ntr('fixed','固定参数','Fixed weights','重みを固定')\ntr('prefix-value','读取每个历史前缀','Reads each history prefix','各時点までの履歴を読む')\ntr('rewards','构造奖励 rt','Construct rewards rt','報酬 rt を作る')\ntr('reward-sub','终点得分 + KL 约束','Terminal score + KL penalty','終点スコア＋KL 制約')\ntr('gae-sub','按位置回传反馈','Propagate feedback backward','各位置へ評価を遡らせる')\ntr('actor-update','更新 Actor','Update Actor','Actor を更新')\ntr('actor-update-sub','PPO 裁剪目标','Clipped PPO objective','PPO のクリップ目的関数')\ntr('critic-update','更新 Critic','Update Critic','Critic を更新')\ntr('critic-update-sub','拟合回报目标 Ĝt','Fit return targets Ĝt','リターン目標 Ĝt に回帰')\ntr('command','工具调用','Tool calls','ツール呼び出し')\ntr('observation','工具返回','Observations','ツールの返り値')\ntr('complete','完整执行','Complete execution','完了した実行')\ntr('prefix-action','前缀 + token','Prefix + token','接頭辞＋token')\ntr('prefix','前缀 ht','Prefix ht','接頭辞 ht')\ntr('score','得分 R','Score R','スコア R')\ntr('ref-probs','参考概率','Reference probabilities','参照確率')\ntr('values','价值 Vt','Values Vt','価値 Vt')\ntr('advantage','优势 At','Advantages At','アドバンテージ At')\ntr('return-target','回报目标 Ĝt','Return targets Ĝt','リターン目標 Ĝt')\ntr('next-actor','新 Actor 继续采样','Updated Actor collects the next batch','更新した Actor で次のバッチを収集')\ntr('new-critic','更新后的价值预测','Updated value predictions','更新後の価値予測')\ntr('sample-data','已采样 token 与旧概率','Sampled tokens + old probabilities','採用済み token と旧確率')\ntr('old-probs','保存的 log πold','Saved log πold','保存した log πold')\ntr('rm-title','A · 奖励模型怎样学会评分','A · How the reward model learns','A · 報酬モデルはどう学ぶか')\ntr('rm-caption','图 2 · 两条完整执行分别经过同一个 RM。偏好标签监督分数的相对顺序，损失反向传播到 RM。训练完成后，RM 在 PPO 中固定。','Figure 2 · Two complete attempts pass through the same RM. Preference labels supervise score ordering; gradients update the RM. The trained RM stays fixed during PPO.','図 2 · 二つの完了済み実行を同一の RM で採点する。選好ラベルでスコアの順序を学び、損失を RM に逆伝播する。学習後は PPO 中に固定する。')\ntr('attempt-a','任务 + 完整执行 A','Task + complete attempt A','課題＋完了済み実行 A')\ntr('attempt-a-sub','Decimal 求和 → 输出 0.30','Decimal sum → output 0.30','Decimal で加算 → 0.30')\ntr('attempt-b','任务 + 完整执行 B','Task + complete attempt B','課題＋完了済み実行 B')\ntr('attempt-b-sub','float 求和 → 保留误差','float sum → rounding error','float で加算 → 誤差が残る')\ntr('shared-rm','同一个 RM','One shared RM','同一の RM')\ntr('model-head','语言模型 + 标量头','Language model + scalar head','言語モデル＋スカラーヘッド')\ntr('pair-scores','两次前向计算','Two forward passes','二回の順伝播')\ntr('human-label','偏好标签：A 优于 B','Preference label: A over B','選好ラベル：A が B より良い')\ntr('pair-loss','偏好损失','Preference loss','選好損失')\ntr('rm-gradient','反向传播 · 更新 RM 参数','Backpropagation · update RM weights','逆伝播で RM の重みを更新')\ntr('trace-title','B · Actor 与工具如何完成一次修复','B · One repair, through Actor and tools','B · Actor とツールによる一回の修正')\ntr('trace-caption','图 3 · 金额汇总教学案例。工具返回加入历史，Actor 据此生成下一步调用。执行完成后，整条记录交给 RM 评分。','Figure 3 · An illustrative repair. Tool responses join the history used for the next call. The RM scores the completed record.','図 3 · 金額集計を修正する学習用の例。ツールの返り値を履歴に加え、次の呼び出しを生成する。実行完了後に全記録を RM で採点する。')\ntr('task','任务：把 \"0.10\" 与 \"0.20\" 相加，输出 0.30','Task: sum \"0.10\" and \"0.20\", then print 0.30','課題：\"0.10\" と \"0.20\" を加算し、0.30 を出力')\ntr('reads-script','读取脚本','Read the script','スクリプトを読む')\ntr('float-source','读取到 float 求和代码','Find a float-based sum','float による加算を確認')\ntr('run-test','运行测试','Run the test','テストを実行')\ntr('fail','测试失败','Test fails','テスト失敗')\ntr('patch','写入修复','Apply the patch','修正を適用')\ntr('patched','文件已更新','File updated','ファイルを更新')\ntr('retest','再次测试','Test again','再テスト')\ntr('passed','测试通过','Test passes','テスト成功')\ntr('submit','提交修复与测试结果','Submit the fix and test result','修正とテスト結果を提出')\ntr('rm-end','RM 读取完整执行，给分 R = 8','RM reads the completed attempt: R = 8','RM が完了した実行を評価：R = 8')\ntr('critic-title','C · 从完整结果构造 Critic 的训练样本','C · Turning outcomes into Critic training data','C · 実行結果から Critic の学習例を作る')\ntr('critic-caption','图 4 · 同一条执行产生多条“历史前缀—回报目标”样本。只在终点给 R=8，β=0、γ=λ=1，故两处目标均为 8，优势分别为 3 与 1。本次回归使用固定目标。','Figure 4 · One execution supplies several prefix–return pairs. With terminal-only R=8, β=0 and γ=λ=1, both targets are 8; the advantages are 3 and 1. The targets stay fixed for this regression update.','図 4 · 一回の実行から複数の「接頭辞—リターン目標」を作る。終点のみ R=8、β=0、γ=λ=1 では両目標は 8、アドバンテージは 3 と 1。この回帰中は目標を固定する。')\ntr('finished','完整修复轨迹 τ','Completed repair τ','完了した修正の軌跡 τ')\ntr('prefixes','两个位置的前缀','Prefixes at two positions','二つの位置の接頭辞')\ntr('prefixes-sub','h₁：修复前　h₂：修复后','h₁: before repair · h₂: after repair','h₁：修正前　h₂：修正後')\ntr('predict','预测后续回报','Predict future returns','今後のリターンを予測')\ntr('two-values','本次预测','Current predictions','現在の予測')\ntr('gae-target','GAE · 构造目标','GAE · Build targets','GAE・目標を作る')\ntr('critic-loss','价值回归损失','Value regression loss','価値の回帰損失')\ntr('critic-gradient','反向传播 · 更新 Critic','Backpropagation · update Critic','逆伝播で Critic を更新')\ntr('to-actor','At 供 Actor 更新','At goes to the Actor update','At は Actor の更新へ')\ntr('ppo-title','D · Actor 如何用同一批轨迹学习','D · How the Actor learns from a batch','D · Actor は同じバッチからどう学ぶか')\ntr('ppo-caption','图 5 · 重算已采样 token 的概率，与采样时保存的旧概率比较。优势给出更新方向，裁剪目标抑制过大的改动。新 Actor 再收集下一批轨迹。','Figure 5 · Recompute probabilities for sampled tokens and compare them with saved collection probabilities. Advantages provide the update direction; clipping limits incentives for large changes. The updated Actor collects a new batch.','図 5 · 採用済み token の確率を再計算し、保存した旧確率と比較する。アドバンテージが更新方向を与え、クリップで大きな変化への誘因を抑える。更新後の Actor で次のバッチを収集する。')\ntr('batch','固定的一批轨迹','One fixed batch','固定した一つのバッチ')\ntr('batch-sub','前缀 ht · 已采样 token at','Prefix ht · sampled token at','接頭辞 ht・採用済み token at')\ntr('current-actor','正在训练的 Actor','Actor being optimized','更新中の Actor')\ntr('new-prob','重新计算概率','Recompute probabilities','確率を再計算')\ntr('saved-prob','采样时保存的概率','Saved collection probabilities','収集時に保存した確率')\ntr('ratio','新旧概率比 ρt','Probability ratio ρt','新旧確率比 ρt')\ntr('clip-loss','PPO 裁剪损失','Clipped PPO loss','PPO クリップ損失')\ntr('actor-gradient','反向传播 · 更新 Actor 参数 θ','Backpropagation · update Actor weights θ','逆伝播で Actor の重み θ を更新')\n\n# Mathematical subscripts remain text/vector content in both diagram styles.\nfor entry in WORDS.values():\n    for language,value in entry.items():\n        for plain,formatted in [('πold','π<sub>old</sub>'),('rt','r<sub>t</sub>'),('At','A<sub>t</sub>'),('Ĝt','Ĝ<sub>t</sub>'),('Vt','V<sub>t</sub>'),('ht','h<sub>t</sub>'),('ρt','ρ<sub>t</sub>')]:\n            value=re.sub(r'(?<![A-Za-z])'+re.escape(plain)+r'(?![A-Za-z])',formatted,value)\n        value=value.replace('token at','token a<sub>t</sub>')\n        entry[language]=value\n\ndef label(lang,key,x,y,w=160,cls=''):\n    return f'<div class=\"ppo-label {cls}\" style=\"left:{x}px;top:{y}px;width:{w}px\">{WORDS[key][lang]}</div>'\ndef node(lang,key,x,y,w=180,h=80,sub=None,cls='',href=None,raw=None):\n    tag='a' if href else 'div'\n    attrs=f' href=\"#{href}\"' if href else ''\n    heading=WORDS[key][lang] if key else raw\n    subtitle=f'<span class=\"sub\">{WORDS[sub][lang] if sub in WORDS else sub}</span>' if sub else ''\n    return f'<{tag} class=\"node ppo-node {cls}\"{attrs} style=\"left:{x}px;top:{y}px;width:{w}px;height:{h}px\"><strong>{heading}</strong>{subtitle}</{tag}>'\ndef edge(points,cls='',arrow=True):\n    out=[]\n    for i,((x1,y1),(x2,y2)) in enumerate(zip(points,points[1:])):\n        width=math.hypot(x2-x1,y2-y1);angle=math.degrees(math.atan2(y2-y1,x2-x1))\n        tip=' arrow' if arrow and i==len(points)-2 else ''\n        out.append(f'<i aria-hidden=\"true\" class=\"edge {cls}{tip}\" style=\"left:{x1}px;top:{y1}px;width:{width}px;transform:rotate({angle}deg)\"></i>')\n    return ''.join(out)\ndef canvas(parts,width,height):\n    return f'<div class=\"canvas ppo-canvas\" style=\"width:{width}px;height:{height}px\">'+''.join(parts)+'</div>'\ndef narrow_canvas(markup,ratio):\n    soup=BeautifulSoup(markup,'html.parser')\n    for element in soup.select('[style]'):\n        style=element['style']\n        style=re.sub(r'left:([\\d.]+)px',lambda m:f'left:{float(m[1])*ratio:g}px',style)\n        if not re.search(r'rotate\\(-?90(?:\\.0)?deg\\)',style):\n            style=re.sub(r'width:([\\d.]+)px',lambda m:f'width:{float(m[1])*ratio:g}px',style)\n        element['style']=style\n    return str(soup)\ndef figure(lang,slug,title,caption,content):\n    text=WORDS[title][lang]\n    return f'<figure class=\"ppo-figure\" id=\"figure-{slug}\" data-diagram-style=\"openai-blog\" data-diagram-kind=\"flow\"><div class=\"ppo-figure-heading\">{text}</div><div class=\"ppo-figure-scroll\" role=\"region\" tabindex=\"0\" aria-label=\"{html.escape(text)}\">{content}</div><figcaption>{WORDS[caption][lang]}</figcaption></figure>'\n\ndef overview(l):\n    p=[label(l,'prep',30,10,1070,'stage'),\n       node(l,'demos',30,48,140,62,href='reward-model'),node(l,'sft',215,48,170,62,href='reward-model'),node(l,'copies',430,48,270,62,'copies-sub',href='reward-model'),\n       node(l,'prefs',755,48,130,62,href='reward-model'),node(l,'rm-training',930,48,170,62,href='reward-model'),\n       edge([(170,79),(215,79)]),edge([(385,79),(430,79)]),edge([(885,79),(930,79)]),\n       '<div class=\"ppo-divider\" style=\"left:30px;top:145px;width:1070px\"></div>',\n       label(l,'collect',30,175,280,'stage'),label(l,'targets',580,175,520,'stage'),label(l,'update',35,720,210,'stage'),\n       node(l,None,30,285,180,82,'actor-sub','soft',href='rollout',raw='Actor'),node(l,'env',30,480,180,82,'env-sub',href='rollout'),\n       node(l,'trajectory',285,285,220,100,'trajectory-sub',href='rollout'),node(l,None,590,235,180,72,'fixed',href='reward-model',raw='RM'),\n       node(l,None,590,365,180,72,'fixed',href='advantages',raw='Reference'),node(l,None,590,535,180,72,'prefix-value','soft',href='advantages',raw='Critic'),\n       node(l,'rewards',870,275,230,88,'reward-sub',href='advantages'),node(l,None,870,525,230,88,'gae-sub',href='advantages',raw='GAE'),\n       node(l,'actor-update',285,735,230,82,'actor-update-sub','accent',href='optimization'),node(l,'critic-update',590,735,230,82,'critic-update-sub','accent',href='advantages'),\n       edge([(210,326),(285,326)]),edge([(75,367),(75,480)]),label(l,'command',25,409,115),\n       edge([(165,480),(165,367)]),label(l,'observation',146,390,125),edge([(210,520),(255,520),(255,370),(285,370)]),\n       edge([(505,310),(545,310),(545,271),(590,271)]),label(l,'complete',490,235,100),\n       edge([(505,335),(558,335),(558,401),(590,401)]),label(l,'prefix-action',472,408,118),\n       edge([(505,360),(540,360),(540,571),(590,571)]),label(l,'prefix',470,500,115),\n       edge([(770,271),(820,271),(820,306),(870,306)]),label(l,'score',775,230,95),\n       edge([(770,401),(820,401),(820,340),(870,340)]),label(l,'ref-probs',775,411,96),\n       edge([(985,363),(985,525)]),'<div class=\"ppo-label math-label\" style=\"left:960px;top:433px;width:50px\">r<sub>t</sub></div>',\n       edge([(770,571),(870,571)]),label(l,'values',770,534,100),\n       edge([(910,613),(910,650),(400,650),(400,735)]),label(l,'advantage',405,590,165),\n       edge([(1035,613),(1035,704),(705,704),(705,735)]),label(l,'return-target',850,655,170),\n       edge([(400,385),(400,600),(320,600),(320,735)],'cache'),label(l,'sample-data',270,547,230),\n       edge([(400,817),(400,870),(10,870),(10,326),(30,326)],'feedback'),label(l,'next-actor',30,880,450),\n       edge([(705,817),(705,870),(830,870),(830,643),(675,643),(675,607)],'feedback'),label(l,'new-critic',650,880,400),\n       edge([(395,285),(395,215),(985,215),(985,275)],'cache'),label(l,'old-probs',365,190,190)]\n    content=canvas(p,1140,915)\n    # Compact only the empty vertical spacing; keep node dimensions and type size.\n    bands=[(145,175),(437,480),(613,643),(817,844)]\n    def compact_y(y):return y-sum(max(0,min(y,b)-a) for a,b in bands)\n    content=re.sub(r'top:([\\d.]+)px',lambda m:f'top:{compact_y(float(m[1])):g}px',content)\n    # Vertical edge lengths share the same compression as their endpoint positions.\n    def compact_edge(m):\n        x,y,w,angle=map(float,m.groups());end=y+w*(1 if angle>0 else -1)\n        return f'left:{x:g}px;top:{compact_y(y):g}px;width:{abs(compact_y(end)-compact_y(y)):g}px;transform:rotate({angle:g}deg)'\n    # Work from uncompressed edge styles to avoid applying the coordinate map twice.\n    originals=re.findall(r'left:([\\d.]+)px;top:([\\d.]+)px;width:([\\d.]+)px;transform:rotate\\((-?90(?:\\.0)?)deg\\)',canvas(p,1140,915))\n    current=re.findall(r'left:([\\d.]+)px;top:([\\d.]+)px;width:([\\d.]+)px;transform:rotate\\((-?90(?:\\.0)?)deg\\)',content)\n    for old,now in zip(originals,current):\n        x,y,w,a=map(float,old);_,cy,cw,ca=map(float,now);end=y+w*(1 if a>0 else -1)\n        oldstyle=f'left:{now[0]}px;top:{now[1]}px;width:{now[2]}px;transform:rotate({now[3]}deg)'\n        newstyle=f'left:{x:g}px;top:{compact_y(y):g}px;width:{abs(compact_y(end)-compact_y(y)):g}px;transform:rotate({a:g}deg)'\n        content=content.replace(oldstyle,newstyle,1)\n    return content.replace('height:915px','height:785px')\n\ndef reward_model(l):\n    p=[node(l,'attempt-a',25,55,310,95,'attempt-a-sub'),node(l,'attempt-b',25,240,310,95,'attempt-b-sub'),\n       node(l,'shared-rm',420,140,230,105,'model-head','soft'),node(l,'pair-scores',735,140,150,105,'r<sub>A</sub>, r<sub>B</sub>'),\n       label(l,'human-label',890,30,235),node(l,'pair-loss',935,140,190,105,'−log σ(r<sub>A</sub> − r<sub>B</sub>)','accent'),\n       edge([(335,102),(375,102),(375,169),(420,169)]),edge([(335,287),(375,287),(375,216),(420,216)]),\n       edge([(650,193),(735,193)]),edge([(885,193),(935,193)]),edge([(1030,65),(1030,140)]),\n       edge([(1030,245),(1030,382),(535,382),(535,245)],'feedback'),label(l,'rm-gradient',595,355,410)]\n    return canvas(p,1150,425)\n\ndef trajectory(l):\n    p=[label(l,'task',25,5,960,'task-title'),node(l,None,50,65,355,60,raw='Actor'),node(l,'env',590,65,355,60),\n       '<div class=\"ppo-lifeline\" style=\"left:225px;top:125px;height:995px\"></div>',\n       '<div class=\"ppo-lifeline\" style=\"left:765px;top:125px;height:870px\"></div>']\n    rows=[('reads-script','cat summarize.py','float-source','float(row[\"amount\"])'),('run-test','pytest -q','fail','0.30000000000000004'),('patch','Decimal(row[\"amount\"])','patched','format(total, \".2f\")'),('retest','pytest -q','passed','0.30')]\n    for i,(action,code,obs,result) in enumerate(rows):\n        y=175+i*210\n        p.extend([node(l,action,50,y,355,76,html.escape(code),'soft'),node(l,obs,590,y+80,355,76,html.escape(result)),edge([(405,y+38),(765,y+38),(765,y+80)]),edge([(590,y+118),(225,y+118),(225,y+210)])])\n    p.extend([node(l,'submit',50,1015,355,76),edge([(405,1053),(590,1053)]),node(l,'rm-end',590,1015,355,90,cls='accent')])\n    return canvas(p,1000,1160)\n\ndef critic(l):\n    p=[node(l,'finished',30,40,280,82),node(l,None,405,40,230,82,'fixed',raw='RM'),node(l,None,725,40,200,82,raw='R = 8'),\n       node(l,'prefixes',30,245,280,100,'prefixes-sub'),node(l,None,405,245,230,100,'predict','soft',raw='Critic'),node(l,'two-values',725,245,200,100,'V(h₁) = 5<br>V(h₂) = 7'),\n       node(l,'gae-target',985,145,230,100,'Ĝ<sub>t</sub> = A<sub>t</sub> + V<sub>t</sub>'),\n       node(l,None,985,465,230,86,'Ĝ₁ = 8 · Ĝ₂ = 8',raw=WORDS['return-target'][l]),node(l,'critic-loss',425,465,260,100,'mean (V<sub>φ</sub>(h<sub>t</sub>) − Ĝ<sub>t</sub>)²','accent'),\n       edge([(310,81),(405,81)]),edge([(635,81),(725,81)]),edge([(925,81),(1100,81),(1100,145)]),\n       edge([(310,295),(405,295)]),edge([(635,295),(725,295)]),edge([(925,295),(1100,295),(1100,245)]),\n       edge([(1215,195),(1245,195),(1245,508),(1215,508)]),edge([(985,508),(685,508)]),edge([(825,345),(825,420),(625,420),(625,465)]),\n       edge([(425,515),(350,515),(350,380),(520,380),(520,345)],'feedback'),label(l,'critic-gradient',85,438,310),\n       label(l,'to-actor',940,610,300),'<div class=\"ppo-label math-label\" style=\"left:960px;top:649px;width:260px\">A₁ = 3 · A₂ = 1</div>',edge([(1215,220),(1270,220),(1270,665),(1220,665)])]\n    return narrow_canvas(canvas(p,1290,710),.9)\n\ndef update(l):\n    p=[node(l,'batch',25,60,270,90,'batch-sub'),node(l,'current-actor',385,60,250,90,'π<sub>θ</sub>','soft'),node(l,'new-prob',735,60,230,90,'π<sub>θ</sub>(a<sub>t</sub> | h<sub>t</sub>)'),\n       node(l,'saved-prob',25,290,270,90,'π<sub>old</sub>(a<sub>t</sub> | h<sub>t</sub>)'),node(l,'ratio',735,290,230,90,'π<sub>θ</sub> / π<sub>old</sub>'),\n       node(l,'advantage',385,290,250,90,'GAE → A<sub>t</sub>'),node(l,'clip-loss',1030,290,190,90,cls='accent'),\n       edge([(295,105),(385,105)]),edge([(635,105),(735,105)]),edge([(850,150),(850,290)]),\n       edge([(160,150),(160,290)],'cache'),edge([(295,335),(335,335),(335,430),(850,430),(850,380)]),\n       edge([(965,335),(1030,335)]),edge([(635,335),(680,335),(680,240),(1125,240),(1125,290)]),\n       edge([(1125,380),(1125,545),(345,545),(345,205),(510,205),(510,150)],'feedback'),label(l,'actor-gradient',625,517,450)]\n    return narrow_canvas(canvas(p,1250,595),.94)\n\nBUILDERS=[('training-overview','overview-title','overview-caption',overview),('reward-value-training','rm-title','rm-caption',reward_model),('trajectory-models','trace-title','trace-caption',trajectory),('critic-training','critic-title','critic-caption',critic),('ppo-update','ppo-title','ppo-caption',update)]\nfor lang in LANGS:\n    for slug,title,caption,builder in BUILDERS:\n        (ROOT/f'{slug}.{lang}.html').write_text(figure(lang,slug,title,caption,builder(lang)),encoding='utf8')\n(ROOT/'figure-texts.json').write_text(json.dumps(WORDS,ensure_ascii=False,indent=2)+'\\n',encoding='utf8')\n(ROOT/'ppo-figures.css').write_text((ROOT/'workflow.css').read_text('utf8'),encoding='utf8')\nprint(f'Built {len(BUILDERS)*len(LANGS)} figures.')\n",
    "figures/critic-training.en.html": "<figure class=\"ppo-figure\" id=\"figure-critic-training\" data-diagram-style=\"openai-blog\" data-diagram-kind=\"flow\"><div class=\"ppo-figure-heading\">C · Turning outcomes into Critic training data</div><div class=\"ppo-figure-scroll\" role=\"region\" tabindex=\"0\" aria-label=\"C · Turning outcomes into Critic training data\"><div class=\"canvas ppo-canvas\" style=\"width:1161px;height:710px\"><div class=\"node ppo-node\" style=\"left:27px;top:40px;width:252px;height:82px\"><strong>Completed repair τ</strong></div><div class=\"node ppo-node\" style=\"left:364.5px;top:40px;width:207px;height:82px\"><strong>RM</strong><span class=\"sub\">Fixed weights</span></div><div class=\"node ppo-node\" style=\"left:652.5px;top:40px;width:180px;height:82px\"><strong>R = 8</strong></div><div class=\"node ppo-node\" style=\"left:27px;top:245px;width:252px;height:100px\"><strong>Prefixes at two positions</strong><span class=\"sub\">h₁: before repair · h₂: after repair</span></div><div class=\"node ppo-node soft\" style=\"left:364.5px;top:245px;width:207px;height:100px\"><strong>Critic</strong><span class=\"sub\">Predict future returns</span></div><div class=\"node ppo-node\" style=\"left:652.5px;top:245px;width:180px;height:100px\"><strong>Current predictions</strong><span class=\"sub\">V(h₁) = 5<br/>V(h₂) = 7</span></div><div class=\"node ppo-node\" style=\"left:886.5px;top:145px;width:207px;height:100px\"><strong>GAE · Build targets</strong><span class=\"sub\">Ĝ<sub>t</sub> = A<sub>t</sub> + V<sub>t</sub></span></div><div class=\"node ppo-node\" style=\"left:886.5px;top:465px;width:207px;height:86px\"><strong>Return targets Ĝ<sub>t</sub></strong><span class=\"sub\">Ĝ₁ = 8 · Ĝ₂ = 8</span></div><div class=\"node ppo-node accent\" style=\"left:382.5px;top:465px;width:234px;height:100px\"><strong>Value regression loss</strong><span class=\"sub\">mean (V<sub>φ</sub>(h<sub>t</sub>) − Ĝ<sub>t</sub>)²</span></div><i aria-hidden=\"true\" class=\"edge arrow\" style=\"left:279px;top:81px;width:85.5px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge arrow\" style=\"left:571.5px;top:81px;width:81px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge\" style=\"left:832.5px;top:81px;width:157.5px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge arrow\" style=\"left:990px;top:81px;width:64.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge arrow\" style=\"left:279px;top:295px;width:85.5px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge arrow\" style=\"left:571.5px;top:295px;width:81px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge\" style=\"left:832.5px;top:295px;width:157.5px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge arrow\" style=\"left:990px;top:295px;width:50.0px;transform:rotate(-90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge\" style=\"left:1093.5px;top:195px;width:27px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge\" style=\"left:1120.5px;top:195px;width:313.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge arrow\" style=\"left:1120.5px;top:508px;width:27px;transform:rotate(180.0deg)\"></i><i aria-hidden=\"true\" class=\"edge arrow\" style=\"left:886.5px;top:508px;width:270px;transform:rotate(180.0deg)\"></i><i aria-hidden=\"true\" class=\"edge\" style=\"left:742.5px;top:345px;width:75.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge\" style=\"left:742.5px;top:420px;width:180px;transform:rotate(180.0deg)\"></i><i aria-hidden=\"true\" class=\"edge arrow\" style=\"left:562.5px;top:420px;width:45.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback\" style=\"left:382.5px;top:515px;width:67.5px;transform:rotate(180.0deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback\" style=\"left:315px;top:515px;width:135.0px;transform:rotate(-90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback\" style=\"left:315px;top:380px;width:153px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback arrow\" style=\"left:468px;top:380px;width:35.0px;transform:rotate(-90.0deg)\"></i><div class=\"ppo-label\" style=\"left:76.5px;top:438px;width:279px\">Backpropagation · update Critic</div><div class=\"ppo-label\" style=\"left:846px;top:610px;width:270px\">A<sub>t</sub> goes to the Actor update</div><div class=\"ppo-label math-label\" style=\"left:864px;top:649px;width:234px\">A₁ = 3 · A₂ = 1</div><i aria-hidden=\"true\" class=\"edge\" style=\"left:1093.5px;top:220px;width:49.5px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge\" style=\"left:1143px;top:220px;width:445.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge arrow\" style=\"left:1143px;top:665px;width:45px;transform:rotate(180.0deg)\"></i></div></div><figcaption>Figure 4 · One execution supplies several prefix–return pairs. With terminal-only R=8, β=0 and γ=λ=1, both targets are 8; the advantages are 3 and 1. The targets stay fixed for this regression update.</figcaption></figure>",
    "figures/critic-training.ja.html": "<figure class=\"ppo-figure\" id=\"figure-critic-training\" data-diagram-style=\"openai-blog\" data-diagram-kind=\"flow\"><div class=\"ppo-figure-heading\">C · 実行結果から Critic の学習例を作る</div><div class=\"ppo-figure-scroll\" role=\"region\" tabindex=\"0\" aria-label=\"C · 実行結果から Critic の学習例を作る\"><div class=\"canvas ppo-canvas\" style=\"width:1161px;height:710px\"><div class=\"node ppo-node\" style=\"left:27px;top:40px;width:252px;height:82px\"><strong>完了した修正の軌跡 τ</strong></div><div class=\"node ppo-node\" style=\"left:364.5px;top:40px;width:207px;height:82px\"><strong>RM</strong><span class=\"sub\">重みを固定</span></div><div class=\"node ppo-node\" style=\"left:652.5px;top:40px;width:180px;height:82px\"><strong>R = 8</strong></div><div class=\"node ppo-node\" style=\"left:27px;top:245px;width:252px;height:100px\"><strong>二つの位置の接頭辞</strong><span class=\"sub\">h₁：修正前　h₂：修正後</span></div><div class=\"node ppo-node soft\" style=\"left:364.5px;top:245px;width:207px;height:100px\"><strong>Critic</strong><span class=\"sub\">今後のリターンを予測</span></div><div class=\"node ppo-node\" style=\"left:652.5px;top:245px;width:180px;height:100px\"><strong>現在の予測</strong><span class=\"sub\">V(h₁) = 5<br/>V(h₂) = 7</span></div><div class=\"node ppo-node\" style=\"left:886.5px;top:145px;width:207px;height:100px\"><strong>GAE・目標を作る</strong><span class=\"sub\">Ĝ<sub>t</sub> = A<sub>t</sub> + V<sub>t</sub></span></div><div class=\"node ppo-node\" style=\"left:886.5px;top:465px;width:207px;height:86px\"><strong>リターン目標 Ĝ<sub>t</sub></strong><span class=\"sub\">Ĝ₁ = 8 · Ĝ₂ = 8</span></div><div class=\"node ppo-node accent\" style=\"left:382.5px;top:465px;width:234px;height:100px\"><strong>価値の回帰損失</strong><span class=\"sub\">mean (V<sub>φ</sub>(h<sub>t</sub>) − Ĝ<sub>t</sub>)²</span></div><i aria-hidden=\"true\" class=\"edge arrow\" style=\"left:279px;top:81px;width:85.5px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge arrow\" style=\"left:571.5px;top:81px;width:81px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge\" style=\"left:832.5px;top:81px;width:157.5px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge arrow\" style=\"left:990px;top:81px;width:64.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge arrow\" style=\"left:279px;top:295px;width:85.5px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge arrow\" style=\"left:571.5px;top:295px;width:81px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge\" style=\"left:832.5px;top:295px;width:157.5px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge arrow\" style=\"left:990px;top:295px;width:50.0px;transform:rotate(-90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge\" style=\"left:1093.5px;top:195px;width:27px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge\" style=\"left:1120.5px;top:195px;width:313.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge arrow\" style=\"left:1120.5px;top:508px;width:27px;transform:rotate(180.0deg)\"></i><i aria-hidden=\"true\" class=\"edge arrow\" style=\"left:886.5px;top:508px;width:270px;transform:rotate(180.0deg)\"></i><i aria-hidden=\"true\" class=\"edge\" style=\"left:742.5px;top:345px;width:75.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge\" style=\"left:742.5px;top:420px;width:180px;transform:rotate(180.0deg)\"></i><i aria-hidden=\"true\" class=\"edge arrow\" style=\"left:562.5px;top:420px;width:45.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback\" style=\"left:382.5px;top:515px;width:67.5px;transform:rotate(180.0deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback\" style=\"left:315px;top:515px;width:135.0px;transform:rotate(-90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback\" style=\"left:315px;top:380px;width:153px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback arrow\" style=\"left:468px;top:380px;width:35.0px;transform:rotate(-90.0deg)\"></i><div class=\"ppo-label\" style=\"left:76.5px;top:438px;width:279px\">逆伝播で Critic を更新</div><div class=\"ppo-label\" style=\"left:846px;top:610px;width:270px\">A<sub>t</sub> は Actor の更新へ</div><div class=\"ppo-label math-label\" style=\"left:864px;top:649px;width:234px\">A₁ = 3 · A₂ = 1</div><i aria-hidden=\"true\" class=\"edge\" style=\"left:1093.5px;top:220px;width:49.5px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge\" style=\"left:1143px;top:220px;width:445.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge arrow\" style=\"left:1143px;top:665px;width:45px;transform:rotate(180.0deg)\"></i></div></div><figcaption>図 4 · 一回の実行から複数の「接頭辞—リターン目標」を作る。終点のみ R=8、β=0、γ=λ=1 では両目標は 8、アドバンテージは 3 と 1。この回帰中は目標を固定する。</figcaption></figure>",
    "figures/critic-training.zh.html": "<figure class=\"ppo-figure\" id=\"figure-critic-training\" data-diagram-style=\"openai-blog\" data-diagram-kind=\"flow\"><div class=\"ppo-figure-heading\">C · 从完整结果构造 Critic 的训练样本</div><div class=\"ppo-figure-scroll\" role=\"region\" tabindex=\"0\" aria-label=\"C · 从完整结果构造 Critic 的训练样本\"><div class=\"canvas ppo-canvas\" style=\"width:1161px;height:710px\"><div class=\"node ppo-node\" style=\"left:27px;top:40px;width:252px;height:82px\"><strong>完整修复轨迹 τ</strong></div><div class=\"node ppo-node\" style=\"left:364.5px;top:40px;width:207px;height:82px\"><strong>RM</strong><span class=\"sub\">固定参数</span></div><div class=\"node ppo-node\" style=\"left:652.5px;top:40px;width:180px;height:82px\"><strong>R = 8</strong></div><div class=\"node ppo-node\" style=\"left:27px;top:245px;width:252px;height:100px\"><strong>两个位置的前缀</strong><span class=\"sub\">h₁：修复前　h₂：修复后</span></div><div class=\"node ppo-node soft\" style=\"left:364.5px;top:245px;width:207px;height:100px\"><strong>Critic</strong><span class=\"sub\">预测后续回报</span></div><div class=\"node ppo-node\" style=\"left:652.5px;top:245px;width:180px;height:100px\"><strong>本次预测</strong><span class=\"sub\">V(h₁) = 5<br/>V(h₂) = 7</span></div><div class=\"node ppo-node\" style=\"left:886.5px;top:145px;width:207px;height:100px\"><strong>GAE · 构造目标</strong><span class=\"sub\">Ĝ<sub>t</sub> = A<sub>t</sub> + V<sub>t</sub></span></div><div class=\"node ppo-node\" style=\"left:886.5px;top:465px;width:207px;height:86px\"><strong>回报目标 Ĝ<sub>t</sub></strong><span class=\"sub\">Ĝ₁ = 8 · Ĝ₂ = 8</span></div><div class=\"node ppo-node accent\" style=\"left:382.5px;top:465px;width:234px;height:100px\"><strong>价值回归损失</strong><span class=\"sub\">mean (V<sub>φ</sub>(h<sub>t</sub>) − Ĝ<sub>t</sub>)²</span></div><i aria-hidden=\"true\" class=\"edge arrow\" style=\"left:279px;top:81px;width:85.5px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge arrow\" style=\"left:571.5px;top:81px;width:81px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge\" style=\"left:832.5px;top:81px;width:157.5px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge arrow\" style=\"left:990px;top:81px;width:64.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge arrow\" style=\"left:279px;top:295px;width:85.5px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge arrow\" style=\"left:571.5px;top:295px;width:81px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge\" style=\"left:832.5px;top:295px;width:157.5px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge arrow\" style=\"left:990px;top:295px;width:50.0px;transform:rotate(-90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge\" style=\"left:1093.5px;top:195px;width:27px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge\" style=\"left:1120.5px;top:195px;width:313.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge arrow\" style=\"left:1120.5px;top:508px;width:27px;transform:rotate(180.0deg)\"></i><i aria-hidden=\"true\" class=\"edge arrow\" style=\"left:886.5px;top:508px;width:270px;transform:rotate(180.0deg)\"></i><i aria-hidden=\"true\" class=\"edge\" style=\"left:742.5px;top:345px;width:75.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge\" style=\"left:742.5px;top:420px;width:180px;transform:rotate(180.0deg)\"></i><i aria-hidden=\"true\" class=\"edge arrow\" style=\"left:562.5px;top:420px;width:45.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback\" style=\"left:382.5px;top:515px;width:67.5px;transform:rotate(180.0deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback\" style=\"left:315px;top:515px;width:135.0px;transform:rotate(-90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback\" style=\"left:315px;top:380px;width:153px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback arrow\" style=\"left:468px;top:380px;width:35.0px;transform:rotate(-90.0deg)\"></i><div class=\"ppo-label\" style=\"left:76.5px;top:438px;width:279px\">反向传播 · 更新 Critic</div><div class=\"ppo-label\" style=\"left:846px;top:610px;width:270px\">A<sub>t</sub> 供 Actor 更新</div><div class=\"ppo-label math-label\" style=\"left:864px;top:649px;width:234px\">A₁ = 3 · A₂ = 1</div><i aria-hidden=\"true\" class=\"edge\" style=\"left:1093.5px;top:220px;width:49.5px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge\" style=\"left:1143px;top:220px;width:445.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge arrow\" style=\"left:1143px;top:665px;width:45px;transform:rotate(180.0deg)\"></i></div></div><figcaption>图 4 · 同一条执行产生多条“历史前缀—回报目标”样本。只在终点给 R=8，β=0、γ=λ=1，故两处目标均为 8，优势分别为 3 与 1。本次回归使用固定目标。</figcaption></figure>",
    "figures/figure-texts.json": "{\n  \"overview-title\": {\n    \"zh\": \"训练全流程\",\n    \"en\": \"The complete training loop\",\n    \"ja\": \"学習の全体像\"\n  },\n  \"overview-caption\": {\n    \"zh\": \"图 1 · A 准备模型，B 收集轨迹，C 计算奖励与优势，D 更新 Actor 与 Critic。RM 与 Reference 在 PPO 中固定。节点可跳转至对应章节。\",\n    \"en\": \"Figure 1 · A prepares models; B collects trajectories; C computes rewards and advantages; D updates Actor and Critic. RM and Reference stay fixed during PPO. Nodes link to the corresponding sections.\",\n    \"ja\": \"図 1 · A はモデル準備、B は軌跡収集、C は報酬とアドバンテージ計算、D は Actor と Critic の更新。PPO 中の RM と Reference は固定。各ノードから対応する節へ移動できる。\"\n  },\n  \"prep\": {\n    \"zh\": \"A · 学习开始前\",\n    \"en\": \"A · Before PPO\",\n    \"ja\": \"A · PPO の前\"\n  },\n  \"demos\": {\n    \"zh\": \"操作示范\",\n    \"en\": \"Examples\",\n    \"ja\": \"操作の実演\"\n  },\n  \"sft\": {\n    \"zh\": \"监督微调 SFT\",\n    \"en\": \"Supervised fine-tuning\",\n    \"ja\": \"教師あり学習 SFT\"\n  },\n  \"copies\": {\n    \"zh\": \"Actor + Reference\",\n    \"en\": \"Actor + Reference\",\n    \"ja\": \"Actor + Reference\"\n  },\n  \"copies-sub\": {\n    \"zh\": \"同一初始策略的两份参数\",\n    \"en\": \"Two copies of the initial policy\",\n    \"ja\": \"同じ初期方策の二つのコピー\"\n  },\n  \"prefs\": {\n    \"zh\": \"成对偏好\",\n    \"en\": \"Preference pairs\",\n    \"ja\": \"選好ペア\"\n  },\n  \"rm-training\": {\n    \"zh\": \"训练 RM\",\n    \"en\": \"Train RM\",\n    \"ja\": \"RM を学習\"\n  },\n  \"collect\": {\n    \"zh\": \"B · 执行任务\",\n    \"en\": \"B · Collect trajectories\",\n    \"ja\": \"B · タスクを実行\"\n  },\n  \"targets\": {\n    \"zh\": \"C · 奖励与优势\",\n    \"en\": \"C · Rewards and advantages\",\n    \"ja\": \"C · 報酬とアドバンテージ\"\n  },\n  \"update\": {\n    \"zh\": \"D · 参数更新\",\n    \"en\": \"D · Parameter updates\",\n    \"ja\": \"D · パラメータを更新\"\n  },\n  \"actor-sub\": {\n    \"zh\": \"当前策略 π<sub>old</sub>\",\n    \"en\": \"Current policy π<sub>old</sub>\",\n    \"ja\": \"現在の方策 π<sub>old</sub>\"\n  },\n  \"env\": {\n    \"zh\": \"工具环境\",\n    \"en\": \"Tool environment\",\n    \"ja\": \"ツール環境\"\n  },\n  \"env-sub\": {\n    \"zh\": \"文件 · Shell · 测试\",\n    \"en\": \"Files · shell · tests\",\n    \"ja\": \"ファイル・Shell・テスト\"\n  },\n  \"trajectory\": {\n    \"zh\": \"轨迹记录\",\n    \"en\": \"Trajectory record\",\n    \"ja\": \"軌跡の記録\"\n  },\n  \"trajectory-sub\": {\n    \"zh\": \"任务 + 动作 + 观察\",\n    \"en\": \"Task + actions + observations\",\n    \"ja\": \"タスク＋行動＋観測\"\n  },\n  \"fixed\": {\n    \"zh\": \"固定参数\",\n    \"en\": \"Fixed weights\",\n    \"ja\": \"重みを固定\"\n  },\n  \"prefix-value\": {\n    \"zh\": \"读取每个历史前缀\",\n    \"en\": \"Reads each history prefix\",\n    \"ja\": \"各時点までの履歴を読む\"\n  },\n  \"rewards\": {\n    \"zh\": \"构造奖励 r<sub>t</sub>\",\n    \"en\": \"Construct rewards r<sub>t</sub>\",\n    \"ja\": \"報酬 r<sub>t</sub> を作る\"\n  },\n  \"reward-sub\": {\n    \"zh\": \"终点得分 + KL 约束\",\n    \"en\": \"Terminal score + KL penalty\",\n    \"ja\": \"終点スコア＋KL 制約\"\n  },\n  \"gae-sub\": {\n    \"zh\": \"按位置回传反馈\",\n    \"en\": \"Propagate feedback backward\",\n    \"ja\": \"各位置へ評価を遡らせる\"\n  },\n  \"actor-update\": {\n    \"zh\": \"更新 Actor\",\n    \"en\": \"Update Actor\",\n    \"ja\": \"Actor を更新\"\n  },\n  \"actor-update-sub\": {\n    \"zh\": \"PPO 裁剪目标\",\n    \"en\": \"Clipped PPO objective\",\n    \"ja\": \"PPO のクリップ目的関数\"\n  },\n  \"critic-update\": {\n    \"zh\": \"更新 Critic\",\n    \"en\": \"Update Critic\",\n    \"ja\": \"Critic を更新\"\n  },\n  \"critic-update-sub\": {\n    \"zh\": \"拟合回报目标 Ĝ<sub>t</sub>\",\n    \"en\": \"Fit return targets Ĝ<sub>t</sub>\",\n    \"ja\": \"リターン目標 Ĝ<sub>t</sub> に回帰\"\n  },\n  \"command\": {\n    \"zh\": \"工具调用\",\n    \"en\": \"Tool calls\",\n    \"ja\": \"ツール呼び出し\"\n  },\n  \"observation\": {\n    \"zh\": \"工具返回\",\n    \"en\": \"Observations\",\n    \"ja\": \"ツールの返り値\"\n  },\n  \"complete\": {\n    \"zh\": \"完整执行\",\n    \"en\": \"Complete execution\",\n    \"ja\": \"完了した実行\"\n  },\n  \"prefix-action\": {\n    \"zh\": \"前缀 + token\",\n    \"en\": \"Prefix + token\",\n    \"ja\": \"接頭辞＋token\"\n  },\n  \"prefix\": {\n    \"zh\": \"前缀 h<sub>t</sub>\",\n    \"en\": \"Prefix h<sub>t</sub>\",\n    \"ja\": \"接頭辞 h<sub>t</sub>\"\n  },\n  \"score\": {\n    \"zh\": \"得分 R\",\n    \"en\": \"Score R\",\n    \"ja\": \"スコア R\"\n  },\n  \"ref-probs\": {\n    \"zh\": \"参考概率\",\n    \"en\": \"Reference probabilities\",\n    \"ja\": \"参照確率\"\n  },\n  \"values\": {\n    \"zh\": \"价值 V<sub>t</sub>\",\n    \"en\": \"Values V<sub>t</sub>\",\n    \"ja\": \"価値 V<sub>t</sub>\"\n  },\n  \"advantage\": {\n    \"zh\": \"优势 A<sub>t</sub>\",\n    \"en\": \"Advantages A<sub>t</sub>\",\n    \"ja\": \"アドバンテージ A<sub>t</sub>\"\n  },\n  \"return-target\": {\n    \"zh\": \"回报目标 Ĝ<sub>t</sub>\",\n    \"en\": \"Return targets Ĝ<sub>t</sub>\",\n    \"ja\": \"リターン目標 Ĝ<sub>t</sub>\"\n  },\n  \"next-actor\": {\n    \"zh\": \"新 Actor 继续采样\",\n    \"en\": \"Updated Actor collects the next batch\",\n    \"ja\": \"更新した Actor で次のバッチを収集\"\n  },\n  \"new-critic\": {\n    \"zh\": \"更新后的价值预测\",\n    \"en\": \"Updated value predictions\",\n    \"ja\": \"更新後の価値予測\"\n  },\n  \"sample-data\": {\n    \"zh\": \"已采样 token 与旧概率\",\n    \"en\": \"Sampled tokens + old probabilities\",\n    \"ja\": \"採用済み token と旧確率\"\n  },\n  \"old-probs\": {\n    \"zh\": \"保存的 log π<sub>old</sub>\",\n    \"en\": \"Saved log π<sub>old</sub>\",\n    \"ja\": \"保存した log π<sub>old</sub>\"\n  },\n  \"rm-title\": {\n    \"zh\": \"A · 奖励模型怎样学会评分\",\n    \"en\": \"A · How the reward model learns\",\n    \"ja\": \"A · 報酬モデルはどう学ぶか\"\n  },\n  \"rm-caption\": {\n    \"zh\": \"图 2 · 两条完整执行分别经过同一个 RM。偏好标签监督分数的相对顺序，损失反向传播到 RM。训练完成后，RM 在 PPO 中固定。\",\n    \"en\": \"Figure 2 · Two complete attempts pass through the same RM. Preference labels supervise score ordering; gradients update the RM. The trained RM stays fixed during PPO.\",\n    \"ja\": \"図 2 · 二つの完了済み実行を同一の RM で採点する。選好ラベルでスコアの順序を学び、損失を RM に逆伝播する。学習後は PPO 中に固定する。\"\n  },\n  \"attempt-a\": {\n    \"zh\": \"任务 + 完整执行 A\",\n    \"en\": \"Task + complete attempt A\",\n    \"ja\": \"課題＋完了済み実行 A\"\n  },\n  \"attempt-a-sub\": {\n    \"zh\": \"Decimal 求和 → 输出 0.30\",\n    \"en\": \"Decimal sum → output 0.30\",\n    \"ja\": \"Decimal で加算 → 0.30\"\n  },\n  \"attempt-b\": {\n    \"zh\": \"任务 + 完整执行 B\",\n    \"en\": \"Task + complete attempt B\",\n    \"ja\": \"課題＋完了済み実行 B\"\n  },\n  \"attempt-b-sub\": {\n    \"zh\": \"float 求和 → 保留误差\",\n    \"en\": \"float sum → rounding error\",\n    \"ja\": \"float で加算 → 誤差が残る\"\n  },\n  \"shared-rm\": {\n    \"zh\": \"同一个 RM\",\n    \"en\": \"One shared RM\",\n    \"ja\": \"同一の RM\"\n  },\n  \"model-head\": {\n    \"zh\": \"语言模型 + 标量头\",\n    \"en\": \"Language model + scalar head\",\n    \"ja\": \"言語モデル＋スカラーヘッド\"\n  },\n  \"pair-scores\": {\n    \"zh\": \"两次前向计算\",\n    \"en\": \"Two forward passes\",\n    \"ja\": \"二回の順伝播\"\n  },\n  \"human-label\": {\n    \"zh\": \"偏好标签：A 优于 B\",\n    \"en\": \"Preference label: A over B\",\n    \"ja\": \"選好ラベル：A が B より良い\"\n  },\n  \"pair-loss\": {\n    \"zh\": \"偏好损失\",\n    \"en\": \"Preference loss\",\n    \"ja\": \"選好損失\"\n  },\n  \"rm-gradient\": {\n    \"zh\": \"反向传播 · 更新 RM 参数\",\n    \"en\": \"Backpropagation · update RM weights\",\n    \"ja\": \"逆伝播で RM の重みを更新\"\n  },\n  \"trace-title\": {\n    \"zh\": \"B · Actor 与工具如何完成一次修复\",\n    \"en\": \"B · One repair, through Actor and tools\",\n    \"ja\": \"B · Actor とツールによる一回の修正\"\n  },\n  \"trace-caption\": {\n    \"zh\": \"图 3 · 金额汇总教学案例。工具返回加入历史，Actor 据此生成下一步调用。执行完成后，整条记录交给 RM 评分。\",\n    \"en\": \"Figure 3 · An illustrative repair. Tool responses join the history used for the next call. The RM scores the completed record.\",\n    \"ja\": \"図 3 · 金額集計を修正する学習用の例。ツールの返り値を履歴に加え、次の呼び出しを生成する。実行完了後に全記録を RM で採点する。\"\n  },\n  \"task\": {\n    \"zh\": \"任务：把 \\\"0.10\\\" 与 \\\"0.20\\\" 相加，输出 0.30\",\n    \"en\": \"Task: sum \\\"0.10\\\" and \\\"0.20\\\", then print 0.30\",\n    \"ja\": \"課題：\\\"0.10\\\" と \\\"0.20\\\" を加算し、0.30 を出力\"\n  },\n  \"reads-script\": {\n    \"zh\": \"读取脚本\",\n    \"en\": \"Read the script\",\n    \"ja\": \"スクリプトを読む\"\n  },\n  \"float-source\": {\n    \"zh\": \"读取到 float 求和代码\",\n    \"en\": \"Find a float-based sum\",\n    \"ja\": \"float による加算を確認\"\n  },\n  \"run-test\": {\n    \"zh\": \"运行测试\",\n    \"en\": \"Run the test\",\n    \"ja\": \"テストを実行\"\n  },\n  \"fail\": {\n    \"zh\": \"测试失败\",\n    \"en\": \"Test fails\",\n    \"ja\": \"テスト失敗\"\n  },\n  \"patch\": {\n    \"zh\": \"写入修复\",\n    \"en\": \"Apply the patch\",\n    \"ja\": \"修正を適用\"\n  },\n  \"patched\": {\n    \"zh\": \"文件已更新\",\n    \"en\": \"File updated\",\n    \"ja\": \"ファイルを更新\"\n  },\n  \"retest\": {\n    \"zh\": \"再次测试\",\n    \"en\": \"Test again\",\n    \"ja\": \"再テスト\"\n  },\n  \"passed\": {\n    \"zh\": \"测试通过\",\n    \"en\": \"Test passes\",\n    \"ja\": \"テスト成功\"\n  },\n  \"submit\": {\n    \"zh\": \"提交修复与测试结果\",\n    \"en\": \"Submit the fix and test result\",\n    \"ja\": \"修正とテスト結果を提出\"\n  },\n  \"rm-end\": {\n    \"zh\": \"RM 读取完整执行，给分 R = 8\",\n    \"en\": \"RM reads the completed attempt: R = 8\",\n    \"ja\": \"RM が完了した実行を評価：R = 8\"\n  },\n  \"critic-title\": {\n    \"zh\": \"C · 从完整结果构造 Critic 的训练样本\",\n    \"en\": \"C · Turning outcomes into Critic training data\",\n    \"ja\": \"C · 実行結果から Critic の学習例を作る\"\n  },\n  \"critic-caption\": {\n    \"zh\": \"图 4 · 同一条执行产生多条“历史前缀—回报目标”样本。只在终点给 R=8，β=0、γ=λ=1，故两处目标均为 8，优势分别为 3 与 1。本次回归使用固定目标。\",\n    \"en\": \"Figure 4 · One execution supplies several prefix–return pairs. With terminal-only R=8, β=0 and γ=λ=1, both targets are 8; the advantages are 3 and 1. The targets stay fixed for this regression update.\",\n    \"ja\": \"図 4 · 一回の実行から複数の「接頭辞—リターン目標」を作る。終点のみ R=8、β=0、γ=λ=1 では両目標は 8、アドバンテージは 3 と 1。この回帰中は目標を固定する。\"\n  },\n  \"finished\": {\n    \"zh\": \"完整修复轨迹 τ\",\n    \"en\": \"Completed repair τ\",\n    \"ja\": \"完了した修正の軌跡 τ\"\n  },\n  \"prefixes\": {\n    \"zh\": \"两个位置的前缀\",\n    \"en\": \"Prefixes at two positions\",\n    \"ja\": \"二つの位置の接頭辞\"\n  },\n  \"prefixes-sub\": {\n    \"zh\": \"h₁：修复前　h₂：修复后\",\n    \"en\": \"h₁: before repair · h₂: after repair\",\n    \"ja\": \"h₁：修正前　h₂：修正後\"\n  },\n  \"predict\": {\n    \"zh\": \"预测后续回报\",\n    \"en\": \"Predict future returns\",\n    \"ja\": \"今後のリターンを予測\"\n  },\n  \"two-values\": {\n    \"zh\": \"本次预测\",\n    \"en\": \"Current predictions\",\n    \"ja\": \"現在の予測\"\n  },\n  \"gae-target\": {\n    \"zh\": \"GAE · 构造目标\",\n    \"en\": \"GAE · Build targets\",\n    \"ja\": \"GAE・目標を作る\"\n  },\n  \"critic-loss\": {\n    \"zh\": \"价值回归损失\",\n    \"en\": \"Value regression loss\",\n    \"ja\": \"価値の回帰損失\"\n  },\n  \"critic-gradient\": {\n    \"zh\": \"反向传播 · 更新 Critic\",\n    \"en\": \"Backpropagation · update Critic\",\n    \"ja\": \"逆伝播で Critic を更新\"\n  },\n  \"to-actor\": {\n    \"zh\": \"A<sub>t</sub> 供 Actor 更新\",\n    \"en\": \"A<sub>t</sub> goes to the Actor update\",\n    \"ja\": \"A<sub>t</sub> は Actor の更新へ\"\n  },\n  \"ppo-title\": {\n    \"zh\": \"D · Actor 如何用同一批轨迹学习\",\n    \"en\": \"D · How the Actor learns from a batch\",\n    \"ja\": \"D · Actor は同じバッチからどう学ぶか\"\n  },\n  \"ppo-caption\": {\n    \"zh\": \"图 5 · 重算已采样 token 的概率，与采样时保存的旧概率比较。优势给出更新方向，裁剪目标抑制过大的改动。新 Actor 再收集下一批轨迹。\",\n    \"en\": \"Figure 5 · Recompute probabilities for sampled tokens and compare them with saved collection probabilities. Advantages provide the update direction; clipping limits incentives for large changes. The updated Actor collects a new batch.\",\n    \"ja\": \"図 5 · 採用済み token の確率を再計算し、保存した旧確率と比較する。アドバンテージが更新方向を与え、クリップで大きな変化への誘因を抑える。更新後の Actor で次のバッチを収集する。\"\n  },\n  \"batch\": {\n    \"zh\": \"固定的一批轨迹\",\n    \"en\": \"One fixed batch\",\n    \"ja\": \"固定した一つのバッチ\"\n  },\n  \"batch-sub\": {\n    \"zh\": \"前缀 h<sub>t</sub> · 已采样 token a<sub>t</sub>\",\n    \"en\": \"Prefix h<sub>t</sub> · sampled token a<sub>t</sub>\",\n    \"ja\": \"接頭辞 h<sub>t</sub>・採用済み token a<sub>t</sub>\"\n  },\n  \"current-actor\": {\n    \"zh\": \"正在训练的 Actor\",\n    \"en\": \"Actor being optimized\",\n    \"ja\": \"更新中の Actor\"\n  },\n  \"new-prob\": {\n    \"zh\": \"重新计算概率\",\n    \"en\": \"Recompute probabilities\",\n    \"ja\": \"確率を再計算\"\n  },\n  \"saved-prob\": {\n    \"zh\": \"采样时保存的概率\",\n    \"en\": \"Saved collection probabilities\",\n    \"ja\": \"収集時に保存した確率\"\n  },\n  \"ratio\": {\n    \"zh\": \"新旧概率比 ρ<sub>t</sub>\",\n    \"en\": \"Probability ratio ρ<sub>t</sub>\",\n    \"ja\": \"新旧確率比 ρ<sub>t</sub>\"\n  },\n  \"clip-loss\": {\n    \"zh\": \"PPO 裁剪损失\",\n    \"en\": \"Clipped PPO loss\",\n    \"ja\": \"PPO クリップ損失\"\n  },\n  \"actor-gradient\": {\n    \"zh\": \"反向传播 · 更新 Actor 参数 θ\",\n    \"en\": \"Backpropagation · update Actor weights θ\",\n    \"ja\": \"逆伝播で Actor の重み θ を更新\"\n  }\n}\n",
    "figures/ppo-figures.css": ".ppo-figure{width:min(1240px,calc(100vw - 56px));margin:42px 0 48px 50%;transform:translateX(-50%);color:var(--diagram-ink,var(--ink,#262a27));font-family:inherit;font-size:16px;line-height:1.6}\n.ppo-figure *{box-sizing:border-box}\n.ppo-figure-heading{padding:14px 0 16px;border-bottom:1px solid var(--line,#dfe2dc);font-size:14px;line-height:1.7;color:var(--muted,#62675e)}\n.ppo-figure-scroll{overflow:auto;max-height:1100px;overscroll-behavior:auto;touch-action:pan-x pan-y pinch-zoom;scrollbar-width:thin;scrollbar-color:var(--diagram-border,#adb3a6) transparent;outline-offset:4px;padding-top:18px}\n.ppo-figure-scroll:focus-visible{outline:1px solid var(--diagram-accent,#6b8e40)}\n.ppo-figure .canvas{position:relative;flex:none;font-family:Arial,\"Hiragino Sans\",\"Microsoft YaHei\",sans-serif;font-size:16px;line-height:1.55;color:var(--diagram-ink,#262a27);background:var(--diagram-paper,#fff);margin:auto}\n.ppo-figure .node{position:absolute;z-index:2;border:1px solid var(--diagram-border,#60665a);border-radius:9px;background:var(--diagram-paper,#fff);padding:10px 12px;display:flex;flex-direction:column;justify-content:center;gap:4px;text-align:center;color:var(--diagram-ink,#262a27);text-decoration:none;font-size:18px;font-weight:400;line-height:1.4}\n.ppo-figure .node strong{font:inherit;color:inherit;letter-spacing:0}\n.ppo-figure .node .sub{display:block;font-size:13px;font-weight:400;line-height:1.45;color:var(--diagram-muted,#65695f)}\n.ppo-figure a.node:hover,.ppo-figure a.node:focus-visible{outline:2px solid var(--diagram-accent,#699c35);outline-offset:4px}\n.ppo-figure .edge{position:absolute;display:block;height:0;border-top:1.5px solid var(--diagram-line,#454a40);transform-origin:left center;z-index:0}\n.ppo-figure .edge.arrow:after{content:'';position:absolute;right:-1px;top:-4px;border-left:7px solid var(--diagram-line,#454a40);border-top:3px solid transparent;border-bottom:3px solid transparent}\n.ppo-figure .edge.cache{border-top-style:dashed}\n.ppo-figure .edge.feedback{border-color:var(--diagram-accent,#699c35)}\n.ppo-figure .edge.feedback.arrow:after{border-left-color:var(--diagram-accent,#699c35)}\n.ppo-figure .ppo-label{position:absolute;z-index:1;padding:3px 4px;text-align:center;color:var(--diagram-muted,#65695f);background:var(--diagram-paper,#fff);font-size:13px;line-height:1.45}\n.ppo-figure .ppo-label.stage{font-size:15px;text-align:left;color:var(--diagram-ink,#262a27);padding-left:0}\n.ppo-figure .ppo-label.task-title{font-size:17px;text-align:left;color:var(--diagram-ink,#262a27);padding-left:0}\n.ppo-figure .math-label{font-family:Georgia,'Times New Roman',serif;font-size:18px;color:var(--diagram-ink,#262a27)}\n.ppo-figure .ppo-divider{position:absolute;border-top:1px solid var(--line,#dfe2dc)}\n.ppo-figure .ppo-lifeline{position:absolute;border-left:1px dashed var(--diagram-border,#909889);opacity:.5}\n.ppo-figure figcaption{font-size:13px;line-height:1.8;color:var(--muted,#65695f);margin-top:16px;max-width:1050px}\n.ppo-figure[data-diagram-style=\"openai-blog\"] .node.soft,.ppo-figure[data-diagram-style=\"openai-blog\"] .node.accent{background-color:var(--diagram-soft,#f5faef);background-image:radial-gradient(#70a33d38 .5px,transparent .65px);background-size:5px 5px;border-color:var(--diagram-accent,#699c35)}\n.ppo-figure[data-diagram-style=\"engineering\"] .node{border-radius:3px;background-image:none}\nhtml[data-theme=\"dark\"] .ppo-figure{--diagram-paper:var(--paper,var(--bg,#181b19));--diagram-ink:var(--ink,#e5e7de);--diagram-muted:var(--muted,#abb2a5);--diagram-line:#aab3a0;--diagram-border:#87927d;--diagram-accent:#a8c984;--diagram-soft:#263321}\nhtml[data-theme=\"dark\"] .ppo-figure .canvas .node{background-color:var(--diagram-paper)!important}\nhtml[data-theme=\"dark\"] .ppo-figure[data-diagram-style=\"openai-blog\"] .canvas .node:is(.soft,.accent){background-color:var(--diagram-soft)!important}\nhtml[data-theme=\"dark\"] .ppo-figure .canvas :is(.ppo-label,.sub){color:var(--diagram-muted);background-color:transparent}\n@media(max-width:700px){.ppo-figure{width:100%;margin:30px 0 36px;transform:none}.ppo-figure-scroll{max-height:78vh}.ppo-figure figcaption{font-size:12px}}\n@media print{.ppo-figure{width:100%;margin:24px 0;transform:none;break-inside:avoid}.ppo-figure-scroll{max-height:none;overflow:visible}}\n",
    "figures/ppo-update.en.html": "<figure class=\"ppo-figure\" id=\"figure-ppo-update\" data-diagram-style=\"openai-blog\" data-diagram-kind=\"flow\"><div class=\"ppo-figure-heading\">D · How the Actor learns from a batch</div><div class=\"ppo-figure-scroll\" role=\"region\" tabindex=\"0\" aria-label=\"D · How the Actor learns from a batch\"><div class=\"canvas ppo-canvas\" style=\"width:1175px;height:595px\"><div class=\"node ppo-node\" style=\"left:23.5px;top:60px;width:253.8px;height:90px\"><strong>One fixed batch</strong><span class=\"sub\">Prefix h<sub>t</sub> · sampled token a<sub>t</sub></span></div><div class=\"node ppo-node soft\" style=\"left:361.9px;top:60px;width:235px;height:90px\"><strong>Actor being optimized</strong><span class=\"sub\">π<sub>θ</sub></span></div><div class=\"node ppo-node\" style=\"left:690.9px;top:60px;width:216.2px;height:90px\"><strong>Recompute probabilities</strong><span class=\"sub\">π<sub>θ</sub>(a<sub>t</sub> | h<sub>t</sub>)</span></div><div class=\"node ppo-node\" style=\"left:23.5px;top:290px;width:253.8px;height:90px\"><strong>Saved collection probabilities</strong><span class=\"sub\">π<sub>old</sub>(a<sub>t</sub> | h<sub>t</sub>)</span></div><div class=\"node ppo-node\" style=\"left:690.9px;top:290px;width:216.2px;height:90px\"><strong>Probability ratio ρ<sub>t</sub></strong><span class=\"sub\">π<sub>θ</sub> / π<sub>old</sub></span></div><div class=\"node ppo-node\" style=\"left:361.9px;top:290px;width:235px;height:90px\"><strong>Advantages A<sub>t</sub></strong><span class=\"sub\">GAE → A<sub>t</sub></span></div><div class=\"node ppo-node accent\" style=\"left:968.2px;top:290px;width:178.6px;height:90px\"><strong>Clipped PPO loss</strong></div><i aria-hidden=\"true\" class=\"edge arrow\" style=\"left:277.3px;top:105px;width:84.6px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge arrow\" style=\"left:596.9px;top:105px;width:94px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge arrow\" style=\"left:799px;top:150px;width:140.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge cache arrow\" style=\"left:150.4px;top:150px;width:140.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge\" style=\"left:277.3px;top:335px;width:37.6px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge\" style=\"left:314.9px;top:335px;width:95.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge\" style=\"left:314.9px;top:430px;width:484.1px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge arrow\" style=\"left:799px;top:430px;width:50.0px;transform:rotate(-90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge arrow\" style=\"left:907.1px;top:335px;width:61.1px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge\" style=\"left:596.9px;top:335px;width:42.3px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge\" style=\"left:639.2px;top:335px;width:95.0px;transform:rotate(-90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge\" style=\"left:639.2px;top:240px;width:418.3px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge arrow\" style=\"left:1057.5px;top:240px;width:50.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback\" style=\"left:1057.5px;top:380px;width:165.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback\" style=\"left:1057.5px;top:545px;width:733.2px;transform:rotate(180.0deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback\" style=\"left:324.3px;top:545px;width:340.0px;transform:rotate(-90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback\" style=\"left:324.3px;top:205px;width:155.1px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback arrow\" style=\"left:479.4px;top:205px;width:55.0px;transform:rotate(-90.0deg)\"></i><div class=\"ppo-label\" style=\"left:587.5px;top:517px;width:423px\">Backpropagation · update Actor weights θ</div></div></div><figcaption>Figure 5 · Recompute probabilities for sampled tokens and compare them with saved collection probabilities. Advantages provide the update direction; clipping limits incentives for large changes. The updated Actor collects a new batch.</figcaption></figure>",
    "figures/ppo-update.ja.html": "<figure class=\"ppo-figure\" id=\"figure-ppo-update\" data-diagram-style=\"openai-blog\" data-diagram-kind=\"flow\"><div class=\"ppo-figure-heading\">D · Actor は同じバッチからどう学ぶか</div><div class=\"ppo-figure-scroll\" role=\"region\" tabindex=\"0\" aria-label=\"D · Actor は同じバッチからどう学ぶか\"><div class=\"canvas ppo-canvas\" style=\"width:1175px;height:595px\"><div class=\"node ppo-node\" style=\"left:23.5px;top:60px;width:253.8px;height:90px\"><strong>固定した一つのバッチ</strong><span class=\"sub\">接頭辞 h<sub>t</sub>・採用済み token a<sub>t</sub></span></div><div class=\"node ppo-node soft\" style=\"left:361.9px;top:60px;width:235px;height:90px\"><strong>更新中の Actor</strong><span class=\"sub\">π<sub>θ</sub></span></div><div class=\"node ppo-node\" style=\"left:690.9px;top:60px;width:216.2px;height:90px\"><strong>確率を再計算</strong><span class=\"sub\">π<sub>θ</sub>(a<sub>t</sub> | h<sub>t</sub>)</span></div><div class=\"node ppo-node\" style=\"left:23.5px;top:290px;width:253.8px;height:90px\"><strong>収集時に保存した確率</strong><span class=\"sub\">π<sub>old</sub>(a<sub>t</sub> | h<sub>t</sub>)</span></div><div class=\"node ppo-node\" style=\"left:690.9px;top:290px;width:216.2px;height:90px\"><strong>新旧確率比 ρ<sub>t</sub></strong><span class=\"sub\">π<sub>θ</sub> / π<sub>old</sub></span></div><div class=\"node ppo-node\" style=\"left:361.9px;top:290px;width:235px;height:90px\"><strong>アドバンテージ A<sub>t</sub></strong><span class=\"sub\">GAE → A<sub>t</sub></span></div><div class=\"node ppo-node accent\" style=\"left:968.2px;top:290px;width:178.6px;height:90px\"><strong>PPO クリップ損失</strong></div><i aria-hidden=\"true\" class=\"edge arrow\" style=\"left:277.3px;top:105px;width:84.6px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge arrow\" style=\"left:596.9px;top:105px;width:94px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge arrow\" style=\"left:799px;top:150px;width:140.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge cache arrow\" style=\"left:150.4px;top:150px;width:140.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge\" style=\"left:277.3px;top:335px;width:37.6px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge\" style=\"left:314.9px;top:335px;width:95.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge\" style=\"left:314.9px;top:430px;width:484.1px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge arrow\" style=\"left:799px;top:430px;width:50.0px;transform:rotate(-90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge arrow\" style=\"left:907.1px;top:335px;width:61.1px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge\" style=\"left:596.9px;top:335px;width:42.3px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge\" style=\"left:639.2px;top:335px;width:95.0px;transform:rotate(-90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge\" style=\"left:639.2px;top:240px;width:418.3px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge arrow\" style=\"left:1057.5px;top:240px;width:50.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback\" style=\"left:1057.5px;top:380px;width:165.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback\" style=\"left:1057.5px;top:545px;width:733.2px;transform:rotate(180.0deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback\" style=\"left:324.3px;top:545px;width:340.0px;transform:rotate(-90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback\" style=\"left:324.3px;top:205px;width:155.1px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback arrow\" style=\"left:479.4px;top:205px;width:55.0px;transform:rotate(-90.0deg)\"></i><div class=\"ppo-label\" style=\"left:587.5px;top:517px;width:423px\">逆伝播で Actor の重み θ を更新</div></div></div><figcaption>図 5 · 採用済み token の確率を再計算し、保存した旧確率と比較する。アドバンテージが更新方向を与え、クリップで大きな変化への誘因を抑える。更新後の Actor で次のバッチを収集する。</figcaption></figure>",
    "figures/ppo-update.zh.html": "<figure class=\"ppo-figure\" id=\"figure-ppo-update\" data-diagram-style=\"openai-blog\" data-diagram-kind=\"flow\"><div class=\"ppo-figure-heading\">D · Actor 如何用同一批轨迹学习</div><div class=\"ppo-figure-scroll\" role=\"region\" tabindex=\"0\" aria-label=\"D · Actor 如何用同一批轨迹学习\"><div class=\"canvas ppo-canvas\" style=\"width:1175px;height:595px\"><div class=\"node ppo-node\" style=\"left:23.5px;top:60px;width:253.8px;height:90px\"><strong>固定的一批轨迹</strong><span class=\"sub\">前缀 h<sub>t</sub> · 已采样 token a<sub>t</sub></span></div><div class=\"node ppo-node soft\" style=\"left:361.9px;top:60px;width:235px;height:90px\"><strong>正在训练的 Actor</strong><span class=\"sub\">π<sub>θ</sub></span></div><div class=\"node ppo-node\" style=\"left:690.9px;top:60px;width:216.2px;height:90px\"><strong>重新计算概率</strong><span class=\"sub\">π<sub>θ</sub>(a<sub>t</sub> | h<sub>t</sub>)</span></div><div class=\"node ppo-node\" style=\"left:23.5px;top:290px;width:253.8px;height:90px\"><strong>采样时保存的概率</strong><span class=\"sub\">π<sub>old</sub>(a<sub>t</sub> | h<sub>t</sub>)</span></div><div class=\"node ppo-node\" style=\"left:690.9px;top:290px;width:216.2px;height:90px\"><strong>新旧概率比 ρ<sub>t</sub></strong><span class=\"sub\">π<sub>θ</sub> / π<sub>old</sub></span></div><div class=\"node ppo-node\" style=\"left:361.9px;top:290px;width:235px;height:90px\"><strong>优势 A<sub>t</sub></strong><span class=\"sub\">GAE → A<sub>t</sub></span></div><div class=\"node ppo-node accent\" style=\"left:968.2px;top:290px;width:178.6px;height:90px\"><strong>PPO 裁剪损失</strong></div><i aria-hidden=\"true\" class=\"edge arrow\" style=\"left:277.3px;top:105px;width:84.6px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge arrow\" style=\"left:596.9px;top:105px;width:94px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge arrow\" style=\"left:799px;top:150px;width:140.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge cache arrow\" style=\"left:150.4px;top:150px;width:140.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge\" style=\"left:277.3px;top:335px;width:37.6px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge\" style=\"left:314.9px;top:335px;width:95.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge\" style=\"left:314.9px;top:430px;width:484.1px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge arrow\" style=\"left:799px;top:430px;width:50.0px;transform:rotate(-90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge arrow\" style=\"left:907.1px;top:335px;width:61.1px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge\" style=\"left:596.9px;top:335px;width:42.3px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge\" style=\"left:639.2px;top:335px;width:95.0px;transform:rotate(-90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge\" style=\"left:639.2px;top:240px;width:418.3px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge arrow\" style=\"left:1057.5px;top:240px;width:50.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback\" style=\"left:1057.5px;top:380px;width:165.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback\" style=\"left:1057.5px;top:545px;width:733.2px;transform:rotate(180.0deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback\" style=\"left:324.3px;top:545px;width:340.0px;transform:rotate(-90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback\" style=\"left:324.3px;top:205px;width:155.1px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback arrow\" style=\"left:479.4px;top:205px;width:55.0px;transform:rotate(-90.0deg)\"></i><div class=\"ppo-label\" style=\"left:587.5px;top:517px;width:423px\">反向传播 · 更新 Actor 参数 θ</div></div></div><figcaption>图 5 · 重算已采样 token 的概率，与采样时保存的旧概率比较。优势给出更新方向，裁剪目标抑制过大的改动。新 Actor 再收集下一批轨迹。</figcaption></figure>",
    "figures/reward-value-training.en.html": "<figure class=\"ppo-figure\" id=\"figure-reward-value-training\" data-diagram-style=\"openai-blog\" data-diagram-kind=\"flow\"><div class=\"ppo-figure-heading\">A · How the reward model learns</div><div class=\"ppo-figure-scroll\" role=\"region\" tabindex=\"0\" aria-label=\"A · How the reward model learns\"><div class=\"canvas ppo-canvas\" style=\"width:1150px;height:425px\"><div class=\"node ppo-node \" style=\"left:25px;top:55px;width:310px;height:95px\"><strong>Task + complete attempt A</strong><span class=\"sub\">Decimal sum → output 0.30</span></div><div class=\"node ppo-node \" style=\"left:25px;top:240px;width:310px;height:95px\"><strong>Task + complete attempt B</strong><span class=\"sub\">float sum → rounding error</span></div><div class=\"node ppo-node soft\" style=\"left:420px;top:140px;width:230px;height:105px\"><strong>One shared RM</strong><span class=\"sub\">Language model + scalar head</span></div><div class=\"node ppo-node \" style=\"left:735px;top:140px;width:150px;height:105px\"><strong>Two forward passes</strong><span class=\"sub\">r<sub>A</sub>, r<sub>B</sub></span></div><div class=\"ppo-label \" style=\"left:890px;top:30px;width:235px\">Preference label: A over B</div><div class=\"node ppo-node accent\" style=\"left:935px;top:140px;width:190px;height:105px\"><strong>Preference loss</strong><span class=\"sub\">−log σ(r<sub>A</sub> − r<sub>B</sub>)</span></div><i aria-hidden=\"true\" class=\"edge \" style=\"left:335px;top:102px;width:40.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge \" style=\"left:375px;top:102px;width:67.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:375px;top:169px;width:45.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge \" style=\"left:335px;top:287px;width:40.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge \" style=\"left:375px;top:287px;width:71.0px;transform:rotate(-90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:375px;top:216px;width:45.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:650px;top:193px;width:85.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:885px;top:193px;width:50.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:1030px;top:65px;width:75.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback\" style=\"left:1030px;top:245px;width:137.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback\" style=\"left:1030px;top:382px;width:495.0px;transform:rotate(180.0deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback arrow\" style=\"left:535px;top:382px;width:137.0px;transform:rotate(-90.0deg)\"></i><div class=\"ppo-label \" style=\"left:595px;top:355px;width:410px\">Backpropagation · update RM weights</div></div></div><figcaption>Figure 2 · Two complete attempts pass through the same RM. Preference labels supervise score ordering; gradients update the RM. The trained RM stays fixed during PPO.</figcaption></figure>",
    "figures/reward-value-training.ja.html": "<figure class=\"ppo-figure\" id=\"figure-reward-value-training\" data-diagram-style=\"openai-blog\" data-diagram-kind=\"flow\"><div class=\"ppo-figure-heading\">A · 報酬モデルはどう学ぶか</div><div class=\"ppo-figure-scroll\" role=\"region\" tabindex=\"0\" aria-label=\"A · 報酬モデルはどう学ぶか\"><div class=\"canvas ppo-canvas\" style=\"width:1150px;height:425px\"><div class=\"node ppo-node \" style=\"left:25px;top:55px;width:310px;height:95px\"><strong>課題＋完了済み実行 A</strong><span class=\"sub\">Decimal で加算 → 0.30</span></div><div class=\"node ppo-node \" style=\"left:25px;top:240px;width:310px;height:95px\"><strong>課題＋完了済み実行 B</strong><span class=\"sub\">float で加算 → 誤差が残る</span></div><div class=\"node ppo-node soft\" style=\"left:420px;top:140px;width:230px;height:105px\"><strong>同一の RM</strong><span class=\"sub\">言語モデル＋スカラーヘッド</span></div><div class=\"node ppo-node \" style=\"left:735px;top:140px;width:150px;height:105px\"><strong>二回の順伝播</strong><span class=\"sub\">r<sub>A</sub>, r<sub>B</sub></span></div><div class=\"ppo-label \" style=\"left:890px;top:30px;width:235px\">選好ラベル：A が B より良い</div><div class=\"node ppo-node accent\" style=\"left:935px;top:140px;width:190px;height:105px\"><strong>選好損失</strong><span class=\"sub\">−log σ(r<sub>A</sub> − r<sub>B</sub>)</span></div><i aria-hidden=\"true\" class=\"edge \" style=\"left:335px;top:102px;width:40.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge \" style=\"left:375px;top:102px;width:67.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:375px;top:169px;width:45.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge \" style=\"left:335px;top:287px;width:40.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge \" style=\"left:375px;top:287px;width:71.0px;transform:rotate(-90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:375px;top:216px;width:45.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:650px;top:193px;width:85.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:885px;top:193px;width:50.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:1030px;top:65px;width:75.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback\" style=\"left:1030px;top:245px;width:137.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback\" style=\"left:1030px;top:382px;width:495.0px;transform:rotate(180.0deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback arrow\" style=\"left:535px;top:382px;width:137.0px;transform:rotate(-90.0deg)\"></i><div class=\"ppo-label \" style=\"left:595px;top:355px;width:410px\">逆伝播で RM の重みを更新</div></div></div><figcaption>図 2 · 二つの完了済み実行を同一の RM で採点する。選好ラベルでスコアの順序を学び、損失を RM に逆伝播する。学習後は PPO 中に固定する。</figcaption></figure>",
    "figures/reward-value-training.zh.html": "<figure class=\"ppo-figure\" id=\"figure-reward-value-training\" data-diagram-style=\"openai-blog\" data-diagram-kind=\"flow\"><div class=\"ppo-figure-heading\">A · 奖励模型怎样学会评分</div><div class=\"ppo-figure-scroll\" role=\"region\" tabindex=\"0\" aria-label=\"A · 奖励模型怎样学会评分\"><div class=\"canvas ppo-canvas\" style=\"width:1150px;height:425px\"><div class=\"node ppo-node \" style=\"left:25px;top:55px;width:310px;height:95px\"><strong>任务 + 完整执行 A</strong><span class=\"sub\">Decimal 求和 → 输出 0.30</span></div><div class=\"node ppo-node \" style=\"left:25px;top:240px;width:310px;height:95px\"><strong>任务 + 完整执行 B</strong><span class=\"sub\">float 求和 → 保留误差</span></div><div class=\"node ppo-node soft\" style=\"left:420px;top:140px;width:230px;height:105px\"><strong>同一个 RM</strong><span class=\"sub\">语言模型 + 标量头</span></div><div class=\"node ppo-node \" style=\"left:735px;top:140px;width:150px;height:105px\"><strong>两次前向计算</strong><span class=\"sub\">r<sub>A</sub>, r<sub>B</sub></span></div><div class=\"ppo-label \" style=\"left:890px;top:30px;width:235px\">偏好标签：A 优于 B</div><div class=\"node ppo-node accent\" style=\"left:935px;top:140px;width:190px;height:105px\"><strong>偏好损失</strong><span class=\"sub\">−log σ(r<sub>A</sub> − r<sub>B</sub>)</span></div><i aria-hidden=\"true\" class=\"edge \" style=\"left:335px;top:102px;width:40.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge \" style=\"left:375px;top:102px;width:67.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:375px;top:169px;width:45.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge \" style=\"left:335px;top:287px;width:40.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge \" style=\"left:375px;top:287px;width:71.0px;transform:rotate(-90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:375px;top:216px;width:45.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:650px;top:193px;width:85.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:885px;top:193px;width:50.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:1030px;top:65px;width:75.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback\" style=\"left:1030px;top:245px;width:137.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback\" style=\"left:1030px;top:382px;width:495.0px;transform:rotate(180.0deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback arrow\" style=\"left:535px;top:382px;width:137.0px;transform:rotate(-90.0deg)\"></i><div class=\"ppo-label \" style=\"left:595px;top:355px;width:410px\">反向传播 · 更新 RM 参数</div></div></div><figcaption>图 2 · 两条完整执行分别经过同一个 RM。偏好标签监督分数的相对顺序，损失反向传播到 RM。训练完成后，RM 在 PPO 中固定。</figcaption></figure>",
    "figures/training-overview.en.html": "<figure class=\"ppo-figure\" id=\"figure-training-overview\" data-diagram-style=\"openai-blog\" data-diagram-kind=\"flow\"><div class=\"ppo-figure-heading\">The complete training loop</div><div class=\"ppo-figure-scroll\" role=\"region\" tabindex=\"0\" aria-label=\"The complete training loop\"><div class=\"canvas ppo-canvas\" style=\"width:1140px;height:785px\"><div class=\"ppo-label stage\" style=\"left:30px;top:10px;width:1070px\">A · Before PPO</div><a class=\"node ppo-node \" href=\"#reward-model\" style=\"left:30px;top:48px;width:140px;height:62px\"><strong>Examples</strong></a><a class=\"node ppo-node \" href=\"#reward-model\" style=\"left:215px;top:48px;width:170px;height:62px\"><strong>Supervised fine-tuning</strong></a><a class=\"node ppo-node \" href=\"#reward-model\" style=\"left:430px;top:48px;width:270px;height:62px\"><strong>Actor + Reference</strong><span class=\"sub\">Two copies of the initial policy</span></a><a class=\"node ppo-node \" href=\"#reward-model\" style=\"left:755px;top:48px;width:130px;height:62px\"><strong>Preference pairs</strong></a><a class=\"node ppo-node \" href=\"#reward-model\" style=\"left:930px;top:48px;width:170px;height:62px\"><strong>Train RM</strong></a><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:170px;top:79px;width:45.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:385px;top:79px;width:45.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:885px;top:79px;width:45.0px;transform:rotate(0.0deg)\"></i><div class=\"ppo-divider\" style=\"left:30px;top:145px;width:1070px\"></div><div class=\"ppo-label stage\" style=\"left:30px;top:145px;width:280px\">B · Collect trajectories</div><div class=\"ppo-label stage\" style=\"left:580px;top:145px;width:520px\">C · Rewards and advantages</div><div class=\"ppo-label stage\" style=\"left:35px;top:617px;width:210px\">D · Parameter updates</div><a class=\"node ppo-node soft\" href=\"#rollout\" style=\"left:30px;top:255px;width:180px;height:82px\"><strong>Actor</strong><span class=\"sub\">Current policy π<sub>old</sub></span></a><a class=\"node ppo-node \" href=\"#rollout\" style=\"left:30px;top:407px;width:180px;height:82px\"><strong>Tool environment</strong><span class=\"sub\">Files · shell · tests</span></a><a class=\"node ppo-node \" href=\"#rollout\" style=\"left:285px;top:255px;width:220px;height:100px\"><strong>Trajectory record</strong><span class=\"sub\">Task + actions + observations</span></a><a class=\"node ppo-node \" href=\"#reward-model\" style=\"left:590px;top:205px;width:180px;height:72px\"><strong>RM</strong><span class=\"sub\">Fixed weights</span></a><a class=\"node ppo-node \" href=\"#advantages\" style=\"left:590px;top:335px;width:180px;height:72px\"><strong>Reference</strong><span class=\"sub\">Fixed weights</span></a><a class=\"node ppo-node soft\" href=\"#advantages\" style=\"left:590px;top:462px;width:180px;height:72px\"><strong>Critic</strong><span class=\"sub\">Reads each history prefix</span></a><a class=\"node ppo-node \" href=\"#advantages\" style=\"left:870px;top:245px;width:230px;height:88px\"><strong>Construct rewards r<sub>t</sub></strong><span class=\"sub\">Terminal score + KL penalty</span></a><a class=\"node ppo-node \" href=\"#advantages\" style=\"left:870px;top:452px;width:230px;height:88px\"><strong>GAE</strong><span class=\"sub\">Propagate feedback backward</span></a><a class=\"node ppo-node accent\" href=\"#optimization\" style=\"left:285px;top:632px;width:230px;height:82px\"><strong>Update Actor</strong><span class=\"sub\">Clipped PPO objective</span></a><a class=\"node ppo-node accent\" href=\"#advantages\" style=\"left:590px;top:632px;width:230px;height:82px\"><strong>Update Critic</strong><span class=\"sub\">Fit return targets Ĝ<sub>t</sub></span></a><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:210px;top:296px;width:75.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:75px;top:337px;width:70px;transform:rotate(90deg)\"></i><div class=\"ppo-label \" style=\"left:25px;top:379px;width:115px\">Tool calls</div><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:165px;top:407px;width:70px;transform:rotate(-90deg)\"></i><div class=\"ppo-label \" style=\"left:146px;top:360px;width:125px\">Observations</div><i aria-hidden=\"true\" class=\"edge \" style=\"left:210px;top:447px;width:45.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge \" style=\"left:255px;top:447px;width:107px;transform:rotate(-90deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:255px;top:340px;width:30.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge \" style=\"left:505px;top:280px;width:40.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge \" style=\"left:545px;top:280px;width:39px;transform:rotate(-90deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:545px;top:241px;width:45.0px;transform:rotate(0.0deg)\"></i><div class=\"ppo-label \" style=\"left:490px;top:205px;width:100px\">Complete execution</div><i aria-hidden=\"true\" class=\"edge \" style=\"left:505px;top:305px;width:53.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge \" style=\"left:558px;top:305px;width:66px;transform:rotate(90deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:558px;top:371px;width:32.0px;transform:rotate(0.0deg)\"></i><div class=\"ppo-label \" style=\"left:472px;top:378px;width:118px\">Prefix + token</div><i aria-hidden=\"true\" class=\"edge \" style=\"left:505px;top:330px;width:35.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge \" style=\"left:540px;top:330px;width:168px;transform:rotate(90deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:540px;top:498px;width:50.0px;transform:rotate(0.0deg)\"></i><div class=\"ppo-label \" style=\"left:470px;top:427px;width:115px\">Prefix h<sub>t</sub></div><i aria-hidden=\"true\" class=\"edge \" style=\"left:770px;top:241px;width:50.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge \" style=\"left:820px;top:241px;width:35px;transform:rotate(90deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:820px;top:276px;width:50.0px;transform:rotate(0.0deg)\"></i><div class=\"ppo-label \" style=\"left:775px;top:200px;width:95px\">Score R</div><i aria-hidden=\"true\" class=\"edge \" style=\"left:770px;top:371px;width:50.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge \" style=\"left:820px;top:371px;width:61px;transform:rotate(-90deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:820px;top:310px;width:50.0px;transform:rotate(0.0deg)\"></i><div class=\"ppo-label \" style=\"left:775px;top:381px;width:96px\">Reference probabilities</div><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:985px;top:333px;width:119px;transform:rotate(90deg)\"></i><div class=\"ppo-label math-label\" style=\"left:960px;top:403px;width:50px\">r<sub>t</sub></div><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:770px;top:498px;width:100.0px;transform:rotate(0.0deg)\"></i><div class=\"ppo-label \" style=\"left:770px;top:461px;width:100px\">Values V<sub>t</sub></div><i aria-hidden=\"true\" class=\"edge \" style=\"left:910px;top:540px;width:7px;transform:rotate(90deg)\"></i><i aria-hidden=\"true\" class=\"edge \" style=\"left:910px;top:547px;width:510.0px;transform:rotate(180.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:400px;top:547px;width:85px;transform:rotate(90deg)\"></i><div class=\"ppo-label \" style=\"left:405px;top:517px;width:165px\">Advantages A<sub>t</sub></div><i aria-hidden=\"true\" class=\"edge \" style=\"left:1035px;top:540px;width:61px;transform:rotate(90deg)\"></i><i aria-hidden=\"true\" class=\"edge \" style=\"left:1035px;top:601px;width:330.0px;transform:rotate(180.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:705px;top:601px;width:31px;transform:rotate(90deg)\"></i><div class=\"ppo-label \" style=\"left:850px;top:552px;width:170px\">Return targets Ĝ<sub>t</sub></div><i aria-hidden=\"true\" class=\"edge cache\" style=\"left:400px;top:355px;width:172px;transform:rotate(90deg)\"></i><i aria-hidden=\"true\" class=\"edge cache\" style=\"left:400px;top:527px;width:80.0px;transform:rotate(180.0deg)\"></i><i aria-hidden=\"true\" class=\"edge cache arrow\" style=\"left:320px;top:527px;width:105px;transform:rotate(90deg)\"></i><div class=\"ppo-label \" style=\"left:270px;top:474px;width:230px\">Sampled tokens + old probabilities</div><i aria-hidden=\"true\" class=\"edge feedback\" style=\"left:400px;top:714px;width:26px;transform:rotate(90deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback\" style=\"left:400px;top:740px;width:390.0px;transform:rotate(180.0deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback\" style=\"left:10px;top:740px;width:444px;transform:rotate(-90deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback arrow\" style=\"left:10px;top:296px;width:20.0px;transform:rotate(0.0deg)\"></i><div class=\"ppo-label \" style=\"left:30px;top:750px;width:450px\">Updated Actor collects the next batch</div><i aria-hidden=\"true\" class=\"edge feedback\" style=\"left:705px;top:714px;width:26px;transform:rotate(90deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback\" style=\"left:705px;top:740px;width:125.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback\" style=\"left:830px;top:740px;width:200px;transform:rotate(-90deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback\" style=\"left:830px;top:540px;width:155.0px;transform:rotate(180.0deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback arrow\" style=\"left:675px;top:540px;width:6px;transform:rotate(-90deg)\"></i><div class=\"ppo-label \" style=\"left:650px;top:750px;width:400px\">Updated value predictions</div><i aria-hidden=\"true\" class=\"edge cache\" style=\"left:395px;top:255px;width:70px;transform:rotate(-90deg)\"></i><i aria-hidden=\"true\" class=\"edge cache\" style=\"left:395px;top:185px;width:590.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge cache arrow\" style=\"left:985px;top:185px;width:60px;transform:rotate(90deg)\"></i><div class=\"ppo-label \" style=\"left:365px;top:160px;width:190px\">Saved log π<sub>old</sub></div></div></div><figcaption>Figure 1 · A prepares models; B collects trajectories; C computes rewards and advantages; D updates Actor and Critic. RM and Reference stay fixed during PPO. Nodes link to the corresponding sections.</figcaption></figure>",
    "figures/training-overview.ja.html": "<figure class=\"ppo-figure\" id=\"figure-training-overview\" data-diagram-style=\"openai-blog\" data-diagram-kind=\"flow\"><div class=\"ppo-figure-heading\">学習の全体像</div><div class=\"ppo-figure-scroll\" role=\"region\" tabindex=\"0\" aria-label=\"学習の全体像\"><div class=\"canvas ppo-canvas\" style=\"width:1140px;height:785px\"><div class=\"ppo-label stage\" style=\"left:30px;top:10px;width:1070px\">A · PPO の前</div><a class=\"node ppo-node \" href=\"#reward-model\" style=\"left:30px;top:48px;width:140px;height:62px\"><strong>操作の実演</strong></a><a class=\"node ppo-node \" href=\"#reward-model\" style=\"left:215px;top:48px;width:170px;height:62px\"><strong>教師あり学習 SFT</strong></a><a class=\"node ppo-node \" href=\"#reward-model\" style=\"left:430px;top:48px;width:270px;height:62px\"><strong>Actor + Reference</strong><span class=\"sub\">同じ初期方策の二つのコピー</span></a><a class=\"node ppo-node \" href=\"#reward-model\" style=\"left:755px;top:48px;width:130px;height:62px\"><strong>選好ペア</strong></a><a class=\"node ppo-node \" href=\"#reward-model\" style=\"left:930px;top:48px;width:170px;height:62px\"><strong>RM を学習</strong></a><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:170px;top:79px;width:45.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:385px;top:79px;width:45.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:885px;top:79px;width:45.0px;transform:rotate(0.0deg)\"></i><div class=\"ppo-divider\" style=\"left:30px;top:145px;width:1070px\"></div><div class=\"ppo-label stage\" style=\"left:30px;top:145px;width:280px\">B · タスクを実行</div><div class=\"ppo-label stage\" style=\"left:580px;top:145px;width:520px\">C · 報酬とアドバンテージ</div><div class=\"ppo-label stage\" style=\"left:35px;top:617px;width:210px\">D · パラメータを更新</div><a class=\"node ppo-node soft\" href=\"#rollout\" style=\"left:30px;top:255px;width:180px;height:82px\"><strong>Actor</strong><span class=\"sub\">現在の方策 π<sub>old</sub></span></a><a class=\"node ppo-node \" href=\"#rollout\" style=\"left:30px;top:407px;width:180px;height:82px\"><strong>ツール環境</strong><span class=\"sub\">ファイル・Shell・テスト</span></a><a class=\"node ppo-node \" href=\"#rollout\" style=\"left:285px;top:255px;width:220px;height:100px\"><strong>軌跡の記録</strong><span class=\"sub\">タスク＋行動＋観測</span></a><a class=\"node ppo-node \" href=\"#reward-model\" style=\"left:590px;top:205px;width:180px;height:72px\"><strong>RM</strong><span class=\"sub\">重みを固定</span></a><a class=\"node ppo-node \" href=\"#advantages\" style=\"left:590px;top:335px;width:180px;height:72px\"><strong>Reference</strong><span class=\"sub\">重みを固定</span></a><a class=\"node ppo-node soft\" href=\"#advantages\" style=\"left:590px;top:462px;width:180px;height:72px\"><strong>Critic</strong><span class=\"sub\">各時点までの履歴を読む</span></a><a class=\"node ppo-node \" href=\"#advantages\" style=\"left:870px;top:245px;width:230px;height:88px\"><strong>報酬 r<sub>t</sub> を作る</strong><span class=\"sub\">終点スコア＋KL 制約</span></a><a class=\"node ppo-node \" href=\"#advantages\" style=\"left:870px;top:452px;width:230px;height:88px\"><strong>GAE</strong><span class=\"sub\">各位置へ評価を遡らせる</span></a><a class=\"node ppo-node accent\" href=\"#optimization\" style=\"left:285px;top:632px;width:230px;height:82px\"><strong>Actor を更新</strong><span class=\"sub\">PPO のクリップ目的関数</span></a><a class=\"node ppo-node accent\" href=\"#advantages\" style=\"left:590px;top:632px;width:230px;height:82px\"><strong>Critic を更新</strong><span class=\"sub\">リターン目標 Ĝ<sub>t</sub> に回帰</span></a><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:210px;top:296px;width:75.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:75px;top:337px;width:70px;transform:rotate(90deg)\"></i><div class=\"ppo-label \" style=\"left:25px;top:379px;width:115px\">ツール呼び出し</div><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:165px;top:407px;width:70px;transform:rotate(-90deg)\"></i><div class=\"ppo-label \" style=\"left:146px;top:360px;width:125px\">ツールの返り値</div><i aria-hidden=\"true\" class=\"edge \" style=\"left:210px;top:447px;width:45.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge \" style=\"left:255px;top:447px;width:107px;transform:rotate(-90deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:255px;top:340px;width:30.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge \" style=\"left:505px;top:280px;width:40.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge \" style=\"left:545px;top:280px;width:39px;transform:rotate(-90deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:545px;top:241px;width:45.0px;transform:rotate(0.0deg)\"></i><div class=\"ppo-label \" style=\"left:490px;top:205px;width:100px\">完了した実行</div><i aria-hidden=\"true\" class=\"edge \" style=\"left:505px;top:305px;width:53.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge \" style=\"left:558px;top:305px;width:66px;transform:rotate(90deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:558px;top:371px;width:32.0px;transform:rotate(0.0deg)\"></i><div class=\"ppo-label \" style=\"left:472px;top:378px;width:118px\">接頭辞＋token</div><i aria-hidden=\"true\" class=\"edge \" style=\"left:505px;top:330px;width:35.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge \" style=\"left:540px;top:330px;width:168px;transform:rotate(90deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:540px;top:498px;width:50.0px;transform:rotate(0.0deg)\"></i><div class=\"ppo-label \" style=\"left:470px;top:427px;width:115px\">接頭辞 h<sub>t</sub></div><i aria-hidden=\"true\" class=\"edge \" style=\"left:770px;top:241px;width:50.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge \" style=\"left:820px;top:241px;width:35px;transform:rotate(90deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:820px;top:276px;width:50.0px;transform:rotate(0.0deg)\"></i><div class=\"ppo-label \" style=\"left:775px;top:200px;width:95px\">スコア R</div><i aria-hidden=\"true\" class=\"edge \" style=\"left:770px;top:371px;width:50.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge \" style=\"left:820px;top:371px;width:61px;transform:rotate(-90deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:820px;top:310px;width:50.0px;transform:rotate(0.0deg)\"></i><div class=\"ppo-label \" style=\"left:775px;top:381px;width:96px\">参照確率</div><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:985px;top:333px;width:119px;transform:rotate(90deg)\"></i><div class=\"ppo-label math-label\" style=\"left:960px;top:403px;width:50px\">r<sub>t</sub></div><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:770px;top:498px;width:100.0px;transform:rotate(0.0deg)\"></i><div class=\"ppo-label \" style=\"left:770px;top:461px;width:100px\">価値 V<sub>t</sub></div><i aria-hidden=\"true\" class=\"edge \" style=\"left:910px;top:540px;width:7px;transform:rotate(90deg)\"></i><i aria-hidden=\"true\" class=\"edge \" style=\"left:910px;top:547px;width:510.0px;transform:rotate(180.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:400px;top:547px;width:85px;transform:rotate(90deg)\"></i><div class=\"ppo-label \" style=\"left:405px;top:517px;width:165px\">アドバンテージ A<sub>t</sub></div><i aria-hidden=\"true\" class=\"edge \" style=\"left:1035px;top:540px;width:61px;transform:rotate(90deg)\"></i><i aria-hidden=\"true\" class=\"edge \" style=\"left:1035px;top:601px;width:330.0px;transform:rotate(180.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:705px;top:601px;width:31px;transform:rotate(90deg)\"></i><div class=\"ppo-label \" style=\"left:850px;top:552px;width:170px\">リターン目標 Ĝ<sub>t</sub></div><i aria-hidden=\"true\" class=\"edge cache\" style=\"left:400px;top:355px;width:172px;transform:rotate(90deg)\"></i><i aria-hidden=\"true\" class=\"edge cache\" style=\"left:400px;top:527px;width:80.0px;transform:rotate(180.0deg)\"></i><i aria-hidden=\"true\" class=\"edge cache arrow\" style=\"left:320px;top:527px;width:105px;transform:rotate(90deg)\"></i><div class=\"ppo-label \" style=\"left:270px;top:474px;width:230px\">採用済み token と旧確率</div><i aria-hidden=\"true\" class=\"edge feedback\" style=\"left:400px;top:714px;width:26px;transform:rotate(90deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback\" style=\"left:400px;top:740px;width:390.0px;transform:rotate(180.0deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback\" style=\"left:10px;top:740px;width:444px;transform:rotate(-90deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback arrow\" style=\"left:10px;top:296px;width:20.0px;transform:rotate(0.0deg)\"></i><div class=\"ppo-label \" style=\"left:30px;top:750px;width:450px\">更新した Actor で次のバッチを収集</div><i aria-hidden=\"true\" class=\"edge feedback\" style=\"left:705px;top:714px;width:26px;transform:rotate(90deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback\" style=\"left:705px;top:740px;width:125.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback\" style=\"left:830px;top:740px;width:200px;transform:rotate(-90deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback\" style=\"left:830px;top:540px;width:155.0px;transform:rotate(180.0deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback arrow\" style=\"left:675px;top:540px;width:6px;transform:rotate(-90deg)\"></i><div class=\"ppo-label \" style=\"left:650px;top:750px;width:400px\">更新後の価値予測</div><i aria-hidden=\"true\" class=\"edge cache\" style=\"left:395px;top:255px;width:70px;transform:rotate(-90deg)\"></i><i aria-hidden=\"true\" class=\"edge cache\" style=\"left:395px;top:185px;width:590.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge cache arrow\" style=\"left:985px;top:185px;width:60px;transform:rotate(90deg)\"></i><div class=\"ppo-label \" style=\"left:365px;top:160px;width:190px\">保存した log π<sub>old</sub></div></div></div><figcaption>図 1 · A はモデル準備、B は軌跡収集、C は報酬とアドバンテージ計算、D は Actor と Critic の更新。PPO 中の RM と Reference は固定。各ノードから対応する節へ移動できる。</figcaption></figure>",
    "figures/training-overview.zh.html": "<figure class=\"ppo-figure\" id=\"figure-training-overview\" data-diagram-style=\"openai-blog\" data-diagram-kind=\"flow\"><div class=\"ppo-figure-heading\">训练全流程</div><div class=\"ppo-figure-scroll\" role=\"region\" tabindex=\"0\" aria-label=\"训练全流程\"><div class=\"canvas ppo-canvas\" style=\"width:1140px;height:785px\"><div class=\"ppo-label stage\" style=\"left:30px;top:10px;width:1070px\">A · 学习开始前</div><a class=\"node ppo-node \" href=\"#reward-model\" style=\"left:30px;top:48px;width:140px;height:62px\"><strong>操作示范</strong></a><a class=\"node ppo-node \" href=\"#reward-model\" style=\"left:215px;top:48px;width:170px;height:62px\"><strong>监督微调 SFT</strong></a><a class=\"node ppo-node \" href=\"#reward-model\" style=\"left:430px;top:48px;width:270px;height:62px\"><strong>Actor + Reference</strong><span class=\"sub\">同一初始策略的两份参数</span></a><a class=\"node ppo-node \" href=\"#reward-model\" style=\"left:755px;top:48px;width:130px;height:62px\"><strong>成对偏好</strong></a><a class=\"node ppo-node \" href=\"#reward-model\" style=\"left:930px;top:48px;width:170px;height:62px\"><strong>训练 RM</strong></a><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:170px;top:79px;width:45.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:385px;top:79px;width:45.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:885px;top:79px;width:45.0px;transform:rotate(0.0deg)\"></i><div class=\"ppo-divider\" style=\"left:30px;top:145px;width:1070px\"></div><div class=\"ppo-label stage\" style=\"left:30px;top:145px;width:280px\">B · 执行任务</div><div class=\"ppo-label stage\" style=\"left:580px;top:145px;width:520px\">C · 奖励与优势</div><div class=\"ppo-label stage\" style=\"left:35px;top:617px;width:210px\">D · 参数更新</div><a class=\"node ppo-node soft\" href=\"#rollout\" style=\"left:30px;top:255px;width:180px;height:82px\"><strong>Actor</strong><span class=\"sub\">当前策略 π<sub>old</sub></span></a><a class=\"node ppo-node \" href=\"#rollout\" style=\"left:30px;top:407px;width:180px;height:82px\"><strong>工具环境</strong><span class=\"sub\">文件 · Shell · 测试</span></a><a class=\"node ppo-node \" href=\"#rollout\" style=\"left:285px;top:255px;width:220px;height:100px\"><strong>轨迹记录</strong><span class=\"sub\">任务 + 动作 + 观察</span></a><a class=\"node ppo-node \" href=\"#reward-model\" style=\"left:590px;top:205px;width:180px;height:72px\"><strong>RM</strong><span class=\"sub\">固定参数</span></a><a class=\"node ppo-node \" href=\"#advantages\" style=\"left:590px;top:335px;width:180px;height:72px\"><strong>Reference</strong><span class=\"sub\">固定参数</span></a><a class=\"node ppo-node soft\" href=\"#advantages\" style=\"left:590px;top:462px;width:180px;height:72px\"><strong>Critic</strong><span class=\"sub\">读取每个历史前缀</span></a><a class=\"node ppo-node \" href=\"#advantages\" style=\"left:870px;top:245px;width:230px;height:88px\"><strong>构造奖励 r<sub>t</sub></strong><span class=\"sub\">终点得分 + KL 约束</span></a><a class=\"node ppo-node \" href=\"#advantages\" style=\"left:870px;top:452px;width:230px;height:88px\"><strong>GAE</strong><span class=\"sub\">按位置回传反馈</span></a><a class=\"node ppo-node accent\" href=\"#optimization\" style=\"left:285px;top:632px;width:230px;height:82px\"><strong>更新 Actor</strong><span class=\"sub\">PPO 裁剪目标</span></a><a class=\"node ppo-node accent\" href=\"#advantages\" style=\"left:590px;top:632px;width:230px;height:82px\"><strong>更新 Critic</strong><span class=\"sub\">拟合回报目标 Ĝ<sub>t</sub></span></a><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:210px;top:296px;width:75.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:75px;top:337px;width:70px;transform:rotate(90deg)\"></i><div class=\"ppo-label \" style=\"left:25px;top:379px;width:115px\">工具调用</div><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:165px;top:407px;width:70px;transform:rotate(-90deg)\"></i><div class=\"ppo-label \" style=\"left:146px;top:360px;width:125px\">工具返回</div><i aria-hidden=\"true\" class=\"edge \" style=\"left:210px;top:447px;width:45.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge \" style=\"left:255px;top:447px;width:107px;transform:rotate(-90deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:255px;top:340px;width:30.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge \" style=\"left:505px;top:280px;width:40.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge \" style=\"left:545px;top:280px;width:39px;transform:rotate(-90deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:545px;top:241px;width:45.0px;transform:rotate(0.0deg)\"></i><div class=\"ppo-label \" style=\"left:490px;top:205px;width:100px\">完整执行</div><i aria-hidden=\"true\" class=\"edge \" style=\"left:505px;top:305px;width:53.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge \" style=\"left:558px;top:305px;width:66px;transform:rotate(90deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:558px;top:371px;width:32.0px;transform:rotate(0.0deg)\"></i><div class=\"ppo-label \" style=\"left:472px;top:378px;width:118px\">前缀 + token</div><i aria-hidden=\"true\" class=\"edge \" style=\"left:505px;top:330px;width:35.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge \" style=\"left:540px;top:330px;width:168px;transform:rotate(90deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:540px;top:498px;width:50.0px;transform:rotate(0.0deg)\"></i><div class=\"ppo-label \" style=\"left:470px;top:427px;width:115px\">前缀 h<sub>t</sub></div><i aria-hidden=\"true\" class=\"edge \" style=\"left:770px;top:241px;width:50.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge \" style=\"left:820px;top:241px;width:35px;transform:rotate(90deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:820px;top:276px;width:50.0px;transform:rotate(0.0deg)\"></i><div class=\"ppo-label \" style=\"left:775px;top:200px;width:95px\">得分 R</div><i aria-hidden=\"true\" class=\"edge \" style=\"left:770px;top:371px;width:50.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge \" style=\"left:820px;top:371px;width:61px;transform:rotate(-90deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:820px;top:310px;width:50.0px;transform:rotate(0.0deg)\"></i><div class=\"ppo-label \" style=\"left:775px;top:381px;width:96px\">参考概率</div><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:985px;top:333px;width:119px;transform:rotate(90deg)\"></i><div class=\"ppo-label math-label\" style=\"left:960px;top:403px;width:50px\">r<sub>t</sub></div><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:770px;top:498px;width:100.0px;transform:rotate(0.0deg)\"></i><div class=\"ppo-label \" style=\"left:770px;top:461px;width:100px\">价值 V<sub>t</sub></div><i aria-hidden=\"true\" class=\"edge \" style=\"left:910px;top:540px;width:7px;transform:rotate(90deg)\"></i><i aria-hidden=\"true\" class=\"edge \" style=\"left:910px;top:547px;width:510.0px;transform:rotate(180.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:400px;top:547px;width:85px;transform:rotate(90deg)\"></i><div class=\"ppo-label \" style=\"left:405px;top:517px;width:165px\">优势 A<sub>t</sub></div><i aria-hidden=\"true\" class=\"edge \" style=\"left:1035px;top:540px;width:61px;transform:rotate(90deg)\"></i><i aria-hidden=\"true\" class=\"edge \" style=\"left:1035px;top:601px;width:330.0px;transform:rotate(180.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:705px;top:601px;width:31px;transform:rotate(90deg)\"></i><div class=\"ppo-label \" style=\"left:850px;top:552px;width:170px\">回报目标 Ĝ<sub>t</sub></div><i aria-hidden=\"true\" class=\"edge cache\" style=\"left:400px;top:355px;width:172px;transform:rotate(90deg)\"></i><i aria-hidden=\"true\" class=\"edge cache\" style=\"left:400px;top:527px;width:80.0px;transform:rotate(180.0deg)\"></i><i aria-hidden=\"true\" class=\"edge cache arrow\" style=\"left:320px;top:527px;width:105px;transform:rotate(90deg)\"></i><div class=\"ppo-label \" style=\"left:270px;top:474px;width:230px\">已采样 token 与旧概率</div><i aria-hidden=\"true\" class=\"edge feedback\" style=\"left:400px;top:714px;width:26px;transform:rotate(90deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback\" style=\"left:400px;top:740px;width:390.0px;transform:rotate(180.0deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback\" style=\"left:10px;top:740px;width:444px;transform:rotate(-90deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback arrow\" style=\"left:10px;top:296px;width:20.0px;transform:rotate(0.0deg)\"></i><div class=\"ppo-label \" style=\"left:30px;top:750px;width:450px\">新 Actor 继续采样</div><i aria-hidden=\"true\" class=\"edge feedback\" style=\"left:705px;top:714px;width:26px;transform:rotate(90deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback\" style=\"left:705px;top:740px;width:125.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback\" style=\"left:830px;top:740px;width:200px;transform:rotate(-90deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback\" style=\"left:830px;top:540px;width:155.0px;transform:rotate(180.0deg)\"></i><i aria-hidden=\"true\" class=\"edge feedback arrow\" style=\"left:675px;top:540px;width:6px;transform:rotate(-90deg)\"></i><div class=\"ppo-label \" style=\"left:650px;top:750px;width:400px\">更新后的价值预测</div><i aria-hidden=\"true\" class=\"edge cache\" style=\"left:395px;top:255px;width:70px;transform:rotate(-90deg)\"></i><i aria-hidden=\"true\" class=\"edge cache\" style=\"left:395px;top:185px;width:590.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge cache arrow\" style=\"left:985px;top:185px;width:60px;transform:rotate(90deg)\"></i><div class=\"ppo-label \" style=\"left:365px;top:160px;width:190px\">保存的 log π<sub>old</sub></div></div></div><figcaption>图 1 · A 准备模型，B 收集轨迹，C 计算奖励与优势，D 更新 Actor 与 Critic。RM 与 Reference 在 PPO 中固定。节点可跳转至对应章节。</figcaption></figure>",
    "figures/trajectory-models.en.html": "<figure class=\"ppo-figure\" id=\"figure-trajectory-models\" data-diagram-style=\"openai-blog\" data-diagram-kind=\"flow\"><div class=\"ppo-figure-heading\">B · One repair, through Actor and tools</div><div class=\"ppo-figure-scroll\" role=\"region\" tabindex=\"0\" aria-label=\"B · One repair, through Actor and tools\"><div class=\"canvas ppo-canvas\" style=\"width:1000px;height:1160px\"><div class=\"ppo-label task-title\" style=\"left:25px;top:5px;width:960px\">Task: sum \"0.10\" and \"0.20\", then print 0.30</div><div class=\"node ppo-node \" style=\"left:50px;top:65px;width:355px;height:60px\"><strong>Actor</strong></div><div class=\"node ppo-node \" style=\"left:590px;top:65px;width:355px;height:60px\"><strong>Tool environment</strong></div><div class=\"ppo-lifeline\" style=\"left:225px;top:125px;height:995px\"></div><div class=\"ppo-lifeline\" style=\"left:765px;top:125px;height:870px\"></div><div class=\"node ppo-node soft\" style=\"left:50px;top:175px;width:355px;height:76px\"><strong>Read the script</strong><span class=\"sub\">cat summarize.py</span></div><div class=\"node ppo-node \" style=\"left:590px;top:255px;width:355px;height:76px\"><strong>Find a float-based sum</strong><span class=\"sub\">float(row[&quot;amount&quot;])</span></div><i aria-hidden=\"true\" class=\"edge \" style=\"left:405px;top:213px;width:360.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:765px;top:213px;width:42.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge \" style=\"left:590px;top:293px;width:365.0px;transform:rotate(180.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:225px;top:293px;width:92.0px;transform:rotate(90.0deg)\"></i><div class=\"node ppo-node soft\" style=\"left:50px;top:385px;width:355px;height:76px\"><strong>Run the test</strong><span class=\"sub\">pytest -q</span></div><div class=\"node ppo-node \" style=\"left:590px;top:465px;width:355px;height:76px\"><strong>Test fails</strong><span class=\"sub\">0.30000000000000004</span></div><i aria-hidden=\"true\" class=\"edge \" style=\"left:405px;top:423px;width:360.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:765px;top:423px;width:42.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge \" style=\"left:590px;top:503px;width:365.0px;transform:rotate(180.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:225px;top:503px;width:92.0px;transform:rotate(90.0deg)\"></i><div class=\"node ppo-node soft\" style=\"left:50px;top:595px;width:355px;height:76px\"><strong>Apply the patch</strong><span class=\"sub\">Decimal(row[&quot;amount&quot;])</span></div><div class=\"node ppo-node \" style=\"left:590px;top:675px;width:355px;height:76px\"><strong>File updated</strong><span class=\"sub\">format(total, &quot;.2f&quot;)</span></div><i aria-hidden=\"true\" class=\"edge \" style=\"left:405px;top:633px;width:360.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:765px;top:633px;width:42.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge \" style=\"left:590px;top:713px;width:365.0px;transform:rotate(180.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:225px;top:713px;width:92.0px;transform:rotate(90.0deg)\"></i><div class=\"node ppo-node soft\" style=\"left:50px;top:805px;width:355px;height:76px\"><strong>Test again</strong><span class=\"sub\">pytest -q</span></div><div class=\"node ppo-node \" style=\"left:590px;top:885px;width:355px;height:76px\"><strong>Test passes</strong><span class=\"sub\">0.30</span></div><i aria-hidden=\"true\" class=\"edge \" style=\"left:405px;top:843px;width:360.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:765px;top:843px;width:42.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge \" style=\"left:590px;top:923px;width:365.0px;transform:rotate(180.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:225px;top:923px;width:92.0px;transform:rotate(90.0deg)\"></i><div class=\"node ppo-node \" style=\"left:50px;top:1015px;width:355px;height:76px\"><strong>Submit the fix and test result</strong></div><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:405px;top:1053px;width:185.0px;transform:rotate(0.0deg)\"></i><div class=\"node ppo-node accent\" style=\"left:590px;top:1015px;width:355px;height:90px\"><strong>RM reads the completed attempt: R = 8</strong></div></div></div><figcaption>Figure 3 · An illustrative repair. Tool responses join the history used for the next call. The RM scores the completed record.</figcaption></figure>",
    "figures/trajectory-models.ja.html": "<figure class=\"ppo-figure\" id=\"figure-trajectory-models\" data-diagram-style=\"openai-blog\" data-diagram-kind=\"flow\"><div class=\"ppo-figure-heading\">B · Actor とツールによる一回の修正</div><div class=\"ppo-figure-scroll\" role=\"region\" tabindex=\"0\" aria-label=\"B · Actor とツールによる一回の修正\"><div class=\"canvas ppo-canvas\" style=\"width:1000px;height:1160px\"><div class=\"ppo-label task-title\" style=\"left:25px;top:5px;width:960px\">課題：\"0.10\" と \"0.20\" を加算し、0.30 を出力</div><div class=\"node ppo-node \" style=\"left:50px;top:65px;width:355px;height:60px\"><strong>Actor</strong></div><div class=\"node ppo-node \" style=\"left:590px;top:65px;width:355px;height:60px\"><strong>ツール環境</strong></div><div class=\"ppo-lifeline\" style=\"left:225px;top:125px;height:995px\"></div><div class=\"ppo-lifeline\" style=\"left:765px;top:125px;height:870px\"></div><div class=\"node ppo-node soft\" style=\"left:50px;top:175px;width:355px;height:76px\"><strong>スクリプトを読む</strong><span class=\"sub\">cat summarize.py</span></div><div class=\"node ppo-node \" style=\"left:590px;top:255px;width:355px;height:76px\"><strong>float による加算を確認</strong><span class=\"sub\">float(row[&quot;amount&quot;])</span></div><i aria-hidden=\"true\" class=\"edge \" style=\"left:405px;top:213px;width:360.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:765px;top:213px;width:42.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge \" style=\"left:590px;top:293px;width:365.0px;transform:rotate(180.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:225px;top:293px;width:92.0px;transform:rotate(90.0deg)\"></i><div class=\"node ppo-node soft\" style=\"left:50px;top:385px;width:355px;height:76px\"><strong>テストを実行</strong><span class=\"sub\">pytest -q</span></div><div class=\"node ppo-node \" style=\"left:590px;top:465px;width:355px;height:76px\"><strong>テスト失敗</strong><span class=\"sub\">0.30000000000000004</span></div><i aria-hidden=\"true\" class=\"edge \" style=\"left:405px;top:423px;width:360.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:765px;top:423px;width:42.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge \" style=\"left:590px;top:503px;width:365.0px;transform:rotate(180.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:225px;top:503px;width:92.0px;transform:rotate(90.0deg)\"></i><div class=\"node ppo-node soft\" style=\"left:50px;top:595px;width:355px;height:76px\"><strong>修正を適用</strong><span class=\"sub\">Decimal(row[&quot;amount&quot;])</span></div><div class=\"node ppo-node \" style=\"left:590px;top:675px;width:355px;height:76px\"><strong>ファイルを更新</strong><span class=\"sub\">format(total, &quot;.2f&quot;)</span></div><i aria-hidden=\"true\" class=\"edge \" style=\"left:405px;top:633px;width:360.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:765px;top:633px;width:42.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge \" style=\"left:590px;top:713px;width:365.0px;transform:rotate(180.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:225px;top:713px;width:92.0px;transform:rotate(90.0deg)\"></i><div class=\"node ppo-node soft\" style=\"left:50px;top:805px;width:355px;height:76px\"><strong>再テスト</strong><span class=\"sub\">pytest -q</span></div><div class=\"node ppo-node \" style=\"left:590px;top:885px;width:355px;height:76px\"><strong>テスト成功</strong><span class=\"sub\">0.30</span></div><i aria-hidden=\"true\" class=\"edge \" style=\"left:405px;top:843px;width:360.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:765px;top:843px;width:42.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge \" style=\"left:590px;top:923px;width:365.0px;transform:rotate(180.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:225px;top:923px;width:92.0px;transform:rotate(90.0deg)\"></i><div class=\"node ppo-node \" style=\"left:50px;top:1015px;width:355px;height:76px\"><strong>修正とテスト結果を提出</strong></div><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:405px;top:1053px;width:185.0px;transform:rotate(0.0deg)\"></i><div class=\"node ppo-node accent\" style=\"left:590px;top:1015px;width:355px;height:90px\"><strong>RM が完了した実行を評価：R = 8</strong></div></div></div><figcaption>図 3 · 金額集計を修正する学習用の例。ツールの返り値を履歴に加え、次の呼び出しを生成する。実行完了後に全記録を RM で採点する。</figcaption></figure>",
    "figures/trajectory-models.zh.html": "<figure class=\"ppo-figure\" id=\"figure-trajectory-models\" data-diagram-style=\"openai-blog\" data-diagram-kind=\"flow\"><div class=\"ppo-figure-heading\">B · Actor 与工具如何完成一次修复</div><div class=\"ppo-figure-scroll\" role=\"region\" tabindex=\"0\" aria-label=\"B · Actor 与工具如何完成一次修复\"><div class=\"canvas ppo-canvas\" style=\"width:1000px;height:1160px\"><div class=\"ppo-label task-title\" style=\"left:25px;top:5px;width:960px\">任务：把 \"0.10\" 与 \"0.20\" 相加，输出 0.30</div><div class=\"node ppo-node \" style=\"left:50px;top:65px;width:355px;height:60px\"><strong>Actor</strong></div><div class=\"node ppo-node \" style=\"left:590px;top:65px;width:355px;height:60px\"><strong>工具环境</strong></div><div class=\"ppo-lifeline\" style=\"left:225px;top:125px;height:995px\"></div><div class=\"ppo-lifeline\" style=\"left:765px;top:125px;height:870px\"></div><div class=\"node ppo-node soft\" style=\"left:50px;top:175px;width:355px;height:76px\"><strong>读取脚本</strong><span class=\"sub\">cat summarize.py</span></div><div class=\"node ppo-node \" style=\"left:590px;top:255px;width:355px;height:76px\"><strong>读取到 float 求和代码</strong><span class=\"sub\">float(row[&quot;amount&quot;])</span></div><i aria-hidden=\"true\" class=\"edge \" style=\"left:405px;top:213px;width:360.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:765px;top:213px;width:42.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge \" style=\"left:590px;top:293px;width:365.0px;transform:rotate(180.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:225px;top:293px;width:92.0px;transform:rotate(90.0deg)\"></i><div class=\"node ppo-node soft\" style=\"left:50px;top:385px;width:355px;height:76px\"><strong>运行测试</strong><span class=\"sub\">pytest -q</span></div><div class=\"node ppo-node \" style=\"left:590px;top:465px;width:355px;height:76px\"><strong>测试失败</strong><span class=\"sub\">0.30000000000000004</span></div><i aria-hidden=\"true\" class=\"edge \" style=\"left:405px;top:423px;width:360.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:765px;top:423px;width:42.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge \" style=\"left:590px;top:503px;width:365.0px;transform:rotate(180.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:225px;top:503px;width:92.0px;transform:rotate(90.0deg)\"></i><div class=\"node ppo-node soft\" style=\"left:50px;top:595px;width:355px;height:76px\"><strong>写入修复</strong><span class=\"sub\">Decimal(row[&quot;amount&quot;])</span></div><div class=\"node ppo-node \" style=\"left:590px;top:675px;width:355px;height:76px\"><strong>文件已更新</strong><span class=\"sub\">format(total, &quot;.2f&quot;)</span></div><i aria-hidden=\"true\" class=\"edge \" style=\"left:405px;top:633px;width:360.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:765px;top:633px;width:42.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge \" style=\"left:590px;top:713px;width:365.0px;transform:rotate(180.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:225px;top:713px;width:92.0px;transform:rotate(90.0deg)\"></i><div class=\"node ppo-node soft\" style=\"left:50px;top:805px;width:355px;height:76px\"><strong>再次测试</strong><span class=\"sub\">pytest -q</span></div><div class=\"node ppo-node \" style=\"left:590px;top:885px;width:355px;height:76px\"><strong>测试通过</strong><span class=\"sub\">0.30</span></div><i aria-hidden=\"true\" class=\"edge \" style=\"left:405px;top:843px;width:360.0px;transform:rotate(0.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:765px;top:843px;width:42.0px;transform:rotate(90.0deg)\"></i><i aria-hidden=\"true\" class=\"edge \" style=\"left:590px;top:923px;width:365.0px;transform:rotate(180.0deg)\"></i><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:225px;top:923px;width:92.0px;transform:rotate(90.0deg)\"></i><div class=\"node ppo-node \" style=\"left:50px;top:1015px;width:355px;height:76px\"><strong>提交修复与测试结果</strong></div><i aria-hidden=\"true\" class=\"edge  arrow\" style=\"left:405px;top:1053px;width:185.0px;transform:rotate(0.0deg)\"></i><div class=\"node ppo-node accent\" style=\"left:590px;top:1015px;width:355px;height:90px\"><strong>RM 读取完整执行，给分 R = 8</strong></div></div></div><figcaption>图 3 · 金额汇总教学案例。工具返回加入历史，Actor 据此生成下一步调用。执行完成后，整条记录交给 RM 评分。</figcaption></figure>",
    "figures/workflow.css": ".ppo-figure{width:min(1240px,calc(100vw - 56px));margin:42px 0 48px 50%;transform:translateX(-50%);color:var(--diagram-ink,var(--ink,#262a27));font-family:inherit;font-size:16px;line-height:1.6}\n.ppo-figure *{box-sizing:border-box}\n.ppo-figure-heading{padding:14px 0 16px;border-bottom:1px solid var(--line,#dfe2dc);font-size:14px;line-height:1.7;color:var(--muted,#62675e)}\n.ppo-figure-scroll{overflow:auto;max-height:1100px;overscroll-behavior:auto;touch-action:pan-x pan-y pinch-zoom;scrollbar-width:thin;scrollbar-color:var(--diagram-border,#adb3a6) transparent;outline-offset:4px;padding-top:18px}\n.ppo-figure-scroll:focus-visible{outline:1px solid var(--diagram-accent,#6b8e40)}\n.ppo-figure .canvas{position:relative;flex:none;font-family:Arial,\"Hiragino Sans\",\"Microsoft YaHei\",sans-serif;font-size:16px;line-height:1.55;color:var(--diagram-ink,#262a27);background:var(--diagram-paper,#fff);margin:auto}\n.ppo-figure .node{position:absolute;z-index:2;border:1px solid var(--diagram-border,#60665a);border-radius:9px;background:var(--diagram-paper,#fff);padding:10px 12px;display:flex;flex-direction:column;justify-content:center;gap:4px;text-align:center;color:var(--diagram-ink,#262a27);text-decoration:none;font-size:18px;font-weight:400;line-height:1.4}\n.ppo-figure .node strong{font:inherit;color:inherit;letter-spacing:0}\n.ppo-figure .node .sub{display:block;font-size:13px;font-weight:400;line-height:1.45;color:var(--diagram-muted,#65695f)}\n.ppo-figure a.node:hover,.ppo-figure a.node:focus-visible{outline:2px solid var(--diagram-accent,#699c35);outline-offset:4px}\n.ppo-figure .edge{position:absolute;display:block;height:0;border-top:1.5px solid var(--diagram-line,#454a40);transform-origin:left center;z-index:0}\n.ppo-figure .edge.arrow:after{content:'';position:absolute;right:-1px;top:-4px;border-left:7px solid var(--diagram-line,#454a40);border-top:3px solid transparent;border-bottom:3px solid transparent}\n.ppo-figure .edge.cache{border-top-style:dashed}\n.ppo-figure .edge.feedback{border-color:var(--diagram-accent,#699c35)}\n.ppo-figure .edge.feedback.arrow:after{border-left-color:var(--diagram-accent,#699c35)}\n.ppo-figure .ppo-label{position:absolute;z-index:1;padding:3px 4px;text-align:center;color:var(--diagram-muted,#65695f);background:var(--diagram-paper,#fff);font-size:13px;line-height:1.45}\n.ppo-figure .ppo-label.stage{font-size:15px;text-align:left;color:var(--diagram-ink,#262a27);padding-left:0}\n.ppo-figure .ppo-label.task-title{font-size:17px;text-align:left;color:var(--diagram-ink,#262a27);padding-left:0}\n.ppo-figure .math-label{font-family:Georgia,'Times New Roman',serif;font-size:18px;color:var(--diagram-ink,#262a27)}\n.ppo-figure .ppo-divider{position:absolute;border-top:1px solid var(--line,#dfe2dc)}\n.ppo-figure .ppo-lifeline{position:absolute;border-left:1px dashed var(--diagram-border,#909889);opacity:.5}\n.ppo-figure figcaption{font-size:13px;line-height:1.8;color:var(--muted,#65695f);margin-top:16px;max-width:1050px}\n.ppo-figure[data-diagram-style=\"openai-blog\"] .node.soft,.ppo-figure[data-diagram-style=\"openai-blog\"] .node.accent{background-color:var(--diagram-soft,#f5faef);background-image:radial-gradient(#70a33d38 .5px,transparent .65px);background-size:5px 5px;border-color:var(--diagram-accent,#699c35)}\n.ppo-figure[data-diagram-style=\"engineering\"] .node{border-radius:3px;background-image:none}\nhtml[data-theme=\"dark\"] .ppo-figure{--diagram-paper:var(--paper,var(--bg,#181b19));--diagram-ink:var(--ink,#e5e7de);--diagram-muted:var(--muted,#abb2a5);--diagram-line:#aab3a0;--diagram-border:#87927d;--diagram-accent:#a8c984;--diagram-soft:#263321}\nhtml[data-theme=\"dark\"] .ppo-figure .canvas .node{background-color:var(--diagram-paper)!important}\nhtml[data-theme=\"dark\"] .ppo-figure[data-diagram-style=\"openai-blog\"] .canvas .node:is(.soft,.accent){background-color:var(--diagram-soft)!important}\nhtml[data-theme=\"dark\"] .ppo-figure .canvas :is(.ppo-label,.sub){color:var(--diagram-muted);background-color:transparent}\n@media(max-width:700px){.ppo-figure{width:100%;margin:30px 0 36px;transform:none}.ppo-figure-scroll{max-height:78vh}.ppo-figure figcaption{font-size:12px}}\n@media print{.ppo-figure{width:100%;margin:24px 0;transform:none;break-inside:avoid}.ppo-figure-scroll{max-height:none;overflow:visible}}\n",
    "ja.html": "<section aria-labelledby=\"overview\"><h2 id=\"overview\">1 学習ループの全体像</h2><p>コード Agent はファイルを読み、ツールを呼び出し、コードを修正する。行動とツールの返り値を合わせた記録を<strong>軌跡</strong>と呼ぶ。PPO は実行結果を使い、途中で生成した行動の確率を調整する。</p><p>報酬モデルを用いる<strong>人間のフィードバックによる強化学習（RLHF）</strong>では、<strong>Actor が行動を生成し、RM が完了した実行を評価し、Critic が現在の文脈から先のリターンを予測し、Reference が固定した方策の参照を与える</strong>。報酬と価値予測からアドバンテージを計算し、Actor と Critic の学習目標を作る。図の A—D が以下の四つの節に対応する。</p><!-- FIGURE:training-overview --></section>\n<section aria-labelledby=\"reward-model\">\n<h2 id=\"reward-model\">2 A · 方策と報酬モデルを準備する</h2><p>学習は通常、既存の言語モデルに対する<strong>教師ありファインチューニング（SFT）</strong>から始まる。適切な操作の実演を与え、その文脈で同じ操作を生成する確率を高める。その後、PPO では方策ネットワークである <strong>Actor</strong> が自ら試行し、新しい結果から学ぶ。<a href=\"https://arxiv.org/html/2203.02155v1#S3.SS1\">[1]</a></p><p>SFT 後の方策を二つにコピーする。一方を学習し続ける Actor、もう一方を固定した Reference とする。Reference は生成済み token の確率を計算し、Actor が初期方策から離れる度合いを制約する。</p><p>金額集計スクリプトの修正を例にする。文字列の金額 <code>\"0.10\"</code> と <code>\"0.20\"</code> を正確に加算し、<code>0.30</code> を出力する。軌跡と点数は説明用に構成した例である。</p>\n<p>まず 2 つの完全な実行を用意する。A は Decimal に修正してテストに合格し、B は浮動小数点の出力を残している。評価者が A を選ぶと、ラベルは<strong>「A のほうが B より望ましい」</strong>となる。<strong>報酬モデル（RM）</strong>の学習では、「課題＋実行 A」と「課題＋実行 B」を同じモデルに別々に入力し、スコア <var>r<sub>A</sub></var> と <var>r<sub>B</sub></var>を得る。</p>\n<!-- FIGURE:reward-value-training --><div aria-label=\"報酬モデルの選好損失\" class=\"formula-scroll\" role=\"region\" tabindex=\"0\"><math display=\"block\" xmlns=\"http://www.w3.org/1998/Math/MathML\"><msub><mi>L</mi><mtext>RM</mtext></msub><mo>=</mo><mo>−</mo><mi>log</mi><mo>⁡</mo><mi>σ</mi><mo>(</mo><msub><mi>r</mi><mi>A</mi></msub><mo>−</mo><msub><mi>r</mi><mi>B</mi></msub><mo>)</mo></math></div>\n<p><var>σ</var> はシグモイド関数で、スコア差を選好の確率に変換する。この損失を小さくすると、A の相対的なスコアが高くなる方向に学習が進む。多数の選好ペアから、新しい実行を評価する基準を学ぶ。評価者は選好の順序を与え、RM がスコアを学ぶ。RM は一般に、言語モデルの本体に単一の数値を出すスカラー出力ヘッドを加えて構成する。<a href=\"https://arxiv.org/html/2203.02155v1#S3.SS5\">[1]</a></p>\n</section>\n<section aria-labelledby=\"rollout\">\n<h2 id=\"rollout\">3 B · Actor に一回の試行をさせる</h2><p>入力は 1 行に 1 個の JSON オブジェクトを置く JSONL 形式である。元のスクリプトは金額を <code>float</code> に変換し、<code>0.30000000000000004</code> を出力する。Actor は問題を見つけ、金額の文字列を <code>Decimal</code> で処理し、小数点以下 2 桁で表示するよう直す。</p>\n<p>ここでは人間のフィードバックによる強化学習（<strong>RLHF</strong>）の 4 つの役割を使う。<strong>Rollout</strong> は、現在の Actor が環境の中で行う 1 回の試行である。Actor は文字列の符号化単位である token を順に生成し、ツール呼び出しや最終回答を作る。環境から返るファイル内容やテストログは、次の生成の文脈に加わる。</p><!-- FIGURE:trajectory-models -->\n<p>Actor は行動を生成する。RM は実行終了後に課題と全記録を読み、最終スコアを出す。Critic は各生成位置でその時点までの接頭辞を読み、先のリターンを予測する。固定した<strong>参照モデル Reference</strong> は、同じ文脈で生成された token の確率を計算し、方策が出発点からどれだけ変化したかを測る基準となる。</p>\n<p>この例の「テスト合格」はツールからの観測で、最終報酬は RM が与える。信頼できる自動検証器があれば、その判定から直接報酬を作り、RM を置き換えることもできる。</p>\n<p>学習の<strong>マスク</strong>は、Actor が生成した位置を指定する。ファイル内容とテストログは判断材料として入力に残し、方策の損失は生成した token にだけ適用する。Critic の予測は軌跡収集後にまとめて計算できるが、各予測が参照する入力は対応する時点までに限られる。</p>\n</section>\n<section aria-labelledby=\"advantages\"><h2 id=\"advantages\">4 C · Critic は結果からどう学ぶか</h2><p><strong>価値ネットワーク Critic は、現在の Actor がある文脈から実行を続けた場合の平均リターンを予測する。</strong>同じ課題で 4 種類の結果が等確率で生じ、固定した RM が 2、4、6、8 点を付けるとすれば、平均は 5 になる。Critic は繰り返し得られる結果から、この期待値を学ぶ。この点数は説明用の尺度である。</p><p><strong>リターン</strong>は、ある位置から先の報酬を累積した値である。Critic の学習では、試行を終えてから過去の履歴の接頭辞と対応するリターン目標を組にする。<strong>一般化アドバンテージ推定（GAE）</strong>が報酬と価値予測から目標を作る。そのデータの流れを次の図に示す。</p><!-- FIGURE:critic-training --><p>Critic も一般に、言語モデルの本体とスカラー出力ヘッドで構成する。InstructGPT は RM のパラメータで価値ネットワークを初期化し、その後は軌跡のリターンで学習した。再利用するのは初期パラメータであり、その後の教師信号は各接頭辞に対応するリターン目標となる。<a href=\"https://arxiv.org/html/2203.02155v1#S3.SS5\">[1]</a></p><p>Critic の学習サンプルは、接頭辞とリターン目標のペアである。予測が 5、目標が 8 なら、二乗誤差は 9 になる。この誤差を逆伝播し、オプティマイザで学習可能なパラメータを調整する。全パラメータの微調整では、言語モデルの本体とスカラー出力ヘッドの両方を更新する。今回の更新中は目標を固定し、この損失で RM を更新することはない。</p><div aria-label=\"価値の回帰損失\" class=\"equation\" role=\"math\">L<sub>V</sub> = mean [V<sub>φ</sub>(h<sub>t</sub>) − Ĝ<sub>t</sub>]<sup>2</sup></div><p><var>φ</var> は Critic のパラメータを表す。さまざまな結果を繰り返し観測すると、回帰によって平均リターンを学ぶ。文脈に応じたベースラインは、サンプリングによる方策勾配の揺らぎを減らす助けになる。リターンを直接使って方策を学習することもできるが、適切な価値予測は限られたサンプルでの更新を安定させる。<a href=\"https://spinningup.openai.com/en/latest/spinningup/rl_intro3.html#baselines-in-policy-gradients\">[3]</a></p><p>RM は選好から採点基準を学び、Critic は実際のリターンから期待値を学ぶ。PPO の段階では通常 RM を固定し、Critic の学習を続ける。Actor が高得点の実行を生む頻度が上がれば、採点基準が同じでも Critic の予測は上がる。</p><p>一般的な RLHF-PPO では、最終的な RM スコアと参照モデルからの乖離に対するペナルティを組み合わせる。生成位置 <var>t</var> でよく使われるサンプルベースの形は次の通りである。</p><div aria-label=\"生成位置での報酬\" class=\"equation\" role=\"math\">r<sub>t</sub> = −β [log π<sub>old</sub>(a<sub>t</sub> | h<sub>t</sub>) − log π<sub>ref</sub>(a<sub>t</sub> | h<sub>t</sub>)] + 𝟙<sub>t=T</sub> R</div><p><var>h<sub>t</sub></var> は接頭辞、<var>a<sub>t</sub></var> は生成 token、<var>T</var> は最後の生成位置である。<var>R</var> は終点でだけ加え、<var>β</var> が参照制約の強さを決める。行動分布について期待値を取ると、この対数確率差は KL ダイバージェンスに対応する。<a href=\"https://arxiv.org/html/2203.02155v1#S3.SS5\">[1]</a></p><p><strong>一般化アドバンテージ推定（GAE）</strong>は、報酬と価値予測を組み合わせ、後ろから各生成位置のアドバンテージを計算する。</p><div aria-label=\"GAE の再帰式\" class=\"equation\" role=\"math\">δ<sub>t</sub> = r<sub>t</sub> + γ(1 − d<sub>t</sub>)V<sub>t+1</sub> − V<sub>t</sub><br/>A<sub>t</sub> = δ<sub>t</sub> + γλ(1 − d<sub>t</sub>)A<sub>t+1</sub><br/>Ĝ<sub>t</sub> = A<sub>t</sub> + V<sub>t</sub></div><p><var>δ</var> は 1 ステップの予測誤差、<var>γ</var> は将来の報酬の割引率、<var>λ</var> は後続のアドバンテージをどれだけ残すかを決める。<var>d=1</var> は課題が実際に終了したことを表す。<var>Ĝ</var> は Critic に与えるリターン目標である。ここで <var>t</var> は生成の意思決定を数え、ツールの観測は次の位置の文脈に入る。<a href=\"https://arxiv.org/abs/1506.02438\">[2]</a></p><p>例の最終スコアを <strong>R=8</strong> とし、β=0、γ=λ=1、報酬は実際の終了時にだけ与える。このとき、出発点の予測が V=5 ならアドバンテージは <strong>+3</strong>、修正後の別の位置で V=7 なら <strong>+1</strong> となる。リターン目標はどちらも 8 だが、その時点での予測との差が異なる。</p></section>\n<section aria-labelledby=\"optimization\">\n<h2 id=\"optimization\">5 D · Actor は確率をどう更新するか</h2>\n<p>Actor はアドバンテージに応じて、サンプルされた行動の確率を調整する。このバッチを収集した方策を <var>π<sub>old</sub></var>、更新中の方策を <var>π<sub>θ</sub></var> とする。</p>\n<!-- FIGURE:ppo-update --><div aria-label=\"PPO のクリップ目的関数\" class=\"equation\" role=\"math\">ρ<sub>t</sub> = π<sub>θ</sub>(a<sub>t</sub> | h<sub>t</sub>) / π<sub>old</sub>(a<sub>t</sub> | h<sub>t</sub>)<br/>L<sub>π</sub> = −mean min [ρ<sub>t</sub>A<sub>t</sub>, clip(ρ<sub>t</sub>, 1 − ε, 1 + ε)A<sub>t</sub>]</div>\n<p>正のアドバンテージは対応する確率を高める方向、負なら逆方向に働く。<var>clip</var> は目的関数内の確率比を指定範囲に制限し、更新をさらに大きくする誘因を抑える。実際のパラメータ更新にはバッチ全体のサンプルも影響する。<a href=\"https://spinningup.openai.com/en/latest/algorithms/ppo.html\">[4]</a></p>\n<p><strong>旧方策と参照モデルは役割が異なる。</strong>旧方策は今回のバッチの更新基準であり、後のバッチでは入れ替わる。参照モデルは通常、SFT の出発点に固定する。旧方策の対数確率は軌跡と一緒に保存できるため、5 つ目のモデルを常駐させる必要はない。</p>\n</section>\n<section aria-labelledby=\"long-horizon\">\n<h2 id=\"long-horizon\">6 長い軌跡が学習を難しくする理由</h2>\n<p>成功した実行にも、調査、有効な修正、不要な操作が混在する。終点の評価はアドバンテージ推定を通じて途中の位置に伝わるが、依然としてノイズを含む。Critic の予測誤差もその推定に入る。Actor が変化し続けるため、Critic も追従する必要がある。</p>\n<p>ツールログは軌跡の長さにも影響する。実装では、どの位置をアドバンテージの再帰計算に含め、どの間隔で割引を適用するかを明示する必要がある。ログを方策損失から除外するだけでは、この規則は決まらない。計算を分割する場合は後続の価値とアドバンテージを境界越しに引き継ぎ、実際の終了と途中の打ち切りを区別する。</p>\n<p>採点基準も目的に合わせる必要がある。RM が整った完了報告を好むと、実際にはプログラムが直っていなくても高得点になり得る。テスト、選好データ、学習に使わない評価で成果物そのものを確かめる。一方、大きすぎる更新は収集済みの軌跡を早く陳腐化させ、強すぎる KL 制約は探索を抑える。学習率、クリップ、採点の質、サンプリングコストを合わせて考える必要がある。<a href=\"https://arxiv.org/abs/2210.10760\">[5]</a></p>\n</section>\n<section aria-labelledby=\"alternatives\">\n<h2 id=\"alternatives\">7 GRPO と DPO は何を変えるか</h2>\n<p><strong>GRPO</strong> は同じ課題に対して回答群を生成し、群内の平均と標準偏差から相対的なアドバンテージを計算して Critic を省く。原著の手法は RM と参照モデルを残し、自動検証による報酬を使えば RM も置き換えられる。同じ課題を複数回実行するためサンプリングコストが増え、全回答が同点なら相対的な報酬差は得られない。<a href=\"https://arxiv.org/html/2402.03300v3#S4.SS1\">[6]</a></p>\n<p><strong>標準的なオフライン DPO</strong> は、既存の「A のほうが B より望ましい」というデータで直接学習する。Actor と参照モデルを残し、独立した RM、Critic、オンラインの生成・採点ループを省く。KL 正則化付きの報酬最適化を、方策確率の目的関数として書き換える。報酬は方策と参照モデルの対数確率比で表現でき、同じ課題に対する 2 つの回答を比較すると共通の正規化項が消える。そのため、選好データの質とカバー範囲が重要になる。<a href=\"https://arxiv.org/html/2305.18290v3#S4\">[7]</a></p>\n<p>コード課題での選択は、1 回の実行コスト、検証の信頼性、選好ペアの有無にもよる。<a href=\"/writing/terminal-rsi/?lang=ja\">Terminal-RSI</a> は検証器の報酬と PPO を使い、長い軌跡でのアドバンテージ推定と Critic の引き継ぎを研究する。独立した選好 RM は使用しない。</p>\n</section>\n\n",
    "zh.html": "<section aria-labelledby=\"overview\"><h2 id=\"overview\">1 先看完整的训练循环</h2><p>代码 Agent 读文件、调用工具、修改程序；这些动作与工具返回共同组成一条<strong>轨迹</strong>。PPO 利用整次执行的结果，调整沿途生成动作的概率。</p><p>在采用奖励模型的<strong>人类反馈强化学习（RLHF）</strong>中，<strong>Actor 生成动作，RM 评价完整结果，Critic 预测从当前上下文继续执行的回报，Reference 提供固定的策略参照</strong>。一次执行结束后，奖励与价值预测经过优势估计，分别成为 Actor 和 Critic 的训练目标。图中的 A—D 对应下文四个模块。</p><!-- FIGURE:training-overview --></section>\n<section aria-labelledby=\"reward-model\">\n<h2 id=\"reward-model\">2 A · 准备策略与奖励模型</h2><p>训练通常从已有语言模型开始，先做<strong>监督微调（SFT）</strong>：给它合格的操作示范，提高相应上下文下生成这些操作的概率。PPO 随后让策略网络 <strong>Actor</strong> 自己尝试，从新结果中学习。<a href=\"https://arxiv.org/html/2203.02155v1#S3.SS1\">[1]</a></p><p>SFT 后保留两份相同的策略参数：一份成为继续学习的 Actor，另一份固定为 Reference。Reference 对已生成的 token 计算概率；PPO 用这组概率约束 Actor 偏离初始策略的程度。</p><p>下面以修复金额汇总脚本为例：把字符串金额 <code>\"0.10\"</code> 与 <code>\"0.20\"</code> 精确相加，输出 <code>0.30</code>。轨迹与分数采用教学构造。</p>\n<p>先准备两条完整执行：A 改用 Decimal 并通过测试，B 保留浮点输出。标注者选择 A，标签就是<strong>“A 优于 B”</strong>。训练<strong>奖励模型（RM）</strong>时，将“任务＋执行 A”和“任务＋执行 B”分别输入同一个模型，得到分数 <var>r<sub>A</sub></var> 与 <var>r<sub>B</sub></var>。</p>\n<!-- FIGURE:reward-value-training --><div aria-label=\"RM 偏好损失\" class=\"formula-scroll\" role=\"region\" tabindex=\"0\"><math display=\"block\" xmlns=\"http://www.w3.org/1998/Math/MathML\"><msub><mi>L</mi><mtext>RM</mtext></msub><mo>=</mo><mo>−</mo><mi>log</mi><mo>⁡</mo><mi>σ</mi><mo>(</mo><msub><mi>r</mi><mi>A</mi></msub><mo>−</mo><msub><mi>r</mi><mi>B</mi></msub><mo>)</mo></math></div>\n<p><var>σ</var> 是 sigmoid 函数，把分差转换成偏好概率。最小化这个损失，会鼓励 A 的相对分数更高；大量偏好对让 RM 学会评价新执行。人工提供偏好顺序，RM 学习相应的分值。RM 通常使用语言模型骨干接一个标量输出头，输出单个分数。<a href=\"https://arxiv.org/html/2203.02155v1#S3.SS5\">[1]</a></p>\n</section>\n<section aria-labelledby=\"rollout\">\n<h2 id=\"rollout\">3 B · 让 Actor 完成一次尝试</h2><p>输入采用 JSONL，即每行一个 JSON 对象。原脚本把金额转成 <code>float</code> 后求和，得到 <code>0.30000000000000004</code>。Actor 要找到这个问题，改用 <code>Decimal</code> 处理金额字符串，再将结果格式化为两位小数。</p>\n<p>这里采用基于人类反馈的强化学习（<strong>RLHF</strong>）中的四角色设置。<strong>Rollout</strong> 是让当前 Actor 在环境中完成一次尝试。它逐个生成 token，即文字的编码单位，组成工具调用和最终答复；环境返回文件内容与测试日志，成为下一次生成的上下文。</p><!-- FIGURE:trajectory-models -->\n<p>Actor 负责生成；RM 在执行结束后读取任务与完整记录，给出最终分数；Critic 在各生成位置读取当时的前缀，预测后续回报；固定的<strong>参考模型 Reference</strong> 对相同上下文与已生成 token 计算概率，用来衡量策略偏离起点的程度。</p>\n<p>图中“测试通过”先是一条工具观察，最终奖励由 RM 给出。若有可靠的自动验收程序，也可以直接用验收结果构造奖励，替代 RM。</p>\n<p>训练的<strong>掩码</strong>标出 Actor 生成的位置。文件内容和测试日志保留在输入中，帮助模型判断；策略损失只作用于它生成的 token。Critic 的前缀预测可在轨迹收集后批量计算，输入仍截止于对应时刻。</p>\n</section>\n<section aria-labelledby=\"advantages\"><h2 id=\"advantages\">4 C · Critic 怎样从结果中学习</h2><p><strong>价值网络 Critic 预测当前 Actor 从某段上下文继续执行后的平均回报。</strong>假设同题四种结果等概率，固定 RM 给出 2、4、6、8 分，平均值便是 5。Critic 从一次次结果中学习这个均值；这里的数值采用示意刻度。</p><p><strong>回报</strong>是从某个位置往后累积的奖励。训练 Critic 时，先执行到结果已知，再把前面的历史片段与各自回报目标配成样本。<strong>广义优势估计（GAE）</strong>负责用奖励和价值预测计算这些目标，下面先看它的数据流。</p><!-- FIGURE:critic-training --><p>Critic 也常用语言模型骨干加标量头实现。InstructGPT 用 RM 参数初始化价值网络，再用轨迹回报继续训练；复用的是起始参数，后续监督来自各段前缀的回报目标。<a href=\"https://arxiv.org/html/2203.02155v1#S3.SS5\">[1]</a></p><p>Critic 将每段前缀与回报目标配成样本。若预测 5、目标 8，平方误差是 9；对误差反向传播，由优化器调整可训练参数。完整微调时，骨干与标量头都参与更新。目标在这次更新中固定，RM 不随这项损失更新。</p><div aria-label=\"价值回归\" class=\"equation\" role=\"math\">L<sub>V</sub> = mean [V<sub>φ</sub>(h<sub>t</sub>) − Ĝ<sub>t</sub>]<sup>2</sup></div><p><var>φ</var> 是 Critic 的参数。不同结果反复出现，回归逐渐学到平均回报。它提供随上下文变化的基线，减少采样带来的梯度波动。直接使用回报也能训练策略；合适的价值预测让有限样本的更新更稳定。<a href=\"https://spinningup.openai.com/en/latest/spinningup/rl_intro3.html#baselines-in-policy-gradients\">[3]</a></p><p>RM 用偏好关系学习评分标准，Critic 用实际回报学习预期。PPO 阶段通常固定 RM、继续训练 Critic。Actor 更常生成高分执行时，即使评分标准不变，Critic 的预测也应随之提高。</p><p>常见 RLHF-PPO 将最终 RM 分数与参考约束组合。对生成位置 <var>t</var>，一个常用的采样形式是：</p><div aria-label=\"生成位置奖励\" class=\"equation\" role=\"math\">r<sub>t</sub> = −β [log π<sub>old</sub>(a<sub>t</sub> | h<sub>t</sub>) − log π<sub>ref</sub>(a<sub>t</sub> | h<sub>t</sub>)] + 𝟙<sub>t=T</sub> R</div><p><var>h<sub>t</sub></var> 是前缀，<var>a<sub>t</sub></var> 是生成 token，<var>T</var> 是最后一个生成位置。<var>R</var> 只在终点加入；<var>β</var> 控制参考约束强度。对动作分布求期望时，前面的对数概率差对应 KL 散度。<a href=\"https://arxiv.org/html/2203.02155v1#S3.SS5\">[1]</a></p><p><strong>广义优势估计（GAE）</strong>结合奖励与价值预测，从后往前计算每个生成位置的优势：</p><div aria-label=\"GAE 递推\" class=\"equation\" role=\"math\">δ<sub>t</sub> = r<sub>t</sub> + γ(1 − d<sub>t</sub>)V<sub>t+1</sub> − V<sub>t</sub><br/>A<sub>t</sub> = δ<sub>t</sub> + γλ(1 − d<sub>t</sub>)A<sub>t+1</sub><br/>Ĝ<sub>t</sub> = A<sub>t</sub> + V<sub>t</sub></div><p><var>δ</var> 是一步预测差，<var>γ</var> 折扣后续奖励，<var>λ</var> 控制后续优势的保留程度；<var>d=1</var> 表示任务真正结束。<var>Ĝ</var> 是给 Critic 的回报目标。这里 <var>t</var> 枚举生成决策，工具返回进入下一位置的上下文。<a href=\"https://arxiv.org/abs/1506.02438\">[2]</a></p><p>取示例最终分数 <strong>R=8</strong>，暂令 β=0、γ=λ=1，整条轨迹仅在真正结束时奖励。此时起点预测 V=5，优势是 <strong>+3</strong>；修复后另一个位置预测 V=7，优势是 <strong>+1</strong>。两处回报目标都是 8，但与各自预期的差值不同。</p></section>\n<section aria-labelledby=\"optimization\">\n<h2 id=\"optimization\">5 D · Actor 怎样更新概率</h2>\n<p>Actor 使用优势调整已采样行为的概率。生成这一批轨迹的策略称为 <var>π<sub>old</sub></var>，正在更新的策略是 <var>π<sub>θ</sub></var>：</p>\n<!-- FIGURE:ppo-update --><div aria-label=\"PPO 裁剪目标\" class=\"equation\" role=\"math\">ρ<sub>t</sub> = π<sub>θ</sub>(a<sub>t</sub> | h<sub>t</sub>) / π<sub>old</sub>(a<sub>t</sub> | h<sub>t</sub>)<br/>L<sub>π</sub> = −mean min [ρ<sub>t</sub>A<sub>t</sub>, clip(ρ<sub>t</sub>, 1 − ε, 1 + ε)A<sub>t</sub>]</div>\n<p>正优势鼓励提高相应概率，负优势给出相反方向。<var>clip</var> 将概率比截到指定区间，限制目标中继续放大更新的收益；实际更新还受整批样本影响。<a href=\"https://spinningup.openai.com/en/latest/algorithms/ppo.html\">[4]</a></p>\n<p><strong>旧策略与参考模型承担不同工作。</strong>旧策略给本批更新提供比较起点，换批后随之更新；参考模型通常长期固定在 SFT 起点。旧概率可随轨迹保存，不必为它再常驻第五个模型。</p>\n</section>\n<section aria-labelledby=\"long-horizon\">\n<h2 id=\"long-horizon\">6 长轨迹怎样影响学习</h2>\n<p>一次成功会同时包含排错、有效修改和多余操作。终点得分经过优势估计传回各位置，反馈仍有噪声；Critic 的预测偏差也会进入这些优势。Actor 持续变化，因此价值网络需要持续跟进。</p>\n<p>工具日志还会改变轨迹长度。实现需要明确哪些位置参与优势递推、每隔多长应用一次折扣；仅屏蔽日志的策略损失，并没有确定递推规则。计算时分块，应续接后继价值与优势；真正终止与中途截断需要分别处理。</p>\n<p>评分也要跟上目标。若 RM 偏爱漂亮的完成声明，模型可能高分而未修好程序；测试、偏好数据和留出评估要覆盖实际交付。另一方面，更新过猛会让旧轨迹迅速过时，过强的 KL 约束又会抑制探索。学习率、裁剪、评分质量与采样成本需要一起考虑。<a href=\"https://arxiv.org/abs/2210.10760\">[5]</a></p>\n</section>\n<section aria-labelledby=\"alternatives\">\n<h2 id=\"alternatives\">7 GRPO 与 DPO 改变了什么</h2>\n<p><strong>GRPO</strong> 对同一道题生成一组答案，用组内均值和标准差计算相对优势，省去 Critic。原始方法仍使用 RM 和参考模型；改用自动验收奖励还可省去 RM。同题多次执行增加采样成本，全组同分时则没有相对奖励差异。<a href=\"https://arxiv.org/html/2402.03300v3#S4.SS1\">[6]</a></p>\n<p><strong>标准离线 DPO</strong> 直接使用“A 优于 B”的已有数据，保留 Actor 与参考模型，省去独立 RM、Critic 和在线采样评分循环。它将带 KL 正则的奖励优化改写为策略概率目标：奖励可由策略与参考的对数概率比表示，同题共有的归一化项在比较两份答案时相消。偏好数据的质量与覆盖由此成为关键。<a href=\"https://arxiv.org/html/2305.18290v3#S4\">[7]</a></p>\n<p>在代码任务中，选择还取决于一次执行有多贵、能否可靠验收，以及有没有成对偏好数据。<a href=\"/writing/terminal-rsi/?lang=zh\">Terminal-RSI</a> 采用验证器奖励与 PPO，并研究长轨迹的优势估计和 Critic 交接；它没有独立的偏好 RM。</p>\n</section>\n\n"
  }
}