콘텐츠로 이동

Gemma-4-31B(버케팅)

개요

이 튜토리얼은 optimum-rbln의 기본 사용법에 이미 익숙한 사용자를 대상으로 합니다. 먼저 dense 구조의 Gemma4 모델(google/gemma-4-31B-it), 즉 Vision-Language Model(VLM)을 Rebel100™(RBLN-CR13) NPU 1개에서 컴파일하고 실행한 다음, 같은 예제에 버케팅(bucketing)을 적용하는 방법을 설명합니다.

버케팅은 미리 정의한 여러 입력 형태(shape)를 지원하는 단일 모델을 컴파일하는 기능으로, 크기별로 별도의 모델을 만들지 않고도 하나의 런타임이 다양한 크기의 입력을 처리하고 추론 시 형태를 자동으로 전환합니다. 특히 VLM에서 유용합니다. 이 튜토리얼은 Gemma4에 특화된 설정만 다루며, 일반적인 개념과 트레이드오프는 Bucketing 일반 가이드에서 확인할 수 있습니다.

Rebel100™에서 서빙하기

Rebel100™에서는 Gemma4와 같은 모델의 서빙에 RBLN vLLM(vllm serve)를 기본으로 사용하는 것을 권장합니다. 모델 컴파일과 OpenAI 호환 API 서빙을 한 번에 처리합니다. 자세한 내용은 gemma-4-31B-it 레시피에서 확인할 수 있습니다. 이 튜토리얼은 optimum-rbln Python API를 다루며, 컴파일을 확인하거나 추론을 직접 실행할 때 유용합니다.

Note

Rebel100™은 RSD를 지원하지 않으며(버전 매트릭스 참고), Model Zoo의 모든 Rebel100™ 예제가 NPU 1개용으로 컴파일하므로 이 튜토리얼에서도 언어 모델과 비전 인코더 모두 num_devices를 1로 설정합니다.

Note

HuggingFace hub에 게시된 Gemma4 모델은 Google의 Gemma 라이선스에 따라 접근 권한이 제한되어 있습니다. 다운로드하려면 먼저 라이선스에 동의하고 인증을 완료해야 합니다.

환경 설정 및 설치 확인

시작하기 전에 시스템 환경이 올바르게 구성되어 있고 필요한 패키지가 모두 설치되어 있는지 확인합니다. 필요한 항목은 다음과 같습니다:

Note

  • rebel-compiler를 사용하려면 RBLN 포털 계정이 필요합니다.
  • 앞의 명령은 Debian 계열 Linux(예: Ubuntu)에서 pip로 패키지를 설치하는 일반적인 절차를 전제로 합니다. OS나 환경이 다른 경우에는 설치 가이드에서 지원되는 설치 조합과 적용 가능한 명령을 확인할 수 있습니다.

Note

HuggingFace의 google/gemma-4-31B-it 모델은 접근이 제한되어 있습니다. 접근 권한을 부여받은 후, 다음과 같이 hf (huggingface-cli) 명령어로 로그인할 수 있습니다:

$ hf auth login

    _|    _|  _|    _|    _|_|_|    _|_|_|  _|_|_|  _|      _|    _|_|_|      _|_|_|_|    _|_|      _|_|_|  _|_|_|_|
    _|    _|  _|    _|  _|        _|          _|    _|_|    _|  _|            _|        _|    _|  _|        _|
    _|_|_|_|  _|    _|  _|  _|_|  _|  _|_|    _|    _|  _|  _|  _|  _|_|      _|_|_|    _|_|_|_|  _|        _|_|_|
    _|    _|  _|    _|  _|    _|  _|    _|    _|    _|    _|_|  _|    _|      _|        _|    _|  _|        _|
    _|    _|    _|_|      _|_|_|    _|_|_|  _|_|_|  _|      _|    _|_|_|      _|        _|    _|    _|_|_|  _|_|_|_|

    To login, `huggingface_hub` requires a token generated from [https://huggingface.co/settings/tokens](https://huggingface.co/settings/tokens) .
Enter your token (input will not be visible):

RBLN Optimum 사용하기

이 섹션에서는 google/gemma-4-31B-it 모델을 컴파일하고, 컴파일된 모델을 불러온 뒤 이미지-텍스트 추론을 실행합니다(아직 버케팅은 적용하지 않습니다). Gemma4는 최상위 RBLNGemma4ForConditionalGeneration이 vision_tower(이미지 인코더)와 language_model(causal LM) 두 개의 submodule을 감싸는 VLM이며, 각 submodule은 rbln_config에서 개별적으로 설정합니다.

모델 컴파일

먼저, optimum-rbln에서 RBLNGemma4ForConditionalGeneration 클래스를 가져옵니다. 이 클래스의 from_pretrained() 메서드는 HuggingFace 허브에서 Gemma4 모델을 다운로드하고 RBLN Compiler를 사용하여 컴파일합니다. 모델을 익스포트할 때 export=True로 설정하고 rbln_config를 지정하며, 여기서 배치 크기, 각 submodule의 디바이스 수(Rebel100™에서는 1), 언어 모델의 컨텍스트 길이를 설정합니다. 언어 모델은 flash attention을 사용하며 max_seq_len은 262_144, kvcache_partition_len은 8_192입니다. Rebel100™에서 kvcache_partition_len은 1_024 이상 16_384 이하여야 하며, max_seq_len은 그 배수이면서 2배 이상이어야 합니다. 컴파일 후에는 save_pretrained() 메서드를 사용하여 모델 아티팩트를 디스크에 저장합니다. 이 과정은 컴파일된 모델을 포함하는 디렉터리(예: gemma-4-31B-it)를 생성합니다.

from optimum.rbln import RBLNGemma4ForConditionalGeneration

# Define the HuggingFace model ID
model_id = "google/gemma-4-31B-it"

# Compile the model for a single Rebel100™ NPU
model = RBLNGemma4ForConditionalGeneration.from_pretrained(
    model_id=model_id,
    export=True,
    rbln_config={
        "batch_size": 1,
        "language_model": {
            "num_devices": 1,
            "max_seq_len": 262_144,
            "kvcache_partition_len": 8_192,
            "prefill_chunk_size": 128,
            "attn_impl": "flash_attn",
        },
        "vision_tower": {
            "num_devices": 1,
        },
    },
)

model.save_pretrained("gemma-4-31B-it")

모델 추론

컴파일된 모델을 NPU 0에 불러오고(rbln_device=0), 이미지와 텍스트 프롬프트를 담은 채팅 메시지를 구성한 뒤 응답을 생성합니다. apply_chat_template()은 모델 입력용 텐서를 반환하며, 새로 생성된 토큰만 디코딩합니다.

from optimum.rbln import RBLNGemma4ForConditionalGeneration
from transformers import AutoProcessor

# Load the compiled model
model = RBLNGemma4ForConditionalGeneration.from_pretrained(
    model_id="gemma-4-31B-it",
    export=False,
    rbln_device=0,
)

# Build a chat message with an image and a text prompt
processor = AutoProcessor.from_pretrained("google/gemma-4-31B-it")
messages = [
    {
        "role": "user",
        "content": [
            {"type": "image", "url": "https://raw.githubusercontent.com/google-gemma/cookbook/refs/heads/main/apps/sample-data/GoldenGate.png"},
            {"type": "text", "text": "What is shown in this image?"},
        ],
    }
]
inputs = processor.apply_chat_template(
    messages,
    tokenize=True,
    return_dict=True,
    return_tensors="pt",
    add_generation_prompt=True,
)
input_len = inputs["input_ids"].shape[-1]

# Generate and decode only the newly generated tokens
outputs = model.generate(**inputs, max_new_tokens=512)
response = processor.decode(outputs[0][input_len:], skip_special_tokens=False)
print(processor.parse_response(response, prefix=inputs["input_ids"][0][:input_len])['content'])

예시 출력:

This image shows the Golden Gate Bridge in San Francisco, California. The bridge's iconic international orange suspension structure is the central focus, spanning across the water. In the foreground, a portion of Fort Point is visible on the left, and a small rocky outcrop with a bird on it sits in the water. Mountains can be seen in the background under a clear blue sky.

버케팅 적용하기

Gemma4의 이미지 프로세서는 각 이미지를 정해진 개수의 이미지 토큰으로 압축합니다. 이 개수는 사용자가 선택하는 max_soft_tokens 값(70, 140, 280, 560, 1120 중 하나)이며, 모델은 이 값 하나에 맞춰 컴파일됩니다. 이렇게 컴파일된 단위를 버킷이라고 합니다. 단일 버킷으로 컴파일하면 모든 이미지가 그 값에 고정되어, 재컴파일 없이는 단순한 이미지에 더 적은 토큰을 쓰거나 디테일이 많은 이미지에 더 많은 토큰을 쓸 수 없습니다. 버케팅은 여러 버킷을 함께 컴파일하여 하나의 모델에서 이미지별로 max_soft_tokens 값을 선택할 수 있게 합니다.

버케팅은 서로 연결된 두 submodule에 적용됩니다. vision_tower는 선택한 max_soft_tokens 값에 맞춰지고, language_model은 그 이미지 토큰을 프리필하는 별도의 양방향(bidirectional) 그래프의 크기를 정합니다(image_prefill_chunk_size, causal 텍스트 prefill_chunk_size와는 별개이며 각 이미지나 비디오 프레임이 한 번의 프리필로 처리됩니다). 선택한 값이 LM 프리필로 전달되므로 optimum-rbln은 컴파일 시점에 LM 버킷을 비전 버킷에 맞춰 도출하고 검증합니다. 따라서 두 축 모두 rbln_config에서 submodule별로 설정합니다.

필드 submodule 허용 값 효과
max_soft_tokens vision_tower {70, 140, 280, 560, 1120} 중에서 선택한 List[int] 비전 인코더의 이미지 토큰 개수 버킷. 프로세서의 max_soft_tokens가 이미지당 개수를 정하며, 컴파일된 값 중 하나와 일치해야 합니다.
image_prefill_chunk_size language_model 각 값이 128의 배수인 List[int] LM의 이미지 프리필(prefill) 청크 크기 버킷. 런타임에는 해당 이미지에 사용된 max_soft_tokens 이상인 값 중 가장 작은 버킷이 자동으로 선택되므로, 가장 큰 값은 가장 큰 max_soft_tokens 이상이어야 합니다.

버킷 설정

앞의 기본 컴파일 코드에서 max_soft_tokens(vision_tower)와 image_prefill_chunk_size(language_model)를 리스트로 전달하면 해당 버킷이 함께 컴파일됩니다. 다음은 전체 컴파일 코드이며, 추가된 버케팅 줄을 +로 표시했습니다. 기본 컴파일이 사용하는 280의 경우 버케팅을 적용해도 같은 연산을 수행합니다. 버케팅은 같은 가중치로 여러 버킷을 미리 컴파일해 둘 뿐 연산 자체를 바꾸지 않기 때문입니다. 다만 Gemma 4의 generation_config가 샘플링(do_sample=True, top_k=64, top_p=0.95)을 사용하므로, 생성되는 문장은 실행할 때마다 달라질 수 있습니다. 버케팅을 사용하면 이미지마다 max_soft_tokens 값을 선택할 수 있습니다. 즉, max_soft_tokens를 작게 지정하면 토큰과 연산을 적게 쓰고, 크게 지정하면 더 많은 디테일을 유지합니다. 이는 단일 버킷으로 컴파일한 기본 설정으로는 재컴파일 없이 불가능합니다.

Caution

버킷이 많을수록 컴파일 시간이 길어지고 디바이스 메모리 사용량이 늘어납니다. 워크로드에 필요한 max_soft_tokens 값에 맞춰 버킷을 선택하는 것을 권장합니다. 일반적으로 2~4개면 충분합니다.

Note

max_soft_tokens에는 Gemma4 이미지 프로세서가 지원하는 값(70, 140, 280, 560, 1120)만 사용해야 합니다. optimum-rbln은 이 값 자체는 검사하지 않습니다. 대신 컴파일 시점에 image_prefill_chunk_size를 max_soft_tokens에 대해 검증합니다. 각 값은 128의 양의 배수여야 하고, 가장 큰 값은 가장 큰 max_soft_tokens 이상이어야 하며, 각 값은 적어도 하나의 max_soft_tokens에 대해 그 이상인 가장 작은 버킷이어야 합니다(어떤 이미지도 사용하지 않는 버킷이 있으면 검증에 실패합니다). 따라서 두 축을 반드시 맞춰야 합니다:

  • image_prefill_chunk_size를 지정하지 않으면 max_soft_tokens 값마다 버킷이 하나씩 자동으로 도출됩니다(각 값을 128의 배수로 올림하며, 아래 값의 경우 [128, 256, 384, 640, 1152]).
  • 가장 큰 max_soft_tokens보다 작은 단일 값을 지정하면 컴파일에 실패합니다.
  • 큰 단일 값 하나만 지정하면 모든 이미지가 그 크기로 프리필되어 작은 이미지에서 연산이 낭비됩니다.

아래 예제의 [384, 640, 1152]는 70, 140, 280을 384로, 560을 640으로, 1120을 1152로 처리하므로 모든 버킷이 사용됩니다.

추론 시에는 프로세서의 max_soft_tokens를 컴파일된 버킷 중 하나로 지정하면 되며(예: AutoProcessor.from_pretrained(model_id, max_soft_tokens=560)), 이에 맞는 image_prefill_chunk_size는 해당 값 이상인 가장 작은 버킷으로 자동 선택됩니다.

 from optimum.rbln import RBLNGemma4ForConditionalGeneration

 # Define the HuggingFace model ID
 model_id = "google/gemma-4-31B-it"

 # Compile the model for a single Rebel100™ NPU
 model = RBLNGemma4ForConditionalGeneration.from_pretrained(
     model_id=model_id,
     export=True,
     rbln_config={
         "batch_size": 1,
         "language_model": {
             "num_devices": 1,
             "max_seq_len": 262_144,
             "kvcache_partition_len": 8_192,
             "prefill_chunk_size": 128,
             "attn_impl": "flash_attn",
+            "image_prefill_chunk_size": [384, 640, 1152],
         },
         "vision_tower": {
             "num_devices": 1,
+            "max_soft_tokens": [70, 140, 280, 560, 1120],
         },
     },
 )

 model.save_pretrained("gemma-4-31B-it")

버킷 선택

추론 시에는 프로세서에 max_soft_tokens를 설정하여 컴파일된 버킷을 선택하며, 앞의 baseline 추론에서 이 부분만 달라집니다. 값이 작으면(70) 이미지당 토큰을 가장 적게 사용하여 처리량이 가장 높고 지연이 가장 낮지만, 디테일이 가장 거칠어 단순하거나 정보량이 적은 이미지에 적합합니다. 값이 크면(1120) 디테일을 최대한 보존하여 문서나 미세한 질감처럼 디테일이 많은 이미지에 적합하지만, 연산과 메모리를 가장 많이 사용합니다. 컴파일된 버킷이면 무엇이든 사용할 수 있으며, baseline의 model과 messages를 재사용합니다.

# Select any compiled bucket via the processor (70, 140, 280, 560, 1120);
# the rest is the baseline inference flow, reusing `model` and `messages`.
processor = AutoProcessor.from_pretrained(
    "google/gemma-4-31B-it",
    max_soft_tokens=70,
)

inputs = processor.apply_chat_template(
    messages,
    tokenize=True,
    return_dict=True,
    return_tensors="pt",
    add_generation_prompt=True,
)
input_len = inputs["input_ids"].shape[-1]

outputs = model.generate(**inputs, max_new_tokens=512)
response = processor.decode(outputs[0][input_len:], skip_special_tokens=False)
print(processor.parse_response(response, prefix=inputs["input_ids"][0][:input_len])['content'])

예시 출력:

1
2
3
4
5
6
7
max_soft_tokens=70:
The image shows the Golden Gate Bridge in San Francisco, California. The red suspension bridge spans across the water, with one of its large towers and a portion of the roadway visible. To the left, there is a brick building and a shoreline. In the foreground, a small rock with a bird on it sits in the water.

max_soft_tokens=1120:
This image shows the Golden Gate Bridge in San Francisco, California. The iconic orange-red suspension bridge spans across the water, connecting the city to Marin County.

In the foreground, there is a rocky shoreline with Fort Point, a historic masonry fortification, situated directly beneath the bridge's southern end. A small rock with a bird perched on it is visible in the water, and hills can be seen in the background under a clear blue sky.

참고