LLM 추론: vLLM (LLM inference: vLLM)

LLM 추론: vLLM (LLM inference: vLLM)

자체 LLM을 서비스하고 싶을 때 BentoML과 vLLM을 함께 쓰면 OpenAI 호환 엔드포인트를 빠르게 만들 수 있어요. vLLM은 gpt-oss, DeepSeek, Qwen, Llama 같은 LLM을 고효율로 서빙하는 라이브러리인데, PagedAttention과 연속 배치(continuous batching)로 높은 처리량과 효율적인 KV 캐시 메모리 관리를 제공하고, prefill-decode 분리, 스펙큘레이티브 디코딩, KV 캐시 오프로딩 같은 최적화도 지원해요. 이 페이지는 그 예제가 어떻게 구성되는지 풀어서 설명할게요.

출처: https://docs.bentoml.com/en/latest/examples/vllm.html

무엇을 만드는지

이 예제는 채팅 기반 상호작용용으로, OpenAI 호환 엔드포인트를 제공해요. 아래처럼 rolecontent를 담은 메시지를 보내면 모델이 응답하죠.

{
  "role": "user",
  "content": "Who are you? Please respond in pirate speak!"
}

이 예제는 BentoCloud에서 바로 배포하고 확장할 수 있게 준비되어 있어요. 명령 하나로 빠른 자동 스케일링, 보안 배포, 포괄적인 옵저버빌리티를 갖춘 프로덕션급 애플리케이션을 얻을 수 있답니다.

코드 뜯어보기

전체 소스는 GitHub에 있고, 여기서는 핵심 구현을 단계별로 살펴볼게요.

모델과 GPU 설정 정의하기. 이 예제는 meta-llama/Meta-Llama-3.1-8B-Instruct를 쓰는데, Hugging Face 접근 권한이 필요해요. 다른 LLM으로 바꾸고 싶다면 BentoVLLM 리포지토리나 vLLM이 지원하는 다른 모델을 사용하면 돼요. 설정은 템플릿 인자(template arguments)로 정의하는데, bentoml.use_arguments(BentoArgs)로 검증된 파라미터를 serve/build/deploy 시점에 동적으로 넘길 수 있어요.

import pydantic
import bentoml

class BentoArgs(pydantic.BaseModel):
    name: str = 'llama3.1-8b-instruct'
    gpu_type: str = 'nvidia-h100-80gb'
    tp: int = 1  # One GPU here for tensor parallelism
    model_id: str = 'meta-llama/Meta-Llama-3.1-8B-Instruct'

bento_args = bentoml.use_arguments(BentoArgs)

런타임 환경(이미지) 정의하기. Bento의 런타임 환경을 bentoml.images.Image로 정의해요. Bento는 모든 소스 코드, Python 의존성, 모델 참조, 환경 설정을 묶는 통일된 배포 포맷이라, 환경이 달라져도 일관되게 배포할 수 있어요.

image = (
    bentoml.images.Image(python_version='3.12').system_packages('curl', 'git').requirements_file('requirements.txt')
)

Service 정의하기. @bentoml.service 데코레이터로 Service를 정의하고, 모델이 어떻게 서빙될지를 커스터마이즈해요. 타임아웃이나 BentoCloud에서 쓸 GPU 리소스 같은 설정을 넣고, 일부 필드는 위에서 정의한 템플릿 인자를 그대로 참조할 수 있어요.

@bentoml.service(
    name=bento_args.name,
    envs=[
        {'name': 'UV_NO_PROGRESS', 'value': '1'},
        {'name': 'UV_TORCH_BACKEND', 'value': 'cu128'},
    ],
    image=image,
    traffic={'timeout': 300},
    resources={
        'gpu': bento_args.tp,
        'gpu_type': bento_args.gpu_type
    },
)
class LLM:
    ...

모델 로드하기. 클래스 안에서 Hugging Face에서 모델을 불러와 클래스 변수로 정의해요. HuggingFaceModel은 모델 배포를 가속하고 이미지 빌드 시간과 콜드 스타트를 줄여 주는 효율적인 로딩 메커니즘이에요.

class LLM:
    hf_model = bentoml.models.HuggingFaceModel(bento_args.model_id, exclude=[".pth", ".pt", "original/**/*"])

서빙 명령 구성하기. Service가 vLLM의 내장 HTTP 서버를 실행하게 하고, OpenAI 호환 엔드포인트를 노출해요. __command__ 메서드에서 vllm serve를 실행하고 추가 CLI 인자를 넣을 수 있어요.

class LLM:
    def __command__(self) -> list[str]:
        return [
            'vllm', 'serve', self.hf_model,
            '--served-model-name', bento_args.model_id,
        ]

이 정도면 기본 구성은 끝나요. FlashAttention, AMD ROCm 지원, KV 캐시 설정 같은 고급 옵션은 GitHub의 전체 소스를 참고하면 되고, BentoML은 사용 사례에 맞춰 추론 코드를 자유롭게 커스터마이즈할 수 있답니다.

실행해 보기

BentoCloud에 배포하기

BentoCloud는 BentoML을 클라우드에서 빠르게 확장할 수 있는 인프라를 제공해요. 먼저 BentoML을 설치하고 CLI로 로그인해요.

pip install bentoml
bentoml cloud login

그 다음 BentoVLLM 리포지토리를 클론하고 프로젝트를 배포해요. Hugging Face 토큰 같은 환경 변수는 BentoCloud secret으로 저장해 두는 걸 추천해요.

git clone https://github.com/bentoml/BentoVLLM.git
cd BentoVLLM/llama3.1-8b-instruct
bentoml secret create huggingface HF_TOKEN=<your-api-key>
bentoml deploy --secret huggingface

배포가 뜨면 OpenAI 클라이언트의 base_url을 BentoML 서버 주소로 설정해 엔드포인트를 호출할 수 있어요.

from openai import OpenAI

client = OpenAI(base_url='https://llama-3-1-8-b-instruct-ckng-d3767914.mt-guc1.bentoml.ai/v1', api_key='na')

chat_completion = client.chat.completions.create(
    model="meta-llama/Meta-Llama-3.1-8B-Instruct",
    messages=[{"role": "user", "content": "Who are you? Please respond in pirate speak!"}],
    stream=True,
)
for chunk in chat_completion:
    print(chunk.choices[0].delta.content or "", end="")

BentoCloud에 보호된 엔드포인트로 배포했다면, 먼저 OPENAI_API_KEY 환경 변수에 BentoCloud API 키를 설정해야 해요. 또 배포가 특정 레플리카 범위 안에서 자동 스케일링되게 하려면 스케일링 플래그를 추가하면 돼요.

bentoml deploy --secret huggingface --scaling-min 0 --scaling-max 3

이미 배포된 경우에는 bentoml deployment update <deployment-name> --scaling-min 0 --scaling-max 3처럼 레플리카 범위를 갱신할 수 있어요.

로컬에서 서빙하기

로컬에서도 코드를 빠르게 검증할 수 있어요. 리포지토리를 클론하고 프로젝트 디렉터리로 이동한 뒤, 의존성을 설치하고 HF_TOKEN을 export 해요.

git clone https://github.com/bentoml/BentoVLLM.git
cd BentoVLLM/llama3.1-8b-instruct
pip install -r requirements.txt
export HF_TOKEN=<your-hf-token>

그다음 로컬에서 서빙하면 돼요.

bentoml serve

그러면 기본 base URL인 http://localhost:3000/v1에서 OpenAI 호환 엔드포인트를 호출할 수 있어요. 참고로 Llama 3.1 8B Instruct를 로컬에서 돌리려면 최소 16G VRAM의 NVIDIA GPU가 필요해요. 자체 인프라에 커스텀 배포하려면 BentoML로 OCI 호환 이미지를 생성하면 됩니다.

더 알아보기

  • vLLM의 OpenAI API 레퍼런스
  • 동시성·자동 스케일링 구성 방법
  • BentoML로 더 다양한 LLM 서빙하기