File size: 39,106 Bytes
2f59739 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 | # EasyR1-V4-Embody 当前实现与两篇论文的完整串讲
本文档把三件事串起来讲清楚:
1. arXiv:2505.22050, **Reinforced Reasoning for Embodied Planning**。
2. arXiv:2605.27140v1, **StepOPSD: Step-Aware Online Preference Distillation for Agent Reinforcement Learning**。
3. 当前仓库 `EasyR1-V4-Embody` 的代码实现,尤其是 `grpo_step`、`rule` step reward、`forward_proxy`、residual gate / prompt gate。
结论先放在前面:
```text
2505.22050 是一个 embodied VLM 训练 recipe:
SFT 初始化 + rule-based reward + GRPO/RFT,让 Qwen2.5-VL 学会输出多步可执行计划。
2605.27140 StepOPSD 是一个 agent RL 信用分配算法:
把 OPSD teacher-student logp gap 放到 step/action span 上,做 GRPO advantage shaping。
当前 EasyR1-V4-Embody 介于两者之间:
任务设定、数据和输出形式更像 2505.22050;
算法改动、step-level advantage shaping 和 forward_proxy 更像 StepOPSD;
同时又额外实现了 rule step reward、GT-reference teacher、additive advantage、action_id/action_name span control、residual/prompt gates。
```
---
## 1. 三个对象各自解决什么问题
### 1.1 2505.22050 解决的是“怎么训练 embodied planner”
这篇论文的主问题是:开源 VLM 在具身场景里很难做长程、多步、视觉条件下的 planning。模型要看当前视觉 observation、历史动作、自然语言任务,然后输出后续 action sequence。
它的方案是两阶段:
```text
Stage 1: SFT
用强闭源模型 Gemini-2.0-flash 蒸馏出高质量 reasoning + plan 数据。
让 Qwen2.5-VL-7B 先学会任务分解、空间常识、输出格式。
Stage 2: RFT / GRPO
构造 ALFRED 轨迹分解数据。
对模型输出的多步 action plan 设计 rule-based reward。
用 GRPO 做 reinforcement fine-tuning。
```
它的 reward 是规则式的:
```text
R = R_format + R_accuracy
R_format:
JSON 结构是否正确;
必需字段是否存在;
action_id / action_name 是否有效匹配。
R_accuracy:
按 action sequence 和 gold sequence 做 prefix matching。
若连续匹配 n 步,gold 总长为 k:
R(n; k) = n(n + 1) / (k(k + 1))
```
所以 2505.22050 的重点不是“OPSD 信号怎么改 advantage”,而是“具身规划任务上,SFT + 规则奖励 + GRPO 这条 pipeline 能不能训动”。
### 1.2 StepOPSD 解决的是“长轨迹 sparse reward 怎么分给关键 step”
StepOPSD 的主问题是 agent RL 的 credit assignment:
```text
一条长 rollout 可能因为一个局部 action 错了而失败。
标准 GRPO 只有一个 terminal reward。
这个 reward 被广播到整条 response 的所有 token。
结果是:模型知道整条轨迹不好,但不知道是哪一步导致不好。
```
StepOPSD 的核心流程:
```text
rollout
-> trajectory reward / GRPO advantage
-> parse action-centered step spans
-> hindsight teacher context rescoring
-> compute token-level logp gap Delta
-> convert Delta into bounded multiplicative weights
-> reshape GRPO advantage
-> policy update
```
它的信号是:
```text
Delta_{k,j}
= log pi_T(z_{k,j} | hindsight context, prefix)
- log pi_S(z_{k,j} | causal context, prefix)
```
它的 advantage 注入方式是:
```text
w_raw = 2 * sigmoid(sign(A) * Delta)
w = clip(w_raw, 1 - alpha_clip, 1 + alpha_clip)
A_tilde = (1 - lambda_mix) * A + lambda_mix * (w * A)
```
关键性质:
```text
w 始终为正。
因此 StepOPSD 只改变原始 GRPO advantage 的 magnitude,不改变 sign。
它是 sign-preserving 的 credit redistribution。
```
StepOPSD 的 hindsight 来源主要是同一个 GRPO group 中的 successful peer trajectory;teacher 是 stale reference policy,避免 moving target。
### 1.3 当前代码解决的是“one-shot embodied JSON plan 内部的 step credit assignment”
当前仓库的任务形态:
```text
输入:
图像 + human instruction + action history + action list
输出:
一次性生成完整 JSON:
{
"visual_state_description": "...",
"reasoning_and_reflection": "...",
"language_plan": [...],
"executable_plan": [
{"action_id": 133, "action_name": "..."},
...
]
}
```
注意:当前代码不是多轮在线环境交互。它是一行样本生成一整条后续 trajectory plan。
代码里的核心目标:
```text
原来只有整条 trajectory 的 scalar reward。
现在希望在同一条 response 内部,把不同 step 的 token 赋予不同 advantage。
A_token = A^E + omega * A^S
A^E:
原始 GRPO episode advantage。
来自整条轨迹 scalar reward 的组内归一化。
A^S:
新增 step-level per-token advantage。
可以来自 rule action_id 匹配,也可以来自 forward_proxy teacher-student logp contrast。
```
因此,当前实现和 2505.22050 的任务设定很近,和 StepOPSD 的算法思想也很近。
---
## 2. 当前代码端到端数据流
### 2.1 Dataset:把 EB-ALFRED 样本变成 VLM prompt
主要文件:
```text
verl/utils/dataset.py
```
当前 embodied dataset 的 `__getitem__` 做了这些事:
1. 从 parquet 行里读:
```text
instruction
history
action_id # 可用动作列表
image
gt_bbox
gt_action
gt_input_text
gt_action_close / gt_action_open 等字段保留在 row_dict 中
```
2. 构造 prompt:
```text
You are Embodied-R1 ...
Given the current visual state <image> ...
Current context: {history}
Action Descriptions and Validity Rules
...
The available action names are:
{actionlist}
Output ONLY a valid JSON object:
visual_state_description
reasoning_and_reflection
language_plan
executable_plan
```
3. 把 `<image>` 替换为 Qwen-VL 视觉占位:
```text
<|vision_start|><|image_pad|><|vision_end|>
```
4. 用 processor 编码图像和 prompt,生成:
```text
input_ids
attention_mask
position_ids
raw_prompt_ids
multi_modal_data = {"images": raw_images}
ground_truth = json.dumps(gt)
```
这里的 `ground_truth` 不是直接的 `executable_plan` list,而是一个包装后的 JSON,内部包含:
```text
action
gt_bbox
input_text
gt_open_ans
```
其中 `input_text` 里还能解析出 GT 的 `executable_plan`。
### 2.2 Rollout:模型一次性生成 response
训练主循环在:
```text
verl/trainer/ray_trainer.py
```
核心顺序:
```text
prepare_rollout_engine
-> _make_batch_data
-> release_rollout_engine
-> _balance_batch
-> compute_reward
-> compute_old_log_probs
-> compute_ref_log_probs
-> build step_adv_raw if adv_estimator == grpo_step
-> compute_advantage
-> update actor
```
这里的 response 是完整 JSON plan,不是一步环境 action。
### 2.3 Trajectory-level reward:verify model 给整条计划打分
主要文件:
```text
verl/workers/reward/function.py
verl/workers/reward/verify.py
```
`compute_reward_batch` 的行为是:
1. decode response。
2. 尝试解析 JSON。
3. 从 response 中提取:
```text
executable_plan
```
4. 从 ground truth 中提取:
```text
ground_truth_open = json.loads(ground_truth["input_text"])["executable_plan"]
```
5. 构造 verify prompt:
```text
Sentence 1: {GT executable_plan}
Sentence 2: {pred executable_plan}
You are judging whether a predicted embodied action trajectory matches
the ground-truth trajectory at the intent level.
Focus on FUNCTIONAL EQUIVALENCE ...
Compare mainly by action_name, not exact action_id.
Be lenient about extra/missing find steps ...
Only output: True or False.
```
6. 调用 `ask_llm`,用 verify VLM 生成一个 token,取 True / False 相关概率。
7. 得到:
```text
format = 1.0 if JSON parse ok else 0.0
accuracy = verify probability, False 会转成负值
overall = 0.8 * accuracy + 0.2 * format
```
8. 把 `overall` 写到最后一个 response token:
```text
reward_tensor[i, cur_response_length - 1] = score["overall"]
```
这意味着整条 trajectory 的 reward 在张量里仍然是一个 terminal scalar。
### 2.4 原始 GRPO:A^E 怎么来
主要文件:
```text
verl/trainer/core_algos.py
```
标准 GRPO advantage 逻辑是:
```text
scores = token_level_rewards.sum(-1)
按 uid 分组:
同一个 prompt 的 n 条 rollout 共享 uid。
对每个 uid group:
A^E_i = (R_i - mean(R_group)) / (std(R_group) + eps)
然后:
A^E_i 广播到该 response 的所有有效 token。
```
所以没有 step reward 时,同一条 response 里的每个 token 都拿同一个 advantage。
这正是当前工作要改的地方。
### 2.5 grpo_step:在 A^E 上加 A^S
主要文件:
```text
verl/trainer/core_algos.py
verl/trainer/ray_trainer.py
verl/trainer/step_reward.py
```
新增 estimator:
```text
AdvantageEstimator.GRPO_STEP = "grpo_step"
```
核心函数:
```python
episode_adv, _ = compute_grpo_outcome_advantage(...)
if step_adv_raw is None:
return episode_adv, episode_adv
step_adv = step_adv_raw * response_mask
advantages = episode_adv + step_advantage_w * step_adv
return advantages, advantages
```
公式就是:
```text
A_token = A^E + omega * A^S_token
```
其中:
```text
A^E:
仍然是原始 GRPO,完全复用。
A^S:
shape = (bs, response_length)
response 内不同 token 可以不同。
解析失败、scaffolding、非目标 token 为 0。
```
这个点非常关键:当前实现不是额外加一个 KL loss,也不是重写 GRPO,而是在 advantage 估计阶段加一条旁路信号。
---
## 3. step_adv_raw 的两条来源
当前代码把 `step_adv_raw` 做成可切换的:
```yaml
algorithm.adv_estimator: grpo_step
algorithm.step_reward_kind: rule | forward_proxy
```
### 3.1 Rule:硬规则 step reward
文件:
```text
verl/trainer/step_reward.py
```
入口:
```text
build_step_adv_raw
-> build_step_adv_vector
-> compute_step_match_rewards
```
流程:
1. decode response。
2. 容错解析 `executable_plan`。
3. 解析 GT:
```text
gt_steps_from_close(gt_close)
```
4. 对 predicted steps 和 GT steps 做匹配。
支持三种匹配:
```text
exact:
pred[i] == gt[i] 才算对。
prefix:
最长正确前缀;第一个错后面全算错。
lcs:
longest common subsequence,对顺序扰动更宽松。
```
默认匹配键:
```yaml
algorithm.step_match_key: action_id
```
reward 转 advantage:
```text
匹配:+1
不匹配:-1
scaffolding / 非 step token:0
解析失败:整条 A^S = 0,退化为纯 GRPO
```
这条路和 2505.22050 很接近:都是用 GT action sequence 做 rule-based correctness signal。
但也有差别:
```text
2505.22050:
rule reward 先变成 response-level scalar reward,再进入 GRPO。
prefix reward R(n;k) 是整条 response 的 reward。
当前代码 rule:
rule reward 直接变成 per-token step advantage A^S。
一条 response 内部可以前两步 +1,第三步 -1。
```
也就是说,当前 rule 比 2505.22050 更细:不是只给整条轨迹一个分,而是把 step 对错广播到对应 token。
### 3.2 Forward Proxy:GT-aware teacher-student logp contrast
文件:
```text
verl/trainer/teacher_proxy.py
verl/workers/reward/function.py
verl/workers/reward/verify.py
verl/trainer/step_reward.py
```
配置:
```yaml
algorithm.step_reward_kind: forward_proxy
algorithm.step_squash: contrast
algorithm.step_teacher_path: ...
algorithm.step_score_source: action_name | action_id | semantic
algorithm.step_credit_target: action_name | action_id | semantic
```
#### 3.2.1 为什么要跑在 reward actor 上
最初如果在 driver 上做 teacher forward,会遇到:
```text
driver 进程没有 GPU。
verl/Ray 中 GPU 分给 worker actor。
teacher.to("cuda") 会失败。
```
所以当前代码把 forward_proxy 放到 reward actor:
```text
ray.get(self.reward_fn.compute_step_adv.remote(...))
```
reward actor 本来就有 verify model 的 GPU 资源,因此可以 lazy-load teacher scorer。
#### 3.2.2 TeacherLogpScorer 做什么
`TeacherLogpScorer.logp_teacher_student` 对同一段 predicted response tokens 跑两次 forward:
```text
teacher context:
image + "Here is a reference successful language plan:"
+ GT reference plan
+ transition
+ predicted response tokens
student context:
image + "Problem: {instruction}"
+ student instruction
+ predicted response tokens
```
返回:
```text
teacher_logp[t] = log p_model(response_token_t | image, GT context, response_prefix)
student_logp[t] = log p_model(response_token_t | image, problem context, response_prefix)
```
然后:
```text
Delta_t = teacher_logp[t] - student_logp[t]
```
这个 Delta 的语义是:
```text
如果模型看了 GT 后更支持这个 response token,Delta 为正。
如果模型看了 GT 后更不支持这个 response token,Delta 为负。
```
#### 3.2.3 当前代码里的一个重要现实:teacher 不一定等于 policy
`teacher_proxy.py` 和 `config.py` 的注释里仍然写着:
```text
teacher should be same path as policy
same tokenizer, true OPSD self-distillation
```
但当前运行脚本 `examples/qwen25_vl_3b_Domain.sh` 实际是:
```text
policy = Qwen2.5-VL-3B-RobotGPT-R1
teacher = Qwen2.5-VL-3B-Instruct
```
这意味着当前 forward_proxy 的真实语义不是严格的“policy 自蒸馏 OPSD”,而是:
```text
冻结外部 Instruct teacher 在 GT context 和 no-GT context 下的 logp contrast。
```
这点要在论文/报告中说准。
如果 teacher 等于 policy:
```text
更像原始 OPSD / self-distillation。
但实测容易因为 policy 对自己生成的 token 过度自信而 logp diff 塌平。
```
如果 teacher 是未微调 Instruct:
```text
信号更容易有波动。
但它不再代表 policy 自己的 preference shift;
而是外部 teacher 的 GT-conditioned preference shift。
```
当前 `step_adv_heatmaps/_diag.txt` 中能看到 forward_proxy 已有波动,例如:
```text
std ~= 0.9 - 2.3
mean 通常为正
min/max 可到约 -15 / +13
```
这说明“信号活了”,但不自动说明“信号方向一定奖对惩错”。
#### 3.2.4 Delta 怎么变成 step score
文件:
```text
verl/trainer/step_reward.py
build_step_adv_vector_from_logp
```
先选 score tokens:
```yaml
step_score_source:
action_name # 默认
action_id
semantic # action_id + action_name
```
对这些 token 聚合:
```text
contrast 模式:
token_signal = teacher_logp - student_logp
raw_step = robust_mean(token_signal over score tokens)
score = tanh(normalize(raw_step) / score_tau)
prob 模式:
score = 2 * exp(mean teacher_logp) - 1
```
代码和实验笔记都说明:`prob` 容易恒平,因为 GT-conditioned teacher 对很多 token 都很自信;真正有意义的是 `contrast`。
#### 3.2.5 score 写回哪些 token
再选 credit target:
```yaml
step_credit_target:
action_name
action_id
semantic
```
默认 `action_name`,一些 ablation 用:
```yaml
step_score_source: semantic
step_credit_target: action_id
step_action_name_weight: 0.0
```
这个设计很重要:
```text
score_source 决定“用哪些 token 判断这一步好坏”。
credit_target 决定“训练时把 advantage 写到哪些 token 上”。
```
例如:
```text
score_source = semantic:
用 action_id + action_name 一起估计这步是否被支持。
credit_target = action_id:
主要更新离散动作选择,而不是训练自然语言措辞。
```
这是当前实现相对 StepOPSD 的一个具身 JSON plan 特化点。
---
## 4. Token span 对齐:当前实现的工程核心
step reward 最终要进入 PPO/GRPO loss,因此必须是 token 级。
当前代码做了以下事情:
```text
response_ids
-> decode response text
-> extract executable_plan
-> locate each step's action_id / action_name character span
-> map character span back to token indices
-> write step score into selected token positions
```
主要函数:
```text
extract_plan_steps
pred_step_token_spans
_token_char_offsets
_find_action_id_value_span
_find_action_name_value_span
_select_span_tokens
```
### 4.1 JSON 解析
`extract_plan_steps` 能处理:
```text
正常 JSON dict
带 json 标记的 fenced code block
前后有散文的 response
尾部 <|im_end|> / <|endoftext|>
bare list
```
解析失败返回 `None`,后续整条 A^S 为 0。
### 4.2 char offset
`_token_char_offsets` 先尝试:
```text
tokenizer(text, return_offsets_mapping=True)
```
如果 re-tokenize 后 input_ids 和原始 response_ids 一致,就用 tokenizer offset。
如果不一致,则降级为 prefix decode:
```text
逐 token decode ids[:t+1]
用字符串长度差构造 offsets
```
这样比“decode 后重编码”更稳,因为 Qwen/VL tokenizer 在 special token、空格清理、JSON 标点附近可能 round-trip 不一致。
### 4.3 step span
代码先找到 `"executable_plan":` 后面的 list 起点,然后按顺序找每一步:
```text
action_id value span
action_name value span
```
每个 step 得到:
```python
StepTokenSpans(
action_id_tokens=[...],
action_name_tokens=[...],
)
```
然后根据配置选择:
```text
action_id tokens
action_name tokens
semantic tokens = action_id + action_name
```
### 4.4 当前 span 设计与 StepOPSD 的差别
StepOPSD 面向的是一般 agent trajectory,常见 span 是:
```text
<action>...</action>
clean_step_no_observation
```
当前代码面向的是 embodied JSON plan,span 是:
```text
action_id value
action_name value
```
所以当前实现对 `executable_plan` 的结构假设更强,但也更精确:可以只训练 action id,不训练 JSON scaffold 或语言描述。
---
## 5. Gate 扩展:控制 forward_proxy 信号进来的位置和强度
当前代码不止有 plain forward_proxy,还实现了两类 gate。
### 5.1 Residual contrast gate
配置:
```yaml
algorithm.step_gate: residual_contrast
algorithm.step_gate_residual: response_median
algorithm.step_gate_threshold: 0.0
algorithm.step_gate_tau: 1.0
algorithm.step_budget_tau: 1.0
algorithm.step_min_score_tokens: 2
```
逻辑:
1. 先对 token_signal 去 response-level median:
```text
d'_t = d_t - median(d over valid response tokens)
```
2. 每步算 raw score:
```text
raw_k = robust_mean(d'_t over score tokens)
soft_score_k = tanh(z_k / score_tau)
```
3. 再用 unsigned contrast 估计 importance:
```text
imp_k = robust_mean(abs(d'_t) over score tokens)
```
4. 组合三个 gate:
```text
decision_gate = sigmoid((imp_z - threshold) / gate_tau)
budget_gate = clamp(softmax(imp / budget_tau) * num_steps, 0, 1)
confidence = len_gate * var_gate
gate_k = decision_gate * budget_gate * confidence
```
5. 最终:
```text
A^S_k = gate_k * soft_score_k
```
直觉:
```text
soft_score 决定方向:支持还是反对。
gate 决定强度:这一步是否值得更新。
```
### 5.2 Prompt gate
配置:
```yaml
algorithm.step_gate: prompt
algorithm.step_prompt_gate_mode: generation
algorithm.step_prompt_gate_model_path: ...
algorithm.step_prompt_kl_weight: ...
algorithm.step_use_prompt_causal_gate: true
algorithm.step_use_prompt_redundancy_gate: true
```
`PromptGateScorer` 会让 judge 输出每个 predicted step 的:
```json
{
"decision_gate": 0.0,
"redundancy_gate": 0.0,
"causal_gate": 0.0,
"prompt_kl_score": 0.0,
"reason": "..."
}
```
代码把 gate 合成:
```text
gate = decision * (1 - redundancy) * (0.5 + 0.5 * causal)
```
并可把 prompt score 加进 supervised KL score:
```text
supervised_scores =
step_supervised_kl_weight * supervised_scores
+ step_prompt_kl_weight * prompt_scores
```
这个版本的目标是处理 residual contrast 看不懂的情况:
```text
某步 KL 波动很大,但其实只是冗余 find;
某步看起来错,但由于前一步已经错了,后续动作不该被强烈惩罚;
某步是关键 causal action,应该放大。
```
这已经超出 StepOPSD 原始设计,属于当前实现的额外探索。
---
## 6. 当前实现与 2505.22050 的详细对比
### 6.1 共同点
两者共同点很多:
```text
都做 embodied planning。
都使用 Qwen2.5-VL 系列。
都要求模型输出结构化 multi-step plan。
都使用 GRPO/RFT。
都重视 action sequence 的正确性。
都有格式约束。
都不直接在真实机器人上训练。
```
### 6.2 数据和任务形式
2505.22050:
```text
训练:
SFT 数据来自 Gemini-2.0-flash 蒸馏。
RFT 数据来自 ALFRED 轨迹分解。
评测:
Embench。
EB-ALFRED seen。
EB-Habitat unseen。
模型:
Qwen2.5-VL-7B。
```
当前代码:
```text
训练文件:
eb_alfred_success_opsd_cot_multimodal_v2_embody.parquet
输入:
当前图像 + instruction + history + action list。
输出:
一次性完整 JSON plan。
policy:
Qwen2.5-VL-3B-RobotGPT-R1。
teacher for forward_proxy:
Qwen2.5-VL-3B-Instruct。
```
因此,当前代码更像把 2505.22050 的 embodied planning setting 改成了 3B policy + EasyR1/verl 风格训练。
### 6.3 Reward 设计差异
2505.22050 的 reward:
```text
R_total = R_format + R_accuracy
R_accuracy = prefix curve n(n+1)/k(k+1)
```
它是 response-level reward。即使 accuracy 来自 step prefix,最后仍然变成一个 scalar reward 给 GRPO。
当前代码的 reward 分两层:
```text
trajectory-level reward:
verify model 判断 pred plan 与 GT plan 是否 functional equivalent。
overall = 0.8 * verify + 0.2 * format。
写到最后一个 token。
step-level A^S:
rule: action_id exact/prefix/lcs -> per-token +/-1。
forward_proxy: teacher-student logp contrast -> per-token [-1,1]。
```
也就是说,当前代码比 2505.22050 多了一个显式 step advantage 通道。
### 6.4 GRPO 使用方式差异
2505.22050:
```text
GRPO 直接用 composite reward。
每条 sampled response 得一个 reward。
组内归一化后更新整条 response。
```
当前代码:
```text
GRPO 仍然用 trajectory reward 得到 A^E。
但在 compute_advantage 之前额外构造 step_adv_raw。
最终 A = A^E + omega * A^S。
```
所以当前实现是:
```text
GRPO + per-token step advantage shaping
```
而不是单纯的:
```text
GRPO + rule scalar reward
```
### 6.5 输出格式差异
2505.22050 论文要求输出类似:
```text
visual_state_description
reasoning_and_reflection
language_plan
executable_plan
```
当前代码的 prompt 也要求这些字段,而且 reward JSON parser 优先取 `executable_plan`。
但当前代码的 step credit 只关注 `executable_plan` 中的:
```text
action_id
action_name
```
不会给 `visual_state_description`、`reasoning_and_reflection`、`language_plan` 里的 token 直接加 step advantage。
这和当前方法目标一致:训练动作决策,而不是训练解释文本。
---
## 7. 当前实现与 StepOPSD 的详细对比
### 7.1 最大共同点
两者都可以概括为:
```text
step-aware advantage shaping for GRPO。
```
更具体:
```text
都不是把 teacher signal 单独做一个 KL/distillation loss。
都在 rollout 完成后处理 sampled response。
都解析 step/action span。
都把局部 step 信号注入 policy gradient 的 advantage 通道。
都试图修正 trajectory-level sparse reward 的信用分配问题。
```
如果当前论文主方法强调 `forward_proxy`,那和 StepOPSD 的相似度很高,不能写成“完全不同路线”。
### 7.2 Hindsight / teacher 来源
StepOPSD:
```text
teacher context = causal prefix + peer-trajectory hindsight
teacher model = stale reference policy
peer-trajectory hindsight:
同一个 GRPO group 中,如果有成功 rollout,
用第一个成功 peer 给失败 trajectory 提供 hindsight。
```
当前 forward_proxy:
```text
teacher context = image + GT reference plan + transition
student context = image + problem instruction
teacher model = step_teacher_path 指定的模型
```
当前脚本实际:
```text
teacher = 未微调 Qwen2.5-VL-3B-Instruct
policy = Qwen2.5-VL-3B-RobotGPT-R1
```
差异:
```text
StepOPSD 更通用:
不要求数据集中有显式 GT action plan。
只要 group 里有 successful peer。
当前代码监督更强:
直接使用数据集 GT reference plan。
更适合 EB-ALFRED 这种有 reference trajectory 的任务。
```
### 7.3 Delta 到 advantage 的变换方式
StepOPSD:
```text
Delta -> token weight w
w > 0
A_tilde = (1-lambda)A + lambda(wA)
```
性质:
```text
只改变 A 的大小。
不改变 A 的正负。
如果整条 trajectory 的 GRPO advantage 是负的,
局部 step 也不会被改成正方向,只能少罚或多罚。
```
当前代码:
```text
Delta -> step scalar A^S_k = tanh(...)
A = A^E + omega * A^S_k
```
性质:
```text
可以改变局部 token 的训练方向。
如果整条 trajectory A^E 为负,但某一步 rule/teacher 认为是对的,
该 step 的 token 可能被加到正方向。
如果整条 trajectory A^E 为正,但某一步是错的,
该 step 的 token 可能被拉成负方向。
```
这是当前实现和 StepOPSD 最核心的算法差异:
```text
StepOPSD:
sign-preserving multiplicative reweighting。
当前代码:
additive local step advantage。
```
### 7.4 step 粒度
StepOPSD:
```text
token-level Delta
token-level weight
step normalization 用来控制每个 step 的 credit budget
```
当前代码:
```text
先把 token_signal 聚合成 step scalar。
再把 step scalar 写回 action_id/action_name/semantic tokens。
```
当前代码更强调:
```text
step 是决策单位。
token 只是承载这个 step 决策的优化位置。
```
这和 embodied action plan 更匹配,因为 `{"action_id": 133, "action_name": ...}` 整体是一个动作选择。
### 7.5 span 定义
StepOPSD:
```text
ALFWorld:
action_only
Search-QA:
clean_step_no_observation
```
当前代码:
```text
pred_step_token_spans:
action_id_tokens
action_name_tokens
semantic_tokens = union
```
这不是泛化的 agent transcript span,而是 embodied JSON plan 的结构化 span。
### 7.6 normalization / clipping
StepOPSD 有两个核心 knob:
```text
alpha_clip:
控制局部 weight trust region。
lambda_mix:
控制 shaped signal 与原始 advantage 的混合强度。
```
当前代码的 knob:
```text
step_advantage_w:
A^S 总权重 omega。
step_score_tau:
tanh 温度。
step_score_norm:
none / per_response。
step_gate:
none / residual_contrast / prompt。
step_budget_tau:
residual gate 的 per-response budget 控制。
```
当前代码没有实现 StepOPSD 同款:
```text
w = clip(2 * sigmoid(sign(A) * Delta), 1-alpha, 1+alpha)
```
也没有完全等价的:
```text
equal_step_mean_abs
```
但 residual gate 里的 budget gate 有类似“不要让所有 step 都满强度更新”的意图。
### 7.7 对原始 rollout 的干预
两者都不改 rollout:
```text
先采样 rollout。
再做 post-rollout step credit。
最后更新 policy。
```
这点是共同点。
---
## 8. 当前实现的优点、风险和需要说准的地方
### 8.1 优点
#### 优点 1:把 trajectory reward 和 step credit 分开
当前实现没有破坏原始 verify reward:
```text
verify reward 仍然决定整条 trajectory 的 A^E。
step reward 只作为 A^S 叠加。
```
因此:
```text
omega = 0 可以退回纯 GRPO。
解析失败可以 A^S=0,不影响主训练。
```
#### 优点 2:rule step reward 对当前任务非常强
因为 action space 是离散的 `action_id`,且 GT 中有 reference trajectory:
```text
action_id exact/prefix/lcs 是直接的 correctness signal。
```
相比 forward_proxy,它:
```text
不需要额外 teacher。
不占 GPU。
不会自蒸馏塌平。
不会把“像正确动作的错误动作”误判为正。
```
#### 优点 3:forward_proxy 是一个活的软信号对照
当前诊断显示 teacher-student logp diff 不再全平:
```text
std 约 1-2
min/max 有明显波动
```
这意味着 forward_proxy 至少具备可训练信号,不是全 0 对照。
#### 优点 4:action_id/action_name 分离很适合 embodied plan
当前代码可以:
```text
用 semantic tokens 算分。
只把 credit 写到 action_id token。
不给 JSON scaffold 梯度。
```
这比直接对整段 JSON 做 KL 更贴近“动作选择”。
### 8.2 风险
#### 风险 1:forward_proxy 的 Delta 不等于动作正确性
Delta 表示:
```text
teacher 看 GT 后是否更愿意生成这个 token。
```
它不一定表示:
```text
这个 action 是否真的等于 GT action。
```
典型问题:
```text
GT 是 find DiningTable。
预测是 find Sofa。
teacher 可能因为 "find a furniture" 这个模式合理而给正 Delta。
```
所以 forward_proxy 的正确性需要专门验证,不能只看 diff std。
#### 风险 2:外部 teacher 改变了 OPSD 语义
如果 teacher 是 `Qwen2.5-VL-3B-Instruct`,policy 是 `RobotGPT-R1`:
```text
Delta = Instruct(GT context) - Instruct(no-GT context)
```
而不是:
```text
Delta = policy_or_stale_ref(GT context) - policy(causal context)
```
这在论文写法上必须说明,否则会被质疑“这不是 StepOPSD/OPSD 的同模型 rescoring”。
#### 风险 3:additive advantage 可能过强
当前:
```text
A = A^E + omega * A^S
```
如果 `omega=1`,而 A^E 的 group-normalized magnitude 也大约在 0-1 附近,A^S 可能显著改变更新方向。
这既是能力,也是风险:
```text
能力:
能在失败轨迹里保留正确 step。
风险:
如果 A^S 判错,会直接反向更新局部动作。
```
StepOPSD 的 sign-preserving 设计更保守,当前 additive 设计更激进。
#### 风险 4:rule exact 可能太硬
`action_id` exact 对当前任务很干净,但也可能:
```text
对等价替代路径不宽容。
对多余 find / 顺序轻微变化不宽容。
对 object instance 探索不宽容。
```
代码已经提供 `prefix` 和 `lcs`,但默认 `exact`,需要用实验比较。
---
## 9. 三方总表
| 维度 | 2505.22050 | StepOPSD | 当前 EasyR1-V4-Embody |
|---|---|---|---|
| 主问题 | 训练 embodied VLM planner | agent RL credit assignment | one-shot embodied JSON plan 的 step credit assignment |
| 基础算法 | SFT + GRPO/RFT | GRPO + step-aware OPSD shaping | GRPO + additive step advantage |
| 模型 | Qwen2.5-VL-7B | Qwen3-1.7B / Qwen2.5-3B | Qwen2.5-VL-3B RobotGPT-R1 |
| 任务 | Embench / EB-ALFRED / EB-Habitat | ALFWorld / Search-QA | EB-ALFRED parquet embodied planning |
| 输出 | structured reasoning + executable_plan | agent trajectory / actions / search steps | JSON with executable_plan |
| trajectory reward | rule format + prefix accuracy | env/QA reward | verify VLM functional equivalence + format |
| step 信号 | prefix correctness 汇总成 scalar | teacher-student logp gap | rule action_id 或 forward_proxy logp gap |
| step 信号进入方式 | 作为 response reward 的一部分 | multiplicative reweight A | additive A = A^E + omega A^S |
| 是否保留 A 符号 | GRPO scalar reward 决定 | 是 | 否,可能局部翻转 |
| teacher / hindsight | Gemini 用于 SFT,不是 RFT teacher | successful peer + stale ref | GT reference + configured teacher |
| span | action sequence prefix | action-centered step | action_id/action_name token span |
| 是否需要 GT step | 需要 gold sequence | 不需要显式 GT,依赖 peer success | rule 需要;forward_proxy 使用 GT context |
| 是否额外 KL loss | 否 | 否 | 否 |
| 最大风险 | reward 仍较粗,长程困难 | 与当前方法撞车点强 | forward_proxy 正确性、additive 过强、GT 依赖 |
---
## 10. 应该如何给当前方法定位
### 10.1 不建议的写法
如果主方法是 forward_proxy,不建议写:
```text
We propose to use OPSD-style teacher-student logp gap for step-level GRPO advantage shaping.
```
这个表述和 StepOPSD 撞得太正。
也不建议写:
```text
Our method is fundamentally different from StepOPSD.
```
因为两者确实同属 step-aware OPSD advantage shaping。
### 10.2 更准确的写法
可以这样定位:
```text
We study step-level credit assignment for one-shot embodied trajectory planning,
where a VLM generates a structured JSON executable plan in a single response.
Unlike general multi-turn agent trajectories, the decision variables are explicit
action_id/action_name fields. We inject step-local advantages into GRPO by mapping
either GT action matching or GT-reference-privileged teacher contrast onto these
structured action spans.
```
中文表达:
```text
我们不是提出“OPSD 信号用于 advantage shaping”这个大方向本身;
这个方向 StepOPSD 已经非常接近。
我们的具体切入点是:
在 one-shot embodied JSON trajectory planning 中,
利用显式 action_id/action_name 结构,把 GT-reference 或 rule step signal
映射到动作字段 token,并以 additive local step advantage 的方式注入 GRPO。
```
### 10.3 当前实现最清楚的贡献点
可以强调:
1. **任务形态差异**:
```text
one-shot embodied trajectory planning,不是一般 multi-turn agent transcript。
```
2. **结构化 action span**:
```text
显式区分 action_id 和 action_name。
可以 score semantic tokens,但只 credit action_id。
```
3. **additive local advantage**:
```text
允许局部 step 改变更新方向。
这和 StepOPSD 的 sign-preserving multiplicative reweighting 不同。
```
4. **rule vs forward_proxy 的系统比较**:
```text
当任务有干净离散 action_id GT 时,hard rule step reward 可能比 KL soft proxy 更可靠。
forward_proxy 作为软信号和无 step verifier 场景的泛化对照。
```
5. **gate 机制**:
```text
residual gate / prompt gate 用来控制 soft KL 信号进入 action tokens 的强度。
```
---
## 11. 建议补的实验和分析
### 11.1 必做:四个主 baseline
建议最小实验表:
```text
1. GRPO
2. GRPO + rule step reward
3. GRPO + forward_proxy additive
4. GRPO + forward_proxy + residual gate
```
如果资源允许,再加:
```text
5. GRPO + forward_proxy + prompt gate
6. GRPO + StepOPSD-style multiplicative reweighting
```
### 11.2 强烈建议实现 StepOPSD-style multiplicative baseline
为了和 StepOPSD 讲清楚,建议在当前代码里加一个模式:
```text
step_injection_mode:
additive # current
multiplicative_stepopsd
```
multiplicative 公式:
```text
Delta_step 或 Delta_token 来自 forward_proxy。
w = clip(2 * sigmoid(sign(A^E) * Delta), 1 - alpha_clip, 1 + alpha_clip)
A = (1 - lambda_mix) * A^E + lambda_mix * (w * A^E)
```
然后比较:
```text
additive 是否真的优于 sign-preserving?
additive 的 sign flip 是否带来收益?
```
这个实验对论文非常关键,因为它直接回应 StepOPSD。
### 11.3 sign flip 统计
当前 additive 最大差异是可能局部翻转方向。建议统计:
```text
sign_flip_ratio =
mean[ sign(A^E + omega*A^S) != sign(A^E) over action tokens ]
```
并分组看:
```text
成功 trajectory vs 失败 trajectory
正确 step vs 错误 step
Heat/Cool/Clean/PickTwo 等长程任务
```
如果能证明:
```text
失败轨迹中的正确前缀 step 被 additive 保留下来;
成功轨迹中的错误/冗余 step 被局部压低;
```
那就是相对 StepOPSD 的强证据。
### 11.4 forward_proxy 正确性分析
不要只看:
```text
teacher-student diff std
```
还要看:
```text
rule match = 1 的 step,forward_proxy A^S 分布。
rule match = 0 的 step,forward_proxy A^S 分布。
```
理想情况:
```text
correct steps: mean A^S > 0
wrong steps: mean A^S < 0
```
如果 wrong steps 也大量为正,说明 forward_proxy 更像 style/trajectory prior,而不是 correctness signal。
### 11.5 rule mode 消融
比较:
```text
exact
prefix
lcs
```
可能结论:
```text
exact:
信号干净但太硬。
prefix:
更符合 embodied execution,一旦前面错了后面不该继续强判。
lcs:
对顺序和多余 find 更宽容,但可能奖励不可执行的乱序计划。
```
### 11.6 credit target 消融
比较:
```text
score_source=action_name, credit_target=action_name
score_source=semantic, credit_target=action_id
score_source=semantic, credit_target=semantic
```
重点看:
```text
只训练 action_id 是否比训练 action_name 更稳定。
action_name token 是否引入措辞/格式梯度噪声。
```
---
## 12. 当前代码路径速查
### 12.1 数据和 prompt
```text
verl/utils/dataset.py
embodied prompt 构造
image processor
multi_modal_data
ground_truth 包装
```
### 12.2 trajectory reward
```text
verl/workers/reward/function.py
compute_reward_batch
verify prompt
overall = 0.8 * accuracy + 0.2 * format
reward 写最后一个 token
verl/workers/reward/verify.py
ask_llm
load_verify / load_verify_qwen3
```
### 12.3 step reward / step advantage
```text
verl/trainer/step_reward.py
extract_plan_steps
compute_step_match_rewards
pred_step_token_spans
build_step_adv_vector
build_step_adv_vector_from_logp
build_step_adv_raw
```
### 12.4 forward_proxy teacher
```text
verl/trainer/teacher_proxy.py
TeacherLogpScorer
PromptGateScorer
verl/workers/reward/verify.py
step_logp_vl
verl/workers/reward/function.py
AutoRewardManager.compute_step_adv
```
### 12.5 GRPO 接线
```text
verl/trainer/core_algos.py
AdvantageEstimator.GRPO_STEP
compute_grpo_step_outcome_advantage
verl/trainer/ray_trainer.py
compute_advantage
_build_step_adv
_dump_adv_heatmaps
_save_total_adv_heatmaps
```
### 12.6 配置和脚本
```text
verl/trainer/config.py
AlgorithmConfig 中所有 step_* 字段
examples/qwen25_vl_3b_Domain.sh
当前 forward_proxy 主运行脚本
examples/qwen25_vl_3b_residual_gate_ablation.sh
residual gate 消融
examples/qwen25_vl_3b_prompt_gate_ablation.sh
prompt gate 消融
```
---
## 13. 最后总结
如果用一句话串起来:
```text
2505.22050 告诉我们 embodied planning 可以用 SFT + rule reward + GRPO 训;
StepOPSD 告诉我们长轨迹 agent RL 的关键是 step-aware advantage shaping;
当前 EasyR1-V4-Embody 把这两个方向接到一起:
在 one-shot embodied JSON plan 上,用 verify model 给整轨 reward,
再用 rule 或 GT-aware forward_proxy 给 executable_plan 的 action spans 加 step-local advantage。
```
当前实现最应该讲清楚的不是“我们用了 GRPO”,也不是“我们用了 OPSD”,而是:
```text
我们如何把 embodied JSON plan 中的结构化动作字段变成可训练的 token-level step credit;
以及 additive step advantage 相比 StepOPSD sign-preserving reweighting 的差异、收益和风险。
```
当前代码已经具备一套完整实验框架:
```text
GRPO
GRPO + rule
GRPO + forward_proxy
GRPO + residual gate
GRPO + prompt gate
```
下一步最有价值的是补:
```text
StepOPSD-style multiplicative baseline
sign-flip analysis
forward_proxy correctness-vs-rule correlation
rule exact/prefix/lcs 消融
credit target 消融
```
这些实验能把“和两篇论文的关系”从文字解释变成可验证证据。
|