Skip to content

feat(#431): 新增 reward 评分端点 /admin/api/fine-tune/reward/score (Phase1→Phase2 闭环) - #433

Open
dahai80 wants to merge 1 commit into
mainfrom
feat/reward-score-431
Open

feat(#431): 新增 reward 评分端点 /admin/api/fine-tune/reward/score (Phase1→Phase2 闭环)#433
dahai80 wants to merge 1 commit into
mainfrom
feat/reward-score-431

Conversation

@dahai80

@dahai80 dahai80 commented Aug 8, 2026

Copy link
Copy Markdown
Owner

解决 #431

RLSL 两阶段闭环的缺口:Phase1 (#424) 训出的 reward adapter (value head) 没有 HTTP 评分端点,Phase2 GRPO (#363) 的 reward_endpoint 回调无处可指。

改动

新增 POST /admin/api/fine-tune/reward/score:

请求: {model_id, adapter_name, prompt, completions:[str]}
响应: {rewards:[float], model_id, adapter_name}

model_id/adapter_name 也可走 query param —— 适配 GRPO 回调协议只发 {prompt, completions} 的约束(URL 形如 .../reward/score?key=T&model_id=X&adapter_name=Y)。

  • reward.py score_text():standalone load (LoRA via adapter_path) + 从 adapters.safetensors 恢复 value_head 权重(标准 mlx_utils.load(adapter_path=) 只还原 LoRA,不还原自定义 head),逐 completion 前向取 last-token hidden → value_head 投影标量。
  • fine_tune_route.py score_reward_endpoint:standalone load-and-evict(同 logprob 模式),asyncio.to_thread 跑。
  • test_reward_score_route.py:7 个路由单测(happy path / query param / 各缺失字段 400 / adapter 404 / 非 reward model 400)。

验证(真实端到端)

  1. reward/score 对训练好的 reward adapter(Qwen3-0.6B-4bit, 4 偏好对):
    score(chosen)=+6.76 > score(rejected)=-7.23,与 Bradley-Terry 目标一致。
  2. 闭环:把 reward/score URL(含 key/model_id/adapter_name query)作为 reward_endpoint 传给 GRPO 作业 → status=completed,progress.mean_reward=0.83(真实 reward,非 length fallback),adapter 写出。Phase1(reward 训练)→ reward/score → Phase2(GRPO 策略更新)全链路打通。

依赖

Closes #431

🤖 Generated with Claude Code

RLSL 两阶段闭环缺一个 reward 评分端点:Phase1 (#424) 训出的 reward
adapter (value head) 没有任何 HTTP 端点把它作为评分服务暴露,Phase2
GRPO (#363) 的 reward_endpoint 回调无处可指。

新增 POST /admin/api/fine-tune/reward/score:
  请求: {model_id, adapter_name, prompt, completions:[str]}
         (model_id/adapter_name 也可走 query param,适配 GRPO 回调
          协议只发 {prompt, completions} 的约束)
  响应: {rewards:[float], model_id, adapter_name}

实现:
- reward.py 新增 score_text():standalone load (LoRA via adapter_path) +
  从 adapters.safetensors 恢复 value_head 权重 (标准 load 不还原自定义
  head),逐 completion 前向取 last-token hidden -> value_head 投影标量。
- fine_tune_route.py 新增 score_reward_endpoint,standalone load-and-evict
  (同 logprob 模式),asyncio.to_thread 跑。
- 7 个路由单测 (test_reward_score_route.py) 覆盖 happy path / query param
  / 各缺失字段 400 / adapter 404 / 非 reward model 400。

验证 (真实端到端):
- reward/score 对训练好的 reward adapter (Qwen3-0.6B-4bit, 4 偏好对):
  score(chosen) > score(rejected),与 Bradley-Terry 目标一致。
- 闭环:把 reward/score URL (含 key/model_id/adapter_name query) 作为
  reward_endpoint 传给 GRPO 作业 -> status=completed,
  progress.mean_reward=0.83 (真实 reward,非 length fallback),adapter 写出。
  Phase1(reward 训练)-> reward/score -> Phase2(GRPO 策略更新)全链路打通。

依赖 #430 (GRPO stream bug,需先修才能 GRPO 跑通)。

Closes #431

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(training): 新增 reward 评分端点 /admin/api/fine-tune/reward/score (Phase1→Phase2 闭环)

1 participant