구조화된 출력 (Structured Outputs)

구조화된 출력 (Structured Outputs)

Databricks에서 AI 애플리케이션 워크플로의 일부로, 정해진 JSON 형식으로 응답을 생성하게 하는 기능이에요. 지원되는 채팅 모델이라면 어떤 프로바이더든 response_format 필드 하나로 동작해서, 모델 프로바이더가 달라도 같은 요청 형식을 사용해요. 프로바이더별 번역은 Databricks가 알아서 처리하니까, 각 프로바이더의 고유 구조화 출력 형식을 쓸 필요가 없어요.

출처: Structured outputs on Databricks

왜 쓰나

구조화된 출력은 입력 데이터에서 JSON 객체 형태의 구조화 데이터를 생성하는 방법이에요. 평문, 구조화되지 않은 JSON 객체, 특정 JSON 스키마를 따르는 JSON 객체 중에서 골라 생성할 수 있어요. Foundation Model APIs의 pay-per-token·provisioned throughput 엔드포인트로 서빙되는 채팅 모델에서 지원돼요.

다음 같은 시나리오에서 권장돼요.

  • 대량 문서에서 데이터 추출. 예: 제품 리뷰 피드백을 부정/중립/긍정으로 분류.
  • 지정된 형식의 출력이 필요한 배치 추론 작업.
  • 비정형 데이터를 정형 데이터로 바꾸는 데이터 처리.

사용법

채팅 요청에 response_format으로 구조화 출력을 지정해요. 예를 들어 리서치 페이퍼 메타데이터(title, authors, abstract, keywords)를 특정 JSON 스키마로 추출하는 사례를 보면, OpenAI 클라이언트에 base_url로 Databricks 엔드포인트를 주고 response_formattype: "json_schema"와 스키마를 넘겨요.

import os
import json
from openai import OpenAI

DATABRICKS_TOKEN = os.environ.get('YOUR_DATABRICKS_TOKEN')
DATABRICKS_BASE_URL = os.environ.get('YOUR_DATABRICKS_BASE_URL')

client = OpenAI(
  api_key=DATABRICKS_TOKEN,
  base_url=DATABRICKS_BASE_URL
  )

response_format = {
      "type": "json_schema",
      "json_schema": {
        "name": "research_paper_extraction",
        "schema": {
          "type": "object",
          "properties": {
            "title": { "type": "string" },
            "authors": {
              "type": "array",
              "items": { "type": "string" }
            },
            "abstract": { "type": "string" },
            "keywords": {
              "type": "array",
              "items": { "type": "string" }
            }
          },
        },
        "strict": True
      }
    }

messages = [{
        "role": "system",
        "content": "You are an expert at structured data extraction. You will be given unstructured text from a research paper and should convert it into the given structure."
      },
      {
        "role": "user",
        "content": "..."
      }]

response = client.chat.completions.create(
    model="databricks-gpt-oss-20b",
    messages=messages,
    response_format=response_format
)

print(json.dumps(response.choices[0].message.model_dump()['content'], indent=2))

모델만 바꾸면 databricks-claude-sonnet-4-5 같은 Claude 모델에도 같은 요청 형식을 그대로 쓸 수 있어요. JSON 스키마를 미리 모를 때는 response_format{"type": "json_object"}로 주면 스키마 제약 없이 JSON 객체를 생성해요.

JSON 스키마 제약

Foundation Model APIs는 OpenAI가 수용하는 구조화 출력을 대부분 지원하지만, 더 단순한 JSON 스키마가 더 높은 품질의 JSON 생성을 만드니 지원하지 않는 일부 사양이 있어요.

  • pattern을 쓰는 정규식
  • anyOf, oneOf, allOf, prefixItems, $ref를 쓰는 복잡한 중첩·스키마 합성·검증
  • [type, "null"](한 타입은 유효 JSON 타입이고 다른 쪽은 "null") 특수 케이스를 제외한 타입 목록

그리고 다음 한계도 참고해요.

  • JSON 스키마에 지정할 수 있는 키 최대 개수는 64.
  • 객체·배열의 길이·크기 제약(maxProperties, minProperties, maxLength 등)은 강제하지 않아요.
  • 깊게 중첩된 JSON 스키마는 생성 품질이 낮아지니, 가능하면 스키마를 평탄화하는 게 좋아요.

프롬프트 인젝션 같은 기법이 구조화 출력 품질을 높이는 데 쓰이고, 이는 모델이 소비하는 입력·출력 토큰 수에 영향을 줘서 과금에도 반영돼요.

Claude 모델 추가 제약

  • json_schema 타입만 지원하고 json_object는 지원하지 않아요. 제약 없는 출력이 필요하면 response_format을 생략해요.
  • 스트리밍과 함께 쓸 수 없어요. response_format을 지정하면 streamfalse로 설정해야 해요.
  • response_formattoolstool_choice와 함께 쓸 수 없어요.

더 알아보기