巧妙之处、边界与全局代码地图
这章讲什么: 把前四章里散落的「妙处」集中提炼成可借鉴的技术,诚实列出这个库刻意不做什么、会在哪崩,最后给一张跨全库的跳转表。这是读者要带走的精华。
1. 巧妙之处(可借鉴的技术)
1.1 按函数签名自动注入参数
妙在哪: 用户写回调(奖励函数、停止条件、钩子)时,想要哪个参数就写哪个参数名,框架用 inspect.signature 只喂匹配的、带 **kwargs 的则全喂。用户不用记一长串固定签名,框架也能自由扩展可注入对象而不破坏老代码。
两代都用这招:
- 经典:
Rubric._call_individual_reward_func(verifiers/rubrics/rubric.py:182)。 - v1:
invoke(verifiers/v1/decorators.py),Taskset.score里给@reward注入task/trace/runtime(verifiers/v1/taskset.py:121)。
1.2 装饰器打标 + 运行时收集 + 优先级排序
妙在哪: 停止条件、清理、打分、钩子,全走同一套:装饰器只给方法加个属性标记(verifiers/decorators.py),初始化时 discover_decorated 用 inspect.getmembers 扫出来、按 priority 排序。加一条新规则 = 写个带装饰器的方法,不碰主循环。error 检查靠 priority=100 天然排最前。
1.3 判分器跑在沙箱里,依赖不污染主进程
妙在哪: v1 的奖励可以是「把一个自带依赖的 uv 脚本写进 runtime 执行」(environments/gsm8k_v1/gsm8k_v1/taskset.py 的 correct)。判分器的依赖(如 math-verify)永远不进评测进程,且在 subprocess/docker/远程沙箱上行为一致。经典 API 的 MathRubric 用另一招达到类似隔离——把判分丢进 ProcessPoolExecutor 子进程 + 硬超时(verifiers/rubrics/math_rubric.py:106),防止符号解析卡死主事件循环。