{"record":{"id":"381038f6b4c445ec","repo":"huggingface/open-r1","slug":"max-penalty-max-penalty-should-not-be-positive","errorCode":null,"errorMessage":"max_penalty {max_penalty} should not be positive","messagePattern":"max_penalty (.+?) should not be positive","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/open_r1/rewards.py","lineNumber":296,"sourceCode":"            rewards.append(float(reward))\n\n        return rewards\n\n    return cosine_scaled_reward\n\n\ndef get_repetition_penalty_reward(ngram_size: int, max_penalty: float, language: str = \"en\"):\n    \"\"\"\n    Computes N-gram repetition penalty as described in Appendix C.2 of https://huggingface.co/papers/2502.03373.\n    Reference implementation from: https://github.com/eddycmu/demystify-long-cot/blob/release/openrlhf/openrlhf/reward/repetition.py\n\n    Args:\n    ngram_size: size of the n-grams\n    max_penalty: Maximum (negative) penalty for wrong answers\n    language: Language of the text, defaults to `en`. Used to choose the way to split the text into n-grams.\n    \"\"\"\n    if max_penalty > 0:\n        raise ValueError(f\"max_penalty {max_penalty} should not be positive\")\n\n    if language == \"en\":\n\n        def zipngram(text: str, ngram_size: int):\n            words = text.lower().split()\n            return zip(*[words[i:] for i in range(ngram_size)]), words\n\n    elif language == \"zh\":\n        from transformers.utils.import_utils import _is_package_available\n\n        if not _is_package_available(\"jieba\"):\n            raise ValueError(\"Please install jieba to use Chinese language\")\n\n        def zipngram(text: str, ngram_size: int):\n            import jieba\n\n            seg_list = list(jieba.cut(text))\n            return zip(*[seg_list[i:] for i in range(ngram_size)]), seg_list","sourceCodeStart":278,"sourceCodeEnd":314,"githubUrl":"https://github.com/huggingface/open-r1/blob/1416fa0cf21595d2083b399a2a0bbddd7f6e9563/src/open_r1/rewards.py#L278-L314","documentation":"get_repetition_penalty_reward requires max_penalty to be non-positive: it is the maximum (negative) penalty applied to repetitive completions. Passing a positive value is treated as a logic error and rejected with this ValueError before any reward computation.","triggerScenarios":"get_repetition_penalty_reward(ngram_size=..., max_penalty=1.0, ...) — any max_penalty > 0, e.g. 0.5 or 1.0, often from copying a 'reward weight' style positive value.","commonSituations":"Misunderstanding the sign convention (thinking larger positive = stronger penalty); wiring a config value meant for a different reward function; inverting a scale during refactoring.","solutions":["Pass a non-positive max_penalty, e.g. max_penalty=-1.0 for full repetition penalty.","If you want a milder penalty, move closer to 0 from below, e.g. -0.5.","Review the docstring: it is the 'Maximum (negative) penalty', so negate your intended magnitude."],"exampleFix":"// before\nreward = get_repetition_penalty_reward(ngram_size=3, max_penalty=1.0)\n// after\nreward = get_repetition_penalty_reward(ngram_size=3, max_penalty=-1.0)","handlingStrategy":"validation","validationCode":"if max_penalty > 0:\n    max_penalty = -abs(max_penalty)  # or reject upstream","typeGuard":"def is_valid_max_penalty(v) -> bool:\n    return isinstance(v, (int, float)) and v <= 0","tryCatchPattern":"try:\n    reward = get_repetition_penalty_reward(ngram_size=n, max_penalty=p, language=lang)\nexcept ValueError as e:\n    if \"should not be positive\" in str(e):\n        reward = get_repetition_penalty_reward(ngram_size=n, max_penalty=-abs(p), language=lang)\n    else:\n        raise","preventionTips":["Remember the sign convention: penalties are negative","Clamp/abs-negate config values before constructing reward funcs","Add a unit test asserting max_penalty <= 0 in reward factory configs"],"tags":["python","validation","rewards","grpo"],"backgroundTag":"invalid-parameter-value","analyzedSha":"1416fa0cf21595d2083b399a2a0bbddd7f6e9563","analyzedAt":"2026-08-30T08:56:53.400Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}