#
# Apache License, Version 2.0("라이선스")에 따라 라이선스가 부여됩니다.
# 이 파일은 라이선스에 따라만 사용할 수 있습니다.
# 라이선스 사본은 다음에서 가져올 수 있습니다
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# 적용 가능한 법률에 의해 요구되거나 서면으로 합의되지 않는 한, 소프트웨어
# 라이선스에 따라 배포되는 본 소프트웨어는 "있는 그대로"
# 명시적이든 묵시적이든 어떠한 종류의 보증이나 조건도 없이 제공됩니다.
# 권한을 관리하는 특정 언어에 대한 라이선스를 참조하세요
# 라이선스 하의 제한 사항.
-->

# GLM-Image

## 개요

GLM-Image은 하이브리드 오토리그레시브 + 디퓨전 디코더 아키텍처를 채택한 이미지 생성 모델로, 시각적 충실도와 세밀한 디테일의 상한선을 효과적으로 끌어올립니다. 일반적인 이미지 생성 품질 측면에서는 업계 표준인 LDM 기반 접근 방식과 동등한 수준을 유지하며, 지식 집약적인 이미지 생성 시나리오에서 뚜렷한 우위를 보입니다.

모델 아키텍처: 하이브리드 오토레그레시브 + 디퓨전 디코더 설계

+ Autoregressive generator: [GLM-4-9B-0414](https://huggingface.co/zai-org/GLM-4-9B-0414)에서 초기화된 9B 파라미터 모델로, 시각 토큰을 포함하도록 어휘가 확장되었습니다. 모델은 먼저 약 256개의 토큰으로 구성된 압축된 인코딩을 생성한 후, 1K~2K 고해상도 이미지 출력에 해당하는 1K~4K 토큰으로 확장합니다. `transformers` 라이브러리의 `GlmImageForConditionalGeneration` 클래스에서 AR 모델을 확인할 수 있습니다.
+ Diffusion Decoder: 잠재 공간 이미지 디코딩을 위한 단일 스트림 DiT 아키텍처 기반의 7B 파라미터 디코더입니다. Glyph Encoder 텍스트 모듈을 갖추고 있어 이미지 내 텍스트 렌더링의 정확도를 크게 향상시킵니다.

Post-training with decoupled reinforcement learning: 모델은 GRPO 알고리즘을 사용하여 세분화되고 모듈화된 피드백 전략을 도입하여 의미 이해와 시각적 디테일 품질을 모두 크게 향상시킵니다.

+ 자기회귀 모듈: 미학 및 의미 정렬에 초점을 맞춘 저주파 피드백 신호를 제공하여 지시 따르기 및 예술적 표현력을 향상시킵니다.
+ Decoder 모듈: 디테일 충실도와 텍스트 정확도를 목표로 하는 고주파 피드백을 제공하여 매우 사실적인 텍스처, 조명 및 색상 재현과 함께 더 정확한 텍스트 렌더링을 달성합니다.

GLM-Image는 단일 모델 내에서 텍스트-이미지 생성과 이미지-이미지 생성을 모두 지원합니다

+ 텍스트-이미지: 텍스트 설명에서 높은 디테일의 이미지를 생성하며, 특히 정보 밀도가 높은 시나리오에서 뛰어난 성능을 발휘합니다.
+ Image-to-image: 이미지 편집, 스타일 전이, 다중 대상 일관성, 사람 및 객체의 신원 보존 생성 등 다양한 작업을 지원합니다.

이 파이프라인은 [zRzRzRzRzRzRzR](https://github.com/zRzRzRzRzRzRzR)님이 기여했습니다. 코드베이스는 [여기](https://huggingface.co/zai-org/GLM-Image)에서 찾을 수 있습니다.

## 사용 예시

### 텍스트에서 이미지 생성

```python
import torch
from diffusers.pipelines.glm_image import GlmImagePipeline

pipe = GlmImagePipeline.from_pretrained("zai-org/GLM-Image",dtype=torch.bfloat16,device_map="cuda")
prompt = "A beautifully designed modern food magazine style dessert recipe illustration, themed around a raspberry mousse cake. The overall layout is clean and bright, divided into four main areas: the top left features a bold black title 'Raspberry Mousse Cake Recipe Guide', with a soft-lit close-up photo of the finished cake on the right, showcasing a light pink cake adorned with fresh raspberries and mint leaves; the bottom left contains an ingredient list section, titled 'Ingredients' in a simple font, listing 'Flour 150g', 'Eggs 3', 'Sugar 120g', 'Raspberry puree 200g', 'Gelatin sheets 10g', 'Whipping cream 300ml', and 'Fresh raspberries', each accompanied by minimalist line icons (like a flour bag, eggs, sugar jar, etc.); the bottom right displays four equally sized step boxes, each containing high-definition macro photos and corresponding instructions, arranged from top to bottom as follows: Step 1 shows a whisk whipping white foam (with the instruction 'Whip egg whites to stiff peaks'), Step 2 shows a red-and-white mixture being folded with a spatula (with the instruction 'Gently fold in the puree and batter'), Step 3 shows pink liquid being poured into a round mold (with the instruction 'Pour into mold and chill for 4 hours'), Step 4 shows the finished cake decorated with raspberries and mint leaves (with the instruction 'Decorate with raspberries and mint'); a light brown information bar runs along the bottom edge, with icons on the left representing 'Preparation time: 30 minutes', 'Cooking time: 20 minutes', and 'Servings: 8'. The overall color scheme is dominated by creamy white and light pink, with a subtle paper texture in the background, featuring compact and orderly text and image layout with clear information hierarchy."
image = pipe(
    prompt=prompt,
    height=32 * 32,
    width=36 * 32,
    num_inference_steps=30,
    guidance_scale=1.5,
    generator=torch.Generator(device="cuda").manual_seed(42),  # or "mps", "xpu", "cpu"
).images[0]

image.save("output_t2i.png")
```

### 이미지에서 이미지 생성

```python
import torch
from diffusers.pipelines.glm_image import GlmImagePipeline
from PIL import Image

pipe = GlmImagePipeline.from_pretrained("zai-org/GLM-Image",dtype=torch.bfloat16,device_map="cuda")
image_path = "cond.jpg" 
prompt = "Replace the background of the snow forest with an underground station featuring an automatic escalator."
image = Image.open(image_path).convert("RGB")
image = pipe(
    prompt=prompt,
    image=[image], # can input multiple images for multi-image-to-image generation such as [image, image1]
    height=33 * 32,
    width=32 * 32,
    num_inference_steps=30,
    guidance_scale=1.5,
    generator=torch.Generator(device="cuda").manual_seed(42),  # or "mps", "xpu", "cpu"
).images[0]

image.save("output_i2i.png")
```

+ GLM-Image에서 사용되는 AR 모델은 기본적으로 `do_sample=True`와 `0.95`의 temperature로 설정되어 있어, 실행마다 생성된 이미지가 크게 달라질 수 있습니다. AR 모델에서 부정확하거나 열화(degenerate)된 출력을 초래할 수 있으므로 do_sample=False로 설정하는 것은 권장하지 않습니다.

## GlmImagePipeline[[diffusers.GlmImagePipeline]]

#### diffusers.GlmImagePipeline[[diffusers.GlmImagePipeline]]

```python
diffusers.GlmImagePipeline(tokenizer: ByT5Tokenizer, processor: GlmImageProcessor, text_encoder: T5EncoderModel, vision_language_encoder: GlmImageForConditionalGeneration, vae: AutoencoderKL, transformer: GlmImageTransformer2DModel, scheduler: FlowMatchEulerDiscreteScheduler)
```

[소스](https://github.com/huggingface/diffusers/blob/main/src/diffusers/pipelines/glm_image/pipeline_glm_image.py#L161)

**매개변수:**

tokenizer (`PreTrainedTokenizer`) : 텍스트 인코더용 토크나이저.

processor (`AutoProcessor`) : AR 모델의 채팅 템플릿 및 토큰화를 처리하는 프로세서.

text_encoder (`T5EncoderModel`) : 글리프 임베딩을 위한 고정된 텍스트 인코더.

vision_language_encoder (`GlmImageForConditionalGeneration`) : 텍스트 프롬프트에서 이미지 토큰을 생성하는 AR 모델입니다.

vae ([AutoencoderKL](/docs/diffusers/main/ko/api/models/autoencoderkl#diffusers.AutoencoderKL)) : 이미지를 잠재 표현으로 인코딩하고 잠재 표현에서 이미지로 디코딩하는 Variational Auto-Encoder (VAE) 모델입니다.

transformer ([GlmImageTransformer2DModel](/docs/diffusers/main/ko/api/models/glm_image_transformer2d#diffusers.GlmImageTransformer2DModel)) : 인코딩된 이미지 잠재 변수를 디노이즈하기 위한 텍스트 조건부 트랜스포머 (DiT).

scheduler ([SchedulerMixin](/docs/diffusers/main/ko/api/schedulers/overview#diffusers.SchedulerMixin)) : `transformer`와 함께 사용되어 인코딩된 이미지 latents의 노이즈를 제거하는 스케줄러입니다.

GLM-Image를 사용한 텍스트-이미지 생성을 위한 Pipeline

이 파이프라인은 토큰 생성을 위한 AR(자기회귀) 모델과 이미지 디코딩을 위한 DiT(확산 변환기) 모델을 모두 통합합니다.

#### __호출__[[diffusers.GlmImagePipeline.__call__]]

```python
__call__(prompt: str | list[str] | None = None, image: typing.Union[PIL.Image.Image, numpy.ndarray, torch.Tensor, list[PIL.Image.Image], list[numpy.ndarray], list[torch.Tensor], NoneType] = None, height: int | None = None, width: int | None = None, num_inference_steps: int = 50, timesteps: list[int] | None = None, sigmas: list[float] | None = None, guidance_scale: float = 1.5, num_images_per_prompt: int = 1, generator: typing.Union[torch.Generator, list[torch.Generator], NoneType] = None, latents: typing.Optional[torch.Tensor] = None, prompt_embeds: typing.Optional[torch.Tensor] = None, negative_prompt_embeds: typing.Optional[torch.Tensor] = None, prior_token_ids: typing.Optional[torch.Tensor] = None, prior_token_image_ids: list[torch.Tensor] | None = None, source_image_grid_thw: list[torch.Tensor] | None = None, crops_coords_top_left: tuple = (0, 0), output_type: str = 'pil', return_dict: bool = True, attention_kwargs: dict[str, typing.Any] | None = None, callback_on_step_end: typing.Union[typing.Callable[[int, int, dict], NoneType], diffusers.callbacks.PipelineCallback, diffusers.callbacks.MultiPipelineCallbacks, NoneType] = None, callback_on_step_end_tensor_inputs: list = ['latents'], max_sequence_length: int = 2048)
```

[소스](https://github.com/huggingface/diffusers/blob/main/src/diffusers/pipelines/glm_image/pipeline_glm_image.py#L719)

**매개변수:**

prompt (`str` 또는 `list[str]`, *선택 사항*) : 이미지 생성을 안내하는 프롬프트입니다. H와 W가 토큰 차원(d32)인 'H W' 형식의 shape 정보를 포함해야 합니다. 예: "A beautiful sunset36 24"는 1152x768 이미지를 생성합니다.

image : 이미지-대-이미지 생성을 위한 선택적 조건 이미지.

height (`int`, *선택 사항*) : 픽셀 단위의 높이. 제공되지 않으면 프롬프트 형식 정보에서 유도됩니다.

width (`int`, *선택 사항*) : 픽셀 단위의 너비. 제공되지 않으면 프롬프트 형식 정보에서 유도됩니다.

num_inference_steps (`int`, *선택 사항*, 기본값 `50`) : DiT의 디노이징 단계 수입니다.

timesteps (`list[int]`, *선택 사항*) : 노이즈 제거 과정에 사용할 커스텀 timesteps입니다. 정의되지 않은 경우, `num_inference_steps`에 대한 스케줄러의 기본 스케줄이 사용됩니다.

sigmas (`list[float]`, *선택 사항*) : 노이즈 제거 과정에 사용할 커스텀 시그마입니다. 정의되지 않은 경우 스케줄러의 기본 스케줄이 사용됩니다.

guidance_scale (`float`, *선택 사항*, 기본값 `1.5`) : classifier-free guidance의 guidance scale입니다.

num_images_per_prompt (`int`, *선택 사항*, 기본값 `1`) : 프롬프트당 생성할 이미지의 수입니다.

generator (`torch.Generator`, *선택 사항*) : 재현성을 위한 랜덤 생성기.

latents (`torch.Tensor`, *선택 사항*) : 이미지 생성의 입력으로 사용할 사전 생성된 노이즈된 잠재 변수(latents).

prompt_embeds (`torch.Tensor`, *선택 사항*) : 미리 생성된 텍스트 임베딩입니다. 제공되지 않으면 `prompt`에서 임베딩이 생성됩니다.

negative_prompt_embeds (`torch.Tensor`, *선택 사항*) : 미리 생성된 부정 텍스트 임베딩. classifier-free guidance가 활성화된 경우 사용됩니다.

prior_token_ids (`torch.Tensor`, *선택 사항*) : `generate_prior_tokens`에서 사전 생성된 prior 토큰 ID입니다. 값이 제공되면 prior 생성이 건너뜁니다.

prior_token_image_ids (`list[torch.Tensor]`, *선택 사항*) : `prior_token_ids`와 연관된 이미지 토큰 ID입니다.

source_image_grid_thw (`list[torch.Tensor]`, *선택 사항*) : 소스 이미지 토큰에 대한 샘플별 THW 그리드 정보.

crops_coords_top_left (`tuple[int, int]`, *선택 사항*, 기본값 `(0, 0)`) : 조건부 임베딩에 사용되는 크롭의 왼쪽 위 좌표입니다.

output_type (`str`, *선택 사항*, 기본값 `"pil"`) : 출력 형식: "pil", "np" 또는 "latent".

return_dict (`bool`, *선택 사항*, 기본값 `True`) : 일반 튜플 대신 `GlmImagePipelineOutput`을 반환할지 여부.

attention_kwargs (`dict`, *선택 사항*) : 지정된 경우 `AttentionProcessor`에 전달되는 kwargs 사전입니다.

callback_on_step_end (`Callable`, `PipelineCallback`, `MultiPipelineCallbacks`, *선택 사항*) : 각 노이즈 제거 단계의 끝에서 호출되는 함수.

callback_on_step_end_tensor_inputs (`list[str]`, *선택 사항*) : `callback_on_step_end`에 전달되는 Tensor 입력.

max_sequence_length (`int`, *선택 사항*, 기본값 `2048`) : 텍스트 인코더의 최대 시퀀스 길이입니다.

**반환값:** `GlmImagePipelineOutput` 또는 `tuple`

생성된 이미지.

생성을 위해 파이프라인을 호출할 때 호출되는 함수.

예:
```python
>>> import torch
>>> from diffusers import GlmImagePipeline

>>> pipe = GlmImagePipeline.from_pretrained("zai-org/GLM-Image", torch_dtype=torch.bfloat16)
>>> pipe.to("cuda")

>>> prompt = "A photo of an astronaut riding a horse on mars"
>>> image = pipe(prompt).images[0]
>>> image.save("output.png")
```

#### encode_prompt[[diffusers.GlmImagePipeline.encode_prompt]]

```python
encode_prompt(prompt: str | list[str], do_classifier_free_guidance: bool = True, num_images_per_prompt: int = 1, prompt_embeds: typing.Optional[torch.Tensor] = None, negative_prompt_embeds: typing.Optional[torch.Tensor] = None, device: typing.Optional[torch.device] = None, dtype: typing.Optional[torch.dtype] = None, max_sequence_length: int = 2048)
```

[소스](https://github.com/huggingface/diffusers/blob/main/src/diffusers/pipelines/glm_image/pipeline_glm_image.py#L545)

**매개변수:**

prompt (`str` 또는 `list[str]`, *선택 사항*) : 인코딩할 프롬프트

do_classifier_free_guidance (`bool`, *선택 사항*, 기본값 `True`) : classifier free guidance를 사용할지 여부.

num_images_per_prompt (`int`, *선택 사항*, 기본값 1) : 프롬프트당 생성할 이미지 수. 결과 임베딩을 배치할 torch 장치

prompt_embeds (`torch.Tensor`, *선택 사항*) : 미리 생성된 텍스트 임베딩입니다. *예를 들어* 프롬프트 가중치와 같은 텍스트 입력을 쉽게 조정하는 데 사용할 수 있습니다. 제공되지 않으면 `prompt` 입력 인자에서 텍스트 임베딩이 생성됩니다.

device : (`torch.device`, *선택 사항*): torch device

dtype : (`torch.dtype`, *선택 사항*): torch dtype

max_sequence_length (`int`, 기본값 `2048`) : 인코딩된 프롬프트의 최대 시퀀스 길이입니다. 다른 값으로 설정할 수 있지만 결과가 저하될 수 있습니다.

프롬프트를 텍스트 인코더의 히든 상태로 인코딩합니다.

#### generate_prior_tokens[[diffusers.GlmImagePipeline.generate_prior_tokens]]

```python
generate_prior_tokens(prompt: str | list[str], height: int, width: int, image: list[list[PIL.Image.Image]] | None = None, device: typing.Optional[torch.device] = None, generator: typing.Optional[torch.Generator] = None)
```

[소스](https://github.com/huggingface/diffusers/blob/main/src/diffusers/pipelines/glm_image/pipeline_glm_image.py#L321)

**매개변수:**

prompt : 단일 프롬프트 또는 프롬프트 목록

height : 대상 이미지 높이

width : 대상 이미지 너비

image : List[List[PIL.Image]] 형식으로 정규화된 이미지 입력. 이 메서드를 호출하기 전에 _validate_and_normalize_images()를 사용하여 사전 검증해야 합니다.

device : 대상 장치

generator : 재현성을 위한 랜덤 생성기

**반환값:** `Tuple of`

- prior_token_ids: 업샘플링된 이전 토큰을 포함하는 (batch_size, num_tokens) 형태의 Tensor
- prior_token_image_ids_per_sample: 샘플당 하나씩 포함된 텐서 목록입니다. 각 텐서에는 해당 샘플의 모든 조건 이미지에 대한 업샘플링된 prior 토큰 ID가 포함되어 있습니다. t2i의 경우 None입니다.
- source_image_grid_thw_per_sample: 샘플당 하나씩 포함된 텐서 목록. 각 텐서는 업샘플링된 그리드 정보를 포함하며, 형태는 (num_condition_images, 3)입니다. t2i의 경우 None입니다.

AR 모델을 사용하여 DiT 모델의 이전 토큰을 생성합니다.

#### get_glyph_texts[[diffusers.GlmImagePipeline.get_glyph_texts]]

```python
get_glyph_texts(prompt)
```

[소스](https://github.com/huggingface/diffusers/blob/main/src/diffusers/pipelines/glm_image/pipeline_glm_image.py#L476)

프롬프트에서 글리프 텍스트를 추출합니다. 배치 처리를 위해 리스트의 리스트를 반환합니다.

## GlmImagePipelineOutput[[diffusers.pipelines.glm_image.pipeline_output.GlmImagePipelineOutput]]

#### diffusers.pipelines.glm_image.pipeline_output.GlmImagePipelineOutput[[diffusers.pipelines.glm_image.pipeline_output.GlmImagePipelineOutput]]

```python
diffusers.pipelines.glm_image.pipeline_output.GlmImagePipelineOutput(images: list[PIL.Image.Image] | numpy.ndarray)
```

[소스](https://github.com/huggingface/diffusers/blob/main/src/diffusers/pipelines/glm_image/pipeline_output.py#L10)

**매개변수:**

images (`List[PIL.Image.Image]` 또는 `np.ndarray`) : 길이가 `batch_size`인 denoised PIL 이미지 목록 또는 shape이 `(batch_size, height, width, num_channels)`인 numpy 배열입니다. PIL 이미지 또는 numpy 배열은 diffusion pipeline의 denoised 이미지를 나타냅니다.

CogView3 파이프라인의 출력 클래스입니다.

