새 확산 모델 지원
새 확산 모델 지원 (Support New Diffusion Models)
이 페이지는 SGLang-Diffusion에 확산 모델 패밀리를 추가하기 위한 간결한 구현 가이드예요. 이 가이드를 모델을 지원할 수 있는 가장 작은 변경을 찾는 트리아지 흐름으로 사용해요. 런타임이 별도 폴더로 분리되어 있어도 대부분의 새 모델 작업은 작은 파일 집합을 건드려야 해요.
출처: 문서
본문
이 가이드를 모델을 지원할 수 있는 가장 작은 변경을 찾는 트리아지(triage) 흐름으로 사용해요. 런타임이 별도 폴더로 분리되어 있더라도 대부분의 새 모델 작업은 작은 파일 집합을 건드려야 해요.
이 순서로 코드 읽기 (Read the Code in This Order)
파일은 런타임 책임별로 분리돼요. 새 모델의 경우 요청 경로를 먼저 읽어요:
registry.py가 모델 패밀리, 샘플링 파라미터, 파이프라인 구성 선택.configs/pipeline_configs/{model}.py가 모델별 디노이징 및 디코딩 동작 정의.runtime/pipelines/{model}.py가 모듈을 단계에 연결.runtime/pipelines_core/stages/가 공유 단계 로직 실행.runtime/models/는 아키텍처를 재사용할 수 없을 때만 네이티브 모델 컴포넌트 포함.
이것이 의존성 방향이에요. 독자가 다른 순서로 폴더 사이를 뛰어다녀야 하는 모델 PR을 피해요.
runtime/models/는 모델링 코드를 소유해요: 체크포인트 정의 신경 모듈, 아키텍처 래퍼, 한 모델 패밀리에 고유한 가중치 로딩 또는 forward 경로 세부 사항. 재사용 가능한 서빙 인프라는 runtime/cache/, runtime/distributed/, runtime/utils/, 또는 공유 파이프라인 단계 같은 SGLang-Diffusion 런타임 폴더에 속해요. 여기에는 캐시 관리자, 그래프 러너, 프로세스 그룹 전송, 요청 유틸리티, 공통 액션-정책 헬퍼가 포함돼요. 모델 패키지는 이 헬퍼들을 호출할 수 있어요. 코드가 정말 아키텍처 특정이 아니라면 소유권을 공유 런타임 폴더에 유지해요.
헬퍼를 소유자와 함께 배치 (Place helpers with their owners)
유틸리티 모듈을 추가하기 전에 가장 좁은 기존 소유자를 사용해요:
| Scope | Location |
|---|---|
| 한 파일에서만 사용되거나 한 연산에 특정 | 소비 파일의 비공개 헬퍼; 짧은 일회성 표현식 인라인 |
| 도메인 내에서 공유 | 해당 도메인의 목적 명명 모듈(예: runtime/realtime/video.py 또는 runtime/layers/attention/mask_strategy.py) |
| 모델 또는 파이프라인 의미 없이 도메인 간 공유 | argparse.py, process.py, precision.py 같은 runtime/utils/ 아래 기존 집중 모듈 |
최상위 utils/ 패키지를 만들거나 catch-all utils.py / common.py를 키우지 마세요. 대규모 혼합 책임 파일을 임의 줄 수가 아니라 소유권 경계로 분할해요. 헬퍼 폴더는 여러 응집 모듈이 필요할 때만 정당하며 단일 함수나 가상의 재사용용이 아니에요.
모델 코드는 파이프라인 단계를 import해서는 안 돼요. 모델과 단계가 공유하는 계약은 더 낮은 수준의 도메인 모듈에 두어요. 예를 들어 실시간 캐시 키는 runtime/realtime/ 아래에 속해요. GPU 초기화, monkey 패치, 모델 로딩을 일반 유틸리티 import에서 제외해요.
내부 헬퍼를 옮길 때 모든 호출자, 테스트, 쿡북 예시를 함께 업데이트해요. 문서화된 등록 및 서빙 진입점을 보존하고, 폐기된 내부 유틸리티 경로를 유지하기 위해 재내보내기 체인을 추가하지 마세요.
트리 밖 모델 및 파이프라인 (Out-of-Tree Models and Pipelines)
설치된 패키지는 SGLang-Diffusion을 수정하지 않고 네이티브 컴포넌트 모델과 파이프라인을 등록할 수 있어요. 패키지의 __init__.py에 등록해요:
from sglang.multimodal_gen.registry import register_pipeline
from sglang.multimodal_gen.runtime.models.registry import ModelRegistry
from .configs import CustomPipelineConfig, CustomSamplingParams
from .pipeline import CustomPipeline
ModelRegistry.register_model(
"CustomTransformer2DModel",
"custom_diffusion.models:CustomTransformer2DModel",
)
register_pipeline(
CustomPipeline,
sampling_param_cls=CustomSamplingParams,
pipeline_config_cls=CustomPipelineConfig,
hf_model_paths=["my-org/custom-diffusion-model"],
model_detectors=[lambda value: "custom-diffusion" in value.lower()],
)
서버 환경에 패키지를 설치하고 SRT 플러그인과 동일한 환경 변수를 설정해요:
pip install -e /path/to/custom-diffusion
SGLANG_EXTERNAL_MODEL_PACKAGE=custom_diffusion \
sglang serve --model-path my-org/custom-diffusion-model
참고 사항:
register_model의 문자열 형식은 컴포넌트 import를 지연적(lazy)으로 유지해요.hf_model_paths는model_index.json이 없는 체크포인트도 지원해요. 다른 Diffusers 체크포인트는_class_name으로 파이프라인을 선택할 수 있어요.- 독립형 safetensors 파일의 경우
--pipeline CustomPipeline을 전달해요. - 환경 변수를 시작 전에 설정해요. 각 프로세스는 패키지를 한 번 import해요. 내장 파이프라인을 의도적으로 대체할 때만
overwrite=True를 사용해요.
가장 작은 변경으로 시작 (Start With the Smallest Change)
파일을 추가하기 전에 어떤 경로가 모델에 맞는지 결정해요.
| Situation | What to do |
|---|---|
| 새 체크포인트가 기존 네이티브 패밀리 사용 | Hugging Face 경로와 필요 시 작은 SamplingParams 또는 PipelineConfig 변형 추가. 기존 파이프라인과 모듈 재사용. |
| 모델에 새 네이티브 DiT/UNet 아키텍처 | 네이티브 SGLang 파이프라인과 누락된 모델 컴포넌트 추가. 측정된 동작이 모델별 로직을 요구하지 않는 한 디노이징과 디코딩을 공유 단계에 유지. |
| 모델이 롱테일이거나 먼저 호환성만 필요 | 호환성 우선 지원을 위해 Diffusers 백엔드를 선호. 성능이나 배포 필요가 정당화할 때 나중에 네이티브 지원 추가. |
Diffusers 저장소 레이아웃을 미러링하려고 폴더를 추가하지 마세요. 기존 파이프라인, 단계, 모듈, 구성, 샘플러가 동작을 명확히 표현할 수 없을 때만 새 파일을 추가해요.
최소 파일 맵 (Minimal File Map)
소스 트리는 런타임 책임별로 분리돼요. 이 분리는 최적화에 유용해요. 새 모델 PR을 모델 동작이 요구하는 파일에 집중해요.
| Area | Add or edit when | Typical file |
|---|---|---|
| Registry | 이미 등록된 패밀리를 확장하지 않는 한 항상 | python/sglang/multimodal_gen/registry.py |
| Runtime parameters | 요청 스키마가 기존 모델과 다름 | configs/sample/{model}.py |
| Pipeline config | 디노이징, 디코딩, 정밀도, 위치 인코딩, CFG 훅이 다름 | configs/pipeline_configs/{model}.py |
| Pipeline wiring | 모델에 새 단계 레이아웃이나 모듈 목록 필요 | runtime/pipelines/{model}.py |
| DiT/UNet module | 디노이징 네트워크가 새 것 | runtime/models/dits/{model}.py |
| dVLA or policy module | 체크포인트가 새 액션-정책 아키텍처 정의 | runtime/models/{family}/modeling_*.py 또는 작업별 모델 하위 폴더 |
| Shared runtime infrastructure | 캐시, CUDA graph, 분산 전송, 요청 유틸리티, 액션-정책 헬퍼를 미래 모델이 재사용 가능 | runtime/cache/, runtime/distributed/, runtime/utils/, runtime/pipelines_core/stages/ |
| Model component config | 모델 컴포넌트가 정적 아키텍처 구성 | configs/models/dits/{model}.py, configs/models/vaes/{model}.py |
| Model-specific stage | 한 단계의 런타임 의미를 네이티브 단계나 그 좁은 하위 클래스로 표현할 수 없음 | runtime/pipelines_core/stages/model_specific_stages/{model}.py |
| Encoder, VAE, scheduler | 재사용할 기존 구현이 없음 | runtime/models/encoders/, runtime/models/vaes/, runtime/models/schedulers/ |
새 네이티브 아키텍처의 공통 최소는:
registry.pyconfigs/sample/{model}.pyconfigs/pipeline_configs/{model}.pyruntime/pipelines/{model}.pyruntime/models/dits/{model}.py
추가 파일마다 기존 코드가 명확히 표현할 수 없는 모델 동작에 매핑되어야 해요.
dVLA나 다른 비-이미지 확산 정책의 경우 동일한 소유권 규칙을 유지해요. 정책 네트워크, VLM/액션 전문가 모듈, 체크포인트 매핑, 모델별 forward 코드는 runtime/models/ 아래에 속해요. 프리픽스 캐시, 요청-로컬 컨텍스트, 디노이징 그래프 러너, OpenPI 호환 전송, 프리픽스/액션 프로세스 그룹 유틸리티는 첫 모델 너머에도 유용할 때 공유 SGLang-Diffusion 런타임 인프라여야 해요.
참조 먼저 읽기 (Read the Reference First)
모델의 Diffusers 파이프라인, 공식 구현 또는 model_index.json을 진실의 원천으로 사용해요. 다음을 적어 두세요:
- 로드해야 할 모듈: 토크나이저, 텍스트 인코더, 이미지 인코더, 트랜스포머, 스케줄러, VAE, 프로세서, 추가 어댑터.
- 프롬프트와 이미지 인코딩 흐름.
- 잠재 형태, 패킹, 스케일, 시프트, dtype, 디바이스 규칙.
- Timestep 및 sigma 스케줄.
- 디노이징 네트워크가 기대하는 정확한
forward()kwargs. - VAE 디코드 규칙과 출력 후처리.
새 모델이 Flux, Qwen-Image, GLM-Image, Wan, HunyuanVideo 또는 LTX에 가까우면 빈 파일에서 시작하기 전에 그 구현을 확장해요.
파이프라인 형태 선택 (Choose a Pipeline Shape)
SGLang-Diffusion은 ComposedPipelineBase를 사용해 단계를 연결해요. 대부분의 네이티브 파이프라인은 런타임 의미를 보존하는 가장 덜 침습적인 단계 형태를 선택해야 해요.
| Shape | Use when | Layout |
|---|---|---|
| Native stages | 텍스트/이미지 인코딩, 잠재 준비, timestep 준비, 디노이징, 디코딩이 기존 헬퍼와 일치 | add_standard_t2i_stages(), add_standard_ti2i_stages() 또는 유사 헬퍼 |
| Native-stage subclass | 한 단계에 모델별 세부 사항이 있지만 단계 경계와 배치 계약이 기존 네이티브 단계와 여전히 일치 | {Model}TextEncodingStage(TextEncodingStage) -> LatentPreparationStage -> TimestepPreparationStage -> DenoisingStage -> DecodingStage |
| Custom single-purpose stage | 한 단계가 다른 상태 소유자 또는 배치-필드 수명 주기를 가지며 네이티브 단계에서 깨끗히 상속 불가 | 하나의 {Model}{Purpose}Stage를 삽입하거나 대체한 네이티브 단계 |
| Aggregated custom stage | 참조 파이프라인에서 여러 준비 단계가 분리 불가능하고 취약한 중복 상태 없이는 분할 불가 | {Model}BeforeDenoisingStage -> DenoisingStage -> DecodingStage |
이 순서를 선호해요:
- 네이티브 단계를 직접 사용. 이렇게 하면 모델이 offload, 컴포넌트 준비, 프로파일링, 분리, 배칭, 미래 단계 수준 최적화의 공유 코드 경로에 유지돼요.
- 가장 좁은 네이티브 단계를 하위 클래스화. 프롬프트 처리만 다르면
TextEncodingStage에서 상속. 잠재 설정, timestep 설정, 디노이징, 디코드만 다르면 해당 특정 네이티브 단계에서 상속. 가능할 때마다 기존 입력/출력 필드를 보존. - 네이티브 단계 계약이 맞지 않을 때만 커스텀 단일 목적 단계 추가. 단계 소유자를 좁게 유지: 한 단계는 하나의 응집 변환(예: 커스텀 조건 조립 단계 또는 모델별 정책/액션 브리지)을 소유해야 해요.
- 집계
BeforeDenoisingStage는 최후의 수단으로만 사용. 이는 하나의 단계에 여러 런타임 책임을 숨기고, 코드 크기와 리뷰 비용을 늘리며, offload, 프로파일링, 분리, 배칭, 미래 단계 수준 최적화의 공유 훅을 우회하므로 가장 선호되지 않는 형태예요.
조각 구현 (Implement the Pieces)
1. 샘플링 파라미터 (Sampling Params)
사용자가 런타임에 설정할 수 있는 값에 대해서만 요청 파라미터를 만들어요.
# python/sglang/multimodal_gen/configs/sample/my_model.py
from dataclasses import dataclass
from sglang.multimodal_gen.configs.sample.sampling_params import ImageSamplingParams
@dataclass
class MyModelSamplingParams(ImageSamplingParams):
guidance_scale: float = 4.0
num_inference_steps: int = 28
2. 파이프라인 구성 (Pipeline Config)
PipelineConfig는 공유 디노이징 및 디코딩 단계가 모델별 콜백을 얻는 곳이에요.
# python/sglang/multimodal_gen/configs/pipeline_configs/my_model.py
from dataclasses import dataclass, field
@dataclass
class MyModelPipelineConfig(ImagePipelineConfig):
task_type: ModelTaskType = ModelTaskType.T2I
should_use_guidance: bool = True
dit_config: DiTConfig = field(default_factory=MyModelDiTConfig)
vae_config: VAEConfig = field(default_factory=MyModelVAEConfig)
def prepare_pos_cond_kwargs(self, batch, latent_model_input, t, **kwargs):
return {
"hidden_states": latent_model_input,
"encoder_hidden_states": batch.prompt_embeds[0],
"timestep": t,
}
def prepare_neg_cond_kwargs(self, batch, latent_model_input, t, **kwargs):
return {
"hidden_states": latent_model_input,
"encoder_hidden_states": batch.negative_prompt_embeds[0],
"timestep": t,
}
이 kwargs가 디노이징 모듈의 forward() 시그니처와 정확히 일치하게 만들어요.
3. 파이프라인 연결 (Pipeline Wiring)
모델이 표준 헬퍼에 맞으면 그것을 사용해요.
# python/sglang/multimodal_gen/runtime/pipelines/my_model.py
class MyModelPipeline(LoRAPipeline, ComposedPipelineBase):
pipeline_name = "MyModelPipeline"
_required_config_modules = [
"text_encoder",
"tokenizer",
"transformer",
"scheduler",
"vae",
]
def create_pipeline_stages(self, server_args: ServerArgs):
self.add_standard_t2i_stages()
EntryClass = [MyModelPipeline]
표준 헬퍼가 충분하지 않을 때 먼저 하나의 네이티브 단계만 모델별 동작이 필요한지 확인해요. 그렇다면 그 단계를 하위 클래스화하고 파이프라인의 나머지는 표준으로 유지해요. 예를 들어 커스텀 토크나이제이션 또는 프롬프트-윈도우 로직은 보통 TextEncodingStage에서 직접 상속해야 해요.
class MyModelPipeline(LoRAPipeline, ComposedPipelineBase):
pipeline_name = "MyModelPipeline"
_required_config_modules = [
"text_encoder",
"tokenizer",
"transformer",
"scheduler",
"vae",
]
def create_pipeline_stages(self, server_args: ServerArgs):
self.add_stage(InputValidationStage())
self.add_stage_factory(
RoleType.ENCODER,
lambda: MyModelTextEncodingStage(
text_encoder=self.get_module("text_encoder"),
tokenizer=self.get_module("tokenizer"),
),
"my_model_text_encoding_stage",
)
self.add_standard_latent_preparation_stage()
self.add_standard_timestep_preparation_stage()
self.add_standard_denoising_stage()
self.add_standard_decoding_stage()
EntryClass = [MyModelPipeline]
커스텀 단일 목적 단계는 참조 파이프라인에 훅이나 네이티브-단계 하위 클래스로 깨끗히 표현할 수 없는 단계가 하나 있을 때만 사용해요. 커스텀 단계를 좁게 유지하고 그 전후에 네이티브 단계를 재사용해요.
class MyModelPipeline(LoRAPipeline, ComposedPipelineBase):
pipeline_name = "MyModelPipeline"
_required_config_modules = [
"text_encoder",
"tokenizer",
"transformer",
"scheduler",
"vae",
]
def create_pipeline_stages(self, server_args: ServerArgs):
self.add_stage(InputValidationStage())
self.add_standard_text_encoding_stage()
self.add_stage_factory(
RoleType.ENCODER,
lambda: MyModelConditioningStage(
scheduler=self.get_module("scheduler"),
vae=self.get_module("vae"),
),
"my_model_conditioning_stage",
)
self.add_standard_latent_preparation_stage()
self.add_standard_timestep_preparation_stage()
self.add_standard_denoising_stage()
self.add_standard_decoding_stage()
EntryClass = [MyModelPipeline]
집계 BeforeDenoisingStage는 참조 파이프라인이 여러 준비 단계를 너무 밀접하게 결합해 분할이 취약한 중복 상태나 추가 동기화를 요구할 때만 사용해요. 이 형태로 시작하지 마세요.
class MyModelPipeline(LoRAPipeline, ComposedPipelineBase):
pipeline_name = "MyModelPipeline"
_required_config_modules = [
"text_encoder",
"tokenizer",
"transformer",
"scheduler",
"vae",
]
def create_pipeline_stages(self, server_args: ServerArgs):
self.add_stage(InputValidationStage())
self.add_stage(
MyModelBeforeDenoisingStage(
text_encoder=self.get_module("text_encoder"),
tokenizer=self.get_module("tokenizer"),
scheduler=self.get_module("scheduler"),
vae=self.get_module("vae"),
)
)
self.add_standard_denoising_stage()
self.add_standard_decoding_stage()
EntryClass = [MyModelPipeline]
컴포넌트 로더 재사용
대부분의 컴포넌트는 해당 역할(트랜스포머, 텍스트 인코더, VAE, 스케줄러, 토크나이저)의 기본 로더를 유지해야 해요. model_cls(**config)를 받고 변경되지 않은 state dict를 로드하는 보조 모듈의 경우 모델별 로더 클래스를 추가하는 대신 PlainStateDictComponentLoader를 선택해요:
from sglang.multimodal_gen.runtime.loader.component_loaders.component_loader import (
PlainStateDictComponentLoader,
)
class MyModelPipeline(ComposedPipelineBase):
_required_config_modules = ["transformer", "queryformer", "text_projection"]
component_loaders = {
"queryformer": PlainStateDictComponentLoader,
"text_projection": PlainStateDictComponentLoader,
}
# Wire the stages as in the examples above.
매핑은 _extra_config_module_map에 선언된 별칭을 포함해 정확한 파이프라인 컴포넌트 이름을 사용해요. 이는 이 파이프라인에 로컬이며, 생략된 컴포넌트는 기존 디스패치를 유지해요. 명시적으로 선택된 로더는 다른 구현으로 폴백하지 않고 오류에서 실패해요.
각 모듈을 모델 파일의 EntryClass 또는 out-of-tree 패키지의 ModelRegistry.register_model을 통해 등록해요. 공유 로더:
config.json의_class_name에서 등록된 클래스를 해석하고,model_index.json의 아키텍처로 폴백하며, 비-메타데이터 구성 필드를 생성자에 전달해요.- 공유 체크포인트 선택기를 사용해 단일 safetensors 파일 또는 인덱스화된 샤딩 체크포인트를 로드하며, 엄격한 키와 형태 검사가 있어요.
--component-weights-paths.queryformer PATH및--component-precisions.queryformer bf16같은 정확한 오버라이드를 존중해요. 정밀도는 파이프라인의dit_precision으로 기본 설정돼요.- eval 모드와 최종 CPU/GPU 배치는 공유 로딩 수명 주기에 맡겨요. TP/FSDP 가중치 샤딩, 양자화, 직접 GPU 로딩을 구현하지 않아요. 명시적 양자화 및 직접 GPU 로딩 오버라이드는 거부돼요.
컴포넌트가 구성-객체 생성자, 가중치 재매핑 또는 융합, 샤딩, 비표준 체크포인트 형식을 필요로 하면 특수 로더를 유지해요. 그런 로더도 component_loaders로 선택할 수 있으며, 모델을 등록하는 것만으로는 그것이 일반 state-dict 프로토콜을 옵트인하지 않아요.
4. 최후 수단 Before-Denoising 단계 (Last-Resort Before-Denoising Stage)
BeforeDenoisingStage는 네이티브 단계의 catch-all 대체가 아니에요. 모델이 LatentPreparationStage 또는 TimestepPreparationStage에 맞지 않는 커스텀 잠재 패킹, 조건 조립, timestep 준비, 요청-로컬 상태를 가질 때, 그리고 작업이 네이티브-단계 하위 클래스 또는 커스텀 단일 목적 단계가 될 수 있는지 확인한 후에만 사용해요. 차이가 프롬프트 처리라면 대신 TextEncodingStage를 하위 클래스로 만들어요.
적절한 BeforeDenoisingStage는 DenoisingStage가 소비하는 배치 필드를 채워야 해요.
class MyModelBeforeDenoisingStage(PipelineStage):
@torch.no_grad()
def forward(self, batch: Req, server_args: ServerArgs) -> Req:
prompt_embeds, negative_prompt_embeds = self._encode_prompt(batch)
latents = self._prepare_latents(batch)
timesteps, sigmas = self._prepare_timesteps(batch)
batch.prompt_embeds = [prompt_embeds]
batch.negative_prompt_embeds = [negative_prompt_embeds]
batch.latents = latents
batch.timesteps = timesteps
batch.num_inference_steps = len(timesteps)
batch.sigmas = sigmas.tolist()
batch.raw_latent_shape = latents.shape
return batch
DenoisingStage에 필요한 필드:
| Field | Notes |
|---|---|
batch.latents |
모델이 요구하는 패킹을 포함한 초기 잠재 텐서. |
batch.timesteps |
참조 파이프라인이 사용하는 정확한 순서의 timestep 텐서. |
batch.sigmas |
스케줄러가 sigma 값을 기대할 때 Python 목록. |
batch.prompt_embeds |
목록으로 감싼 양(positive) 임베딩. |
batch.negative_prompt_embeds |
CFG를 사용할 때 목록으로 감싼 음(negative) 임베딩. |
batch.num_inference_steps |
디노이징 반복 횟수. |
batch.raw_latent_shape |
패킹 전 원본 잠재 형태, 디코드가 필요할 때. |
5. 분산 및 메모리 통합 (Distributed and memory integration)
단일 GPU 패리티는 첫 번째 이정표일 뿐이에요. 완전한 네이티브 지원은 또한 필요해요:
- Encoder 및 DiT TP/SP: TP용 네이티브 병렬 프로젝션과 샤딩된 가중치 로딩, SP용
USPAttention사용. 복제된 전체 모델로 폴백하지 않고 마스크, RoPE, 패딩, 출력 수집 처리. TP와 SP가 함께 동작해야 해요. - VAE 병렬 디코드:
ParallelTiledVAE를 하위 클래스화하거나 동일한 계약의 기존 네이티브 베이스 재사용.DecodingStage와 공유 디코드 그룹을 통해 tiled 및spatial_shard디코드 지원. 맞는 곳에서runtime/layers/parallel_conv.py와runtime/models/vaes/parallel/diffusers_spatial.py재사용. - 레이어 단위 offload: 모든 로드된 신경 모듈은
LayerwiseOffloadableModuleMixin을 상속하고 모든 반복 블록 경로를layer_names에 나열해야 해요. 비-DiT 모듈에layerwise_offload_dit_group_enabled = False를 설정해요. 컴포넌트 CPU offload는 대체가 아니에요.
DiT TP/SP는 wanvideo.py와 qwen_image.py, encoder TP와 offload는 gemma_3.py, VAE 디코드는 autoencoder_kl_qwenimage.py 또는 ltx_2_vae.py를 참고해요. Diffusers 백엔드는 호환성 우선이며 이 네이티브 통합 계약을 충족할 필요가 없어요.
6. 레지스트리 (Registry)
샘플링 파라미터와 파이프라인 구성이 생기면 패밀리를 등록해요.
register_configs(
model_family="my_model",
sampling_param_cls=MyModelSamplingParams,
pipeline_config_cls=MyModelPipelineConfig,
hf_model_paths=["org/my-model"],
)
파이프라인 파일은 EntryClass를 통해 발견돼요. 기존 레지스트리가 요구하지 않는 한 두 번째 파이프라인 레지스트리를 추가하지 마세요.
포팅 검증 (Verify the Port)
참조 구현과 비교할 때 하나의 결정적 프롬프트와 시드를 사용해요.
- 단일 GPU 스모크 테스트를 실행하고 출력에 응집된 콘텐츠가 있는지 확인.
- 잠재 스케일과 시프트, timestep 순서, sigma 값, 조건 kwargs를 Diffusers 또는 공식 구현과 비교.
- VAE 디코드를 tiled 및 다중 GPU
spatial_shard포함 별도로 비교. - Encoder 및 DiT TP, SP, 결합 TP × SP,
--layerwise-offload-components all실행하고 단일 GPU 상주 기준선과 비교. - 모델이 LoRA, CFG 병렬 처리, 분리를 지원하면 각 기능을 명시적으로 테스트.
- 사용자가 새 실행 명령을 필요로 할 때 쿡북, 예시, Supported Models 카탈로그 추가 또는 업데이트.
일반적인 실패 지점:
- 잘못된 잠재 스케일 또는 시프트.
- 뒤집히거나 dtype이 불일치한 timesteps.
- CFG 활성화 시 누락된 음의 임베딩.
- DiT
forward()와 불일치한 조건 kwarg 이름. - Rotary embedding 형태 또는 스타일 불일치.
raw_latent_shape를 복원하지 않고 패킹된 잠재 디코딩.
PR 체크리스트 (PR Checklist)
- 가능한 곳마다 기존 패밀리, 단계, 모듈, 스케줄러 또는 VAE를 재사용했다.
- 새 모델 접촉 표면을 작게 유지하고 추가 파일을 정당화했다.
- 네이티브 지원이 필요할 때
SamplingParams,PipelineConfig, 파이프라인 연결, DiT 모듈, 레지스트리 항목을 추가했다. - 해당될 때
pipeline_name이 Diffusersmodel_index.json_class_name과 일치하는지 확인했다. -
_required_config_modules가 모델 저장소와 일치하는지 확인했다. - 이미지 또는 비디오 품질을 참조 출력에 대해 검증했다.
- 위의 분산 및 메모리 통합 검사를 완료했다.
- 해당될 때 CFG 병렬 처리와 분산 서빙 경로를 테스트했다.