o
    i1                     @   s<  d Z ddlZddlmZmZmZ ddlmZmZm	Z	m
Z
 ddlmZ ddlmZ ddlmZ eedd	dd
dZ	 dedB defddZdededefddZdededB dedB dejdededejdB dejdB dejdB dejdB dedeejdB ejdB f fdd ZG d!d" d"ZG d#d$ d$ZG d%d& d&ZdS )'uK  Flat denoiser classes — transformer received at call time, not stored.
Three implementations of the :class:`~ltx_pipelines.utils.types.Denoiser` protocol:
* :class:`SimpleDenoiser` — single transformer call, no guidance.
* :class:`GuidedDenoiser` — static guiders, handles CFG + STG + isolated modality.
* :class:`FactoryGuidedDenoiser` — resolves guiders per-step from sigma.
``GuidedDenoiser`` and ``FactoryGuidedDenoiser`` share the core multi-pass
logic via the module-level :func:`_guided_denoise` function, which batches
all guidance passes into a single transformer call.
    N)MultiModalGuiderMultiModalGuiderFactoryMultiModalGuiderParams)BatchedPerturbationConfigPerturbationPerturbationConfigPerturbationType)X0Model)LatentState)modality_from_latent_stateg      ?        )	cfg_scale	stg_scalemodality_scale)paramsguiderreturnc                 C   s   | dur| S t S )zIReturn the guider as-is, or a positive-only guider for absent modalities.N)_POSITIVE_ONLY_GUIDER)r    r   N/home/ubuntu/LTX-2/packages/ltx-pipelines/src/ltx_pipelines/utils/denoisers.py_ensure_guider   s   r   statenc                    s\   dt jdt jf fdd}t|| j|| j|| j|| j| jdur*|| jdS ddS )u   Repeat a ``LatentState`` *n* times along the batch dimension.
    ``(B, ...) → (n*B, ...)`` by tiling the whole tensor n times, so the
    ordering is ``[item0, item1, ..., item0, item1, ...]`` — matching
    ``torch.cat`` of n per-pass contexts.
    tr   c                    s    dg|    } |d< | |S )N   r   )dimrepeat)r   repeatsr   r   r   _repeat*   s   
z_repeat_state.<locals>._repeatN)latentdenoise_mask	positionsclean_latentattention_mask)torchTensorr
   r    r!   r"   r#   r$   )r   r   r   r   r   r   _repeat_state#   s   r'   transformervideo_stateaudio_statesigmavideo_guideraudio_guider	v_context	a_contextlast_denoised_videolast_denoised_audio
step_indexc          &         sP  | |
}| |
}|r|r||	fS |dur|du rtd|dur*|du r*tdtttjdB tjdB tf }d||t fg}| sI| r| rV|j	du rVtd| rc|j	du rctd|j	durk|j	n|}|j	duru|j	n|}|
d||t f g }| r|
ttj|jjd | r|
ttj|jjd |r|
d||t|f | s| r|
d	||tttjddttjddgf d
d |D }dd |D }t| dtdtjf fdd}d}|durtjdd |D dd}tt| |||| d}d}|dur1tjdd |D dd}tt| |||| d}| ||t|d\}}|durHt| ndg  }|durYt| ndg  }tt|t||dddd}|d \}}|dd\}}|dd\} }!|d	d\}"}#|r|n| ||| |"}$|r|	n| |||!|#}%|$|%fS )uZ  Core guided denoising — batches all guidance passes into one transformer call.
    Collects per-pass contexts first, then builds a single batched Modality
    per present modality via :func:`modality_from_latent_state`.  When wrapped
    with :class:`~ltx_core.batch_split.BatchSplitAdapter`, the transformer may
    split this batch into sequential chunks internally.
    Guiders must not be ``None``. For absent modalities, callers should pass
    :data:`_POSITIVE_ONLY_GUIDER` (via :func:`_ensure_guider`) so that only
    the conditioned pass runs and ``calculate()`` returns cond unchanged.
    Nz2v_context is required when video_state is providedz2a_context is required when audio_state is providedcondz8Negative context is required for unconditioned denoisinguncond)typeblocksptbmodc                 S   s   g | ]\}}}}|qS r   r   ).0name_r   r   r   
<listcomp>       z#_guided_denoise.<locals>.<listcomp>c                 S   s   g | ]\}}}}|qS r   r   )r9   r;   r7   r   r   r   r<      r=   r   r   c                    s    | jjd   S )z<Expand scalar sigma to (n * B,) matching the repeated state.r   )expandr    shape)r   r   r+   r   r   _batched_sigma   s   z'_guided_denoise.<locals>._batched_sigmac                 S   s   g | ]\}}}}|qS r   r   )r9   r;   vcr   r   r   r<      r=   r   )r   )enabledc                 S   s   g | ]\}}}}|qS r   r   )r9   r;   acr   r   r   r<      r=   videoaudioperturbationsr   T)strict)r   r   )!should_skip_step
ValueErrortuplestrr%   r&   r   emptydo_unconditional_generationnegative_contextappenddo_perturbed_generationr   r   SKIP_VIDEO_SELF_ATTNr   
stg_blocksSKIP_AUDIO_SELF_ATTNdo_isolated_modality_generationSKIP_A2V_CROSS_ATTNSKIP_V2A_CROSS_ATTNlenr
   catr   r'   r   listchunkdictzipget	calculate)&r(   r)   r*   r+   r,   r-   r.   r/   r0   r1   r2   v_skipa_skip_passpassesv_nega_negstg_perturbations
pass_namesptb_configsrA   batched_videobatched_audioall_vall_asplits_vsplits_arcond_vcond_auncond_vuncond_aptb_vptb_amod_vmod_adenoised_videodenoised_audior   r@   r   _guided_denoise8   s   





""r{   c                   @   sr   e Zd ZdZdejdB dejdB ddfddZded	edB d
edB dejde	de
ejdB ejdB f fddZdS )SimpleDenoiserz^Single transformer call, no guidance.
    Passes ``None`` Modality for absent modalities.
    r.   Nr/   r   c                 C   s   || _ || _d S N)r.   r/   )selfr.   r/   r   r   r   __init__   s   
zSimpleDenoiser.__init__r(   r)   r*   sigmasr2   c           	      C   sJ   || }|d urt || j|nd }|d urt || j|nd }|||d dS )NrE   )r   r.   r/   )	r~   r(   r)   r*   r   r2   r+   	pos_video	pos_audior   r   r   __call__   s   zSimpleDenoiser.__call__)__name__
__module____qualname____doc__r%   r&   r   r	   r
   intrL   r   r   r   r   r   r|      s,    
r|   c                   @      e Zd ZdZ		ddejdB dejdB dedB dedB ddf
dd	Zd
ede	dB de	dB dejde
deejdB ejdB f fddZdS )GuidedDenoiseru   Static guiders — handles CFG + STG + isolated modality.
    Context/guider can be ``None`` for absent modalities (a positive-only
    guider is substituted at call time).
    Nr.   r/   r,   r-   r   c                 C   s(   || _ || _|| _|| _d | _d | _d S r}   )r.   r/   r,   r-   _last_denoised_video_last_denoised_audio)r~   r.   r/   r,   r-   r   r   r   r      s   
zGuidedDenoiser.__init__r(   r)   r*   r   r2   c                 C   sN   t ||||| t| jt| j| j| j| j| j|d\}}|| _|| _||fS N)r(   r)   r*   r+   r,   r-   r.   r/   r0   r1   r2   )r{   r   r,   r-   r.   r/   r   r   )r~   r(   r)   r*   r   r2   ry   rz   r   r   r   r      s    
zGuidedDenoiser.__call__NN)r   r   r   r   r%   r&   r   r   r	   r
   r   rL   r   r   r   r   r   r      s8    	
r   c                   @   r   )FactoryGuidedDenoiserzLResolves guiders per-step from sigma, then delegates to shared guided logic.Nr.   r/   video_guider_factoryaudio_guider_factoryr   c                 C   s.   || _ || _|| _|| _d | _d | _d | _d S r}   )r.   r/   r   r   r   r   _sigma_vals_cached)r~   r.   r/   r   r   r   r   r   r      s   
zFactoryGuidedDenoiser.__init__r(   r)   r*   r   r2   c                 C   s   | j d u r|   | _ | j | }t| jr| j|nd }t| js'| jr0| jp,| j|nd }t||||| ||| j	| j
| j| j|d\}	}
|	| _|
| _|	|
fS r   )r   detachcputolistr   r   build_from_sigmar   r{   r.   r/   r   r   )r~   r(   r)   r*   r   r2   	sigma_valr,   r-   ry   rz   r   r   r   r     s:   


zFactoryGuidedDenoiser.__call__r   )r   r   r   r   r%   r&   r   r   r	   r
   r   rL   r   r   r   r   r   r      s8    
r   )r   r%   ltx_core.components.guidersr   r   r   ltx_core.guidance.perturbationsr   r   r   r   ltx_core.model.transformerr	   ltx_core.typesr
   ltx_pipelines.utils.helpersr   r   r   r   r'   r&   rL   r{   r|   r   r   r   r   r   r   <module>   sR    


z.