3.3 カスタムバリデーター
Custom Validators
カスタムバリデーターの作成
ビジネス固有のルールや複雑な検証ロジックには、カスタムバリデーターを作成する。
基本構造
from guardrails.validators import ( Validator, register_validator, PassResult, FailResult ) @register_validator(name="my-custom-validator", data_type="string") class MyCustomValidator(Validator): def __init__(self, param1, param2=None, **kwargs): super().__init__(**kwargs) self.param1 = param1 self.param2 = param2 def validate(self, value, metadata) -> PassResult | FailResult: if self._check_valid(value): return PassResult() return FailResult( error_message=f"'{value}' は条件を満たしません", fix_value=self._suggest_fix(value) ) def _check_valid(self, value): # 検証ロジック return True def _suggest_fix(self, value): # 修正候補を返す(オプション) return value
実用的なカスタムバリデーター例
例1: 日本語のみを許可
import re @register_validator(name="japanese-only", data_type="string") class JapaneseOnly(Validator): def validate(self, value, metadata): # ひらがな、カタカナ、漢字、句読点のみ許可 pattern = r'^[\u3040-\u309F\u30A0-\u30FF\u4E00-\u9FFF\u3000-\u303F\s]+$' if re.match(pattern, value): return PassResult() return FailResult( error_message="日本語以外の文字が含まれています" )
例2: 禁止語句チェック
@register_validator(name="no-banned-words", data_type="string") class NoBannedWords(Validator): def __init__(self, banned_words: list[str], **kwargs): super().__init__(**kwargs) self.banned_words = [w.lower() for w in banned_words] def validate(self, value, metadata): value_lower = value.lower() found = [w for w in self.banned_words if w in value_lower] if not found: return PassResult() return FailResult( error_message=f"禁止語句が含まれています: {found}" ) # 使用例 class Response(BaseModel): text: Annotated[str, NoBannedWords(banned_words=["競合A", "競合B"])]
例3: 価格フォーマット検証
@register_validator(name="valid-price-format", data_type="string") class ValidPriceFormat(Validator): def validate(self, value, metadata): # "¥1,000" または "1000円" 形式を許可 patterns = [ r'^¥[\d,]+$', r'^[\d,]+円$', r'^\d+$' ] for p in patterns: if re.match(p, value): return PassResult() return FailResult( error_message="価格フォーマットが不正です", fix_value=self._normalize(value) ) def _normalize(self, value): # 数値部分を抽出して正規化 nums = re.findall(r'\d+', value) if nums: return f"¥{','.join(nums)}" return value
カスタムバリデーターの登録と使用
# モデルで使用 class ProductInfo(BaseModel): name: Annotated[str, JapaneseOnly()] description: Annotated[str, NoBannedWords(banned_words=["NG語"])] price: Annotated[str, ValidPriceFormat()] # Guardで使用 guard = Guard.from_pydantic(ProductInfo) result = guard( llm_api=openai.chat.completions.create, model="gpt-4", messages=[...] )
ベストプラクティス
・fix_valueを実装してFIXアクションを有効活用
・明確なerror_messageでデバッグを容易に
・再利用可能な粒度で設計
参考文献
[1] Guardrails AI - Custom Validators - https://docs.guardrailsai.com/how_to_guides/custom_validators/
[1] Guardrails AI - Custom Validators - https://docs.guardrailsai.com/how_to_guides/custom_validators/