Files
AI/참고/guardrails-main/guardrails/validator_service/__init__.py

143 lines
4.0 KiB
Python
Raw Normal View History

2026-05-12 19:40:31 +09:00
import asyncio
import os
from typing import Any, Iterator, Optional, Tuple
import warnings
from guardrails.actions.filter import apply_filters
from guardrails.actions.refrain import apply_refrain
from guardrails.classes.history import Iteration
from guardrails.classes.output_type import OutputTypes
from guardrails.classes.validation.validation_result import StreamValidationResult
from guardrails.types import ValidatorMap
from guardrails.telemetry.legacy_validator_tracing import trace_validation_result
# Keep this imported for backwards compatibility
from guardrails.validator_service.validator_service_base import ValidatorServiceBase # noqa
from guardrails.validator_service.async_validator_service import AsyncValidatorService
from guardrails.validator_service.sequential_validator_service import (
SequentialValidatorService,
)
try:
import uvloop # type: ignore
except ImportError:
uvloop = None
def should_run_sync():
run_sync = os.environ.get("GUARDRAILS_RUN_SYNC", "false")
bool_values = ["true", "false"]
if run_sync.lower() not in bool_values:
warnings.warn(
f"GUARDRAILS_RUN_SYNC must be one of {bool_values}! Defaulting to 'false'."
)
return run_sync.lower() == "true"
def get_loop() -> asyncio.AbstractEventLoop:
try:
loop = asyncio.get_running_loop()
except RuntimeError:
loop = None
if loop is not None:
raise RuntimeError("An event loop is already running.")
if uvloop is not None:
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
return asyncio.get_event_loop()
def validate(
value: Any,
metadata: dict,
validator_map: ValidatorMap,
iteration: Iteration,
disable_tracer: Optional[bool] = True,
path: Optional[str] = None,
**kwargs,
):
if path is None:
path = "$"
loop = None
if should_run_sync():
validator_service = SequentialValidatorService(disable_tracer)
else:
try:
loop = get_loop()
validator_service = AsyncValidatorService(disable_tracer)
except RuntimeError:
warnings.warn(
"Could not obtain an event loop."
" Falling back to synchronous validation."
)
validator_service = SequentialValidatorService(disable_tracer)
return validator_service.validate(
value,
metadata,
validator_map,
iteration,
path,
path,
loop=loop, # type: ignore It exists when we need it to.
**kwargs,
)
def validate_stream(
value_stream: Iterator[Tuple[Any, bool]],
metadata: dict,
validator_map: ValidatorMap,
iteration: Iteration,
disable_tracer: Optional[bool] = True,
path: Optional[str] = None,
**kwargs,
) -> Iterator[StreamValidationResult]:
if path is None:
path = "$"
sequential_validator_service = SequentialValidatorService(disable_tracer)
gen = sequential_validator_service.validate_stream(
value_stream, metadata, validator_map, iteration, path, path, **kwargs
)
return gen
async def async_validate(
value: Any,
metadata: dict,
validator_map: ValidatorMap,
iteration: Iteration,
disable_tracer: Optional[bool] = True,
path: Optional[str] = None,
stream: Optional[bool] = False,
**kwargs,
) -> Tuple[Any, dict]:
if path is None:
path = "$"
validator_service = AsyncValidatorService(disable_tracer)
return await validator_service.async_validate(
value, metadata, validator_map, iteration, path, path, stream, **kwargs
)
def post_process_validation(
validation_response: Any,
attempt_number: int,
iteration: Iteration,
output_type: OutputTypes,
) -> Any:
validated_response = apply_refrain(validation_response, output_type)
# Remove all keys that have `Filter` values.
validated_response = apply_filters(validated_response)
trace_validation_result(
validation_logs=iteration.validator_logs, attempt_number=attempt_number
)
return validated_response