Pydantic
Pydantic은 Python에서 데이터 유효성 검사와 구조화를 위한 라이브러리입니다. Pydantic을 사용하면 데이터 모델을 정의하고 입력 데이터를 검증할 수 있습니다. 이를 통해 코드의 안정성을 높이고 유지 보수를 용이하게 할 수 있습니다.
Pydantic은 간단하고 직관적인 구문을 제공하여 사용하기 쉽습니다. 데이터 모델은 일반적으로 Python 클래스로 정의되며 필드와 필드 유효성 검사 규칙을 포함합니다. 이를 통해 입력 데이터가 예상한 형식과 구조를 따르는지 확인할 수 있습니다.
Pydantic은 다양한 유효성 검사 규칙을 지원하며, 예를 들어 필드의 타입, 최소 및 최대 값, 길이 등을 검사할 수 있습니다. 또한, Pydantic은 JSON 직렬화 및 역직렬화, 데이터 파싱 및 변환 등의 유용한 기능도 제공합니다.
Pydantic은 웹 애플리케이션, 데이터베이스, API 등 다양한 영역에서 사용될 수 있습니다. 문서에서 제공하는 많은 예제와 자세한 설명을 통해 Pydantic의 다양한 기능과 활용 방법을 학습할 수 있습니다.
기본 구조
Model
Models are simply classes which inherit from pydantic.BaseModel and define fields as annotated attributes.
from pydantic import BaseModel
class User(BaseModel):
id: int
name: str = 'Jane Doe'
Python
복사
Field
The Field function is used to customize and add metadata to fields of models.
from pydantic import BaseModel, Field
class User(BaseModel):
name: str = Field(default='John Doe')
user = User()
print(user)
#> name='John Doe'
Python
복사
Validators
Pydantic provides a way to apply validators via use of Annotated. You should use this whenever you want to bind validation to a type instead of model or field.
from typing import Any, List
from typing_extensions import Annotated
from pydantic import BaseModel, ValidationError
from pydantic.functional_validators import AfterValidator
def check_squares(v: int) -> int:
assert v**0.5 % 1 == 0, f'{v} is not a square number'
return v
def double(v: Any) -> Any:
return v * 2
MyNumber = Annotated[int, AfterValidator(double), AfterValidator(check_squares)]
class DemoModel(BaseModel):
number: List[MyNumber]
print(DemoModel(number=[2, 8]))
#> number=[4, 16]
try:
DemoModel(number=[2, 4])
except ValidationError as e:
print(e)
"""
1 validation error for DemoModel
number.1
Assertion failed, 8 is not a square number
assert ((8 ** 0.5) % 1) == 0 [type=assertion_error, input_value=4, input_type=int]
"""
Python
복사
In this example we used some type aliases (MyNumber = Annotated[...]). While this can help with legibility of the code, it is not required, you can use Annotated directly in a model field type hint. These type aliases are also not actual types but you can use a similar approach with TypeAliasType to create actual types. See Custom Types for a more detailed explanation of custom types.
•
Field Validators
If you want to attach a validator to a specific field of a model you can use the @field_validator decorator.
from pydantic import (
BaseModel,
ValidationError,
ValidationInfo,
field_validator,
)
class UserModel(BaseModel):
id: int
name: str
@field_validator('name')
@classmethod
def name_must_contain_space(cls, v: str) -> str:
if ' ' not in v:
raise ValueError('must contain a space')
return v.title()
# you can select multiple fields, or use '*' to select all fields
@field_validator('id', 'name')
@classmethod
def check_alphanumeric(cls, v: str, info: ValidationInfo) -> str:
if isinstance(v, str):
# info.field_name is the name of the field being validated
is_alphanumeric = v.replace(' ', '').isalnum()
assert is_alphanumeric, f'{info.field_name} must be alphanumeric'
return v
print(UserModel(id=1, name='John Doe'))
#> id=1 name='John Doe'
try:
UserModel(id=1, name='samuel')
except ValidationError as e:
print(e)
"""
1 validation error for UserModel
name
Value error, must contain a space [type=value_error, input_value='samuel', input_type=str]
"""
try:
UserModel(id='abc', name='John Doe')
except ValidationError as e:
print(e)
"""
1 validation error for UserModel
id
Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='abc', input_type=str]
"""
try:
UserModel(id=1, name='John Doe!')
except ValidationError as e:
print(e)
"""
1 validation error for UserModel
name
Assertion failed, name must be alphanumeric
assert False [type=assertion_error, input_value='John Doe!', input_type=str]
"""
Python
복사
Pydantic + Langchain
We can use pydantic with lanchain to get structured output.
from langchain.output_parsers import PydanticOutputParser
Python
복사
•
Example
# Define your desired data structure.
class Joke(BaseModel):
setup: str = Field(description="question to set up a joke")
punchline: str = Field(description="answer to resolve the joke")
# You can add custom validation logic easily with Pydantic.
@validator("setup")
def question_ends_with_question_mark(cls, field):
if field[-1] != "?":
raise ValueError("Badly formed question!")
return field
# And a query intented to prompt a language model to populate the data structure.
joke_query = "Tell me a joke."
# Set up a parser + inject instructions into the prompt template.
parser = PydanticOutputParser(pydantic_object=Joke)
prompt = PromptTemplate(
template="Answer the user query.\n{format_instructions}\n{query}\n",
input_variables=["query"],
partial_variables={"format_instructions": parser.get_format_instructions()},
)
_input = prompt.format_prompt(query=joke_query)
output = model(_input.to_string())
parser.parse(output)
Python
복사
Using Custom Model
class StepMetaSchema(BaseModel):
"""스텝 메타 스키마"""
story: str
class StepResponseSchema(BaseModel):
"""스텝 스키마"""
introduction: StepMetaSchema = Field(..., description="사건의 암시: 등장인물과 배경을 소개하고 앞으로 일어날 사건의 실마리를 드러낸다")
rising_action: StepMetaSchema = Field(..., description="사건의 발생: 사건이 발생하고, 갈등이 점점 빚어진다.")
climax: StepMetaSchema = Field(..., description="사건의 심화: 새로운 사건이 발생하고, 갈등은 점점 더 고조된다.")
falling_action: StepMetaSchema = Field(..., description="사건의 전환: 이야기가 반전되고, 갈등은 최고조에 이르다가 결말로 향한다")
conclusion: StepMetaSchema = Field(..., description="사건의 해결: 모든 사건이 해결된다.")
Python
복사
•
Declare classes that you need and use it as pydantic model.