# 策展 · X (Twitter) 🔥🔥🔥

> 作者：Avi Chawla (@_avichawla) · 平台：X (Twitter) · 日期：2026-04-29

> 原始來源：https://x.com/_avichawla/status/2049037299334472015

## 中文摘要

# 2026 年頂尖 AI 實驗室如何建構 RL Agent（運用 Karpathy 的系統提示詞學習理念）

Anthropic、OpenAI 和 DeepSeek 正逐漸達成共識：將系統提示詞（System Prompt）作為獎勵函數（Reward Function）。本文將完整解析從 RLHF 到 RULER 的 RL 演進，並附上程式碼。

---

Reinforcement Learning (強化學習) 的核心概念很直觀：系統採取一個行動，環境給予獎勵，Agent 隨後更新其行為以在長期內最大化該獎勵。

上述互動過程以離散步驟運作。在每個步驟中，依序發生三件事：

![](https://pub-75d4fe1e4e80421b9ecb1245a7ae0d1a.r2.dev/curated/1777430840778-diaHG3B58Qa8AA51xjpg.jpg)

- Agent 觀察環境的當前狀態 (S)。狀態是對 Agent 所處情境的描述，足以決定下一步該做什麼。例如，在西洋棋中，狀態是棋盤位置；在對話模型中，狀態是目前的對話歷史。

- Agent 根據觀察結果選擇一個行動 (A)。行動是 Agent 的輸出，也是它影響環境的唯一方式。例如，在西洋棋中，行動是合法的走法；對於 LLM 而言，行動則是生成的回答。

- 環境隨後執行兩件事：轉換到新狀態 (S')，並發出一個獎勵 (R)，這是一個用來評估該行動的純量數值。接著進入下一個步驟，循環持續進行。

將這些步驟串聯起來，就形成了一條軌跡（Trajectory）：

![](https://pub-75d4fe1e4e80421b9ecb1245a7ae0d1a.r2.dev/curated/1777430840843-diaHGzpNVaYAEkmGApng.png)

從左到右閱讀，這就是 Agent 與環境互動的完整歷史。每個 (S, A, R, S') 四元組就是一次轉換，而 RL 的大部分工作都在於從這些轉換中學習。

---

# 將 RL 應用於 LLM

當 RL 首次應用於 LLM 時，環境是人類偏好。

OpenAI 的 InstructGPT (2022) 引入了 RLHF (Reinforcement Learning from Human Feedback)，其中：

![](https://pub-75d4fe1e4e80421b9ecb1245a7ae0d1a.r2.dev/curated/1777430840688-iaHG3CI8ca0AAantAjpg.jpg)

- 人類對模型輸出進行排名。

- 這些排名用於訓練一個獎勵模型（Reward Model）。

- PPO (Proximal Policy Optimization) 使用該獎勵模型來微調 LLM。

ChatGPT 正是建立在這個流程之上。

但人類無法坐在訓練迴圈中即時評分每一個輸出。如果模型在數千個訓練步驟中，每個提示詞生成 16 個回答，那就是數十萬次的評估。

OpenAI 透過將流程分為兩個階段解決了這個問題。

![](https://pub-75d4fe1e4e80421b9ecb1245a7ae0d1a.r2.dev/curated/1777430840805-iaHG3DisybAAAFNx0jpg.jpg)

- 首先是離線階段。在此階段，人類對一組相對較小的模型輸出進行排名並生成兩兩比較。這是昂貴的人力成本部分，但屬於一次性投入。

- 其次，他們根據這些排名訓練了一個獎勵模型，這是一個獨立的 LLM，學會了預測人類會偏好什麼。現在，你擁有一個可以立即為任何輸出評分的類神經網路，無需等待人類。獎勵模型是人類判斷的壓縮近似值，速度快到足以放入訓練迴圈中。

有了獎勵模型，PPO 就能以 GPU 的速度進行實際的 RL 訓練。模型生成回答，獎勵模型進行評分，PPO 更新權重，無需大量人力介入。

然而，代價是 PPO 需要同時在記憶體中載入四個全尺寸模型。

![](https://pub-75d4fe1e4e80421b9ecb1245a7ae0d1a.r2.dev/curated/1777430840856-iaHG3EgWuacAAHGn2jpg.jpg)

- Policy（正在訓練的 LLM）。

- Reference Policy（原始模型的凍結副本，用於透過 KL 散度懲罰防止訓練過度偏移）。

- 獎勵模型（上述用於為每個輸出評分的人類偏好近似器）。

- Critic，也稱為價值模型（Value Model，詳見下文）。

Critic 的存在是為了回答一個問題：

> 相對於我們對此提示詞的預期，這個獎勵是好還是壞？

我們需要它，因為單獨看 0.7 的原始獎勵毫無意義。例如，在一個大多數回答都能得 0.9 的簡單事實性問題中，0.7 低於平均水準。

但在一個大多數回答只能得 0.4 的複雜開放式問題中，0.7 則是極佳的表現。

![](https://pub-75d4fe1e4e80421b9ecb1245a7ae0d1a.r2.dev/curated/1777430840838-iaHG3E3T0bUAAiqmFjpg.jpg)

Critic 透過在訓練期間觀察數千個（提示詞，獎勵）對來學習這個基準。

PPO 的實際訓練訊號是優勢（Advantage），計算方式為獎勵減去 Critic 預測的基準。

這使得訊號在不同難度的提示詞之間保持穩定。但代價是 Critic 本身就是一個全尺寸的 LLM，這又增加了一個模型所需的記憶體。

對於一個 7B 參數的 LLM 來說，這意味著記憶體中同時需要大約 28B 參數。

---

# DeepSeek R1 使用可驗證獎勵的突破

2025 年 1 月，DeepSeek 發布了 R1，採用了一種與獎勵訊號截然不同的方法。

他們沒有從人類偏好中訓練獎勵模型（RLHF 流程的第 1 和第 2 階段），而是使用了 RLVR (Reinforcement Learning with Verifiable Rewards)。

這是一種簡單的、基於規則的驗證，由環境本身提供訊號。

![](https://pub-75d4fe1e4e80421b9ecb1245a7ae0d1a.r2.dev/curated/1777430840787-iaHG3FvH2bkAAbjZBjpg.jpg)

例如：

- 對於數學問題，驗證器檢查模型的答案是否與已知解相符。

- 對於程式碼，編譯器執行輸出並回傳通過或失敗。二元獎勵：正確為 1，錯誤為 0。

由於有可用的（或可推斷的）基準真理作為獎勵，因此不需要人類排名或明確的獎勵模型。

RL 優化器是 GRPO (Group Relative Policy Optimization)，它去除了 PPO 的大部分基礎設施。

它完全移除了 Critic 模型。

GRPO 沒有訓練一個單獨的模型來預測每個提示詞的預期獎勵，而是針對同一個提示詞生成多個回答（通常為 16 個），並在每個群組內對獎勵進行標準化。

![](https://pub-75d4fe1e4e80421b9ecb1245a7ae0d1a.r2.dev/curated/1777430840872-iaHG0GJUqa4AAtcMRjpg.jpg)

如果 16 個回答中有 4 個答對了數學問題，這 4 個就會獲得正向優勢，而其他 12 個則獲得負向優勢。

這一步從記憶體中節省了一個完整的全尺寸模型。

GRPO 也消除了對學習型獎勵模型的需求，因為 RLVR 的驗證器直接處理了評分。

因此，四模型 PPO 設定（Policy + Reference + Critic + 獎勵模型）縮減為僅兩個，即正在訓練的 Policy 和用於 KL 正則化的 Reference 副本。

事實上，在實務中，有些實作會將 Reference 合併到 Policy 檢查點中，使其接近單模型設定。

透過這種設定，DeepSeek R1-Zero 僅使用 GRPO 和可驗證獎勵（完全沒有監督微調），在 AIME 2024 數學問題上的準確率從 15.6% 提升到了 77.9%。

透過多數決投票，準確率達到了 86.7%，與 OpenAI 的 o1 持平。

該模型完全從二元的正確/錯誤訊號中發展出了自我驗證、反思和思維鏈推理能力，沒有人教它如何一步步推理。

RL 訓練迴圈發現推理能改善獎勵，因此模型學會了推理。

RLVR 搭配 GRPO 成為 2025 年訓練推理模型的主流方法。

每家大型實驗室都遵循這個配方發布了推理變體。

---

# 問題所在

GRPO 本身是通用型的。

它不在乎獎勵是來自數學驗證器、程式碼編譯器、人類還是 Python 腳本。

![](https://pub-75d4fe1e4e80421b9ecb1245a7ae0d1a.r2.dev/curated/1777430840863-iaHG5F2StawAA12Ngjpg.jpg)

它只需要為每個回答提供一個數值，並在每個群組內進行標準化以產生訓練訊號。

但這裡明顯的瓶頸在於這些獎勵來自何處。

對於數學和程式碼，這沒問題，因為環境提供了確定性的訊號。

但與現實世界工具和資料互動的 Agent，其產生的輸出無法透過字串比對來對照標準答案。

RAG Agent 檢索上下文並生成回答。沒有單一正確答案可供比較。客服 Agent 起草回覆。沒有編譯器可以執行它。摘要 Agent 濃縮 20 頁的文件。有很多有效的摘要，沒有字串比對驗證器能區分好壞。

![](https://pub-75d4fe1e4e80421b9ecb1245a7ae0d1a.r2.dev/curated/1777430840669-iaHG5Ho8baQAAYjmXjpg.jpg)

在這些情況下，環境不會像數學問題那樣給你獎勵訊號。

當然，有些 Agent 任務確實有可驗證的結果，對於這些任務，RLVR 運作得很好，即使是多步驟工具使用也是如此。可驗證性取決於任務的結果，而不是模型是否作為 Agent 運作。

但對於大多數 Agent 工作流程，結果是主觀的或多維度的。

直覺上，GRPO 在這裡仍然是合適的，因為採取多步驟、呼叫工具和組合回答的 Agent，可以透過探索、嘗試不同方法並為有效行為獲得強化來受益。

因此，雖然 RL 框架是合適的，但缺失的部分是評分函數。

一種解決方案是編寫自定義獎勵函數，透過 Python 程式碼根據手動定義的標準對每個輸出進行評分。

![](https://pub-75d4fe1e4e80421b9ecb1245a7ae0d1a.r2.dev/curated/1777430840745-iaHG5G9IEbEAEw8aajpg.jpg)

- RAG 獎勵函數可能會檢查回答是否使用了檢索到的上下文（忠實度）、懲罰不在上下文中的內容（幻覺）、獎勵完整性，並處理上下文本身模稜兩可的情況。

- 工具使用獎勵函數可能會對多步驟任務的進度進行評分、懲罰不必要的 API 呼叫，並衡量 Agent 是否達到了正確的最終狀態。

每個標準都會回傳一個部分分數，這些分數會被加總或加權成最終獎勵。

這有效，但引入了一系列問題。

編寫一個好的獎勵函數需要數天的迭代。研究人員需要預測邊緣情況、校準不同標準之間的權重，並測試該函數是否確實獎勵了你想要的行為。

一個過度權衡格式合規性而輕視忠實度的獎勵函數，會訓練出一個產生格式精美但充滿幻覺的 Agent。

獎勵函數也很脆弱。如果你更改了檢索流程、添加了新工具或修改了系統提示詞，獎勵函數就需要重寫。

除錯也很麻煩。

當 Agent 在訓練期間學到不良行為時，原因可能是獎勵函數、訓練超參數、資料或其他因素。

但由於獎勵函數是自定義程式碼，通常在訓練模型並評估輸出之前，你無法判斷該函數是否在測量你認為它在測量的東西。

---

這就是為什麼 RL 被廣泛採用於可驗證任務（數學、程式碼、邏輯），卻未被採用於 Agent 工作流程（RAG、客服、工具使用、摘要）的主要原因。

RLVR 為推理模型提供了一種通用、自動的獎勵訊號，它們可以檢查答案並回傳 0 或 1。對於大多數 Agent 工作流程，不存在這樣的對應物。

區別不在於模型。同一個 Qwen 2.5 14B 可以扮演這兩種角色。

區別在於任務。我們能否驗證 Agent 是否產生了可以自動檢查的輸出？

---

# AI 實驗室如何處理這個問題？

這不僅僅是開源從業者注意到的差距。

各大 AI 實驗室正從不同方向匯聚到同一個問題上。

Anthropic 證明了你根本不需要人類參與 RL 迴圈。

他們的 Constitutional AI 工作表明，如果你寫下一套原則（「憲法」），AI 就可以根據這些原則評估輸出，並為 RL 訓練生成偏好資料。

![](https://pub-75d4fe1e4e80421b9ecb1245a7ae0d1a.r2.dev/curated/1777430840681-iaHG5vOYIbkAAPSGZjpg.jpg)

AI 根據書面原則判斷自己的輸出，並將這些判斷用作 RL 訊號。這是一個重大的概念轉變，即用規則文件取代了人類評估員大軍。

OpenAI 內部也在進行類似的工作。他們正在開發「通用驗證器」（Universal Verifiers），這是一種將 RL 擴展到數學和程式碼之外的技術，應用於生物學、醫學和一般知識等領域，在這些領域中，答案無法透過簡單的字串比對來檢查。

細節尚未公開，但方向很明確，我們需要適用於任何領域的通用獎勵訊號，而不僅僅是那些具有確定性驗證器的領域。

Karpathy 也指出了這個方向。

![](https://pub-75d4fe1e4e80421b9ecb1245a7ae0d1a.r2.dev/curated/1777430840736-diaHGey1DbAAAWhPnpng.png)

他在 2025 年主張，我們缺少一種主要的 LLM 學習範式，他暫時稱之為「系統提示詞學習」（system prompt learning）。

核心思想是系統提示詞攜帶的訊號比純量獎勵更豐富，RL 訓練應該尋找利用該訊號的方法，而不是僅僅依賴手工製作的獎勵函數。

---

# RULER

如果你想在實務中看到這一點，RULER（內建於 OpenPipe 的 ART 框架中，開源且擁有 9k+ 星數）是一個通用獎勵函數，它用單一函數呼叫取代了所有那些自定義評分程式碼。

![](https://pub-75d4fe1e4e80421b9ecb1245a7ae0d1a.r2.dev/curated/1777430840847-iaHG28tSUb0AAVAFGjpg.jpg)

它使用 LLM-as-judge 來對多條軌跡進行排名，其運作方式是利用使 GRPO 強大的相同特性，即只有相對排名才重要。

以下是逐步運作方式：

![](https://pub-75d4fe1e4e80421b9ecb1245a7ae0d1a.r2.dev/curated/1777430840859-iaHG5JSCfboAAqUB8jpg.jpg)

- 對於每個訓練步驟，針對同一個場景生成 N 條軌跡（通常為 4 到 8 條）。

- RULER 將所有 N 條軌跡發送給一個 Judge LLM（如 o3、o4-mini，甚至是本地的 Qwen3 32B）。

- Judge 閱讀 Agent 的系統提示詞以了解 Agent 應該做什麼，然後相對於其他軌跡，對每條軌跡進行 0 到 1 的評分。

兩個特性使這項技術奏效：

1) 相對評分比絕對評分更容易。

LLM 在絕對評分上表現不佳，因為沒有共享的校準機制。

但詢問「這 4 個回答中哪一個最符合系統提示詞的指令」是一個比較任務，LLM 在這方面表現一致且出色。

RULER 透過將所有軌跡放在一起並要求 Judge 進行相互排名來利用這一點。

2) GRPO 本來就會在每個群組內進行標準化。

最好的軌跡在絕對意義上是得了 0.9 還是 0.3 分並不重要。

GRPO 獲取群組內的分數，計算平均值和標準差，然後進行標準化。

訓練訊號來自相對排序，透過了解哪些軌跡高於平均水準，哪些低於平均水準。RULER 的相對排名直接對應於 GRPO 的預期。

---

## 簡要 walkthrough

在進入程式碼之前，我們先從概念上追蹤發生了什麼。假設你正在訓練一個 RAG Agent。在每個訓練步驟中，GRPO 為同一個查詢生成多個回答：

```plaintext
Scenario: "What is the refund policy?"
Retrieved context: "Refunds within 30 days. Digital products non-refundable..."

(Faithful)
Response A: "Refunds within 30 days. Email support@example.com."     

(hallucinated)
Response B: "Refunds within 30 days. Also store credit for 90 days."

(ignored context)
Response C: "Not sure, check the website."

(verbose but accurate)
Response D: "The policy states that refunds are available within..."
```

在傳統設定中，你會編寫一個獎勵函數來為這些回答評分：

```python
def reward_function(response, context):
    score = 0.0
    if uses_context(response, context):
        score += 0.4
    if not has_hallucination(response, context):
        score += 0.3
    if is_complete(response, context):
        score += 0.2
    if is_concise(response):
        score += 0.1
    return score
```

每一個輔助函數（uses_context, has_hallucination, is_complete, is_concise）都是一個獨立的工程專案。

你需要精確定義「使用上下文」的含義、決定閾值、處理邊緣情況並測試所有內容。

使用 RULER，你可以將所有這些替換為：

```python
scored_group = await ruler_score_group(group, "openai/o3")
```

Judge LLM 閱讀系統提示詞（「僅使用檢索到的上下文進行回答。不要添加上下文中沒有的資訊。」），閱讀所有四個回答並進行評分。

系統提示詞已經隱含地定義了忠實度、幻覺和完整性。Judge 在不使用 Python 實作的情況下應用了這些標準。

---

## 軌跡與群組

ART 將每個 Agent 回答表示為 Trajectory，這是一系列訊息（system, user, assistant）的序列，並封裝了 GRPO 訓練所需的元資料。

針對同一個場景的多條軌跡形成一個 TrajectoryGroup。這是 RULER 評分和 GRPO 訓練的單位。

```python
# A single trajectory: one complete agent interaction
traj = art.Trajectory(
    messages_and_choices=[
        {"role": "system", "content": "You are a RAG support agent..."},
        {"role": "user", "content": "What is the refund policy?\n\n[Context]: ..."},
        Choice(finish_reason="stop", index=0,
               message=ChatCompletionMessage(role="assistant", content="...")),
    ],
    reward=0.0,  # RULER fills this in
)

# A group: multiple trajectories for the same scenario
group = art.TrajectoryGroup([traj_a, traj_b, traj_c, traj_d])

# Score the entire group relatively
judged_group = await ruler_score_group(group, "openai/o3")
```

reward=0.0 的初始化是一個佔位符。

- 在 ruler_score_group 回傳後，每條軌跡的 reward 欄位都會更新為 Judge 的分數。

- Choice 和 ChatCompletionMessage 物件是 OpenAI 的標準類型，因此如果你已經在使用 OpenAI SDK 進行推論，這些就是你已經在使用的物件。

---

# 兩個具體範例

RULER 有兩個層級的 API。

1) 低階的 `ruler` 函數適用於普通的訊息字典，因此不需要 ART 特定的物件。

這是了解 RULER 實際運作方式最快的方法。

讓我們看一個針對同一個 RAG 查詢的三條軌跡的最小範例。

在下方，我們定義了三個訊息列表：一個是忠實的，一個有幻覺，另一個完全忽略了上下文。

```python
message_lists = [
    # Good: uses retrieved context accurately
    [
        {"role": "system", "content": "You are a RAG-based support agent. Use the retrieved context to answer user queries accurately."},
        {"role": "user", "content": "What is our refund policy?\n\n[Retrieved context]: Refunds are available within 30 days of purchase. Digital products are non-refundable after download. Contact support@example.com to initiate."},
        {"role": "assistant", "content": "You can get a refund within 30 days of purchase. However, digital products are non-refundable once downloaded. To start the process, email support@example.com."},
    ],
    # Mediocre: partially uses context, adds hallucinated details
    [
        {"role": "system", "content": "You are a RAG-based support agent. Use the retrieved context to answer user queries accurately."},
        {"role": "user", "content": "What is our refund policy?\n\n[Retrieved context]: Refunds are available within 30 days of purchase. Digital products are non-refundable after download. Contact support@example.com to initiate."},
        {"role": "assistant", "content": "Our refund policy allows returns within 30 days. You can also get store credit for up to 90 days. Just call our hotline at 1-800-REFUND."},
    ],
    # Bad: ignores context entirely
    [
        {"role": "system", "content": "You are a RAG-based support agent. Use the retrieved context to answer user queries accurately."},
        {"role": "user", "content": "What is our refund policy?\n\n[Retrieved context]: Refunds are available within 30 days of purchase. Digital products are non-refundable after download. Contact support@example.com to initiate."},
        {"role": "assistant", "content": "I'm not sure about the refund policy. You should check the website or contact someone from the billing team."},
    ],
]
```

接下來，我們執行評分：

```python
from art.rewards import ruler

scores = await ruler(message_lists, "openai/o3")

for label, score in zip(["Faithful", "Hallucinated", "Ignored context"], scores):
    print(label)
    print("→", score.score)
    print("→", score.explanation)
```

這會產生以下輸出：

```
Faithful:
→ 0.97 
→ Accurately reflects the retrieved policy
  details, complete and concise.

Hallucinated:
→ 0.45
→ Gives correct 30-day refund info but adds
  unsupported details (90-day credit, hotline),
  reducing accuracy.

Ignored context:
→ 0.05
→ Provides no useful information and ignores available context.
```

請注意，我們從未編寫過忠實度檢查器或編碼過幻覺檢測器。

系統提示詞提到了「使用檢索到的上下文準確回答使用者查詢」，Judge 將其作為評估標準。

幻覺回答得分 0.45（不是零），因為它部分使用了上下文。關於 30 天退款的部分是正確的。

Judge 對於正確的部分給予了部分分數，並對其編造的部分進行了懲罰。

這是一個細微的區別，若要將其編碼到基於規則的獎勵函數中，需要大量的工程工作。

此外，分數分佈在 0-1 範圍內：0.97, 0.45, 0.05，而不是二元的通過/失敗。

RULER 產生了一個反映相對品質的梯度。GRPO 可以使用這個梯度來應用比例更新，從而強烈強化忠實行為，輕微抑制幻覺模式（因為它部分正確），並強烈抑制忽略上下文的行為。

2) 上面的 `ruler` 函數適用於理解和實驗，但 ART 的訓練迴圈是在 Trajectory 和 TrajectoryGroup 物件上運作的。

這些物件攜帶 GRPO 讀取的 reward 欄位、用於檢查的除錯日誌，以及 model.train() 預期的結構。

在此之後，高階的 ruler_score_group 函數處理轉換。

下面，讓我們看看同一個 RAG 場景，以你在真實訓練流程中會使用的方式進行結構化，現在有 4 條軌跡而不是 3 條。

```python
# The system prompt defines the agent's goal
# RULER uses this as the implicit reward function
system_msg = {
    "role": "system",
    "content": (
        "You are a RAG-based support agent. "
        "Answer user queries using ONLY the retrieved context. "
        "Do not add information that is not in the context."
    ),
}

user_msg = {
    "role": "user",
    "content": (
        "What is the refund policy?\n\n"
        "[Retrieved context]: Refunds are available within 30 days "
        "of purchase. Digital products are non-refundable after "
        "download. Contact support@example.com to initiate."
    ),
}

responses = [
    "You can get a refund within 30 days of purchase. Digital products "
    "are non-refundable once downloaded. Email support@example.com to start.",

    "Refunds are available within 30 days. You can also get store credit "
    "for up to 90 days, and our hotline is 1-800-REFUND.",

    "I'm not sure about the refund policy. Please check the website or "
    "contact the billing team for more details.",

    "Based on the information I have, the refund policy states that "
    "refunds are available within 30 days of purchase. It is important "
    "to note that digital products cannot be refunded after they have "
    "been downloaded. If you wish to initiate a refund, you should "
    "reach out to support@example.com.",
]

```

現在我們有 4 條軌跡而不是 3 條。第四條是一個冗長但準確的回答，它僅使用檢索到的上下文，但包裝在不必要的填充詞/句子中。

接下來，我們定義 Trajectories 和 Groups：

```python
import art
from openai.types.chat.chat_completion import Choice
from openai.types.chat import ChatCompletionMessage

trajectories = []
for resp in responses:
    traj = art.Trajectory(
        messages_and_choices=[
            system_msg, user_msg,
            Choice(
                finish_reason="stop", index=0,
                message=ChatCompletionMessage(role="assistant", content=resp),
            ),
        ],
        reward=0.0,
    )
    trajectories.append(traj)

group = art.TrajectoryGroup(trajectories)
```

最後，我們執行評分：

```python
from art.rewards import ruler_score_group

judged_group = await ruler_score_group(group, "openai/o3", debug=True)

```

設定 debug=True 時，RULER 會列印 Judge 的原始推理過程以及實際分數。

這是原始推理過程：

```json
{
    "scores": [
        {
            "trajectory_id": "1",
            "explanation": "Accurately answers the question using only the retrieved context, concisely and completely.",
            "score": 0.98
        },
        {
            "trajectory_id": "2",
            "explanation": "Includes unsupported details about store credit and a hotline that are not in the retrieved context, so it violates the instruction to use only the context.",
            "score": 0.2
        },
        {
            "trajectory_id": "3",
            "explanation": "Does not answer the question despite the needed information being present in the retrieved context.",
            "score": 0.05
        },
        {
            "trajectory_id": "4",
            "explanation": "Accurately and completely answers the question using only the retrieved context, though slightly more verbose than necessary.",
            "score": 0.96
        }
    ]
}
```

這些是分數（已排名）：

```plaintext
Rank 1 | Score: 0.980 — Concise, faithful response
Rank 2 | Score: 0.960 — Verbose but accurate response
Rank 3 | Score: 0.200 — Hallucinated store credit and hotline
Rank 4 | Score: 0.050 — Ignored the retrieved context entirely
```

如果你仔細觀察...

- 簡潔的忠實回答 (0.98) 得分僅略高於冗長的準確回答 (0.96)。兩者都僅使用檢索到的上下文，兩者都是正確的，但系統提示詞說「僅使用檢索到的上下文進行回答」，簡潔版本更直接地做到了這一點。Judge 將冗長識別為一個輕微的品質問題，而不是正確性問題。這是一個細微的區別，很難編碼到評分函數中，因為你怎麼寫一個規則說「技術上正確但過於冗長，扣 0.02 分」？

- 幻覺回答在第一個實驗中得分 0.45，這裡降到了 0.20。區別在於系統提示詞。第一個實驗說「使用檢索到的上下文準確回答」。這一個說「不要添加上下文中沒有的資訊」。更嚴格的指令產生了更嚴格的評分。Judge 自動適應了。如果你收緊系統提示詞，RULER 就會相應地收緊評估，而無需你更改任何評分程式碼。

- 忽略上下文的回答在兩個實驗中都得了 0.05 分。當答案就在檢索到的上下文中，而 Agent 說「我不確定」時，無論系統提示詞如何措辭，都沒有歧義。

這些評分後的軌跡正是 model.train() 所預期的，讓我們看看接下來的內容。

---

# 完整的訓練迴圈

要真正使用這些分數進行訓練，你需要將硬編碼的回答替換為真實的模型推論。

ART 的 `gather_trajectory_groups` 處理編排。

本質上，對於每個場景，它使用模型當前的權重生成一組軌跡，用 RULER 進行評分，並收集結果供 GRPO 使用：

```python
for step in range(num_steps):
    groups = await art.gather_trajectory_groups(
        (
            art.TrajectoryGroup(
                rollout(model, scenario) for _ in range(4)
            )
            for scenario in scenarios
        ),
        after_each=lambda g: ruler_score_group(
            g, "openai/o3"),
    )
    await model.train(groups)  # GRPO updates LoRA weights
```

在每一步中，模型使用其當前權重為每個場景生成 4 個回答，RULER 進行相對排名，GRPO 強化高分行為並抑制低分行為。

Agent 在每次迭代中都會變得更擅長遵循系統提示詞的指令。

經過多次步驟，模型學會了得分高的模式（忠實、簡潔、基於上下文），並遺忘了得分低的模式（幻覺、忽略上下文、冗長）。

請注意，這段程式碼中沒有定義任何獎勵函數。

---

# 自定義準則

對於大多數任務，系統提示詞為 RULER 提供了足夠的訊號來進行有效評分。但當你需要更具體的評估標準時，RULER 支援自定義準則：

```python
custom_rubric = """
- Prioritize responses that are concise and clear
- Penalize responses that include emojis or informal language
- Reward responses that cite sources
"""

await ruler_score_group(group, "openai/o3", rubric=custom_rubric)
```

準則使用自然語言而非 Python，因此迭代速度很快。

你只需更改一個句子，重新執行，然後檢查分數。

將此與編輯獎勵函數進行比較，在獎勵函數中，一個放錯位置的權重或一個有 Bug 的條件可能會默默地教導 Agent 不良行為，直到訓練完成後你才會注意到。

---

# 應用於不可驗證的任務

RULER 是通用型的。它適用於任何任務，而不僅僅是那些自定義獎勵很痛苦的自由形式任務。

實際問題是 RULER 何時比簡單的替代方案更有價值。

對於純粹的確定性任務（SQL 查詢是否回傳了正確的行？），二元驗證器更便宜且訊號更清晰。

對於純粹的主觀任務（摘要是否寫得好？），RULER 是唯一的自動化選擇。對於介於兩者之間的任務（Agent 是否找到了正確答案並解釋得很好？），你可以結合兩者：

```python
judged_group = await ruler_score_group(group, "openai/o3")

for traj in judged_group.trajectories:
    independent_reward = verify_correctness(traj)  # binary 0/1
    traj.reward += independent_reward
```

RULER 保留了你在 rollout 期間分配的任何獎勵作為單獨的指標，因此你可以在確定性驗證之上疊加 LLM-judge 評分，而不會丟失任何訊號。

---

# 實務細節

以下是我根據使用 RULER 收集到的一些實務見解：

→ 你不需要最昂貴的模型作為 Judge。像 Qwen3 32B 這樣較便宜的模型通常運作良好。你也可以使用 Claude、透過 Ollama 的本地模型，或任何 LiteLLM 支援的模型。選擇是一個成本與品質的權衡，而不是硬性要求。

→ 每個群組 4 到 8 條軌跡是建議範圍。少於 4 條會讓 Judge 沒有足夠的比較對象。超過 8 條可能會混淆 Judge 並增加成本，而沒有成比例的好處。

→ 當群組中的所有軌跡共享相同的系統提示詞和使用者訊息（通常如此）時，RULER 會自動去重公共前綴。Judge 只會看到一次共享上下文，後面跟著不同的回答。這顯著減少了長系統提示詞或多輪對話的 token 使用量。

→ RULER 會將 Judge 的回應快取到磁碟。如果你重新執行相同的軌跡，它不會再次呼叫 API。這在除錯時很重要，特別是在迭代系統提示詞或準則時。

---

將 RL 應用於 Agent 的瓶頸從來不是優化演算法。

GRPO 處理得很好。

瓶頸一直是獎勵訊號。

RLVR 透過讓環境直接為輸出評分，解決了可驗證任務的問題。

RULER 透過讓 LLM Judge 相對地為輸出評分，解決了所有任務（可驗證或不可驗證）的問題。

完整實作在 ART 儲存庫中，並附有逐步引導訓練迴圈的 Colab 筆記本。

Repo: https://github.com/OpenPipe/ART (別忘了給它一顆星 ⭐️)

![](https://pub-75d4fe1e4e80421b9ecb1245a7ae0d1a.r2.dev/curated/1777430840810-iaHG28GnwasAAgFpVjpg.jpg)

---

以上就是全部內容！

如果你喜歡這篇教學：

找到我 → @_avichawla

我每天都會分享關於 DS、ML、LLM 和 RAG 的教學與見解。

## 標籤

Agent, 研究論文, 教學資源, Anthropic, OpenAI, DeepSeek
