ZZIN33
re-code-cord
ZZIN33
전체 방문자
오늘
어제
  • 분류 전체보기 (52)
    • Paper (4)
      • Generative Model (2)
      • Segmentation (1)
      • 모델 경량화 (1)
    • Study (34)
      • AI (10)
      • MLOps (8)
      • CS (4)
      • OpenCV (1)
      • Algorithm (9)
      • ETC (2)
    • Project (6)
    • ETC (8)
      • 부스트캠프 AI Tech (2)
      • 도서 리뷰 (5)

블로그 메뉴

  • Home
  • About
  • Github

인기 글

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
ZZIN33

re-code-cord

Study/MLOps

pydantic을 사용하여, 안정성 높이기

2023. 1. 26. 18:00

Before start


Overview

pydantic은 Python type hints를 사용하여 데이터의 유효성을 검사하는 라이브러리이다. 파이썬에서 타입 힌트는 말 그대로 변수 타입에 대한 힌트일 뿐, 다른 타입을 사용한다고 해서 문제가 발생하지는 않는다. 이런 세상 쉽게 사는 파이썬에게 pydantic은 런타임에서 타입 힌트를 강제하고, 유효하지 않으면 error를 발생시킨다. pydantic 공식 document에서는 다음과 같이 소개하고 있다.

Data validation and settings management using Python type annotations.
pydantic enforces type hints at runtime, and provides user friendly errors when data is invalid.
Define how data should be in pure, canonical Python; validate it with pydantic.

pydantic은 기본적으로 유효성 검사를 위해 사용되지만, 정확하게 따지자면 parsing 라이브러리이다. 출력 모델의 자료형이나 제약 조건을 보장하기 위한 수단으로 입력 데이터의 유효성을 검사한다고 볼 수 있다. 결론적으로, 주로 사용되는 API의 I/O뿐 아니라 다양한 함수를 안정적으로 사용하기 위한 도구로 볼 수 있다.

 

Install

pydantic은 Python 3.7+ 이상이라면 문제없이 사용할 수 있다.

pip install pydantic

 

Example

간단한 예제를 통해서 pydantic의 역할을 알아보자.

from datetime import datetime
from typing import List, Optional
from pydantic import BaseModel

class Model(BaseModel):
    a: int
    b: float
    c: str

우선 명시된 자료형에 맞는 자료가 들어온다면, 코드는 정상적으로 동작한다.

external_data = {
    'a': 10,
    'b': 0.05,
    'c': '10',
}
print(Model(**external_data).dict())
#> {'a': 10, 'b': 0.05, 'c': '10'}

다른 자료형이 들어오면 에러를 발생시키고 사용자가 확인하기 쉽도록 명시해준다.

external_data = {
    'a': 'abc',
    'b': 0.05,
    'c': '10',
}
print(Model(**external_data).dict())
#> ValidationError: 1 validation error for Model
#> a
#>   value is not a valid integer (type=type_error.integer)

예외적으로 처리 가능한 값이라면 자동으로 명시된 자료형에 맞춰주어 코드의 안정성을 높여준다.

external_data = {
    'a': 10.05,
    'b': 0,
    'c': 10,
}
print(Model(**external_data).dict())
#> {'a': 10, 'b': 0.0, 'c': '10'}

 

How to Use


Making Models

Models는 BaseModel로부터 상속받은 Class로, parsing과 validation을 통해 정의된 필드와 제약을 보장해준다. 앞선 예시를 통해서 유효성 검사를 통해 자료형을 확인해 준다는 것은 알고 있다.
추가적으로 또 어떤 것들이 가능할지 다음 예시를 통해서 살펴보자.

from typing import List, Optional    
from pydantic import BaseModel       

class Person(BaseModel):
    first_name: str
    middle_name: Optional[str]
    last_name: str
    age: int 
    interest: Optional[List[str]] = []
    
data = {
    'first_name': 'SungJin',
    'last_name': 'Park',
    'age': 26,
}
print(Person(**data))
#> first_name='SungJin' middle_name=None last_name='Park' age=26 interest=None

여기서 Person이라는 Model Class에서 정의된 필드들을 살펴보자.

first_name : str 타입의 변수를 의미한다. 그리고 반드시 필요한 필드이다.

middle_name : str 타입의 변수를 의미한다. 그리고 반드시 필요하지 않은 필드이며, 설정하지 않으면 None으로 설정된다.

last_name : str 타입의 변수를 의미한다. 그리고 반드시 필요한 필드이다.

age : int 타입의 변수를 의미한다. 그리고 반드시 필요한 필드이다.

interest : str 타입의 리스트를 의미한다. 그리고 반드시 필요하지 않은 필드이며, 설정하지 않으면 []으로 설정된다.

정의되지 않은 필드가 들어가거나 변환 가능한 경우 정의된 필드에 맞도록 처리해주며, 반드시 필요한 필드가 없는 경우는 에러를 발생시킨다.

data = {
    'first_name': 'SungJin',
    'last_name': 'Park',
    'age': 26,
    'interest': ['game', 'drawing', 'swim'],
    'address': 'Some Sevit, 2085-14, Olympic-daero, Seocho-gu, Seoul' 
}
print(Person(**data))
#> first_name='SungJin' middle_name=None last_name='Park' age=26 interest=['game', 'drawing', 'swim']

data = {
    'first_name': 'SungJin',
    'age': 26,
    'interest': ['game', 'drawing', 'swim'],
}
print(Person(**data))
#> ValidationError: 1 validation error for Person
#> last_name
#>   field required (type=value_error.missing)
 

Avaliable Field Types (details)

기본적으로 pydantic은 Python에서 제공하는 자료형뿐 아니라 typing이나, datetime 등 일반적인 자료형을 지원한다. 이외에도 직접 만들어서 사용할 수도 있으며, 기존의 자료형을 제한해서 사용하는 것도 가능하다.

Standard Library Types

가장 흔하게 사용되는 자료형으로, 대표적으로 Python standard types와 typing 그리고 datetime을 생각하면 된다. (이외에도 몇 가지가 더 있지만 Pydantic Types에서 더 잘 지원하고 있어 생략)

Pydantic Types

pydantic에서 지원하는 자료형이다. 파일 경로나 UUID, URI/URL, JSON 등 API I/O로 사용하기 좋은 자료형이 많다.

Constrained Types

Standard Library Types에서 약간의 제약을 둔 자료형이다. 일정 값 이상 혹은 이하의 int의 값을 받는다 던가 특정 날짜 이후만 받는 등 다양한 조건문을 활용할 수 있다.

Strict Types

앞선 예시에서 float를 int로 변환하거나 int를 str로 자동으로 변환해주는 기능이 있었는데, 이를 보다 엄격하게 검사하는 것으로 변환 가능한 경우에도 에러를 발생시킨다.

Custom Data Types

기본적으로 제공되는 자료형 외에도 classmethod __get_validators__를 사용하여 직접 Class를 만들어서 사용할 수 있다.

 

Custom validation (details)

validator decorator를 사용하여 자체적인 규칙을 만들어 유효성 검사를 진행할 수 있다.

from typing import List, Optional    
from pydantic import BaseModel, validator, ValidationError       

class Person(BaseModel):
    name: str
    age: int

    @validator('name')
    def name_must_english(cls, v):
        assert v.encode().isalpha(), ValueError('Must be english')
        return v

    @validator('age')
    def adult_check(cls, v):
        if v <= 19:
            raise ValueError('This Class is rated R')
        return v

data = {
    'name': '박성진',
    'age': 12,
}
try:
    Person(**data)
except ValidationError as e:
    print(e)
#> 2 validation errors for Person
#> name
#>   Must be english (type=assertion_error)
#> age
#>   This Class is rated R (type=value_error)

 

Making JSON from Model

pydantic은 Model로부터 JSON을 만드는 것도 가능하다.

from pydantic import BaseModel       

class Person(BaseModel):
    first_name: str
    last_name: str
    age: int

data = {
    'first_name': 'SungJin',
    'last_name': 'Park',
    'age': 26,
}

# this is equivalent to json.dumps(Person(**data).schema(), indent=2)
print(Person(**data).schema_json(indent=2))
 
{
  "title": "Person",
  "type": "object",
  "properties": {
    "first_name": {
      "title": "First Name",
      "type": "string"
    },
    "last_name": {
      "title": "Last Name",
      "type": "string"
    },
    "age": {
      "title": "Age",
      "type": "integer"
    }
  },
  "required": [
    "first_name",
    "last_name",
    "age"
  ]
}

 

 

Pydantic Base Setting (details)

BaseModel에서 유효성 검사를 진행하듯, BaseSetting를 상속한 Class를 사용하면 환경변수를 받아 유효성 검사를 진행할 수 있다. 기존에 .yaml 등의 형태로 제공하던 환경 변수(config)를 보다 쉽게 변경 가능하다. 즉, 따로 config를 저장하지 않고, BaseSetting을 통해서 config를 만들어 사용하는 방법. 다양한 환경에 따라서 조건을 설정해두면 보다 유연하게 사용 가능하다.

 

저작자표시 (새창열림)

'Study > MLOps' 카테고리의 다른 글

AWS Container Support Service (1/3)  (0) 2024.03.07
근본의 Ansible?  (0) 2024.01.03
Slurm과 Kubernetes 정답은?  (0) 2023.12.06
도대체 MLOps는 무엇일까?  (1) 2023.11.21
BentoML로 모델 서빙하기  (0) 2022.11.03

    티스토리툴바