Source code for oumi.judges.rules.regex
# Copyright 2025 - Oumi
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import re
from oumi.core.registry import RegistryType, register
from oumi.judges.rules.base_rule import BaseRule
[docs]
@register("regex", RegistryType.RULE)
class RegexRule(BaseRule):
r"""Rule that checks if input text matches a regex pattern.
Config Parameters:
pattern (str): The regex pattern to match against
input_field (str): The field name to extract text from input_data
match_mode (str): How to match - "search", "match", "fullmatch"
inverse (bool): If True, pass when pattern does NOT match (default: False)
flags (int): Optional regex flags (e.g., re.IGNORECASE) (default: 0)
Examples:
Match a phone number pattern:
>>> rule_config = {
... "pattern": r"\\d{3}-\\d{4}",
... "input_field": "text",
... "match_mode": "search"
... }
>>> rule = RegexRule()
>>> result, score = rule.apply({"text": "Call 555-1234"}, rule_config)
>>> print(result, score)
True 1.0
Inverse matching (expect NOT to match):
>>> rule_config = {
... "pattern": r"error|fail",
... "input_field": "output",
... "inverse": True
... }
>>> result, score = rule.apply({"output": "Success!"}, rule_config)
>>> print(result, score)
True 1.0
"""
[docs]
def apply(
self, input_data: dict[str, str], rule_config: dict
) -> tuple[bool, float]:
"""Apply regex pattern matching to input data.
Args:
input_data: Dictionary containing input fields
(e.g., {"text": "...", "expected": "..."})
rule_config: Configuration with 'pattern', 'input_field', 'inverse', etc.
Returns:
Tuple of (judgment: bool, score: float)
- judgment: True if test passes (matches, or doesn't match if inverse=True)
- score: 1.0 if judgment is True, 0.0 otherwise
Raises:
ValueError: If required config parameters are missing or invalid
"""
pattern = rule_config.get("pattern")
if not pattern:
raise ValueError("rule_config must contain 'pattern' for regex rule")
input_field = rule_config.get("input_field", "text")
if input_field not in input_data:
raise ValueError(
f"input_field '{input_field}' not found in input_data. "
f"Available fields: {list(input_data.keys())}"
)
text = input_data[input_field]
match_mode = rule_config.get("match_mode", "search")
inverse = rule_config.get("inverse", False)
flags = rule_config.get("flags", 0)
try:
compiled_pattern = re.compile(pattern, flags)
except re.error as e:
raise ValueError(f"Invalid regex pattern '{pattern}': {e}") from e
if match_mode == "search":
match = compiled_pattern.search(text)
elif match_mode == "match":
match = compiled_pattern.match(text)
elif match_mode == "fullmatch":
match = compiled_pattern.fullmatch(text)
else:
raise ValueError(
f"Invalid match_mode '{match_mode}'. "
"Must be one of: 'search', 'match', 'fullmatch'"
)
matched = match is not None
judgment = matched != inverse
score = 1.0 if judgment else 0.0
return (judgment, score)