ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • LLM 서빙하기 (2) - Triton Inference Server로 LLM 서빙하기 (HuggingFace 모델을 Triton으로 배포하는 방법)
    AI/NLP 2025. 4. 5. 20:03
    728x90

     

     

    LLM 서빙하기 (2) - Triton Inference Server로 LLM 서빙하기
     (HuggingFace 모델을 Triton으로 배포하는 방법)

     

     

     

     

     

     

     

    아래에선 HuggingFace 모델을 Triton으로 배포하는 방법을 배워보자

     

    https://github.com/triton-inference-server/tutorials/tree/main/HuggingFace

     

     

     


     

     

    Triton에 HuggingFace 모델 배포하는 2가지 방법:


    방법 1: Python Backend 사용 (전체 파이프라인 통째로 배포)

    빠르고 간단하게 배포하고 싶을 때 사용

    • Python 코드 안에 전처리 → 모델 추론 → 후처리 모두 포함
    • model.py에서 TritonPythonModel 클래스를 만들고,
      • initialize()에서 모델 로딩
      • execute()에서 추론 실행
      • finalize()는 선택
    • 서버에서 tritonserver --model-repository=/models로 실행
    • 클라이언트는 Python SDK로 추론 요청

    🟢 장점:

    • 설정 간단, 빠르게 실행 가능
    • HuggingFace 모델 그대로 사용 가능

    🔴 단점:

    • 모든 단계가 CPU에서 실행될 수도 있음
    • 추론 성능 최적화가 어려움

    방법 2: Triton Ensemble 사용 (전처리/모델/후처리 분리)

    성능 최적화와 확장성을 원할 때 사용

    • 파이프라인을 구성 요소별로 분리:
      • 전처리: Python Backend (예: feature extractor)
      • 모델: ONNX, TensorRT 등 고성능 backend
      • 후처리: 필요 시 Python Backend
    • 각 구성 요소를 Triton의 Ensemble 기능으로 연결
      • BLS: preprocessing - tensorrt_llm - postprocessing을 하나의 chain으로 구성
        • preprocessing: 전처리
        • tensorrt_llm: LLM 모델 (우리는 TensorRT-LLM을 통해 LLM 속 연산들을 최적화할 것임)
        • postprocessing: 후처리
    • 모델 저장 구조 예:

     

     
    model_repository/
    ├── ensemble_model/
    │   └── config.pbtxt
    ├── preprocessing/
    │   ├── 1/model.py
    │   └── config.pbtxt
    └── vit/
        ├── 1/model.onnx
        └── config.pbtxt

     

    🟢 장점:

    • **모델 추론을 GPU + 고성능 백엔드(TensorRT, ONNX)**에서 실행 가능
    • 병렬화 및 파이프라인 최적화 용이

    🔴 단점:

    • 설정이 조금 복잡하고 구성요소가 더 많음

     

    방법 1 Python Backend로 전체 파이프라인 배포 (빠르고 유연함)
    방법 2 Ensemble로 전처리/모델/후처리 분리 (최적화에 유리)
    추천 개발 초기엔 방법 1 → 서비스 단계에선 방법 2로 전환

     

     


     

     

    2번 방법에 대해서 더 알아보자 

     

     

    Triton Inference Server의 Ensemble 기능을 사용하여 HuggingFace 모델 중 ViT을 배포하는 방법을 단계별로 살펴본다 

     

     

    ✅ 전체 과정 요약: Triton Ensemble 배포 흐름

    1. HuggingFace 모델 다운로드 및 ONNX 변환
    2. Triton 모델 저장소(모델 리포지토리) 구조 구성
    3. Triton Python Backend를 이용한 전처리
    4. ONNX Runtime으로 모델 추론
    5. Ensemble로 위 두 단계를 연결
    6. Triton Server 실행 & 클라이언트 요청

    🧩 1. 모델 다운로드 및 ONNX 변환

    docker run -it --gpus=all -v ${PWD}:/workspace nvcr.io/nvidia/pytorch:23.05-py3

     

    • PyTorch NGC 컨테이너 실행
    • GPU 사용 가능하고, PyTorch 환경이 사전 설정됨
     
    pip install transformers
    pip install transformers[onnx]

     

    • HuggingFace Transformers 라이브러리 설치
    • ONNX 변환 기능도 함께 설치
    python -m transformers.onnx --model=google/vit-base-patch16-224 --atol=1e-3 onnx/vit

     

     

    • ViT 모델을 ONNX 형식으로 변환 (onnx/vit/model.onnx 생성됨)
    • --atol=1e-3은 변환 시 허용 오차

     

    🧩 2. Triton 모델 저장소 구조

    model_repository/
    ├── ensemble_model/            ← Ensemble 전체를 정의
    │   ├── 1/
    │   └── config.pbtxt           ← 연결 정보 작성
    ├── preprocessing/             ← 전처리: Python backend
    │   ├── 1/model.py
    │   └── config.pbtxt
    └── vit/                       ← ONNX 추론 모델
        ├── 1/model.onnx
        └── config.pbtxt (auto-generated 가능)

     

     

    🧩 3. 전처리: Python Backend

     

    model_repository/preprocessing/1/model.py

    from transformers import ViTFeatureExtractor
    import triton_python_backend_utils as pb_utils
    
    class TritonPythonModel:
    
        def initialize(self, args):
            # 모델/리소스 로딩
            pass
    
        def execute(self, requests):
            # 매 요청마다 실행 (추론 수행)
            pass
    
        def finalize(self):
            # 모델 종료 시 실행
            pass

     

     

    Triton에서 Python Backend를 쓸 경우, 모델 코드를 직접 Python으로 작성해야 하고, TritonPythonModel 클래스를 정의한 뒤 다음 함수들을 구현합니다.

     

    ✅ 1. initialize(self, args)

    Triton이 모델을 처음 로딩할 때 1번만 실행

    🔹 역할:

    • 모델이나 관련 객체를 초기화할 때 사용
    • 예: HuggingFace 모델, 토크나이저, 설정값 등 로딩

    🔹 코드 예시:

     
    def initialize(self, args):
        self.feature_extractor = ViTFeatureExtractor.from_pretrained('google/vit-base-patch16-224-in21k')
        self.model = ViTModel.from_pretrained("google/vit-base-patch16-224-in21k")

     

    ✅ 요약:

    • Triton이 처음 시작할 때 모델 메모리에 올려두는 함수
    • **선택적(optional)**이지만 대부분 정의하는 것이 좋음

     

    ✅ 2. execute(self, requests)

    클라이언트가 요청을 보낼 때마다 매번 실행됨

    🔹 역할:

    • 실제 추론 로직을 수행하는 함수
    • 입력 → 전처리 → 추론 → 출력 변환 → 응답

    🔹 코드 예시:

     

    def execute(self, requests):
        responses = []
        for request in requests:
            # 입력 텐서 받기
            inp = pb_utils.get_input_tensor_by_name(request, "image")
            input_image = np.squeeze(inp.as_numpy()).transpose((2,0,1))
    
            # 전처리
            inputs = self.feature_extractor(images=input_image, return_tensors="pt")
    
            # 추론
            outputs = self.model(**inputs)
    
            # 결과 반환
            inference_response = pb_utils.InferenceResponse(output_tensors=[
                pb_utils.Tensor("label", outputs.last_hidden_state.numpy())
            ])
            responses.append(inference_response)
        return responses

     

    ✅ 요약:

    • 실제 추론이 수행되는 메인 함수
    • 여러 요청을 한 번에 받을 수 있으므로 for request in requests 사용
    • pb_utils를 통해 Triton과 데이터 교환

     

    ✅ 3. finalize(self)

    Triton이 모델을 **종료(unload)**할 때 실행

    🔹 역할:

    • 메모리 해제, 로그 저장, 정리 작업 등
    • 사용하지 않아도 무방하지만 리소스 정리가 필요하면 정의

    ✅ 요약:

    • 리소스 반환 용
    • 선택적(optional)

     

     

     

     

    🧩 4. 모델 추론: ONNX Backend

    • vit/1/model.onnx는 ONNXRuntime backend가 자동 인식
    • config.pbtxt는 자동 생성되지만, 명시하고 싶으면 수동으로 작성 가능

     

     

    🧩 5. Ensemble 구성

    ensemble_model/config.pbtxt 예: (protobuf 형식)

     

    name: "ensemble_model"
    platform: "ensemble"
    input [
      {
        name: "INPUT_IMAGE"
        data_type: TYPE_UINT8
        dims: [3, 224, 224]
      }
    ]
    output [
      {
        name: "OUTPUT_LABEL"
        data_type: TYPE_FP32
        dims: [768]
      }
    ]
    ensemble_scheduling {
      step [
        {
          model_name: "preprocessing"
          model_version: -1
          input_map { key: "image" value: "INPUT_IMAGE" }
          output_map { key: "features" value: "EXTRACTED_FEATURES" }
        },
        {
          model_name: "vit"
          model_version: -1
          input_map { key: "pixel_values" value: "EXTRACTED_FEATURES" }
          output_map { key: "last_hidden_state" value: "OUTPUT_LABEL" }
        }
      ]
    }

     

     

    • ensemble_scheduling 안에서 각 모델 연결
    • 입력/출력을 매핑해서 파이프라인 구성

     

     

    🖥️ Terminal 실행

    🔹 Terminal 1: Triton Server

     

    # 모델 디렉토리 구성
    mv ensemble_model_repository model_repository
    mkdir -p model_repository/vit/1
    mv vit/model.onnx model_repository/vit/1/
    mkdir model_repository/ensemble_model/1
    
    
    
    # Triton 컨테이너 실행 (예: 23.05 버전)
    docker run --gpus=all -it --shm-size=256m --rm \
      -p8000:8000 -p8001:8001 -p8002:8002 \
      -v ${PWD}:/workspace/ \
      -v ${PWD}/model_repository:/models \
      nvcr.io/nvidia/tritonserver:23.05-py3 bash
      
      
      # 의존성 설치
    pip install torch torchvision torchaudio transformers Image
    
    # Triton 서버 실행
    tritonserver --model-repository=/models

     

    🔹 Terminal 2: Triton Client

     
    docker run -it --net=host -v ${PWD}:/workspace/ \
      nvcr.io/nvidia/tritonserver:23.05-py3-sdk bash
    
    python3 client.py --model_name "ensemble_model"

     

     

    • client.py는 HTTP/gRPC를 통해 ensemble_model에 요청을 보냄
    • 입력 이미지 전처리 → ONNX 모델 추론 → 결과 반환

     

     

     


     

     

     

    위 방법은 Python Backend로 LLM을 서빙하는 것이기 때문에

    TensorRT-LLM이나 vLLM를 Backend로 사용하는 것보다는 당연히 느릴 수 밖에 없다 

     

     

    TensorRT-LLM이나 vLLM를 Backend로 사용하는 것이 궁금하다면 아래의 repo를 봐보자 

    우리 회사는 TensorRT-LLM + Triton 조합으로 쓰는데,

    TensorRT-LLM에서 지원하지 않는 모델이 있다면 vLLM에서 지원하는지 확인해보고 사용하는 것도 좋을 듯하다 

     

     

     

     

     

     

    https://github.com/triton-inference-server/tensorrtllm_backend

     

    GitHub - triton-inference-server/tensorrtllm_backend: The Triton TensorRT-LLM Backend

    The Triton TensorRT-LLM Backend. Contribute to triton-inference-server/tensorrtllm_backend development by creating an account on GitHub.

    github.com

     

    https://github.com/triton-inference-server/vllm_backend

     

    GitHub - triton-inference-server/vllm_backend

    Contribute to triton-inference-server/vllm_backend development by creating an account on GitHub.

    github.com

     

     

     

    728x90
Designed by Tistory.