Files
AI/참고/guardrails-main/guardrails/classes/history/inputs.py

107 lines
3.9 KiB
Python
Raw Normal View History

2026-05-12 19:40:31 +09:00
from __future__ import annotations
from typing_extensions import deprecated
from typing import Any, Dict, List, Optional, Union
from pydantic import Field, field_serializer, field_validator
from guardrails.classes.generic.arbitrary_model import ArbitraryModel
from guardrails.classes.llm.prompt_callable import PromptCallableBase
from guardrails.prompt.prompt import Prompt
from guardrails.prompt.messages import Messages
from guardrails.prompt.instructions import Instructions
class Inputs(ArbitraryModel):
"""Inputs represent the input data that is passed into the validation
loop."""
llm_api: Optional[PromptCallableBase] = Field(
description="The constructed class for calling the LLM.", default=None
)
llm_output: Optional[str] = Field(
description="The string output from an external LLM call"
"provided by the user via Guard.parse.",
default=None,
)
messages: Optional[
Union[List[Dict[str, Union[str, Prompt, Instructions]]], Messages]
] = Field(
description="The message history provided by the user for chat model calls.",
default=None,
)
prompt_params: Optional[Dict] = Field(
description="The parameters provided by the user"
"that will be formatted into the final LLM prompt.",
default=None,
)
num_reasks: Optional[int] = Field(
description="The total number of reasks allowed; user provided or defaulted.",
default=None,
)
metadata: Optional[Dict[str, Any]] = Field(
description="The metadata provided by the user to be used during validation.",
default=None,
)
full_schema_reask: Optional[bool] = Field(
description="Whether to perform reasks across the entire schema"
"or at the field level.",
default=None,
)
stream: Optional[bool] = Field(
description="Whether to use streaming.",
default=False,
)
@field_serializer("llm_api")
def serialize_llm_api(self, llm_api: PromptCallableBase | None) -> str | None:
if llm_api:
return str(llm_api)
return None
@field_validator("llm_api", mode="before")
@classmethod
def deserialize_llm_api(cls, llm_api: Any) -> PromptCallableBase | None:
if isinstance(llm_api, PromptCallableBase):
return llm_api
# Note: We can potentially identify the correct
# PrompCallable Class and reconstruct it,
# but the previous implementation always just returned None.
return None
@field_serializer("messages")
def serialize_messages(
self, messages: list[dict[str, str | Prompt | Instructions]] | Messages | None
) -> list[dict[str, Any]] | None:
# Legacy serialization logic from previous to_interface implementation
# TODO: Just make Prompt, Instructions, and Messages pydantic models
if messages:
serialized_messages = []
for msg in messages:
ser_msg = {**msg}
content = ser_msg.get("content")
if content:
ser_msg["content"] = (
content.source if isinstance(content, Prompt) else content
)
serialized_messages.append(ser_msg)
return serialized_messages
return None
@deprecated("Use Inputs.model_dump() instead.")
def to_interface(self) -> dict[str, Any]:
return self.model_dump(exclude_none=True, by_alias=True)
@deprecated("Use Inputs.model_dump() instead.")
def to_dict(self) -> dict[str, Any]:
return self.model_dump(exclude_none=True, by_alias=True)
@classmethod
@deprecated("Use Inputs.model_validate() instead.")
def from_interface(cls, i_inputs: Any) -> "Inputs":
return cls.model_validate(i_inputs)
@classmethod
@deprecated("Use Inputs.model_validate() instead.")
def from_dict(cls, obj: Any) -> "Inputs":
return cls.model_validate(obj)