Small Asteroid Blog

[Python] OpenAI 결과를 고정된 JSON 포맷(Structured Output)으로 받는 방법 본문

백엔드/Python

[Python] OpenAI 결과를 고정된 JSON 포맷(Structured Output)으로 받는 방법

작은소행성☄️ 2025. 3. 21. 15:51
728x90

OpenAI API를 사용할 때 가장 자주 마주치는 문제 중 하나는 결과의 형식이 일정하지 않다는 점입니다. 

일반적으로 자연어 응답은 유연하고 사람처럼 말하는 게 장점이지만, API로 사용할 경우엔 결과가 고정된 포맷으로 오는 것이 훨씬 다루기 편합니다.

이 글에서는 OpenAI API에서 Structured Output, 즉 고정된 JSON 형식으로 결과를 받아내는 방법을 소개합니다. 

특히 pydantic과 OpenAI의 pydantic_function_tool 기능을 활용하여 예측 가능하고 안정적인 결과를 만드는 방법에 대해 설명합니다.

 

 

왜 Structured Output이 필요한가?

Structured Output은 명확하고, 키-값 형태의 JSON으로 결과를 반환해 사용하기 편합니다.

JSON Object 로도 반환해달라고 해보았지만 유효한 JSON 이 아니면 파싱단계에서 에러가 날 수 있습니다.

 

 

Pydantic

Python 기반 데이터 유효성 검사 라이브러리입니다. 

JSON 같은 구조화된 데이터를 객체처럼 쉽게 다룰 수 있게 합니다. 

from pydantic import BaseModel

class Summary(BaseModel):
    summary: str

 

pydantic_function_tool

OpenAI의 Function Calling 기능을 사용할 때, 직접 JSON 스키마를 정의하는 대신 Pydantic 모델을 그대로 쓸 수 있게 해주는 도구입니다. 매우 깔끔하고, 타입 안전하며, 구조화된 결과를 쉽게 다룰 수 있습니다.

 

 

예제

Pydantic 모델 정의

from pydantic import BaseModel

class Summary(BaseModel):
    summary: str

 

 

함수 정의 

from openai import OpenAI
from openai.types.beta.threads import MessageContentText
from openai_function_call import pydantic_function

@pydantic_function
def summarize_text(text: str) -> Summary:
    """주어진 문장을 요약합니다."""
    return Summary(summary="")  # 초기값은 무시됨

 

 

OpenAI API 호출

client = OpenAI()

response = client.chat.completions.create(
    model="gpt-4-1106-preview",
    messages=[{
        "role": "user",
        "content": "이 제품은 가볍고 내구성이 뛰어나며 휴대하기 좋습니다. 요약해줘."
    }],
    tools=[summarize_text],
    tool_choice="auto"
)

result = summarize_text.extract_tool_call(response)
print(result.model_dump())

 

 

결과 

{
  "summary": "가볍고 내구성 좋은 제품입니다."
}

 

 

 

좋은점 

  • 형식이 보장됨: 항상 원하는 필드가 존재하고, 타입이 일치합니다.
  • 파싱할 필요 없음: 결과를 바로 Pydantic 모델로 다룰 수 있습니다.
  • 스키마 기반 응답 설계: API 응답 스펙처럼 구조화된 결과를 설계할 수 있습니다.

 

 

 

 

 

https://platform.openai.com/docs/guides/function-calling?api-mode=chat

https://python.useinstructor.com/

728x90
반응형