| from typing import List, Union, Literal, Optional |
| from pydantic import BaseModel, ConfigDict, Field |
| import json |
| import re |
|
|
| class SemanticFilter(BaseModel): |
| filter_type: Literal["substring", "regex_pattern", "length_limit", "entropy_threshold", "keyword_match"] |
| value: Union[str, int, float] |
|
|
| class LogicNode(BaseModel): |
| operator: Literal["AND", "OR", "NOT"] |
| children: List[Union["LogicNode", SemanticFilter]] = Field(..., min_length=1) |
|
|
| class GuardrailGraph(BaseModel): |
| graph_id: str |
| description: str |
| root: LogicNode |
|
|
| LogicNode.model_rebuild() |
|
|
| class Observation(BaseModel): |
| adversarial_samples: List[str] |
| benign_samples: List[str] |
|
|
| class Action(BaseModel): |
| ast_json: str |
| baseline_ast_json: Optional[str] = None |
|
|
| class StepResult(BaseModel): |
| observation: Observation |
| reward: float |
| done: bool |
| info: dict |
|
|
| def extract_and_clean_json(text: str) -> str: |
| |
| text = text.strip() |
| match = re.search(r"```(?:json)?\s*(.*?)\s*```", text, re.DOTALL) |
| if match: |
| text = match.group(1) |
| |
| |
| text = re.sub(r',\s*}', '}', text) |
| text = re.sub(r',\s*]', ']', text) |
| |
| return text.strip() |
|
|