로짓 프로세서

로짓 프로세서 (Logits Processors)

!!! important 일부 로짓 프로세서 설계 변경이 아직 진행 중이고, API가 가까운 미래에 바뀔 수 있어요. 이 부분 API는 곧 안정화되길 바라고 있어요.

이 문서는 vLLM 엔진이 로짓 프로세서와 어떻게 상호작용하는지, 그리고 vLLM이 로짓 프로세서 구현을 위해 지원하는 프로그래밍 모델을 설명해요.

로짓 프로세서 배경

로짓 프로세서(logits processor)는 다음 토큰 확률 분포를 조정해서, 보통 모델을 원하는 종류의 동작으로 이끄는 데 써요.

vLLM에서 로짓 프로세서는 배치 단위(batch granularity) 로 동작해요. 주어진 엔진 스텝 동안 로짓 프로세서는 모델이 출력한 (num_requests) x (vocab_size) 텐서의 raw 로짓을 소비해요. 로짓 프로세서를 활성화한 모든 요청에 대해, 로짓 프로세서는 로짓 텐서의 해당 행에 변환을 적용하고 나머지 행은 그대로 둬요. 변환된 로짓 텐서는 그다음 softmax로 전달돼요.

vLLM 엔진에서의 로짓 프로세서

vLLM 엔진의 영속 배치(persistent batch) 데이터 구조는 로드된 로짓 프로세서 목록을 유지해요.

전체 배치를 한 번에 연산하기 위해 각 로짓 프로세서는 배치 내 요청에 대한 메타데이터(각 요청의 로짓 프로세서별 설정값)를 유지할 수 있어요. 그래서 로짓 프로세서는 상태를 가집니다(stateful).

각 엔진 스텝에서 vLLM 엔진은 (1) 각 로짓 프로세서의 내부 상태를 갱신하고 (2) 로짓 프로세서를 모델 출력 로짓에 적용해요.

로짓 프로세서 내부 상태 갱신

각 엔진 스텝 시작에서 영속 배치는 스케줄러 출력에 따라 요청을 추가·제거·재정렬할 수 있어요. 영속 배치가 재구성된 뒤, vLLM 엔진은 각 로짓 프로세서의 update_state() 메서드를 호출해요. 이는 로짓 프로세서의 내부 상태가 엔진 스텝 시작 시 새 영속 배치 상태와 일치하도록 재구성되게 하기 위해 필요한 작업이에요.

아래 의사코드는 vLLM 영속 배치가 각 로짓 프로세서에 배치 상태 변경을 알리는 과정을 보여줘요.

# gpu_model_runner.py

class GPUModelRunner(...):

    ...

    def execute_model(self, scheduler_output, ...):
        self._update_states(scheduler_output)

        ...

    def _update_states(...):

        ...

        # ...update persistent batch to reflect new/finished requests & reordering
        # of requests within batch...

        ...

        self.input_batch.refresh_metadata()


# gpu_input_batch.py

class InputBatch:

    ...

    def refresh_metadata(self):

        ...

        # Update each logits processor's state to reflect persistent batch state
        batch_update = self.batch_update_builder.get_and_reset(self.num_reqs)
        for logit_proc in self.logitsprocs.all:
            logit_proc.update_state(batch_update)

        ...


# vllm/v1/sample/logits_processor/interface.py

@dataclass(frozen=True)
class BatchUpdate:
    # Batch state-change data structure which is passed to logits processors'
    # update_state() methods

    batch_size: int

    removed: Sequence[RemovedRequest]
    added: Sequence[AddedRequest]
    moved: Sequence[MovedRequest]

로짓 프로세서를 모델 출력 로짓에 적용

영속 배치 상태를 갱신한 뒤, vLLM 모델 러너는 모델 추론을 수행해 로짓을 얻어요. 그다음 모델 러너는 로짓에 대해 샘플러를 호출해요. 샘플러 동작의 일부로 모델 출력 로짓 프로세서에 대해 로짓 프로세서의 apply() 메서드를 호출해 변환된 로짓을 만들죠(apply() 메서드는 로짓을 in-place 또는 out-of-place로 수정할 수 있는데, in-place가 메모리 효율이 더 좋아요). 이 과정을 의사코드로 보면 이렇게 돼요.

샘플러는 SamplingMetadata.logitsprocs를 통해 로짓 프로세서에 접근해요. vLLM 엔진이 SamplingMetadata를 만들 때, 로짓 프로세서 목록에 대한 참조가 영속 배치 데이터 구조에서 SamplingMetadata로 전달돼요.

# gpu_model_runner.py

class GPUModelRunner(...):

    ...

    def execute_model(self, scheduler_output, ...):
        # (discussed in previous section)
        self._update_states(scheduler_output)

        ...

        # ...run model inference to obtain logits...

        ...

        # Invoke sampler, which applies logits processors
        sampler_output = self.sampler(logits=logits,
                                      sampling_metadata=sampling_metadata)

        ...


# sampler.py

class Sampler(nn.Module):

    ...

    def forward(self, logits, sampling_metadata):

        ...

        # Apply non-argmax-invariant logits processors to model output logits
        for processor in (sampling_metadata.logitsprocs.non_argmax_invariant):
            logits = processor.apply(logits)

        sampled = self.sample(logits, sampling_metadata)

        ...

        # ...return sampler output data structure...


    def sample(self, logits, sampling_metadata)

        ...

        # ...exit early if all requests are greedy-sampling...

        ...

        # Apply argmax-invariant logits processors
        for processor in sampling_metadata.logitsprocs.argmax_invariant:
            logits = processor.apply(logits)

        ...

        # ...perform sampling and return sampling result...

샘플링 시점에 샘플러는 영속 배치의 모든 요청이 greedy 샘플링을 쓰는지 확인해요. 그렇다면 샘플러는 "argmax 변환 불변(argmax-invariant)" 로짓 프로세서를 건너뛰어 연산을 아껴요. 여기서 "argmax"는 로짓 텐서에서 주어진 행에서 로짓 값이 가장 높은 토큰 ID(즉 특정 요청에 대해 모델이 가장 높게 가중한 토큰)를 뜻해요.

  • argmax 변환 불변 로짓 프로세서는 Min-P처럼 argmax를 바꾸지 않는 로짓 프로세서예요. 예를 들어 가장 낮은 확률 토큰을 마스킹하는 로짓 프로세서는 어떤 토큰 ID가 최대 로짓을 갖는지는 바꾸지 않아요. Greedy 샘플링은 항상 가장 높은 로짓 값 토큰 ID를 고르므로, 개념적으로 argmax 변환 불변 로짓 프로세서는 greedy 샘플링 요청에 대해 건너뛸 수 있어요.

  • argmax 변환 비불변(non-argmax-invariant) 로짓 프로세서는 argmax를 바꿀 수 있는 로짓 프로세서예요. 예를 들어 어떤 스텝 수 이후 디코딩을 강제로 끝내려고 EOS 외의 모든 토큰을 마스킹하는 로짓 프로세서는 최대 로짓 값 토큰을 마스킹해서 argmax를 바꿀 수 있어요. 개념적으로 이런 로짓 프로세서는 greedy 샘플링 요청에서도 건너뛸 수 없어요.

vLLM 로짓 프로세서 추상화는 엔진이 배치 단위로 로짓 프로세서를 적용하도록 요구해요. 그래서 실제로는 전체 배치가 greedy 샘플링을 쓸 때만 argmax 변환 불변 로짓 프로세서를 건너뛸 수 있어요.

로짓 프로세서 프로그래밍 모델

앞 섹션들은 vLLM 로짓 프로세서가 지원해야 할 인터페이스를 암시했어요. 이 섹션에서는 vLLM 엔진과 호환되는 로짓 프로세서를 구현하는 프로그래밍 모델을 완전히 소개할게요. LogitsProcessor 기반 클래스와 그것의 인터페이스 메서드, 그리고 영속 배치 상태 변경을 나타내는 BatchUpdate 데이터 구조가 포함돼요. 둘 다 아래 코드에 나와 있어요.

from abc import ABC, abstractmethod
from collections.abc import Sequence
from dataclasses import dataclass
from enum import Enum, auto
from typing import TYPE_CHECKING

import torch

from vllm import SamplingParams

if TYPE_CHECKING:
    from vllm.config import VllmConfig


class MoveDirectionality(Enum):
    # One-way i1->i2 req move within batch
    UNIDIRECTIONAL = auto()
    # Two-way i1<->i2 req swap within batch
    SWAP = auto()


# (index, params, prompt_tok_ids, output_tok_ids) tuples for new
# requests added to the batch.
AddedRequest = tuple[int, SamplingParams, list[int], list[int]]

# (index 1, index 2, directionality) tuples representing
# one-way moves or two-way swaps of requests in batch
MovedRequest = tuple[int, int, MoveDirectionality]

# Batch indices of any removed requests.
RemovedRequest = int


@dataclass(frozen=True)
class BatchUpdate:
    """Persistent batch state change info for logitsprocs"""
    batch_size: int  # Current num reqs in batch

    # Metadata for requests added to, removed from, and moved
    # within the persistent batch.
    #
    # Key assumption: the `output_tok_ids` list (which is an element of each
    # tuple in `added`) is a reference to the request's running output tokens
    # list; via this reference, the logits processors always see the latest
    # list of generated output tokens
    removed: Sequence[RemovedRequest]
    moved: Sequence[MovedRequest]
    added: Sequence[AddedRequest]


class LogitsProcessor(ABC):

    @abstractmethod
    def __init__(self, vllm_config: "VllmConfig", device: torch.device,
                is_pin_memory: bool) -> None:
        raise NotImplementedError

    @abstractmethod
    def apply(self, logits: torch.Tensor) -> torch.Tensor:
        raise NotImplementedError

    @abstractmethod
    def is_argmax_invariant(self) -> bool:
        """True if logits processor has no impact on the
        argmax computation in greedy sampling.
        NOTE: may or may not have the same value for all
        instances of a given LogitsProcessor subclass,
        depending on subclass implementation.
        """
        raise NotImplementedError

    @abstractmethod
    def update_state(
        self,
        batch_update: "BatchUpdate" | None,
    ) -> None:
        """Called when there are new output tokens, prior
        to each forward pass.

        Args:
            batch_update is non-None iff there have been
            changes to the batch makeup.
        """
        raise NotImplementedError

    @classmethod
    def validate_params(cls, sampling_params: SamplingParams):
        """Validate sampling params for this logits processor.

        Raise ValueError for invalid ones.
        """
        return None

vLLM 로짓 프로세서는 LogitsProcessor를 상속하고 (최소한) 다음 메서드들을 정의해야 해요.

  • __init__(self, vllm_config: VllmConfig, device: torch.device, is_pin_memory: bool)

    • vllm_config: 엔진 구성 데이터 구조
    • device: 하드웨어 가속기 장치 정보
    • is_pin_memory: 로짓 프로세서 구현을 지원하는 pin memory 사용 가능 여부 플래그
  • apply(self, logits: torch.Tensor) -> torch.Tensor

    • (num_requests) x (vocab_size) 로짓 텐서(logits)를 소비
    • 배치 단위로 로짓 프로세서 변환 적용
    • 변환된 (num_requests) x (vocab_size) 로짓 텐서 반환
    • 입력 로짓을 in-place 또는 out-of-place로 수정 가능, in-place가 메모리 효율적
  • is_argmax_invariant(self) -> bool

    • 로짓 프로세서가 argmax 불변(주어진 요청에서 가장 높은 로짓 값 토큰 ID를 절대 바꾸지 않음)이면 True, argmax를 수정할 수 있으면 False 반환
    • is_argmax_invariant()는 시작 시 한 번 평가돼요. True면 vLLM은 모든 요청이 greedy 샘플링을 쓰는 스텝에서 이 로짓 프로세서 적용을 건너뜀
  • update_state(self, batch_update: "BatchUpdate" | None) -> None

    • 현재 엔진 스텝 시작 시 영속 배치 상태 변경을 나타내는 BatchUpdate 데이터 구조를 소비
    • BatchUpdate 멤버를 사용해 로짓 프로세서 내부 상태 갱신
    • 참고: 배치 업데이트 구조가 None일 수 있는데, 이는 배치 구성 요소에 변화가 없음을 뜻해요. 이 경우에도 LogitsProcessor는 추가될 때 보관해 둔 갱신된 output_token_ids 목록을 기반으로 상태를 갱신하고 싶을 수 있어요.
  • validate_params(cls, sampling_params: SamplingParams)

    • SamplingParams에 로짓 프로세서가 쓰는 (특히 커스텀) 잘못된 인자가 있으면 ValueError를 발생
    • 요청이 entrypoint로 보내질 때 validate_params()SamplingParams를 검증하고 잘못된 인자의 요청을 거부

BatchUpdate 데이터 구조

BatchUpdate 추상화는 영속 배치를 요청 목록으로 모델링하고, 배치 상태를 바꾸는 다음 연산을 지원해요(아래 언급 순서는 update_state()에서 처리해야 할 순서를 반영해요).

  • 제거 (Remove): 인덱스 i의 요청을 (대체 없이) 제거

    • Batchupdate.removed에서 int(i)로 표현

    • 배치에 미치는 효과:

      Batch: [A,B,C]
      Remove @ i:  1
      
      =>
      
      New Batch: [A,x,C] # Discard B and leave an empty slot
      
  • 추가 (Add): 인덱스 i에 새 요청을 추가(또는 기존 요청을 대체). 요청을 대체하면 그 상태는 폐기돼야 해요.

    • Batchupdate.added에서 튜플로 표현:

      (index, new request SamplingParams, prompt token ids, output token ids)
      
    • prompt token idsoutput token ids는 각각 요청의 프롬프트 토큰 ID 목록과 출력 토큰 ID 목록에 대한 참조예요. 출력 토큰 ID 목록은 매 엔진 스텝마다 커지고, 출력 토큰 ID가 참조로 전달되므로 이 증가가 로짓 프로세서에 보여요. 지금까지 생성된 토큰을 고려하는 LogitsProcessor에게 이는 중요해요.

    • 특정 로짓 프로세서 서브클래스의 구현이 added 요청 튜플의 필드를 내부 표현으로 어떻게 소화할지 결정해요. 예를 들어 프롬프트나 출력 토큰 ID를 사용하지 않는 로짓 프로세서는 indexSamplingParams만 쓰고 다른 튜플 필드는 버릴 수 있어요.

    • 인덱스 i에 현재 요청이 있으면 대체 발생:

      Batch: [A,B,C]
      New request to be added @ i: D @ 1
      
      =>
      
      New Batch: [A,D,C] # Add D, discard B
      
    • 인덱스 i에 현재 요청이 없으면(i가 현재 배치 크기를 벗어남):

      Batch: [A,B,C]
      New request to be added @ i: D @ 3
      
      =>
      
      New Batch: [A,B,C,D] # Add D, extending batch
      
  • 이동 (Move): 인덱스 s의 요청을 인덱스 d로 이동하거나, 인덱스 sd의 요청을 교환

    • Batchupdate.moved에서 튜플로 표현:

      (s, d, UNIDIRECTIONAL or SWAP)
      
    • UNIDIRECTIONAL이면:

      • 인덱스 s의 요청을 인덱스 d로 이동, s는 빈 슬롯이 됨
      • 인덱스 d에 다른 요청이 이미 있으면 대체·폐기
    • SWAP이면 인덱스 sd의 요청이 서로 자리를 교환

추가로 BatchUpdate 데이터 구조는 엔진 스텝 시작 시 영속 배치 크기를 나타내는 표현(batch_size)을 포함해요.

vLLM 엔진이 BatchUpdate 데이터 구조를 만드는 방법

로짓 프로세서 update_state() 구현은 모델 러너가 영속 배치 상태를 갱신하는 다음 모델을 가정해야 해요(BatchUpdate 추상화로 표현):

  1. 현재 엔진 스텝에서 끝난 요청의 인덱스 식별
  2. 현재 스텝에서 도입된 새 요청 식별
  3. Add 연산으로 가능한 한 많은 끝난 요청을 새 요청으로 대체, 대체되는 요청의 증가 인덱스(가장 낮은 인덱스부터) 순서로
  4. 새 요청과 끝난 요청의 상대 수에 따라:
    1. 새 요청 수와 끝난 요청 수가 같으면 다음 스텝으로 진행
    2. 새 요청이 끝난 요청보다 많으면: 끝난 요청을 대체하지 않은 남은 새 요청으로 배치를 확장하는 Add 연산 적용. current_max_batch_index + 1부터 시작해 이 새 요청들에 연속 인덱스 할당
    3. 새 요청이 끝난 요청보다 적으면:
      • 이전 단계에서 새 요청으로 대체되지 않은 끝난 요청에 Remove 연산 적용. 이 제거된 요청 인덱스는 필연적으로 이전 단계에서 대체된 끝난 요청의 가장 큰 인덱스보다 큼. Remove는 배치를 비연속 상태로 만들 수 있음
      • "Condense" 배치를 연속으로: 가장 낮은 인덱스의 빈 슬롯(Remove로 생긴)부터 시작해, 배치에서 현재 가장 높은 비-빈 슬롯의 요청을 Unidirectional Move로 빈 슬롯을 채움. 배치가 연속이 될 때까지 증가하는 빈 슬롯 대상 인덱스와 감소하는 비-빈 슬롯 소스 인덱스 순서로 추가 Unidirectional Move 연산 진행
      • 배치 축소: condense의 부작용으로 Remove 연산으로 생긴 빈 슬롯이 배치 배열 끝에 연속 블록으로 모임. 따라서 condense 후 BatchUpdate.batch_size를 갱신해 비-빈 슬롯 수를 반영
  5. 효율 향상을 위해 배치 재정렬. 어텐션 백엔드 구현과 배치 현재 특성에 따라 0개 이상의 Swap Move 연산을 적용해 배치를 재정렬

참고:

  • 로짓 프로세서 update_state() 메서드는 배치 업데이트 연산을 다음 순서로 처리해야 해요: removes, adds, moves
  • Add 연산의 인덱스 인자는 Add가 발생한 시점의 인덱스를 뜻해요. 즉 어떤 Move 연산 이전의 인덱스예요.
    • 예: 요청이 인덱스 5에 Added된 뒤 인덱스 3과 swap되면, BatchUpdate.added의 Add 연산은 인덱스 5(3이 아님)와 연관
    • 즉 Move 연산은 Add와 Remove 이후에 적용된다고 가정할 수 있어요
  • Move 연산은 BatchUpdate.moved에 나타난 순서대로 적용된다고 가정할 수 있어요
  • 새/끝난 요청이 없고 배치 재정렬도 없으면 로짓 프로세서에 대한 배치 업데이트는 None이에요

예시: 새 요청이 끝난 요청보다 적은 배치 업데이트

1개 새 요청이 도입되고 2개 끝난 요청이 제거되며, 어텐션 백엔드가 배치 순서 최적화를 위해 swap을 수행하는 엔진 스텝을 모델링한 예시예요.

Batch state (beginning of engine step): [A,B,C,D]
Batch size: 4

New requests: E

Finished requests: A, C

Processing steps (using BatchUpdate abstraction):

1. Add E at index 0

[E,B,C,D] # Discard A
Batch size: 4

2. Remove at index 2

[E,B,x,D] # Discard C, empty slot at index 2
Batch size: 4

3. Condense batch with a Unidirectional Move 3 -> 2 operation and shrink batch

[E,B,D] x # Empty slot is now outside batch
Batch size: 3

4. Attention backend optimization: reorder batch with Swap 0 <-> 1

[B,E,D]
Batch size: 3

결과 BatchUpdate 데이터 구조:

BatchUpdate instance
* added: [(0,E's SamplingParams,E's prompt tokens ref,E's output tokens ref)]
* removed: [2] # request C was removed without replacement
* moved: [(3,2,UNIDIRECTIONAL),(0,1,SWAP)]

예시: 새 요청이 끝난 요청보다 많은 배치 업데이트

2개 새 요청이 도입되고 1개 끝난 요청이 제거되며, 어텐션 백엔드가 배치 순서 최적화를 위해 swap을 수행하는 엔진 스텝을 모델링한 예시예요.

Batch state (beginning of engine step): [A,B,C,D]
Batch size: 4

New requests: E,F

Finished requests: C

Processing steps (using BatchUpdate abstraction):

1. Add E at index 2

[A,B,E,D] # Discard C
Batch size: 4

2. Add F at index 4 (current max batch index + 1)

[A,B,E,D,F] # Extend batch by 1
Batch size: 5

4. Attention backend optimization: reorder batch with Swap 0 <-> 1

[B,A,E,D,F]
Batch size: 5

Remove 연산이 남긴 빈 슬롯이 없으므로 배치 condense는 건너뛰어요.

결과 BatchUpdate 데이터 구조:

BatchUpdate instance
* added: [(2,E's SamplingParams,E's prompt tokens ref,E's output tokens ref),(4,F's SamplingParams,F's prompt tokens ref,F's output tokens ref)]
* removed: [] # no requests were removed without replacement
* moved: [(0,1,SWAP)]

vLLM에 새 로짓 프로세서 도입하기

내장 로짓 프로세서 작성 모범 사례

  • 로짓 프로세서는 배치 단위로 동작한다는 점을 고려해 효율적인 apply()update_state()를 작성해요.
    • 예를 들어 효율적인 벡터화 연산으로 apply()를 구현하거나 update_state()에서 내부 상태 벡터를 갱신할 수 있어요.
    • 다만 로짓 프로세서가 자주 쓰이지 않을 것 같으면 요청 상태의 "희소(sparse)" 표현이 적절할 수 있어요. 즉 클래스가 로짓 프로세서를 활성화한 요청에 대한 메타데이터만 저장하는 딕셔너리로 요청 구성을 나타낼 수 있어요.
  • 로짓 프로세서 작성자가 정해야 할 것들:
    1. 로짓 프로세서의 동작을 요청별로 구성하는 요청별 속성. 예를 들어 vLLM용 새 내장 로짓 프로세서를 작성 중이라면 SamplingParams와 vLLM REST API에 필드를 추가해야 할 수도, 아닐 수도 있어요.
    2. 로짓 프로세서가 요청별로 활성화/비활성화되는 조건. 의도가 내장 로짓 프로세서가 항상 모든 요청에 동작하도록 하는 게 아니라면, 특정 요청에 대해 로짓 프로세서를 비활성화할 수 있게 작성해야 해요. 예를 들어 인자를 기본 None으로 하거나 do-nothing 값(예: 0.0)을 넘기는 식이에요. 로짓 프로세서를 비활성화한 요청에 대한 연산·메모리를 아끼도록 노력해요.
    3. 로짓 프로세서가 배치 레벨에서 단락(short-circuit)되는 조건. 요청 레벨에서 비활성화 방법을 정의해도 이를 연산 절약으로 바꾸기 어려울 수 있어요. 예를 들어 update_state()apply() 구현이 전체 영속 배치를 단일 명령으로 연산하는 효율적 벡터화 구현을 쓴다면, 한 요청이 로짓 프로세서를 비활성화했다고 해서 apply()의 벡터화 연산 전체를 건너뛸 수는 없어요. 실행 중 요청이 아무도 내장 로짓 프로세서를 쓰지 않는 엣지 케이스에서 연산을 아끼려면, 모든 요청이 로짓 프로세서를 비활성화했다면 apply()가 수정하지 않은 입력 텐서를 반환하도록 설계하는 걸 권장해요. 마찬가지로 어떤 요청도 로짓 프로세서를 활성화하지 않으면 update_state()에서 스텝을 건너뛸 수 있는지 고려해요.
      • 추가로 update_state()에서 연산을 쉽게 아끼는 방법은 batch_update가 None일 때 일찍 종료하는 거예요.
  • 로짓 프로세서 update_state 메서드가 끝난 요청(Add로 대체되거나 Remove 대상인 요청)에 대한 정보를 폐기하도록 해요.
  • is_argmax_invariant()는 로짓 프로세서가 일관된 동작을 가지면 TrueFalse로 하드코딩할 수 있어요. 다만 argmax 불변성은 프로그램적으로 결정될 수도 있어요(로짓 프로세서가 argmax 불변성에 영향을 주는 방식으로 사용자 커스터마이즈 가능한 경우). 그래서 is_argmax_invariant()는 클래스 메서드가 아니에요.

내장 로짓 프로세서

내장 로짓 프로세서는 vLLM 엔진이 시작될 때 항상 로드돼요. 새 내장 vLLM 로짓 프로세서 작성 예시는 vllm/v1/sample/logits_processor/builtin.py의 기존 내장 로짓 프로세서를 참고하세요. 넓은 사용자층에 유용할 것 같다면 새 로짓 프로세서를 내장으로 도입하는 PR을 작성하는 게 타당해요. vLLM은 현재 위 프로그래밍 모델을 기반으로 다음 내장 로짓 프로세서를 사용해요.

  • Min-P
  • Logit bias
  • Min-tokens

내장 로짓 프로세서 작성 지침은 이 구현들을 검토하면 돼요.

추가로, 다음 로짓 프로세서 유사 기능들은 샘플러에 하드코딩되어 있고 아직 위 프로그래밍 모델을 사용하지 않아요. 대부분 앞서 언급한 로짓 프로세서 프로그래밍 모델을 쓰도록 리팩터링될 거예요.

  • Allowed token IDs
  • Bad words
  • Repetition penalty
  • Frequency penalty
  • Presence penalty
  • Temperature
  • Top-K
  • Top-P

커스텀 로짓 프로세서

vLLM은 사용자 제공 커스텀 로짓 프로세서로 확장할 수 있어요.

더 알아보기 (Learn more)