6.6.2 Outlines 라이브러리를 활용한 정규표현식 및 JSON 스키마 가이드 생성

6.6.2 Outlines 라이브러리를 활용한 정규표현식 및 JSON 스키마 가이드 생성

오픈소스 언어 모델(LLM)을 엔터프라이즈 파이프라인에 통합할 때 가장 큰 난관은, 파라미터 수가 적은 로컬 모델일수록 프롬프트의 지시를 무시하고 자유분방한 텍스트를 생성하려는 경향이 강하다는 점이다. 이러한 파편화된 출력을 결정론적 오라클(Deterministic Oracle)로 검증하기 위해서는 생성 단계(Generation Phase)에서부터 모델의 출력을 물리적으로 옥죄어(Constrain) 원천적으로 무결성을 확보해야 한다. 이를 위한 가장 강력하고 우아한 오픈소스 솔루션 중 하나가 바로 Outlines 라이브러리다.

1. 생성의 물리적 통제 원리 (Constrained Text Generation)

Outlines는 일반적인 프롬프트 엔지니어링 도구가 아니라, 언어 모델의 텍스트 생성 엔진 깊숙이 개입하여 다음에 올 수 있는 토큰(Token)의 확률 분포를 조작하는 라이브러리다.

  • 유한 상태 기계(FSM)와 정규표현식: 개발자가 특정 정규표현식(Regex)을 Outlines에 주입하면, 라이브러리는 이를 유한 상태 기계(Finite State Machine)로 컴파일한다.
  • 토큰 마스킹(Token Masking): 모델이 다음 토큰을 디코딩(Decoding)하는 매 스텝마다, FSM 상에서 유효하지 않은(정규식에 위배되는) 모든 토큰의 확률(Logit)을 음의 무한대(-\infty)로 덮어씌운다. 결과적으로 모델은 구조적으로 ‘문제가 있는’ 응답 자체를 산출할 수 없게 되며, 개발자가 정의한 구조 내에서만 사고하고 텍스트를 토해내게 된다.

2. 정규표현식(Regex)을 이용한 원시 타입 강제

IP 주소, 이메일, 주민등록번호, 날짜와 같이 엄격한 형태를 지녀야 하는 데이터를 추출할 때, 단순 프롬프팅만으로는 오류를 막을 수 없다. Outlines를 이용하면 런타임에서 완벽한 매칭을 보장받을 수 있다.

import outlines
from pydantic import BaseModel

# 로컬 모델 로드 (예: vLLM 또는 Hugging Face Transformers)
model = outlines.models.transformers("meta-llama/Llama-3-8b-Instruct")

# 정규표현식을 씌운 제너레이터(Generator) 생성
# 예: YYYY-MM-DD 형식의 날짜만 출력하도록 강제
date_generator = outlines.generate.regex(model, r"20[0-9]{2}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])")

# 텍스트 생성: 모델은 정해진 정규식 외의 문자를 뱉을 수 없음
result = date_generator("사용자의 계약 만료일을 알려줘.")
print(result) # 출력 예: "2024-11-30"

위의 예시에서 AI는 “계약 만료일은 2024년 11월 30일입니다“라는 군더더기를 만들어내지 못한다. 오라클 시스템은 별도의 복잡한 파싱(Parsing)이나 예외 처리 파이프라인 없이, 산출된 텍스트 자체를 즉시 ParseDate(result) 함수에 밀어 넣고 결정론적 검증을 시작할 수 있다.

3. Pydantic을 활용한 JSON 스키마 바인딩

Outlines의 핵심 기능은 Pydantic 라이브러리와의 긴밀한 통합이다. 복잡한 다중 필드를 취급하는 비즈니스 통신 규격에서, 엔지니어는 자신이 작성한 파이썬 데이터 클래스(Data Class)를 그대로 AI의 응답 구조로 강제할 수 있다.

import outlines
from pydantic import BaseModel, constr

# Pydantic을 이용한 스키마 및 제약 조건 정의
class ProductReview(BaseModel):
    sentiment: constr(regex=r"^(Positive|Negative|Neutral)$")  # Enum 방식의 제약
    score: int
    key_features: list[str]

# Pydantic 모델을 JSON 스키마 제너레이터로 변환
json_generator = outlines.generate.json(model, ProductReview)

text = "이 휴대폰은 배터리가 너무 빨리 닳지만 카메라 화질은 정말 경이롭습니다."
structured_result = json_generator(text)

# 산출된 결과는 완전한 ProductReview 객체로 매핑됨
# 오라클은 structured_result.score 등을 즉각적으로 평가 가능

Outlines가 적용된 파이프라인에서는 “AI가 JSON을 망가뜨렸을 때 어떻게 복구할 것인가?“라는 사후 복구(Fallback) 전략에 에너지를 쏟을 필요가 없다. JSON 문법 에러나 스키마 불일치(Type Mismatch)는 연산 계층에서 기계적으로 원천 봉쇄되기 때문이다. 이는 로컬 LLM을 파이프라인의 불확실성 리스크(Risk)에서 강력한 결정론적 유틸리티 함수(Utility Function)로 격상시키는 가장 공학적인 접근 프레임워크다.