- Published on
LangChain Pydantic v2 호환 오류 5분 해결법
- Authors
- Name
- 스타차일드
- https://x.com/ETFBITX
서론
LangChain을 쓰는 프로젝트에서 의존성을 업데이트하다가 갑자기 앱이 부팅조차 안 되거나, 도구(tool) 스키마 생성/검증 단계에서 예외가 터지는 경우가 많습니다. 특히 Pydantic v2 전환은 파급이 큽니다. LangChain(및 그 하위 패키지들)도 v2 대응을 진행해왔지만, 프로젝트가 가진 다른 라이브러리(예: FastAPI, OpenAI SDK, 자체 모델 코드)와의 조합에 따라 **“Pydantic v1/v2가 섞인 상태”**가 되면 오류가 폭발합니다.
이 글은 “원인 분석에 1시간 쓰지 말고”, 5분 안에 아래 3가지를 끝내는 것을 목표로 합니다.
- 지금 내 환경이 Pydantic v1/v2 중 무엇을 쓰는지 즉시 확인
- LangChain과의 호환 조합을 빠르게 맞추기(핀 고정 또는 업그레이드)
- 코드 레벨에서 가장 자주 터지는 import/스키마 포인트를 최소 수정으로 정리
1) 증상으로 빠르게 분류하기: 가장 흔한 에러 패턴
Pydantic v2 호환 문제는 메시지 패턴이 꽤 정형적입니다. 아래 중 하나라도 보이면 이 글의 대상입니다.
패턴 A: v1 API를 v2에서 호출
ImportError: cannot import name 'BaseSettings' from 'pydantic'ImportError: cannot import name 'validate_arguments' from 'pydantic'AttributeError: type object 'BaseModel' has no attribute 'parse_obj'
원인: v2에서 일부 API가 이동/변경되었습니다. (BaseSettings는 pydantic-settings로 분리, parse_obj는 model_validate로 대체 등)
패턴 B: 스키마/JSON schema 생성 관련 예외
PydanticInvalidForJsonSchema: Cannot generate a JsonSchema for ...TypeError: Object of type '...' is not JSON serializable
원인: LangChain의 tool/function schema 생성 과정에서 v2의 schema 규칙과 충돌하거나, Field/Annotated 조합이 꼬인 경우가 많습니다.
패턴 C: “v1과 v2 혼용”의 전형
UserWarning: Mixing V1 and V2 models is not supportedTypeError: BaseModel.__init__() takes 1 positional argument but 2 were given(간접 원인)
원인: 일부 라이브러리는 v1을, 일부는 v2를 전제하고 있어 런타임에 모델 타입이 섞입니다.
2) 30초 진단: 내 환경에서 실제로 무엇이 설치됐는지 확인
가장 먼저 버전과 의존성 트리를 확인해야 합니다. “내가 pydantic==2로 올렸는데 왜 v1 API를 찾지?” 같은 혼란은 대부분 여기서 끝납니다.
pip 기반 프로젝트
python -c "import pydantic; print('pydantic', pydantic.__version__)"
python -c "import langchain; import langchain_core; print('langchain', langchain.__version__); print('langchain_core', langchain_core.__version__)"
pip show pydantic langchain langchain-core langchain-community
pipdeptree | egrep -i "pydantic|langchain" -n
Poetry 기반 프로젝트
poetry show pydantic langchain langchain-core langchain-community
poetry show --tree | egrep -i "pydantic|langchain" -n
여기서 포인트는 2가지입니다.
- pydantic이 1.x인지 2.x인지
- LangChain이 단일 패키지인지(
langchain) + core/community가 어떤 버전인지
LangChain은 한동안 패키지 분리가 진행되어 langchain-core, langchain-community 등의 조합이 중요합니다. 버전이 엇갈리면 “어떤 모듈은 v2 대응, 어떤 모듈은 v1 전제” 같은 애매한 상태가 됩니다.
3) 5분 해결의 핵심 전략 2가지
현실적인 해결책은 크게 둘 중 하나입니다.
- (권장) LangChain 쪽을 최신 호환 조합으로 올리고 Pydantic v2를 유지
- 빠른 롤백: Pydantic을 v1로 핀 고정(급한 운영 장애/배포 차단 해소용)
둘 중 무엇을 택할지는 “내 프로젝트가 이미 Pydantic v2를 전제로 작성되었는지”에 달려 있습니다.
4) 선택지 A: Pydantic v2 유지 + LangChain 호환 버전으로 정렬
A-1) 버전 정렬 원칙
langchain,langchain-core,langchain-community버전을 같은 릴리즈 라인으로 맞추기- 프로젝트 내 다른 프레임워크(FastAPI 등)가 Pydantic v2를 요구한다면, LangChain도 v2 대응 버전으로 올리기
실무에서 가장 흔한 실패는 아래입니다.
langchain만 올렸는데langchain-core가 옛날 버전으로 남아있음- 반대로
langchain-core만 올라가고langchain-community는 낮아서 tool/schema 생성이 깨짐
A-2) pip 예시(개념 예시)
아래는 “호환 조합으로 한 번에 정렬”하는 방식의 예시입니다. (정확한 버전 숫자는 프로젝트 시점에 따라 달라지므로, 핵심은 동시에 업그레이드입니다.)
pip install -U "langchain" "langchain-core" "langchain-community" "pydantic>=2" "pydantic-settings>=2"
업데이트 후 다시 진단:
python -c "import pydantic; import langchain_core; print(pydantic.__version__); print(langchain_core.__version__)"
5) 선택지 B: 1분 응급처치 — Pydantic v1로 핀 고정
배포가 막혔고, 지금 당장 코드를 손댈 시간이 없으면 가장 빠른 방법은 Pydantic v1로 롤백입니다.
pip install "pydantic<2"
# 또는 requirements.txt/poetry.lock에 고정
다만 이 선택지는 다음 상황에서만 추천합니다.
- 기존 코드/의존성이 Pydantic v1 기반이고, v2 마이그레이션을 아직 계획하지 않음
- 운영 장애를 즉시 막아야 함(빌드/부팅 실패)
FastAPI 최신 버전 등 다른 의존성이 Pydantic v2를 강제하는 경우에는 v1 핀 고정이 오히려 더 큰 충돌을 만들 수 있습니다.
6) 코드 레벨에서 가장 많이 터지는 포인트 4개(바로 고치기)
여기부터는 “버전 정렬을 했는데도” 남는 잔여 오류를 5분 안에 제거하는 체크리스트입니다.
6-1) BaseSettings 이동: pydantic-settings로 교체
Pydantic v2에서 설정 관리는 분리되었습니다.
변경 전(v1 스타일)
from pydantic import BaseSettings
class Settings(BaseSettings):
openai_api_key: str
변경 후(v2 스타일)
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
openai_api_key: str
의존성도 추가해야 합니다.
pip install -U pydantic-settings
6-2) parse_obj() → model_validate()
LangChain 주변 코드에서 입력 dict를 모델로 바꾸는 부분이 있으면 자주 터집니다.
from pydantic import BaseModel
class ToolInput(BaseModel):
query: str
payload = {"query": "hello"}
obj = ToolInput.model_validate(payload) # v2
6-3) dict() → model_dump()
tool output이나 로그/저장 단계에서 직렬화가 필요할 때:
data = obj.model_dump() # 기본
json_data = obj.model_dump_json() # JSON 문자열
6-4) schema() → model_json_schema()
LangChain tool/function schema 생성 커스터마이징을 했다면 여기서 깨질 수 있습니다.
schema = ToolInput.model_json_schema()
7) LangChain Tool/Function 스키마에서 자주 생기는 v2 이슈와 해결
LangChain을 쓰면서 Pydantic v2 호환 문제가 가장 자주 표면화되는 지점은 Tool 입력 스키마 생성입니다. 특히 OpenAI function calling/툴 호출에 들어가는 JSON schema를 만들 때 v2의 엄격함이 드러납니다.
7-1) Annotated/Field로 명시적 타입과 설명을 주기
스키마 생성이 불안정할 때는 타입/설명을 명확히 주는 것이 효과적입니다.
from typing import Annotated
from pydantic import BaseModel, Field
class SearchInput(BaseModel):
query: Annotated[str, Field(description="검색할 키워드")]
top_k: Annotated[int, Field(default=5, ge=1, le=20, description="반환 개수")]
7-2) 임의 객체/콜러블을 필드로 넣지 않기
아래처럼 “클래스 인스턴스”나 “함수”를 모델 필드로 넣으면 JSON schema 생성에서 실패하기 쉽습니다.
# 피해야 하는 패턴(예시)
from pydantic import BaseModel
class BadInput(BaseModel):
handler: object # JSON schema로 표현 불가
대신 식별자(string)나 enum으로 표현하고 런타임에 매핑하세요.
8) 재현 가능한 최소 테스트로 ‘정상화’ 확인하기
업그레이드/핀 고정 후에는 “LangChain이 실제로 tool schema를 만들고, Pydantic 모델이 validate/dump 되는지”를 최소 코드로 확인하는 게 안전합니다.
from typing import Annotated
from pydantic import BaseModel, Field
class ToolInput(BaseModel):
text: Annotated[str, Field(description="입력 텍스트")]
def sanity_check():
payload = {"text": "ping"}
obj = ToolInput.model_validate(payload)
assert obj.text == "ping"
schema = ToolInput.model_json_schema()
assert "properties" in schema
dumped = obj.model_dump()
assert dumped == payload
if __name__ == "__main__":
sanity_check()
print("OK")
이 테스트가 통과하면, 적어도 Pydantic v2 모델 라이프사이클(검증/스키마/직렬화)은 정상입니다. 이후 LangChain 쪽에서 깨진다면 대부분 패키지 버전 불일치이거나, 커스텀 Tool 정의에서 “JSON schema 불가능한 타입”을 넣은 경우입니다.
9) 운영 관점 팁: 의존성 업데이트는 ‘콜드 스타트’처럼 터진다
Pydantic/LangChain 이슈는 로컬에서는 우연히 지나가도, 컨테이너 빌드/배포 후 런타임 import 단계에서 한 번에 터지곤 합니다. 특히 서버리스나 오토스케일 환경에서는 “새로운 파드/인스턴스”가 뜨는 순간 장애가 됩니다.
의존성 import 병목/레이어 구성 때문에 장애가 증폭되는 패턴은 Lambda에서도 자주 보입니다. 비슷한 관점의 실전 대응은 이 글이 도움이 됩니다: AWS Lambda Python 콜드 스타트가 갑자기 2~5초로 늘어날 때 컨테이너 이미지 레이어 의존성 import 병목과 Provisioned Concurrency로 80% 줄이는 실전 가이드
또한 LLM 서비스는 502/504, 스트리밍 끊김 등 네트워크/서버 튜닝 이슈와 결합되면 디버깅 난이도가 급상승합니다. 인퍼런스/LLM API 게이트웨이 운영 중이라면 아래도 같이 참고하세요: Kubernetes LLM 서비스 502 504 간헐 장애와 스트리밍 끊김을 끝내는 NGINX Ingress와 Gunicorn Uvicorn 실전 튜닝
10) 결론: 5분 체크리스트
마지막으로 “진짜 5분 해결”을 위한 순서를 체크리스트로 정리합니다.
pydantic,langchain,langchain-core,langchain-community버전 확인- 혼용 상태면 결정:
- Pydantic v2 유지 → LangChain 패키지들을 함께 업그레이드/정렬
- 응급처치 →
pydantic<2로 핀 고정
- 코드 수정이 필요하면 4가지만 우선 교체:
BaseSettings→pydantic_settings.BaseSettingsparse_obj→model_validatedict()→model_dump()schema()→model_json_schema()
- 최소 테스트 코드로 validate/schema/dump 정상 동작 확인
이 흐름대로 하면 “원인 찾느라 반나절” 쓰는 일을 대부분 줄일 수 있습니다.