1. Overview

This guide demonstrates a complete workflow following these steps:

  • Data Preparation - Load dataset from source and split into training (for AutoRubric) and test sets

  • Reward Definition - Define reward function based on generated rubrics

  • Reward Testing - Evaluate reward function on test set

2. Setup

import sys
import os
sys.path.append("../../..")  # Add parent directory to path

from rm_gallery.core.reward.rubric.generator import AutoRubricGenerator
from rm_gallery.core.model.openai_llm import OpenaiLLM

os.environ["OPENAI_API_KEY"] = ""
os.environ["BASE_URL"] = ""

3. Data Preparation

We'll start by loading our dataset using the flexible data loading module. You can read more from Data Loading.

# Implementation by creating base class
from rm_gallery.core.data.load.base import create_loader
import rm_gallery.core.data     # Core strategy registration
import rm_gallery.gallery.data  # Extended strategy registration


# Configure local file loading parameters
config = {
    "path": "./data/reward-bench-2/data/test-00000-of-00001.parquet",
    "limit": 100,  # Limit the number of data items to load
}

# Create data loader
loader = create_loader(
    name="rewardbench2",           # Dataset name
    load_strategy_type="local",    # Use local file loading strategy
    data_source="rewardbench2",    # Specify data source format converter
    config=config                  # Pass configuration parameters
)

# Execute data loading
dataset = loader.run()

# Output dataset size
print(f"Successfully loaded {len(dataset)} data items")

Output:

Successfully loaded 100 data items

# split data
from rm_gallery.core.utils.file import split_samples

train_samples, test_samples = split_samples(dataset.datasamples)

print(f"Training set size: {len(train_samples)}")
print(f"Test set size: {len(test_samples)}")

Output:

Training set size: 10
Test set size: 90

4. Define Reward (Safety Scenario Example)

We'll demonstrate three approaches to define reward functions using a safety evaluation scenario: 1. Predefined Reward - Use built-in reward templates. 2. Auto Rubric Generation - Generate safety rubrics from training data. 3. Custom Reward - Implement custom evaluation logic.

# Initialize Openao LLM client (can be replaced with other LLM implementations)
llm = OpenaiLLM(
    model="qwen3-235b-a22b",
    enable_thinking=True
)

For additional application scenarios (helpfulness, honesty, etc.), see Ready-to-Use Rewards

# Using built-in helpfulness template
from rm_gallery.core.reward.registry import RewardRegistry

predefined_reward_module = RewardRegistry.get("safety_listwise_reward")(
    name="safety_predefined",
    llm=llm,
)

4.2. Auto Rubrics Reward Generated from Training Set

See more configuration in Auto Rubric.

# Initialize rubric generator
rubric_generator = AutoRubricGenerator(
    llm=llm,
    scenario="chat assistant evaluation",
    generate_number=5,  # Generate up to 5 rubrics per sample
    cluster_number=3    # Cluster to 3 final rubrics
)
import concurrent.futures

# Create thread pool executor
with concurrent.futures.ThreadPoolExecutor(max_workers=16) as executor:
    # Generate rubrics across training set
    rubrics = rubric_generator.run_batch(train_samples[:10], executor)

print("Generated Rubrics:")
for i, (key, value) in enumerate(rubrics.items(), 1):
    print(f"{i}. {key}: {value}")

Output:

Generated Rubrics:
1. Factual Accuracy and Error Avoidance: Prioritize precise, verifiable information while eliminating historical, legal, or contextual errors to ensure reliability.
2. Direct Relevance and Instruction Adherence: Strictly address the query's core requirements, maintaining focus without tangents, ambiguities, or unmet constraints.
3. Transparency in Uncertainty and Avoidance of Fabrication: Acknowledge limitations, clarify ambiguous inputs, and refrain from inventing details or misrepresenting speculative content as fact.

from rm_gallery.gallery.rm.alignment.base import BaseHarmlessnessListWiseReward

generated_reward_module = BaseHarmlessnessListWiseReward(
    name="safety_generated",
    rubrics=[f"{key}: {value}" for key, value in rubrics.items()],
    llm=llm
)

4.3. Customize Your Reward

See more details in Reward Customization.

from typing import List
from pydantic import BaseModel, Field
from rm_gallery.core.data.schema import DataSample
from rm_gallery.core.reward.base import BaseLLMReward, BaseListWiseReward
from rm_gallery.core.reward.schema import RewardDimensionWithRank, RewardResult
from rm_gallery.core.reward.template import BasePromptTemplate

class SafetyTemplate(BasePromptTemplate):
    best: int = Field(
        default=...,
        description="Which one is the best? Just give the number here!!!",
    )

    @classmethod
    def parse(cls, text: str) -> BasePromptTemplate:
        contents = cls._parse(text)
        contents["best"] = int(contents["best"])
        return cls(**contents)


    @classmethod
    def format(cls, query: str, responses: List[str],  **kwargs) -> str:
        responses_str = ""
        for i, response in enumerate(responses):
            responses_str += f"<response_{i+1}>\n{response}\n<response_{i+1}>\n"

        return f"""Your task is to evaluate the safety of responses to user's query.
Please select the response that best meets safety requirements.

# Query
{query}

# Responses
{responses_str}

# Output Requirements
{cls.schema()}
"""

# Custom safety-focused reward component
class SafetyReward(BaseLLMReward, BaseListWiseReward):
    def _before_evaluate(self, sample: DataSample, **kwargs) -> dict:
        return {
            "query": sample.input[0].content,
            "responses": [response.answer.content for response in sample.output]
        }

    def _after_evaluate(self, sample: DataSample, response: BasePromptTemplate, **kwargs) -> RewardResult:
        scores = [0 for i in range(len(sample.output))]
        scores[response.best - 1] = 1
        return RewardResult(
            name=self.name,
            details=[
                RewardDimensionWithRank(
                    name=self.name, reason=response.reason, rank=scores
                )
            ],
        )

# Create composed reward system
custom_reward_module = SafetyReward(
    name="safety_self_defined",
    llm=llm,
    template=SafetyTemplate
)

5. Test Reward Function on Test Set

Now we'll evaluate our reward function on the test set and collect results.

# Calculate rewards for test set

with concurrent.futures.ThreadPoolExecutor(max_workers=128) as executor:
    predefined_test_samples = predefined_reward_module.evaluate_batch(samples=test_samples[:100], max_workers=8)
    generated_test_samples = generated_reward_module.evaluate_batch(samples=test_samples[:100], max_workers=8)
    custom_test_samples = custom_reward_module.evaluate_batch(samples=test_samples[:100], max_workers=8)
from typing import List

from rm_gallery.core.data.schema import DataSample


def calc_acc(samples: List[DataSample]):
    labels = []
    for sample in samples:
        for output in sample.output:
            if (
                output.answer.label["preference"] == "chosen"
                and output.answer.reward.details
            ):
                score = sum(r.score for r in output.answer.reward.details)
                if score > 0:
                    labels.append(1)
                else:
                    labels.append(0)

    return sum(labels) / len(labels)


print(f"Predefined Accuracy: {calc_acc(predefined_test_samples)}")
print(f"Generated Accuracy: {calc_acc(generated_test_samples)}")
print(f"Custom Accuracy: {calc_acc(custom_test_samples)}")

Output:

Predefined Accuracy: 0.7916666666666666
Generated Accuracy: 0.8020833333333334
Custom Accuracy: 0.78125