4장. 대화형 챗봇과 메모리 전략
Pydantic 으로 틀 정하기
은행 창구의 서식에는 "생년월일(숫자 8자리)", "금액(숫자만)"처럼 칸마다 조건이 적혀 있습니다. 직원은 서식을 받으면 칸을 하나씩 훑어보고, 금액 칸에 "많이"라고 적혀 있으면 다시 써 달라고 돌려줍니다. Pydantic 이 하는 일이 이 직원입니다. 파이썬 클래스로 칸과 조건을 정해 두면, 값이 들어올 때마다 조건에 맞는지 검사합니다.
네 상자는 틀을 정하고 값을 넣어 검사하는 차례입니다. 마지막 상자에서 길이 둘로 갈립니다. 조건을 모두 지키면 값이 담긴 객체가 만들어지고, 하나라도 어기면 어느 칸이 왜 틀렸는지 적힌 ValidationError 가 납니다. 여기서 은행 서식이 BaseModel 을 물려받은 클래스, 칸마다 적힌 조건이 Field(...), 다시 써 달라고 돌려주는 일이 ValidationError 입니다. 비유와 다른 점은, Pydantic 은 "2"처럼 숫자로 바꿀 수 있는 글자는 돌려보내지 않고 알아서 숫자 2 로 바꿔 받는다는 것입니다.
칸에 붙이는 조건
| 쓰는 것 | 원래 말 | 뜻 | 예 |
|---|---|---|---|
int, str, list[str] | 자료형 | 칸에 들어갈 값의 종류 | nights: int |
description= | 설명 | 칸의 뜻. 모델에게도 그대로 전해진다 | "몇 박인지. 2박 3일이면 2" |
ge= | greater than or equal | 이 값 이상 | ge=1 (1박 이상) |
le= | less than or equal | 이 값 이하 | le=30 |
default= | 기본값 | 값이 없을 때 쓸 값 | default=0 |
짧은 예시
여행 조건의 틀을 정하고, 맞는 값과 틀린 값을 넣어 봅니다. 칸 이름은 모델이 읽기 쉽게 영어로 쓰고, 뜻은 description 에 한국어로 적었습니다.
from pydantic import BaseModel, Field, ValidationError
class TripRequest(BaseModel):
"""손님의 여행 조건"""
destination: str = Field(description="여행 목적지")
nights: int = Field(description="몇 박인지. 2박 3일이면 2", ge=1, le=30)
adults: int = Field(description="어른 수", ge=1)
children: int = Field(default=0, description="아이 수. 없으면 0", ge=0)
# "2" 는 글자지만 숫자로 바꿀 수 있어서 2 로 받는다. children 은 비워서 기본값 0
ok = TripRequest(destination="제주도", nights="2", adults=2)
print(ok)
print("박수의 자료형:", type(ok.nights).__name__)
try:
# 박수가 -1, 어른이 0 이라 두 칸이 조건을 어긴다
TripRequest(destination="제주도", nights=-1, adults=0)
except ValidationError as e:
print("틀린 칸 수:", e.error_count())
for err in e.errors():
# loc = location(위치, 어느 칸), type = 어긴 조건의 이름
print(err["loc"], err["type"])destination='제주도' nights=2 adults=2 children=0
박수의 자료형: int
틀린 칸 수: 2
('nights',) greater_than_equal
('adults',) greater_than_equal첫 줄은 검사를 통과한 객체입니다. 글자 "2"가 정수 2 로 바뀌었고, 비워 둔 children 에는 기본값 0 이 들어갔습니다. 둘째 시도는 두 칸이 조건을 어겨 ValidationError 가 났고, 어느 칸이(nights, adults) 어떤 조건(greater_than_equal, 이상이어야 함)을 어겼는지 알려 줍니다.
코드가 의미하는 것
이 코드는 은행 서식과 서식을 훑는 직원을 파이썬으로 옮긴 것입니다. 서식(틀)을 정하고, 맞게 쓴 서식과 틀리게 쓴 서식을 한 장씩 넣어 봅니다.
| 코드 | 하는 일 | 챗봇에서 뜻하는 것 |
|---|---|---|
class TripRequest(BaseModel) | 칸 넷의 틀을 정한다 | 모델의 답이 가져야 할 상담 카드의 양식입니다. 틀의 칸 이름이 곧 답의 열쇠 이름이 됩니다 |
Field(description=…, ge=1, le=30) | 칸에 뜻과 범위를 붙인다 | 1박부터 30박까지만 받겠다는 규칙입니다. description 은 다음 절에서 모델에게도 그대로 전해집니다 |
TripRequest(destination="제주도", nights="2", adults=2) | 값을 넣어 객체를 만든다 | 모델이 채운 답이 틀을 지나가는 순간입니다. 숫자로 바꿀 수 있는 글자 "2"는 숫자로 바꿔 받습니다 |
except ValidationError as e | 조건을 어긴 값을 잡는다 | 모델이 칸은 채웠지만 값이 말이 안 될 때, 그 값이 프로그램 안으로 들어가기 전에 막는 자리입니다 |
e.errors() 의 loc, type | 어느 칸이 어떤 조건을 어겼는지 꺼낸다 | 오류를 기록하거나 손님에게 다시 물을 때 쓸 단서입니다 |
결과에서 읽을 것은 세 가지입니다.
- 기본값이 빈칸을 메웠다.
children을 넘기지 않았는데children=0이 들어갔습니다. 아이 이야기가 없는 요청에서도 칸이 비지 않습니다. - 글자 "2"가 정수가 됐다. 박수의 자료형이
int입니다. 모델이 숫자를 글자로 적어 보내도 틀이 바로잡습니다. - 틀린 칸을 한꺼번에 알려 준다.
틀린 칸 수: 2이고 두 칸 모두greater_than_equal입니다. 첫 오류에서 멈추지 않고 어긴 칸을 모두 모아 줍니다.
주의할 점
description은 사람을 위한 메모이면서 모델에게 보내는 설명이기도 합니다. "몇 박인지. 2박 3일이면 2"처럼 헷갈릴 만한 곳을 예로 적어 두면 모델이 덜 틀립니다.- Pydantic 은 틀에 맞는지만 봅니다. "제주"와 "제주도"처럼 뜻은 같고 글자가 다른 값은 둘 다 통과합니다. 목적지 이름을 맞추려면 고를 수 있는 값을 정해 두는 방법(
Literal["제주도", "부산"])을 씁니다.