workbench / tests /unit /test_reward_eval.py
GitHub Actions
Initial ZeroGPU deployment with spaces shim
7f9dfed
Raw
History Blame Contribute Delete
3.98 kB
from __future__ import annotations
import unittest
from training.reward_eval import RewardCriteria, RewardEvaluator
class RewardEvalTest(unittest.TestCase):
def test_scores_are_deterministic_and_local(self) -> None:
evaluator = RewardEvaluator()
first = evaluator.evaluate(
"Should model weights download on startup?",
"No. Keep inference local and do not download on startup.",
)
second = evaluator.evaluate(
"Should model weights download on startup?",
"No. Keep inference local and do not download on startup.",
)
self.assertEqual(first.score, second.score)
self.assertIn("positive_terms", first.notes)
def test_best_of_n_selects_highest_reward(self) -> None:
evaluator = RewardEvaluator()
best = evaluator.best_of_n(
"What format should corrected training data use?",
["wrong", "Use JSONL for corrected field note training data."],
)
self.assertEqual(best.response, "Use JSONL for corrected field note training data.")
self.assertEqual(best.rank, 1)
self.assertEqual(best.index, 1)
def test_candidate_ranking_uses_input_order_for_ties(self) -> None:
evaluator = RewardEvaluator(RewardCriteria(positive_terms=(), negative_terms=()))
ranked = evaluator.rank_candidates("Prompt", ["same score", "same score"])
self.assertEqual([row.index for row in ranked], [0, 1])
def test_best_of_n_requires_candidates(self) -> None:
evaluator = RewardEvaluator()
with self.assertRaises(ValueError):
evaluator.best_of_n("Prompt", [])
def test_creates_dpo_pairs_from_ranked_responses(self) -> None:
evaluator = RewardEvaluator()
pairs = evaluator.create_dpo_pairs(
{
"How should field notes be exported?": [
"unknown",
"Export corrected field note data as JSONL.",
]
}
)
self.assertEqual(len(pairs), 1)
self.assertEqual(pairs[0].chosen, "Export corrected field note data as JSONL.")
self.assertEqual(pairs[0].rejected, "unknown")
self.assertGreater(pairs[0].reward_gap, 0)
def test_skips_dpo_pairs_without_enough_gap(self) -> None:
evaluator = RewardEvaluator(RewardCriteria(positive_terms=(), negative_terms=()))
pairs = evaluator.create_dpo_pairs(
{"Prompt": ["same score", "same score"]},
min_reward_gap=0.0,
)
self.assertEqual(pairs, [])
def test_reports_lora_vs_base_rewards_from_sequences(self) -> None:
evaluator = RewardEvaluator()
report = evaluator.eval_lora_vs_base(
["Should inference stay local?", "What format should corrected data use?"],
["unknown", "wrong"],
["Yes, keep inference local and offline.", "Use JSONL for field note corrections."],
)
self.assertGreater(report.lora_mean, report.base_mean)
self.assertEqual(report.lora_win_rate, 1.0)
self.assertEqual(report.rows[0].winner, "lora")
self.assertIn("lora_mean", report.as_dict())
self.assertEqual(report.as_table()[0][-1], "lora")
def test_reports_lora_vs_base_rewards_from_mappings(self) -> None:
evaluator = RewardEvaluator()
report = evaluator.eval_lora_vs_base(
["Prompt"],
{"Prompt": "Use JSONL."},
{"Prompt": "wrong"},
)
self.assertEqual(report.rows[0].winner, "base")
def test_missing_sequence_response_is_scored_as_empty(self) -> None:
evaluator = RewardEvaluator()
report = evaluator.eval_lora_vs_base(["Prompt"], [], [])
self.assertEqual(report.base_mean, 0.0)
self.assertEqual(report.lora_mean, 0.0)
self.assertEqual(report.rows[0].winner, "tie")
if __name__ == "__main__":
unittest.main()