
     iJ                     f    d dl mZ d dlmZmZmZmZ d dlmZ dej                  deeef   defdZ
y)    )partial)CallableDictSetTextNtrunkbranchesreturnc                      fd}t         d      r |        g  _         fd} j                  |      } j                  j                  |        fd}t	        |t
              s|D ci c]  }|| }}t               }|j                         D ]*  \  }}	|	|vrt               ||	<   ||	   j                  |       ,  j                         D ]J  \  }	}
|	|vr||	   D ]8  }|
j                  t        ||            } j                  j                  |       : L  fd} j                  |      } j                  j                  |       |S c c}w )a.  Add probing branches to a trunk module

    Parameters
    ----------
    trunk : nn.Module
        Multi-layer trunk.
    branches : {branch_name: layer_name} dict or [layer_name] list
        Indicate where to plug a probing branch.

    Returns
    -------
    revert : Callable
        Callable that, when called, removes probing branches.

    Usage
    -----

    Define a trunk made out of three consecutive layers

    >>> import torch.nn as nn
    >>> class Trunk(nn.Module):
    ...
    ...     def __init__(self):
    ...         super().__init__()
    ...         self.layer1 = nn.Linear(1, 2)
    ...         self.layer2 = nn.Linear(2, 3)
    ...         self.layer3 = nn.Linear(3, 4)
    ...
    ...     def forward(self, x):
    ...         return self.layer3(self.layer2(self.layer1(x)))

    >>> trunk = Trunk()
    >>> x = torch.tensor((0.,))
    >>> trunk(x)
    # tensor([ 0.4548, -0.1814,  0.9494,  1.0445], grad_fn=<AddBackward0>)

    Add two probing branches:
    - first one is called "probe1" and probes the output of "layer1"
    - second one is called "probe2" and probes the output of "layer3"

    >>> revert = probe(trunk, {"probe1": "layer1", "probe2": "layer3"})
    >>> trunk(x)
    # {'probe1': tensor([ 0.5854, -0.9685], grad_fn=<AddBackward0>),
    #  'probe2': tensor([ 0.4548, -0.1814,  0.9494,  1.0445], grad_fn=<AddBackward0>)}

    Use callback returned by `probe` to revert its effect

    >>> revert()
    >>> trunk(x)
    # tensor([ 0.4548, -0.1814,  0.9494,  1.0445], grad_fn=<AddBackward0>)

    For convenience, one can also define probes as a list of layers:

    >>> revert = probe(trunk, ['layer1', 'layer3'])
    >>> trunk(x)
    # {'layer1': tensor([ 0.5854, -0.9685], grad_fn=<AddBackward0>),
    #  'layer3': tensor([ 0.4548, -0.1814,  0.9494,  1.0445], grad_fn=<AddBackward0>)}
    c                  P    ` j                  D ]  } | j                           `y N)__probe__probe_handlesremove)handler   s    o/Volumes/fast/ai/experiments/voice-extract-mac/.venv/lib/python3.12/site-packages/pyannote/audio/utils/probe.pyr   zprobe.<locals>.removeZ   s'    M++FMMO ,!    r   c                 $    t               _        y r   )dictr   )moduleinputr   s     r   __probe_initzprobe.<locals>.__probe_inite   s    r   c                 $    |j                   | <   y r   r   )branch_namer   r   outputr   s       r   __probe_appendzprobe.<locals>.__probe_appendk   s    %+k"r   c                     j                   S r   r   )r   r   r   r   s      r   __probe_returnzprobe.<locals>.__probe_return~   s    }}r   )hasattrr   register_forward_pre_hookappend
isinstancer   itemssetaddnamed_modulesregister_forward_hookr   )r   r	   r   r   r   r   bsehcnarbr   
layer_namelayerr   s   `           r   prober-      sN   x" ui E ,,\:F	  (, h%"*+(QAqD(+ $H#+>>#3ZX%#&5HZ   - $4
 #002
EX%#J/K001UVF!!((0 0 3 ((8F	  (M+ ,s   +
E)	functoolsr   typingr   r   r   r   torch.nnnnModuler-    r   r   <module>r4      s>   0  , , f fd4:&6 f8 fr   