본문 바로가기
Artificial Intelligence/60. Python

[PYTHON] LLM Function Calling 신뢰도를 높이는 3가지 Structured Output 파싱 전략과 해결 방법

by Papa Martino V 2026. 4. 24.
728x90

LLM Function Calling
LLM Function Calling

 

인공지능 모델, 특히 대규모 언어 모델(LLM)을 실무 서비스에 도입할 때 가장 큰 장벽은 '비결정론적 출력'입니다. 모델이 가끔 엉뚱한 JSON 형식을 반환하거나, 필수 인자를 누락하는 문제는 시스템의 안정성을 해치는 치명적인 요소입니다. 본 글에서는 Python 환경에서 Function Calling의 신뢰도를 99% 이상으로 끌어올리기 위한 Structured Output 파싱 전략을 심도 있게 다룹니다.


1. 왜 Structured Output이 중요한가?

기존의 단순 텍스트 생성 방식은 파싱 에러(Parsing Error)에 취약합니다. 하지만 Structured Output(구조화된 출력)을 강제하면 모델은 정의된 스키마에 따라 응답해야만 합니다. 이는 API 연동, 데이터베이스 쿼리 생성, 자동화 워크플로우에서 에러 핸들링 비용을 획기적으로 줄여줍니다.


2. 파싱 전략별 비교 및 분석

현재 업계에서 주로 사용되는 세 가지 핵심 전략을 비교 분석하였습니다. 각 방식은 프로젝트의 복잡도와 모델의 성능에 따라 선택적으로 적용되어야 합니다.

비교 항목 Pydantic 기반 유효성 검사 Jsonformer (Logit Bias 컨트롤) Instructor 프레임워크
주요 특징 Python 표준 라이브러리 활용 토큰 생성 단계에서 형식 강제 OpenAI API에 최적화된 추상화
신뢰도 높음 (사후 검증) 매우 높음 (사전 방지) 매우 높음 (재시도 로직 포함)
구현 난이도 낮음 중간 매우 낮음
적용 분야 일반적인 데이터 파싱 로컬 LLM (Llama-3 등) 최적화 상용 서비스 API 연동

3. 실무 적용을 위한 7가지 개발자 Sample Examples

다음 예제들은 Python 3.10 이상 환경에서 즉시 실행 가능한 수준의 코드들입니다.

Example 1: Pydantic을 이용한 기본적인 Function Calling 정의

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

class ExtractUserInfor(BaseModel):
    name: str = Field(..., description="사용자의 이름")
    age: int = Field(..., gt=0, le=120, description="사용자의 나이")
    skills: List[str] = Field(default_factory=list, description="보유 기술 목록")

# 모델 선언 시 이 클래스를 tool로 전달하여 스키마 일관성을 유지합니다.

Example 2: Instructor 라이브러리를 활용한 자동 재시도(Retry) 전략

import instructor
from openai import OpenAI
from pydantic import BaseModel

class StockPrice(BaseModel):
    symbol: str
    price: float
    currency: str

client = instructor.patch(OpenAI())

def get_reliable_response(user_input: str):
    return client.chat.completions.create(
        model="gpt-4-0613",
        response_model=StockPrice,
        max_retries=3,  # 검증 실패 시 최대 3번 자동 재시도
        messages=[{"role": "user", "content": user_input}]
    )

Example 3: 복합 객체 리스트 추출을 위한 Nested Schema 전략

class Medicine(BaseModel):
    name: str
    dosage: str
    frequency: str

class Prescription(BaseModel):
    patient_name: str
    medications: List[Medicine]

# 처방전 텍스트에서 구조화된 데이터를 한 번에 추출하는 기법입니다.

Example 4: Enum 클래스를 활용한 카테고리 분류 신뢰도 향상

from enum import Enum

class TicketPriority(str, Enum):
    HIGH = "high"
    MEDIUM = "medium"
    LOW = "low"

class SupportTicket(BaseModel):
    issue: str
    priority: TicketPriority  # 지정된 값 이외의 응답을 원천 차단

Example 5: 데이터 유효성 검사 실패 시 자가 수정(Self-Correction) 프롬프트

# Pydantic의 validator를 사용하여 논리적 오류를 검사합니다.
from pydantic import validator

class EventSchedule(BaseModel):
    start_time: str
    end_time: str

    @validator('end_time')
    def check_time_order(cls, v, values):
        if 'start_time' in values and v < values['start_time']:
            raise ValueError("종료 시간은 시작 시간보다 빨라질 수 없습니다.")
        return v

Example 6: JSON 파싱 에러 방지를 위한 Partial JSON Parser 활용

import json
from langchain.output_parsers import OutputFixingParser
from langchain.chat_models import ChatOpenAI

# 형식이 깨진 JSON이 올 경우 LLM이 스스로 수정하도록 유도하는 전략입니다.
parser = OutputFixingParser.from_llm(parser=original_parser, llm=ChatOpenAI())

Example 7: 다중 함수 선택(Router) 기능을 위한 Dispatcher 구현

from typing import Union

class SearchQuery(BaseModel):
    query: str

class DatabaseQuery(BaseModel):
    table_name: str
    filter_condition: str

class Router(BaseModel):
    choice: Union[SearchQuery, DatabaseQuery]

# 사용자의 의도에 따라 어떤 함수를 호출할지 구조적으로 결정합니다.

4. 신뢰도 최적화를 위한 5단계 해결 방법

  1. 명확한 설명(Description) 작성: Pydantic Field에 기술하는 설명이 LLM의 시스템 프롬프트가 됩니다. 예시를 포함하면 정확도가 상승합니다.
  2. Few-shot Prompting 결합: 입출력 쌍 예시 2~3개를 Schema 내부에 주석이나 별도 메시지로 전달하세요.
  3. Token Bias 조절: 특정 키워드(예: 'True', 'False')가 반드시 나와야 한다면 Logit Bias를 사용하여 확률을 강제로 높입니다.
  4. Chain of Thought 유도: 구조화된 응답을 내놓기 전, "thought" 필드를 만들어 모델이 추론 과정을 먼저 적게 하세요.
  5. Strict Mode 활성화: OpenAI API의 경우 strict: true 옵션을 사용하여 스키마 준수를 100% 보장받을 수 있습니다.

5. 결론

Python에서 LLM의 Function Calling 신뢰도를 높이는 핵심은 "모델에게 자유도를 주지 않는 것"입니다. Pydantic과 Instructor 같은 도구를 활용하여 엄격한 가이드라인을 제시하고, 런타임에서 발생할 수 있는 예외를 코드로 방어하는 것이 진정한 의미의 프로덕션 레벨 AI 개발입니다.


참고 및 출처

  • OpenAI Official Documentation: Function Calling & Structured Outputs (2024-2026 Update)
  • Pydantic V2 Core Documentation: Validation and Serialization
  • Instructor Python Library: Advanced Type Prompting Guides
  • LangChain Python Ecosystem: Output Parsers and Error Handling Patterns
728x90