modular transformers로 모델 추가하기

modular transformers로 모델 추가하기

Modular transformers는 import와 상속을 허용하여 모델 추가에 필요한 코드를 줄입니다. 이는 단일 모델, 단일 파일 정책과 대조됩니다. 파일 간에 모델 구성 요소를 반복하는 대신 모델 폴더에 modular 파일을 추가하고 기존 클래스에서 상속합니다.

출처: 문서

본문

Modular transformers는 import와 상속을 허용하여 모델 추가에 필요한 코드를 줄입니다. 이는 단일 모델, 단일 파일 정책과 대조됩니다. 파일 간에 모델 구성 요소를 반복하는 대신 모델 폴더에 modular 파일을 추가하고 기존 클래스에서 상속합니다.

컨버터가 modular 파일에서 독립형 파일을 생성합니다. 사용자는 이미 알고 있는 동일한 단일 파일 인터페이스를 얻게 됩니다.

[!NOTE] Modular transformers는 레거시 모델링 코드를 대체하기 위한 것이 아닙니다. 모델이 기존 모델에 기반하지 않는다면 modeling.py 파일을 수동으로 추가하세요. 유사한 파일에서 깔끔하게 상속할 수 없는 구성, 토크나이제이션 또는 처리 파일에도 동일하게 적용됩니다.

올바른 순서도 없습니다. 일부 기여자는 modular 파일을 먼저 쓰고 그것에서 생성합니다. 다른 사람들은 손으로 쓴 modeling.py로 시작해 나중에 modular 파일로 리팩터링합니다. 두 접근 모두 작동합니다.

modular 파일 구현

먼저 Transformers에서 자신의 모델과 유사한 모델을 찾으세요. 좋은 시작점은 Mistral, Qwen2, Cohere, Cohere2, Llama입니다. 아래 표는 공통 구성 요소를 상속할 수 있는 모델에 매핑합니다.

구성 요소 모델
Mixture of experts Mixtral 또는 Qwen2-MoE
Interleaved (및/또는 부분) rotary embedding GLM, Phi
State space models Jamba, Bamba, Zamba, Mamba2
Recurrent hidden states Gemma2
레이어별 Sliding window attention/full attention 패턴 Gemma2, Cohere2
QKV 클리핑 Olmo
QK 정규화 Olmo2, Cohere
Fused QKV (권장하지 않음) Phi3

[!TIP] modular-detector-v2 도구를 사용해 상속할 기존 구현을 찾으세요. 코드 스니펫을 붙여넣으면 이미 Transformers에 있는 가장 유사한 메서드를 반환하므로, 쓰기 시작 전에 최상의 부모 클래스를 식별할 수 있습니다.

기존 모델을 수정해 새 모델의 상속이 작동하도록 하지 마세요. 부모 클래스의 이름을 바꾸거나 서브클래스화하는 것이 너무 어색하면 관련 코드를 직접 복사하세요.

src/transformers/models/<name>/modular_<name>.py를 만드세요. 여기서 <name>은 snake_case 모델 디렉터리 이름과 일치합니다. 이 섹션은 modular 접근으로 Olmo에서 Olmo2를 구현하는 과정을 안내합니다(원본 modular_olmo2.py 파일 참조).

Config

Olmo2Config가 OlmoConfig와 다른 지점은 두 곳입니다.

  1. 새 인자 rms_norm_eps가 있습니다.
  2. clip_qkv 인자가 더 이상 사용되지 않습니다.

새 인자는 기본값을 가진 클래스 수준 타입 주석으로 선언하세요. 제거된 인자의 경우 AttributeError()를 할당해 생성된 파일에서 상속된 속성을 억제합니다(속성 제거 참조).

- @auto_docstring(checkpoint="allenai/OLMo-7B-hf")
+ @auto_docstring(checkpoint="allenai/Olmo2-7B-1124-hf")
+ @strict
- class OlmoConfig(PreTrainedConfig):
+ class Olmo2Config(OlmoConfig):
      ...
-     model_type = "olmo"
+     model_type = "olmo2"
      ...
+     rms_norm_eps: float = 1e-5
-     clip_qkv: float | None = None
+     clip_qkv = AttributeError()

@auto_docstring는 표준 인자 문서를 자동으로 생성합니다(@auto_docstring 가이드 참조). @strict는 인스턴스화 시점에 알 수 없는 kwargs를 거부하여 오타와 낡은 인자를 일찍 잡습니다. 데코레이터는 부모에서 상속되지 않으므로 모든 config 클래스에 둘 다 추가하세요. 부모 config가 이미 가지고 있더라도 명시적으로 선언하세요.

파생 속성을 설정하거나 하위 호환성 로직을 처리하려면 __init__ 대신 __post_init__을 사용하세요. 예를 들어 Cohere2는 init 시점에 head_dim을 계산하고 layer_types를 파생합니다.

def __post_init__(self, **kwargs):
    if self.num_key_value_heads is None:
        self.num_key_value_heads = self.num_attention_heads
    self.head_dim = self.hidden_size // self.num_attention_heads
    super().__post_init__(**kwargs)

tensor 또는 pipeline parallelism을 지원하는 모델의 경우, config에 클래스 수준 딕셔너리로 base_model_tp_plan과 base_model_pp_plan을 정의하세요. 두 딕셔너리 모두 모델을 장치 간에 어떻게 샤딩할지 정의합니다. 예시는 Olmo2 또는 Cohere2 같은 기존 config를 참조하세요.

class MyNewModelConfig(PreTrainedConfig):
    model_type = "my_new_model"

    # Tensor parallelism: maps layer name patterns to sharding strategies.
    # Use "colwise" / "rowwise" for standard sharding, or the "gather_output" /
    # "split_input" variants when an extra op (e.g. a QK norm) prevents fusing.
    base_model_tp_plan = {
        "layers.*.self_attn.q_proj": "colwise",
        "layers.*.self_attn.k_proj": "colwise",
        "layers.*.self_attn.v_proj": "colwise",
        "layers.*.self_attn.o_proj": "rowwise",
        "layers.*.mlp.gate_proj": "colwise",
        "layers.*.mlp.up_proj": "colwise",
        "layers.*.mlp.down_proj": "rowwise",
    }

    # Pipeline parallelism: maps submodule names to their (input, output) tensor names.
    base_model_pp_plan = {
        "embed_tokens": (["input_ids"], ["inputs_embeds"]),
        "layers": (["hidden_states", "attention_mask"], ["hidden_states"]),
        "norm": (["hidden_states"], ["hidden_states"]),
    }

Norm

변경 없이 부모 클래스를 복사하려면 pass로 상속하세요. linter가 부모의 내용을 복사하고 새 모델에 맞게 모든 참조의 이름을 바꿉니다.

from ..olmo.modeling_olmo import OlmoRotaryEmbedding

class Olmo2RotaryEmbedding(OlmoRotaryEmbedding):
    pass

특정 동작을 변경하려면 상속하고 다른 것만 재정의하세요. Olmo2RMSNorm은 LlamaRMSNorm과 한 줄이 다릅니다. 곱셈이 입력 dtype으로 다시 캐스팅하기 전에 발생합니다.

  from ..llama.modeling_llama import LlamaRMSNorm

  class Olmo2RMSNorm(LlamaRMSNorm):
      def forward(self, hidden_states):
          input_dtype = hidden_states.dtype
          hidden_states = hidden_states.to(torch.float32)
          variance = hidden_states.pow(2).mean(-1, keepdim=True)
          hidden_states = hidden_states * torch.rsqrt(variance + self.variance_epsilon)
-         return self.weight * hidden_states.to(input_dtype)
+         return (self.weight * hidden_states).to(input_dtype)

Attention

Olmo2의 attention은 쿼리와 키에 RMSNorm을 적용하고 qkv 클리핑을 제거한다는 점을 제외하면 Olmo와 동일합니다. super().__init__(...)는 부모 본문을 복사하고 두 개의 새 norm 줄을 추가합니다. 쿼리와 키가 이제 프로젝션 전에 norm을 통과하므로 forward는 완전히 재정의됩니다. linter는 apply_rotary_pos_emb, eager_attention_forward 및 그들의 의존성을 포함해 가져온 함수를 생성된 파일로 가져옵니다.

  class Olmo2Attention(OlmoAttention):
      def __init__(self, config: Olmo2Config, layer_idx: int | None = None):
          super().__init__(config, layer_idx=layer_idx)
+         self.q_norm = Olmo2RMSNorm(config.num_attention_heads * self.head_dim, config.rms_norm_eps)
+         self.k_norm = Olmo2RMSNorm(config.num_key_value_heads * self.head_dim, config.rms_norm_eps)

      def forward(self, ...):
          ...
-         query_states = self.q_proj(hidden_states)
-         key_states = self.k_proj(hidden_states)
+         query_states = self.q_norm(self.q_proj(hidden_states))
+         key_states = self.k_norm(self.k_proj(hidden_states))
          value_states = self.v_proj(hidden_states)

-         if self.config.clip_qkv is not None:
-             query_states.clamp_(min=-self.config.clip_qkv, max=self.config.clip_qkv)
-             key_states.clamp_(min=-self.config.clip_qkv, max=self.config.clip_qkv)
-             value_states.clamp_(min=-self.config.clip_qkv, max=self.config.clip_qkv)
-
          ...

DecoderLayer

super().__init__(...) 후에 norm 속성을 Olmo2RMSNorm 인스턴스로 덮어쓰고 self.self_attn을 새 Olmo2Attention 클래스로 재할당합니다. del self.input_layernorm은 Olmo2가 norm을 전에가 아니라 attention 후에 적용하므로 부모의 input_layernorm 할당을 제거합니다. del이 무엇을 제거하고 무엇을 제거하지 않는지에 대한 자세한 내용은 속성 제거를 참조하세요.

forward는 post-attention norm 배치를 반영하도록 재작성됩니다. forward 재작성은 속성이 이름이 바뀔 때만 필요하며, 타입만 바뀔 때는 필요하지 않습니다.

  class Olmo2DecoderLayer(OlmoDecoderLayer):
      def __init__(self, config: Olmo2Config, layer_idx: int):
          super().__init__(config, layer_idx=layer_idx)
-         self.self_attn = OlmoAttention(config=config, layer_idx=layer_idx)
-         self.input_layernorm = OlmoLayerNorm(config.hidden_size)
-         self.post_attention_layernorm = OlmoLayerNorm(config.hidden_size)
+         self.self_attn = Olmo2Attention(config=config, layer_idx=layer_idx)
+         del self.input_layernorm
+         self.post_attention_layernorm = Olmo2RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
+         self.post_feedforward_layernorm = Olmo2RMSNorm(config.hidden_size, eps=config.rms_norm_eps)

      def forward(self, ...):
          residual = hidden_states
-         hidden_states = self.input_layernorm(hidden_states)
          # Self Attention
          hidden_states, _ = self.self_attn(...)
-         hidden_states = residual + hidden_states
+         hidden_states = self.post_attention_layernorm(hidden_states)
+         hidden_states = residual + hidden_states

          # Fully Connected
          residual = hidden_states
-         hidden_states = self.post_attention_layernorm(hidden_states)
          hidden_states = self.mlp(hidden_states)
-         hidden_states = residual + hidden_states
+         hidden_states = self.post_feedforward_layernorm(hidden_states)
+         hidden_states = residual + hidden_states
          return hidden_states

Model

여기서는 self.norm의 타입만 바뀝니다. forward 메서드는 부모와 동일하므로 linter가 자동으로 가져옵니다.

  class Olmo2Model(OlmoModel):
      def __init__(self, config: Olmo2Config):
          super().__init__(config)
-         self.layers = nn.ModuleList(
-             [OlmoDecoderLayer(config, layer_idx) for layer_idx in range(config.num_hidden_layers)]
-         )
-         self.norm = OlmoLayerNorm(config.hidden_size)
+         self.norm = Olmo2RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
+         self.layers = nn.ModuleList(
+             [Olmo2DecoderLayer(config, layer_idx) for layer_idx in range(config.num_hidden_layers)]
+         )

Model head

로직은 OlmoForCausalLM과 동일하므로 변경이 필요 없습니다.

from ..olmo.modeling_olmo import OlmoForCausalLM

class Olmo2ForCausalLM(OlmoForCausalLM):
    pass

기타 클래스

linter가 생성한 modeling_olmo2.py는 modular_olmo2.py에서 명시적으로 정의되지 않은 클래스(Olmo2MLP, Olmo2RotaryEmbedding, Olmo2PreTrainedModel)도 포함합니다.

linter는 명시적으로 재정의하지 않는 한 상속된 클래스가 의존하는 모든 클래스를 가져옵니다. apply_rotary_pos_emb 같은 가져온 함수도 같은 규칙을 따릅니다.

예를 들어 OlmoDecoderLayer에는 self.mlp = OlmoMLP(config)가 있습니다. Olmo2MLP는 modular 파일에서 정의된 적이 없으므로, linter가 pass를 사용하는 것과 동일하게 자동으로 생성합니다.

from ..olmo.modeling_olmo import OlmoMLP

class Olmo2MLP(OlmoMLP):
    pass

Olmo2MLP가 대신 다른 모델에서 상속하게 하려면 명시적으로 하세요.

# switch to Mistral definition
from ..mistral.modeling_mistral import MistralMLP

class Olmo2MLP(MistralMLP):
    pass

파일 마무리

모든 modular 파일은 모듈 수준에서 logger와 __all__ 목록을 선언해야 합니다.

logger = logging.get_logger(__name__)

__all__ = [
    "Olmo2Config",
    "Olmo2ForCausalLM",
    "Olmo2Model",
    "Olmo2PreTrainedModel",
]

__all__은 파일의 모든 공개 클래스를 나열해야 합니다. 컨버터와 다운스트림 import가 그것에 의존합니다. __all__에서 누락된 클래스는 올바르게 export되지 않습니다.

modeling 파일 생성

modular_model_converter.py 스크립트는 modular 파일에서 독립형 modeling.py, configuration.py 및 기타 파일을 생성합니다. 각 상속 클래스에 대해 부모 본문을 자식으로 복사하고, 모든 참조의 이름을 새 모델에 맞게 바꾸며, 해당 부모가 의존하는 모든 헬퍼 함수나 클래스를 가져옵니다.

출력 파일에는 크로스-모델 import가 없고 다른 모델 디렉터리에서의 상속이 없습니다. linter는 상속을 단일 수준으로 평탄화합니다. Olmo2Attention이 OlmoAttention에서 상속하면 생성된 Olmo2Attention은 완전히 독립적입니다. 그러나 OlmoAttention 자체가 다른 것에서 상속했다면 linter는 그 조부모를 인라인하지 않습니다.

modular 파일에서 파일을 생성하려면 아래 명령을 실행하세요.

python utils/modular_model_converter.py your_model

생성된 파일을 직접 편집하지 마세요. 다음 실행 시 모든 변경이 덮어써지기 때문입니다.

modular 파일 패턴

아래 섹션들은 modular 파일로 작업할 때 속성 제거나 장식된 메서드 재정의 같은 일반적인 사용 패턴을 설명합니다.

속성 제거

상속된 속성을 제거하는 방법은 config 클래스인지 nn.Module 서브클래스인지에 따라 다릅니다.

config 클래스의 경우 클래스 수준에서 속성에 AttributeError()를 할당합니다.

class MyNewConfig(ParentConfig):
    removed_attr = AttributeError()

linter는 생성된 config 파일에서 속성 선언을 완전히 제거합니다. config 클래스는 __init__이 없는 dataclass 스타일 레이아웃을 사용하므로 클래스 수준에서 AttributeError()를 할당하는 것이 올바른 접근입니다.

nn.Module 서브클래스의 경우 super().__init__(...) 후에 del self.attribute를 사용합니다.

class MyNewModel(ParentModel):
    def __init__(self, config: MyNewConfig):
        super().__init__(config)
        del self.attribute

del self.attribute는 복사된 부모 본문에서 self.attribute = ... 할당 줄만 제거합니다. self.attribute를 참조하는 다른 줄은 제거하지 않습니다. 부모의 forward나 다른 메서드도 속성을 참조하면 그 메서드들도 재정의하세요.

class DummyModel(nn.Module):
    def __init__(self, config: DummyConfig):
        super().__init__()
        self.attribute = config.attribute
        if self.attribute:
            # do more stuff with `self.attribute` here
            ...

class MyNewDummyModel(DummyModel):
    def __init__(self, config: MyNewDummyConfig):
        super().__init__(config)
        del self.attribute
        # 'self.attribute = config.attribute' is removed, but the 'if self.attribute:' block remains.
        # Override forward() or any other method that references self.attribute.

super() 작업

super().__init__(config)는 컨버터에 부모 본문을 자식으로 복사하라고 지시합니다. 이 동작을 재정의하는 두 가지 패턴이 있습니다.

  • 생성된 출력이 modular 부모가 아니라 조부모(nn.Module.__init__)를 호출해야 할 때 특정 부모 클래스를 직접 호출합니다.
  • **super_kwargs를 사용해 커스텀 docstring을 추가하거나 데코레이터를 교체하면서 부모 메서드의 전체 시그니처를 상속합니다.

조부모 클래스를 직접 호출

super()가 modular 부모가 아닌 생성된 클래스 부모를 대상으로 해야 할 때 어떤 클래스를 호출하는지 명시하세요. 아래 예시는 nn.Module.__init__(self)를 직접 호출합니다. DummyModule 자체가 nn.Module이므로 컨버터는 생성된 MyNewDummyModule에서 그것을 super().__init__()으로 씁니다.

class MyNewDummyModule(DummyModule):                   |     class MyNewDummyModule(nn.Module):
                                                       |
  def __init__(self):                                  |       def __init__(self):
    nn.Module.__init__(self)                           |         super().__init__()
    self.foo = config.foo                              |         self.foo = config.foo
    ...                                                |         ...

super_kwargs

**super_kwargs를 사용해 커스텀 docstring을 추가하거나 데코레이터를 교체하면서 부모 메서드의 전체 시그니처를 상속합니다. 재정의된 시그니처에서, 생성된 출력에서 모든 부모 인자를 확장하라고 linter에 알려줍니다.

가장 흔한 용도는 전체 시그니처를 다시 쓰지 않고 labels 인자를 문서화하는 것 같은 모델별 docstring을 추가하는 것입니다.

# modular_gemma.py
class GemmaForCausalLM(LlamaForCausalLM):
    def forward(**super_kwargs):
        r"""
        Example:

        ```python
        >>> from transformers import AutoTokenizer, GemmaForCausalLM
        >>> model = GemmaForCausalLM.from_pretrained("google/gemma-7b")
        ...
        ```"""
        return super().forward(**super_kwargs)

생성된 GemmaForCausalLM.forward는 수동 복사 없이 전체 LlamaForCausalLM 시그니처를 가집니다.

**super_kwargs는 틈새 경우를 위한 지름길입니다. 동작을 변경한다면 전체 시그니처를 쓰세요.

사용하지 않는 메서드 삭제

raise AttributeError("") 문으로 재정의하여 부모 메서드를 제거합니다. linter는 생성된 파일에서 메서드를 제거합니다.

class GemmaTokenizer(LlamaTokenizer):
    ...

    def get_spm_processor(self):
        raise AttributeError("Not needed for Gemma")

    def unk_token_length(self):
        raise AttributeError("Not needed for Gemma")

장식된 메서드 재정의

장식된 부모 메서드를 재정의하면 부모의 데코레이터가 자동으로 전달됩니다. 자신의 데코레이터를 추가하면 부모의 것을 대체합니다.

라이브러리 전반에 두 데코레이터가 나타나며, 하나는 모델 중간 출력 캡처용, 하나는 docstring 자동 생성용입니다.

아래 예시에서 서브클래스는 자신의 데코레이터를 추가하지 않고 장식된 부모 메서드를 재정의합니다. 부모의 데코레이터가 전달됩니다.

class NewModel(DummyModel):       |   class NewModel(nn.Module):
  ...                             |     ...
                                  |
  def forward(...):               |     @decorator(...)
    ...                           |     def forward(...):
                                  |       ...

새 데코레이터를 추가하면 자신의 데코레이터가 부모의 것을 대체합니다.

class NewModel(DummyModel):       |   class NewModel(nn.Module):
  ...                             |     ...
                                  |
  @my_new_decorator(...)          |     @my_new_decorator(...)
  def forward(...):               |     def forward(...):
    ...                           |       ...

특수 이름 지정

linter는 클래스에서 상속할 때 모든 것을 자동으로 이름을 바꿉니다. 같은 파일의 모든 클래스에 같은 클래스 이름 접두사를 사용하세요.

아래 예시처럼 접두사를 혼합하지 마세요. MyModelIncredibleMLP는 명명 규칙을 깨뜨리며, linter는 더 높은 차수의 의존성을 이름을 바꿀 때 MyModelIncredible을 쓸지 MyModel을 쓸지 알지 못합니다.

class MyModelIncredibleMLP(LlamaMLP):
    ...

class MyModelDecoderLayer(LlamaDecoderLayer):
    ...

암시적 의존성이 없으면 단일 클래스를 로컬에서 이름을 바꿀 수 있습니다. 그 클래스의 다른 모든 언급을 새 이름 패턴으로 명시적으로 재정의하세요. 그렇지 않으면 linter가 MyModelIncredibleMLP 옆에 원치 않는 MyModelMLP 클래스를 추가합니다.

linter는 모호한 접두사를 감지하면 경고를 발생시킵니다.

We detected multiple prefix names when inheriting from transformers.models.llama.modeling_llama: ('Emu3Text', 'Emu3'). We will only use the most used 'Emu3' prefix when grabbing args and dependencies. Make sure to subclass the intermediate classes with the prefix you want (if different from 'Emu3') or use a single prefix in all the modular (best).

모호한 접두사는 클래스 이름에 Text 같은 모달리티 한정사가 포함되는 멀티모달 모델에서 가장 흔합니다. 의존성에 특정 접두사를 주려면 pass로 명시적으로 이름을 바꾸세요.

class Emu3TextMLP(LlamaMLP):
    pass

Config docstring

linter는 아직 부분 docstring 상속을 지원하지 않습니다. config 속성을 추가하거나 제거할 때, 클래스 정의 아래 modular 파일에 전체 docstring을 직접 추가하세요.

체크포인트 변환

modeling 파일을 생성한 후 실제 가중치가 올바르게 로드되는지 확인하세요. 업스트림 체크포인트 형식을 Transformers 호환 형식으로 변환하는 스크립트를 작성한 다음 Hub에 저장하세요.

변환 스크립트 작성

src/transformers/models/<model>/에 convert_<model>_to_hf.py 파일을 추가하세요. 스크립트는 업스트림 가중치를 로드하고, 모듈의 파라미터 이름과 일치하도록 키의 이름을 바꾸고 리셰이프하며, save_pretrained()로 결과를 저장합니다.

[!TIP] 복사해 적응할 기존 스크립트를 찾아보세요. src/transformers/models/ 아래의 모델에는 시작점으로 사용할 수 있는 convert_*_to_hf.py가 포함되어 있습니다.

스크립트를 실행한 후 from_pretrained()로 저장된 체크포인트를 로드하고 예상되는 모든 가중치가 올바르게 로드되었는지 확인하세요. 사용되지 않은 체크포인트 키는 이름이 일치하지 않음을 나타내므로, 문제를 일찍 잡도록 그것들을 출력하세요.

model = YourModelForTask.from_pretrained("path/to/output/")

키를 반복할 때 형태와 이름 일치를 확인하세요. 형태 불일치는 일반적으로 config의 파라미터가 잘못되었거나, 아키텍처가 원본과 다르거나, 가중치를 전치해야 함을 의미합니다.

for key, tensor in original_state_dict.items():
    hf_tensor = hf_model.state_dict().get(mapped_key)
    assert hf_tensor.shape == tensor.shape, (
        f"Shape mismatch for {key}: expected {tensor.shape}, got {hf_tensor.shape}"
    )

모든 가중치가 깨끗하게 로드될 때까지 modular 파일, 생성된 modeling 파일, 변환 스크립트 사이를 오가며 문제를 수정하세요.

체크포인트가 깨끗하게 로드되면 push_to_hub()를 사용해 Hub에 푸시하세요. 자세한 내용은 모델 공유 가이드를 참조하세요.

model.push_to_hub("username/your-model-name")

런타임 변환 매핑

게시된 가중치가 모듈의 파라미터 레이아웃과 일치하지 않을 때 src/transformers/conversion_mapping.py에 런타임 매핑을 추가하세요. 일반적인 경우는 별도로 저장된 퓨전 가중치와 스태킹이 필요한 MoE 전문가 텐서입니다. 매핑을 통해 from_pretrained()이 별도의 export 단계 없이 Hub 체크포인트를 로드할 수 있습니다.

동적 가중치 로드 가이드를 참조해 WeightRenaming과 WeightConverter 규칙을 작성하고 model_type에 대해 등록하는 방법을 알아보세요.

다음 단계

  • 모델 구조 규칙은 모든 modeling_*.py, modular_*.py, configuration_*.py 파일에 시행되는 정적 규칙입니다. PR을 열기 전에 make typing을 실행해 확인하세요.
  • 비전 처리 구성 요소 추가는 멀티모달 모델의 이미지 프로세서, 비디오 프로세서, 프로세서 추가를 안내합니다.
  • docstring 자동 생성은 공유 모델 API의 인자 문서를 손으로 쓰지 않도록 @auto_docstring을 사용하는 방법을 보여줍니다.
  • 모델 테스트 작성은 새 모델의 통합 테스트를 작성하고 로컬에서 실행하는 방법을 다룹니다.
  • Pull request 검사는 PR이 병합되기 전에 통과해야 하는 CI 검사와 이를 로컬에서 재현하고 수정하는 방법을 설명합니다.

더 알아보기 (Learn more)