아웃라인과 Pydantic을 사용하여 유형 안전하고 스키마 제한된 LLM 파이프라인 구축 방법
LLM(대규모 언어 모델)이 점점 더 강력해짐에 따라, 이를 효율적으로 활용하고 신뢰할 수 있는 결과를 얻기 위한 방법도 중요해지고 있습니다. 특히, 비정형적인 텍스트 생성 모델의 특성상, 예측 불가능한 결과가 나올 가능성이 높기 때문에, 이를 제어하고 구조화하는 것이 필수적입니다. 이러한 문제를 해결하기 위해, 아웃라인(Outlines)과 Pydantic이라는 두 가지 강력한 도구를 활용하여 LLM 파이프라인을 구축하는 방법을 소개합니다. 이번 튜토리얼에서는 이 두 도구를 함께 사용하여, 유형 안전하고 스키마에 의해 제한된 LLM 파이프라인을 구축하는 단계별 가이드라인을 제공할 것입니다.
아웃라인은 LLM에서 구조화된 출력을 생성하기 위한 프레임워크이며, Pydantic는 데이터 유효성 검사 및 직렬화를 위한 라이브러리입니다. 이 두 가지를 결합하면 LLM이 예측 가능하고 신뢰할 수 있는 결과를 생성하도록 안내할 수 있습니다. 데이터 과학자와 개발자 모두에게 유용한 정보가 될 것이라고 생각합니다. 지금 바로 시작해 볼까요?
1. 개발 환경 설정 및 기본 라이브러리
먼저, 아웃라인, 트랜스포머, 가속화, 문자열 조각, Pydantic 등의 필수 종속성을 설치해야 합니다. 아래 코드를 사용하여 이 작업을 수행할 수 있습니다. 이 코드는 파이썬 환경에 필요한 라이브러리를 설치하는 과정입니다. GPU 가속을 위한 CUDA를 활성화하거나 CPU를 사용하여 모델을 실행할 수 있습니다.
import os, sys, subprocess, json, textwrap, re
subprocess.check_call([
sys.executable, "-m", "pip", "install", "-q",
"outlines", "transformers", "accelerate", "sentencepiece", "pydantic"
])
import torch
import outlines
from transformers import AutoTokenizer, AutoModelForCausalLM
from typing import Literal, List, Union, Annotated
from pydantic import BaseModel, Field
from enum import Enum
이 코드는 또한 PyTorch 버전을 확인하고 CUDA 사용 가능성을 확인하며 아웃라인 버전을 표시합니다. 이러한 정보는 시스템이 아웃라인과 LLM을 처리하는 데 필요한 적절한 환경을 갖추고 있는지 확인하는 데 도움이 됩니다. 다음 단계는 아웃라인 파이프라인을 초기화하고 간단한 헬퍼 함수를 구축하는 것입니다.
2. 유형 지정 출력: Literal, int, bool
이제 아웃라인을 사용하여 LLM에서 유형 지정 출력을 생성하는 방법을 살펴보겠습니다. 예를 들어, 감성 분석을 수행하고 감정(Positive, Negative, Neutral) 중 하나의 레이블만 반환하도록 LLM을 지시할 수 있습니다. 아래 코드는 이러한 유형 지정 출력을 생성하는 방법을 보여줍니다. LLM은 아웃라인에 의해 강제로 특정 유형의 출력만 생성하도록 제한됩니다.
def extract_json_object(s: str) -> str:
s = s.strip()
start = s.find("{")
if start == -1:
return s
depth = 0
in_str = False
esc = False
for i in range(start, len(s)):
ch = s[i]
if in_str:
if esc:
esc = False
elif ch == "":
esc = True
elif ch == '"':
in_str = False
else:
if ch == '"':
in_str = True
elif ch == "{":
depth += 1
elif ch == "}":
depth -= 1
if depth == 0:
return s[start:i + 1]
return s[start:]
def json_repair_minimal(bad: str) -> str:
bad = bad.strip()
last = bad.rfind("}")
if last != -1:
return bad[:last + 1]
return bad
def safe_validate(model_cls, raw_text: str):
raw = extract_json_object(raw_text)
try:
return model_cls.model_validate_json(raw)
except Exception:
raw2 = json_repair_minimal(raw)
return model_cls.model_validate_json(raw2)
이 코드 스니펫은 아웃라인에서 유효하지 않은 JSON을 복구하고, LLM이 반환하는 출력을 안전하게 검증하는 데 사용되는 유틸리티 함수를 정의합니다. 또한 정수 및 부울 값을 생성하기 위한 LLM 사용 예제를 제공합니다. 이러한 유형의 출력은 데이터가 예상된 형식을 준수하도록 하는 데 중요합니다.
3. 프롬프트 템플릿 사용
다음으로, 아웃라인의 템플릿 기능을 사용하여 더 구조화된 프롬프트를 생성하는 방법을 살펴보겠습니다. 아웃라인 템플릿은 역할 형식과 출력 제한을 유지하면서 사용자 입력을 프롬프트에 동적으로 삽입할 수 있습니다. 이는 재사용성을 향상시키고 일관된 응답을 보장하는 데 도움이 됩니다. 템플릿은 LLM의 동작을 보다 제어하기 쉽게 만들어줍니다.
4. Pydantic으로 구조화된 출력 (고급 제약 조건)
이제 Pydantic을 사용하여 더욱 복잡한 제약 조건을 정의하고 LLM이 생성하는 출력의 구조를 제어하는 방법을 살펴보겠습니다. 예를 들어, 티켓 우선 순위, 카테고리, 세부 정보 등 다양한 정보를 포함하는 서비스 티켓 Pydantic 모델을 정의할 수 있습니다. LLM은 이 모델을 준수하는 JSON 객체를 생성하도록 지시할 수 있습니다. 이 방법은 LLM의 출력을 보다 구조화되고 예측 가능하게 만드는 데 도움이 됩니다.
5. 함수 호출 스타일 (스키마 -> 인수 -> 호출)
마지막으로, 함수 호출 스타일을 사용하여 LLM을 통해 파이썬 함수를 안전하게 실행하는 방법을 살펴보겠습니다. 먼저 LLM이 함수의 입력으로 사용할 인수 목록을 생성하도록 지시합니다. 그런 다음 이 인수를 검증하고 파이썬 함수를 호출합니다. 이러한 방식은 LLM의 출력을 사용하여 복잡한 계산을 수행하는 데 매우 유용합니다. 이는 LLM을 보다 강력하고 유연하게 만듭니다. 이러한 방식으로, LLM의 기능을 확장하고 다양한 애플리케이션에서 사용할 수 있습니다.
결론
결론적으로, 이번 튜토리얼에서는 아웃라인과 Pydantic을 사용하여 LLM 파이프라인을 구축하는 방법을 살펴보았습니다. 이러한 도구를 사용하면 LLM의 출력을 보다 제어하고 구조화하여 더욱 신뢰할 수 있고 예측 가능한 결과를 얻을 수 있습니다. 이 가이드라인을 따르면 LLM 기반 애플리케이션을 구축하는 데 필요한 도구와 지식을 얻을 수 있을 것입니다.
심층 분석 및 시사점
Array
한국어
English